@sphereon/ssi-sdk.data-store 0.34.1-fix.114 → 0.34.1-fix.141

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.
Files changed (30) hide show
  1. package/dist/index.cjs +1606 -1399
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +160 -166
  4. package/dist/index.d.ts +160 -166
  5. package/dist/index.js +1562 -1355
  6. package/dist/index.js.map +1 -1
  7. package/package.json +8 -8
  8. package/src/__tests__/contact.entities.test.ts +2 -2
  9. package/src/__tests__/contact.store.test.ts +1 -1
  10. package/src/__tests__/digitalCredential.entities.test.ts +2 -1
  11. package/src/__tests__/digitalCredential.store.test.ts +5 -5
  12. package/src/__tests__/pd-manager.entities.test.ts +14 -37
  13. package/src/__tests__/pd-manager.store.test.ts +133 -0
  14. package/src/digitalCredential/DigitalCredentialStore.ts +9 -9
  15. package/src/entities/contact/IdentityEntity.ts +2 -1
  16. package/src/entities/digitalCredential/DigitalCredentialEntity.ts +2 -1
  17. package/src/entities/presentationDefinition/PresentationDefinitionItemEntity.ts +1 -1
  18. package/src/migrations/generic/12-CreateBitstringStatusList.ts +32 -2
  19. package/src/migrations/generic/13-UpdatePresentationDefinitionItemNullable.ts +67 -0
  20. package/src/migrations/generic/index.ts +13 -5
  21. package/src/migrations/postgres/1741895823000-CreateBitstringStatusList.ts +13 -2
  22. package/src/migrations/postgres/1756975509000-UpdatePresentationDefinitionItemNullable.ts +15 -0
  23. package/src/migrations/sqlite/1756975340000-UpdatePresentationDefinitionItemNullable.ts +77 -0
  24. package/src/presentationDefinition/PDStore.ts +6 -1
  25. package/src/types/contact/contact.ts +1 -1
  26. package/src/types/digitalCredential/IAbstractDigitalCredentialStore.ts +2 -1
  27. package/src/types/digitalCredential/enums.ts +0 -7
  28. package/src/types/digitalCredential/types.ts +2 -1
  29. package/src/types/presentationDefinition/presentationDefinition.ts +3 -3
  30. package/src/utils/presentationDefinition/MappingUtils.ts +39 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.data-store",
3
- "version": "0.34.1-fix.114+ee98a3e1",
3
+ "version": "0.34.1-fix.141+ea643e42",
4
4
  "source": "src/index.ts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,16 +28,16 @@
28
28
  "dependencies": {
29
29
  "@sphereon/kmp-mdoc-core": "0.2.0-SNAPSHOT.26",
30
30
  "@sphereon/pex": "5.0.0-unstable.28",
31
- "@sphereon/ssi-sdk-ext.did-utils": "0.34.1-fix.114+ee98a3e1",
32
- "@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-fix.114+ee98a3e1",
33
- "@sphereon/ssi-sdk.agent-config": "0.34.1-fix.114+ee98a3e1",
34
- "@sphereon/ssi-sdk.core": "0.34.1-fix.114+ee98a3e1",
35
- "@sphereon/ssi-types": "0.34.1-fix.114+ee98a3e1",
31
+ "@sphereon/ssi-sdk-ext.did-utils": "0.34.1-fix.141+ea643e42",
32
+ "@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-fix.141+ea643e42",
33
+ "@sphereon/ssi-sdk.agent-config": "0.34.1-fix.141+ea643e42",
34
+ "@sphereon/ssi-sdk.core": "0.34.1-fix.141+ea643e42",
35
+ "@sphereon/ssi-types": "0.34.1-fix.141+ea643e42",
36
36
  "@veramo/core": "4.2.0",
37
37
  "@veramo/utils": "4.2.0",
38
38
  "blakejs": "^1.2.1",
39
39
  "class-validator": "0.14.1",
40
- "dcql": "0.2.19",
40
+ "dcql": "1.0.1",
41
41
  "debug": "^4.3.5",
42
42
  "typeorm": "0.3.20"
43
43
  },
@@ -65,5 +65,5 @@
65
65
  "PostgreSQL",
66
66
  "Contact Store"
67
67
  ],
68
- "gitHead": "ee98a3e17c1241de776e164fcfe1e73d162c5902"
68
+ "gitHead": "ea643e42804501f2a323a73971465d527981123d"
69
69
  }
@@ -1,6 +1,8 @@
1
1
  import { getDID } from '@sphereon/ssi-sdk-ext.did-utils'
2
2
  import { DataSources } from '@sphereon/ssi-sdk.agent-config'
3
+ import { CredentialRole } from '@sphereon/ssi-types'
3
4
  import { DataSource, FindOptionsWhere } from 'typeorm'
5
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
4
6
  import { BaseContactEntity } from '../entities/contact/BaseContactEntity'
5
7
  import { ConnectionEntity } from '../entities/contact/ConnectionEntity'
6
8
  import { ContactMetadataItemEntity } from '../entities/contact/ContactMetadataItemEntity'
@@ -18,7 +20,6 @@ import { PartyTypeEntity } from '../entities/contact/PartyTypeEntity'
18
20
  import { PhysicalAddressEntity } from '../entities/contact/PhysicalAddressEntity'
19
21
  import {
20
22
  contactMetadataItemEntityFrom,
21
- CredentialRole,
22
23
  DataStoreContactEntities,
23
24
  DataStoreMigrations,
24
25
  identityMetadataItemEntityFrom,
@@ -57,7 +58,6 @@ import {
57
58
  partyTypeEntityFrom,
58
59
  physicalAddressEntityFrom,
59
60
  } from '../utils/contact/MappingUtils'
60
- import { afterEach, beforeEach, describe, expect, it } from 'vitest'
61
61
  // TODO write test adding two contacts reusing the same contactType
62
62
 
63
63
  describe('Database entities tests', (): void => {
@@ -4,7 +4,6 @@ import { ConnectionType, DataStoreContactEntities, DataStoreMigrations, Identity
4
4
  import { ContactStore } from '../contact/ContactStore'
5
5
  import {
6
6
  CorrelationIdentifierType,
7
- CredentialRole,
8
7
  ElectronicAddress,
9
8
  GetElectronicAddressesArgs,
10
9
  GetIdentitiesArgs,
@@ -27,6 +26,7 @@ import {
27
26
  PhysicalAddress,
28
27
  } from '../types'
29
28
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
29
+ import { CredentialRole } from "@sphereon/ssi-types"
30
30
 
31
31
  describe('Contact store tests', (): void => {
32
32
  let dbConnection: DataSource
@@ -1,6 +1,7 @@
1
1
  import { DataSources } from '@sphereon/ssi-sdk.agent-config'
2
+ import { CredentialRole } from '@sphereon/ssi-types'
2
3
  import { DataSource } from 'typeorm'
3
- import { CredentialRole, DataStoreDigitalCredentialEntities } from '../index'
4
+ import { DataStoreDigitalCredentialEntities } from '../index'
4
5
  import { DataStoreDigitalCredentialMigrations } from '../migrations'
5
6
  import { DigitalCredentialEntity } from '../entities/digitalCredential/DigitalCredentialEntity'
6
7
  import { computeEntryHash } from '@veramo/utils'
@@ -1,9 +1,11 @@
1
1
  import { DataSources } from '@sphereon/ssi-sdk.agent-config'
2
- import { IVerifiablePresentation } from '@sphereon/ssi-types'
2
+ import { defaultHasher } from '@sphereon/ssi-sdk.core'
3
+ import { CredentialRole, IVerifiablePresentation } from '@sphereon/ssi-types'
3
4
  import { DataSource } from 'typeorm'
4
- import { DataStoreDigitalCredentialMigrations } from '../migrations'
5
- import { CredentialRole, DataStoreDigitalCredentialEntities } from '../index'
5
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
6
6
  import { DigitalCredentialStore } from '../digitalCredential/DigitalCredentialStore'
7
+ import { DataStoreDigitalCredentialEntities } from '../index'
8
+ import { DataStoreDigitalCredentialMigrations } from '../migrations'
7
9
  import {
8
10
  AddCredentialArgs,
9
11
  CredentialCorrelationType,
@@ -14,8 +16,6 @@ import {
14
16
  GetCredentialsArgs,
15
17
  GetCredentialsResponse,
16
18
  } from '../types'
17
- import { defaultHasher } from '@sphereon/ssi-sdk.core'
18
- import { afterEach, beforeEach, describe, expect, it } from 'vitest'
19
19
 
20
20
  describe('Database entities tests', (): void => {
21
21
  let dbConnection: DataSource
@@ -1,9 +1,11 @@
1
1
  import { DataSources } from '@sphereon/ssi-sdk.agent-config'
2
+ import { DcqlQuery } from 'dcql'
2
3
  import { DataSource } from 'typeorm'
3
4
  import { PresentationDefinitionItemEntity } from '../entities/presentationDefinition/PresentationDefinitionItemEntity'
4
5
  import { DataStorePresentationDefinitionMigrations } from '../migrations'
5
6
  import { DataStorePresentationDefinitionEntities } from '../index'
6
7
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
8
+ import { SAMPLE_DCQL_QUERY_PAYLOAD } from './pd-manager.store.test'
7
9
 
8
10
  describe('PresentationDefinitionItemEntity tests', (): void => {
9
11
  let dbConnection: DataSource
@@ -28,23 +30,9 @@ describe('PresentationDefinitionItemEntity tests', (): void => {
28
30
  it('should create and retrieve PresentationDefinitionItemEntity with dcqlPayload', async (): Promise<void> => {
29
31
  const repository = dbConnection.getRepository(PresentationDefinitionItemEntity)
30
32
  const entity = new PresentationDefinitionItemEntity()
31
- entity.definitionId = 'definition1'
33
+ entity.definitionId = 'ajax-club'
32
34
  entity.version = '1.0'
33
- entity.definitionPayload = JSON.stringify({ id: 'definition1', input_descriptors: [] })
34
- entity.dcqlPayload = JSON.stringify({
35
- credentials: [
36
- {
37
- id: 'credential1',
38
- format: 'jwt_vc',
39
- claims: [
40
- {
41
- namespace: 'test',
42
- claim_name: 'testClaim',
43
- },
44
- ],
45
- },
46
- ],
47
- })
35
+ entity.dcqlPayload = JSON.stringify(SAMPLE_DCQL_QUERY_PAYLOAD.dcqlQuery)
48
36
 
49
37
  const savedEntity = await repository.save(entity)
50
38
  expect(savedEntity).toBeDefined()
@@ -55,29 +43,18 @@ describe('PresentationDefinitionItemEntity tests', (): void => {
55
43
  expect(retrievedEntity).toBeDefined()
56
44
  expect(retrievedEntity!.dcqlPayload).toBeDefined()
57
45
  const parsedDcql = JSON.parse(retrievedEntity!.dcqlPayload)
58
- expect(parsedDcql.credentials[0].id).toEqual('credential1')
46
+ expect(parsedDcql.credentials[0].id).toEqual('clubcard-v1')
47
+ expect(parsedDcql.credentials[0].format).toEqual('dc+sd-jwt')
48
+ expect(parsedDcql.credentials[0].meta.vct_values).toContain('clubcard-v1')
49
+ expect(parsedDcql.credentials[0].claims).toHaveLength(4)
59
50
  })
60
51
 
61
52
  it('should update PresentationDefinitionItemEntity dcqlPayload', async (): Promise<void> => {
62
53
  const repository = dbConnection.getRepository(PresentationDefinitionItemEntity)
63
54
  const entity = new PresentationDefinitionItemEntity()
64
- entity.definitionId = 'definition1'
55
+ entity.definitionId = 'ajax-club'
65
56
  entity.version = '1.0'
66
- entity.definitionPayload = JSON.stringify({ id: 'definition1', input_descriptors: [] })
67
- entity.dcqlPayload = JSON.stringify({
68
- credentials: [
69
- {
70
- id: 'credential1',
71
- format: 'jwt_vc',
72
- claims: [
73
- {
74
- namespace: 'test',
75
- claim_name: 'testClaim',
76
- },
77
- ],
78
- },
79
- ],
80
- })
57
+ entity.dcqlPayload = JSON.stringify(SAMPLE_DCQL_QUERY_PAYLOAD.dcqlQuery)
81
58
 
82
59
  const savedEntity = await repository.save(entity)
83
60
  expect(savedEntity).toBeDefined()
@@ -85,12 +62,11 @@ describe('PresentationDefinitionItemEntity tests', (): void => {
85
62
  const updatedDcql = {
86
63
  credentials: [
87
64
  {
88
- id: 'credential2',
65
+ id: 'updated-clubcard',
89
66
  format: 'jwt_vc',
90
67
  claims: [
91
68
  {
92
- namespace: 'test',
93
- claim_name: 'updatedClaim',
69
+ path: ['name'],
94
70
  },
95
71
  ],
96
72
  },
@@ -99,7 +75,8 @@ describe('PresentationDefinitionItemEntity tests', (): void => {
99
75
  savedEntity.dcqlPayload = JSON.stringify(updatedDcql)
100
76
  const updatedEntity = await repository.save(savedEntity)
101
77
  expect(updatedEntity).toBeDefined()
102
- expect(JSON.parse(updatedEntity.dcqlPayload).credentials[0].id).toEqual('credential2')
78
+ expect(JSON.parse(updatedEntity.dcqlPayload).credentials[0].id).toEqual('updated-clubcard')
79
+ expect(JSON.parse(updatedEntity.dcqlPayload).credentials[0].format).toEqual('jwt_vc')
103
80
  })
104
81
 
105
82
  it('should create and retrieve PresentationDefinitionItemEntity', async (): Promise<void> => {
@@ -1,9 +1,41 @@
1
1
  import { DataSources } from '@sphereon/ssi-sdk.agent-config'
2
+ import { DcqlQueryPayload } from '@sphereon/ssi-types'
2
3
  import { DataSource } from 'typeorm'
3
4
  import { DataStorePresentationDefinitionEntities, DataStorePresentationDefinitionMigrations, PDStore } from '../index'
4
5
  import { GetDefinitionsArgs, NonPersistedPresentationDefinitionItem, PresentationDefinitionItem } from '../types'
5
6
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
6
7
 
8
+ export const SAMPLE_DCQL_QUERY_PAYLOAD: DcqlQueryPayload = {
9
+ queryId: 'ajax-club',
10
+ dcqlQuery: {
11
+ credentials: [
12
+ {
13
+ id: 'clubcard-v1',
14
+ format: 'dc+sd-jwt',
15
+ require_cryptographic_holder_binding: true,
16
+ multiple: false,
17
+ meta: {
18
+ vct_values: ['clubcard-v1'],
19
+ },
20
+ claims: [
21
+ {
22
+ path: ['personData', 'name'],
23
+ },
24
+ {
25
+ path: ['personData', 'birthDate'],
26
+ },
27
+ {
28
+ path: ['membershipData', 'membershipId'],
29
+ },
30
+ {
31
+ path: ['membershipData', 'season'],
32
+ },
33
+ ],
34
+ },
35
+ ],
36
+ },
37
+ }
38
+
7
39
  describe('PDStore tests', (): void => {
8
40
  let dbConnection: DataSource
9
41
  let pdStore: PDStore
@@ -130,6 +162,23 @@ describe('PDStore tests', (): void => {
130
162
  expect(result.definitionId).toEqual(definition.definitionId)
131
163
  })
132
164
 
165
+ it('should add definition with dcqlPayload', async (): Promise<void> => {
166
+ const definition: NonPersistedPresentationDefinitionItem = {
167
+ definitionId: 'ajax-club',
168
+ version: '1.0',
169
+ definitionPayload: { id: 'ajax-club', input_descriptors: [] },
170
+ dcqlPayload: SAMPLE_DCQL_QUERY_PAYLOAD,
171
+ }
172
+
173
+ const result: PresentationDefinitionItem = await pdStore.addDefinition(definition)
174
+
175
+ expect(result).toBeDefined()
176
+ expect(result.definitionId).toEqual(definition.definitionId)
177
+ expect(result.dcqlPayload).toBeDefined()
178
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].id).toEqual('clubcard-v1')
179
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].format).toEqual('dc+sd-jwt')
180
+ })
181
+
133
182
  it('should update definition', async (): Promise<void> => {
134
183
  const definition: NonPersistedPresentationDefinitionItem = {
135
184
  definitionId: 'definition1',
@@ -151,6 +200,90 @@ describe('PDStore tests', (): void => {
151
200
  expect(result.version).toEqual('1.1')
152
201
  })
153
202
 
203
+ it('should update definition with dcqlPayload', async (): Promise<void> => {
204
+ const definition: NonPersistedPresentationDefinitionItem = {
205
+ definitionId: 'ajax-club',
206
+ version: '1.0',
207
+ definitionPayload: { id: 'ajax-club', input_descriptors: [] },
208
+ dcqlPayload: SAMPLE_DCQL_QUERY_PAYLOAD,
209
+ }
210
+ const savedDefinition: PresentationDefinitionItem = await pdStore.addDefinition(definition)
211
+ expect(savedDefinition).toBeDefined()
212
+
213
+ const updatedDcqlQueryPayload = {
214
+ ...SAMPLE_DCQL_QUERY_PAYLOAD,
215
+ dcqlQuery: {
216
+ credentials: [
217
+ {
218
+ id: 'updated-clubcard',
219
+ format: 'dc+sd-jwt',
220
+ claims: [
221
+ {
222
+ path: ['name'],
223
+ },
224
+ ],
225
+ },
226
+ ],
227
+ },
228
+ } as unknown as DcqlQueryPayload // FIXME I do not have another solution for this atm, I can do Partial<DcqlQuery> but that does not work for its child entities
229
+
230
+ const updatedDefinition: PresentationDefinitionItem = {
231
+ ...savedDefinition,
232
+ version: '1.1',
233
+ dcqlPayload: updatedDcqlQueryPayload,
234
+ }
235
+
236
+ await pdStore.updateDefinition(updatedDefinition)
237
+ const result: PresentationDefinitionItem = await pdStore.getDefinition({ itemId: savedDefinition.id })
238
+
239
+ expect(result).toBeDefined()
240
+ expect(result.version).toEqual('1.1')
241
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].id).toEqual('updated-clubcard')
242
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].format).toEqual('dc+sd-jwt')
243
+ })
244
+
245
+ it('should get definition with dcqlPayload by id', async (): Promise<void> => {
246
+ const definition: NonPersistedPresentationDefinitionItem = {
247
+ definitionId: 'ajax-club',
248
+ version: '1.0',
249
+ definitionPayload: { id: 'ajax-club', input_descriptors: [] },
250
+ dcqlPayload: SAMPLE_DCQL_QUERY_PAYLOAD,
251
+ }
252
+
253
+ const savedDefinition: PresentationDefinitionItem = await pdStore.addDefinition(definition)
254
+ expect(savedDefinition).toBeDefined()
255
+
256
+ const result: PresentationDefinitionItem = await pdStore.getDefinition({ itemId: savedDefinition.id })
257
+
258
+ expect(result).toBeDefined()
259
+ expect(result.dcqlPayload).toBeDefined()
260
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].format).toBe('dc+sd-jwt')
261
+ if (result.dcqlPayload?.dcqlQuery.credentials[0].format === 'dc+sd-jwt') {
262
+ expect(result.dcqlPayload.dcqlQuery.credentials[0].meta?.vct_values).toContain('clubcard-v1')
263
+ }
264
+ expect(result.dcqlPayload?.dcqlQuery.credentials[0].claims).toHaveLength(4)
265
+ })
266
+
267
+ it('should get definitions with dcqlPayload by filter', async (): Promise<void> => {
268
+ const definition: NonPersistedPresentationDefinitionItem = {
269
+ definitionId: 'ajax-club',
270
+ version: '1.0',
271
+ definitionPayload: { id: 'ajax-club', input_descriptors: [] },
272
+ dcqlPayload: SAMPLE_DCQL_QUERY_PAYLOAD,
273
+ }
274
+ const savedDefinition: PresentationDefinitionItem = await pdStore.addDefinition(definition)
275
+ expect(savedDefinition).toBeDefined()
276
+
277
+ const args: GetDefinitionsArgs = {
278
+ filter: [{ definitionId: 'ajax-club' }],
279
+ }
280
+ const result: Array<PresentationDefinitionItem> = await pdStore.getDefinitions(args)
281
+
282
+ expect(result.length).toEqual(1)
283
+ expect(result[0].dcqlPayload).toBeDefined()
284
+ expect(result[0].dcqlPayload?.dcqlQuery.credentials[0].id).toEqual('clubcard-v1')
285
+ })
286
+
154
287
  it('should delete definition', async (): Promise<void> => {
155
288
  const definition: NonPersistedPresentationDefinitionItem = {
156
289
  definitionId: 'definition1',
@@ -1,7 +1,11 @@
1
- import { AbstractDigitalCredentialStore } from './AbstractDigitalCredentialStore'
1
+ import { CredentialRole, OrPromise } from '@sphereon/ssi-types'
2
+ import Debug from 'debug'
3
+ import { DataSource, type FindOptionsOrder, type FindOptionsWhere, Repository } from 'typeorm'
4
+
5
+ import { digitalCredentialFrom, digitalCredentialsFrom, nonPersistedDigitalCredentialEntityFromAddArgs } from '../../src'
6
+ import { DigitalCredentialEntity } from '../entities/digitalCredential/DigitalCredentialEntity'
2
7
  import {
3
8
  AddCredentialArgs,
4
- CredentialRole,
5
9
  CredentialStateType,
6
10
  DigitalCredential,
7
11
  GetCredentialArgs,
@@ -11,14 +15,10 @@ import {
11
15
  RemoveCredentialArgs,
12
16
  UpdateCredentialStateArgs,
13
17
  } from '../types'
14
- import { OrPromise } from '@sphereon/ssi-types'
15
- import { DataSource, type FindOptionsOrder, type FindOptionsWhere, Repository } from 'typeorm'
16
- import Debug from 'debug'
17
- import { DigitalCredentialEntity } from '../entities/digitalCredential/DigitalCredentialEntity'
18
-
19
- import { digitalCredentialFrom, digitalCredentialsFrom, nonPersistedDigitalCredentialEntityFromAddArgs } from '../../src'
20
18
  import { parseAndValidateOrderOptions } from '../utils/SortingUtils'
21
19
 
20
+ import { AbstractDigitalCredentialStore } from './AbstractDigitalCredentialStore'
21
+
22
22
  const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:credential-store')
23
23
 
24
24
  export class DigitalCredentialStore extends AbstractDigitalCredentialStore {
@@ -78,7 +78,7 @@ export class DigitalCredentialStore extends AbstractDigitalCredentialStore {
78
78
  return false
79
79
  }
80
80
 
81
- let query: FindOptionsWhere<DigitalCredentialEntity> = {}
81
+ const query: FindOptionsWhere<DigitalCredentialEntity> = {}
82
82
 
83
83
  if ('id' in args) {
84
84
  query.id = args.id
@@ -17,7 +17,8 @@ import { typeOrmDateTime } from '@sphereon/ssi-sdk.agent-config'
17
17
  import { CorrelationIdentifierEntity } from './CorrelationIdentifierEntity'
18
18
  import { ConnectionEntity } from './ConnectionEntity'
19
19
  import { IdentityMetadataItemEntity } from './IdentityMetadataItemEntity'
20
- import { CredentialRole, IdentityOrigin, ValidationConstraint } from '../../types'
20
+ import { IdentityOrigin, ValidationConstraint } from '../../types'
21
+ import { CredentialRole } from '@sphereon/ssi-types'
21
22
  import { PartyEntity } from './PartyEntity'
22
23
  import { getConstraint } from '../../utils/ValidatorUtils'
23
24
 
@@ -1,9 +1,10 @@
1
1
  import { typeormDate, typeOrmDateTime } from '@sphereon/ssi-sdk.agent-config'
2
+ import { CredentialRole } from '@sphereon/ssi-types'
2
3
  import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
4
+
3
5
  import {
4
6
  CredentialCorrelationType,
5
7
  CredentialDocumentFormat,
6
- CredentialRole,
7
8
  CredentialStateType,
8
9
  type DigitalCredential,
9
10
  DocumentType,
@@ -25,7 +25,7 @@ export class PresentationDefinitionItemEntity extends BaseEntity {
25
25
  @Column({ name: 'name', length: 255, type: 'varchar', nullable: true, unique: false })
26
26
  name?: string
27
27
 
28
- @Column({ name: 'definition_payload', type: 'text', nullable: false, unique: false }) // TODO should this become nullable now we have dcqlPayload?
28
+ @Column({ name: 'definition_payload', type: 'text', nullable: true, unique: false })
29
29
  @IsNotEmpty({ message: 'A blank PD definition payload field is not allowed' })
30
30
  definitionPayload!: string
31
31
 
@@ -1,10 +1,40 @@
1
- import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
2
1
  import Debug from 'debug'
3
- import { CreateBitstringStatusListPG1741895823000 } from '../postgres/1741895823000-CreateBitstringStatusList'
2
+ import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
3
+
4
+ import {
5
+ AddBitstringStatusListEnumPG1741895823000,
6
+ CreateBitstringStatusListPG1741895823000,
7
+ } from '../postgres/1741895823000-CreateBitstringStatusList'
4
8
  import { CreateBitstringStatusListSqlite1741895823001 } from '../sqlite/1741895823001-CreateBitstringStatusList'
5
9
 
6
10
  const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations')
7
11
 
12
+ export class AddBitstringStatusListEnum1741895823000 implements MigrationInterface {
13
+ name = 'AddBitstringStatusListEnum1741895823000'
14
+
15
+ public async up(queryRunner: QueryRunner): Promise<void> {
16
+ debug('migration: creating bitstring status list tables')
17
+ const dbType: DatabaseType = queryRunner.connection.driver.options.type
18
+ switch (dbType) {
19
+ case 'postgres': {
20
+ const mig = new AddBitstringStatusListEnumPG1741895823000()
21
+ await mig.up(queryRunner)
22
+ return
23
+ }
24
+ case 'sqlite':
25
+ case 'expo':
26
+ case 'react-native': {
27
+ return
28
+ }
29
+ default:
30
+ return Promise.reject(`Migrations only supported for sqlite and postgres. Was ${dbType}`)
31
+ }
32
+ }
33
+
34
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
35
+ public async down(queryRunner: QueryRunner): Promise<void> {}
36
+ }
37
+
8
38
  export class CreateBitstringStatusList1741895823000 implements MigrationInterface {
9
39
  name = 'CreateBitstringStatusList1741895823000'
10
40
 
@@ -0,0 +1,67 @@
1
+ import Debug from 'debug'
2
+ import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
3
+
4
+ import { UpdatePresentationDefinitionItemNullablePG1741895824000 } from '../postgres/1756975509000-UpdatePresentationDefinitionItemNullable'
5
+ import { UpdatePresentationDefinitionItemNullableSqlite1756975340000 } from '../sqlite/1756975340000-UpdatePresentationDefinitionItemNullable'
6
+
7
+ const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations')
8
+
9
+ export class UpdatePresentationDefinitionItemNullable1741895824000 implements MigrationInterface {
10
+ name = 'UpdatePresentationDefinitionItemNullable1741895824000'
11
+
12
+ public async up(queryRunner: QueryRunner): Promise<void> {
13
+ debug('migration: updating presentation definition item nullable fields')
14
+ const dbType: DatabaseType = queryRunner.connection.driver.options.type
15
+
16
+ switch (dbType) {
17
+ case 'postgres': {
18
+ debug('using postgres migration file')
19
+ const mig: UpdatePresentationDefinitionItemNullablePG1741895824000 = new UpdatePresentationDefinitionItemNullablePG1741895824000()
20
+ await mig.up(queryRunner)
21
+ debug('Migration statements executed')
22
+ return
23
+ }
24
+ case 'sqlite':
25
+ case 'expo':
26
+ case 'react-native': {
27
+ debug('using sqlite/react-native migration file')
28
+ const mig: UpdatePresentationDefinitionItemNullableSqlite1756975340000 = new UpdatePresentationDefinitionItemNullableSqlite1756975340000()
29
+ await mig.up(queryRunner)
30
+ debug('Migration statements executed')
31
+ return
32
+ }
33
+ default:
34
+ return Promise.reject(
35
+ `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`,
36
+ )
37
+ }
38
+ }
39
+
40
+ public async down(queryRunner: QueryRunner): Promise<void> {
41
+ debug('migration: reverting presentation definition item nullable fields')
42
+ const dbType: DatabaseType = queryRunner.connection.driver.options.type
43
+
44
+ switch (dbType) {
45
+ case 'postgres': {
46
+ debug('using postgres migration file')
47
+ const mig: UpdatePresentationDefinitionItemNullablePG1741895824000 = new UpdatePresentationDefinitionItemNullablePG1741895824000()
48
+ await mig.down(queryRunner)
49
+ debug('Migration statements executed')
50
+ return
51
+ }
52
+ case 'sqlite':
53
+ case 'expo':
54
+ case 'react-native': {
55
+ debug('using sqlite/react-native migration file')
56
+ const mig: UpdatePresentationDefinitionItemNullableSqlite1756975340000 = new UpdatePresentationDefinitionItemNullableSqlite1756975340000()
57
+ await mig.down(queryRunner)
58
+ debug('Migration statements executed')
59
+ return
60
+ }
61
+ default:
62
+ return Promise.reject(
63
+ `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`,
64
+ )
65
+ }
66
+ }
67
+ }
@@ -1,4 +1,8 @@
1
1
  import { CreateContacts1659463079429 } from './1-CreateContacts'
2
+ import { CreatePresentationDefinitions1716533767523 } from './10-CreatePresentationDefinitions'
3
+ import { FixCredentialClaimsReferencesUuid1741895822987 } from './11-FixCredentialClaimsReferenceUuid'
4
+ import { AddBitstringStatusListEnum1741895823000, CreateBitstringStatusList1741895823000 } from './12-CreateBitstringStatusList'
5
+ import { UpdatePresentationDefinitionItemNullable1741895824000 } from './13-UpdatePresentationDefinitionItemNullable'
2
6
  import { CreateIssuanceBranding1659463079429 } from './2-CreateIssuanceBranding'
3
7
  import { CreateContacts1690925872318 } from './3-CreateContacts'
4
8
  import { CreateStatusList1693866470000 } from './4-CreateStatusList'
@@ -7,9 +11,6 @@ import { CreateDigitalCredential1708525189000 } from './6-CreateDigitalCredentia
7
11
  import { CreateMachineStateStore1708098041262 } from './7-CreateMachineStateStore'
8
12
  import { CreateContacts1708525189000 } from './8-CreateContacts'
9
13
  import { CreateContacts1715761125000 } from './9-CreateContacts'
10
- import { CreatePresentationDefinitions1716533767523 } from './10-CreatePresentationDefinitions'
11
- import { FixCredentialClaimsReferencesUuid1741895822987 } from './11-FixCredentialClaimsReferenceUuid'
12
- import { CreateBitstringStatusList1741895823000 } from './12-CreateBitstringStatusList'
13
14
 
14
15
  /**
15
16
  * The migrations array that SHOULD be used when initializing a TypeORM database connection.
@@ -27,11 +28,18 @@ export const DataStoreContactMigrations = [
27
28
  CreateContacts1715761125000,
28
29
  ]
29
30
  export const DataStoreIssuanceBrandingMigrations = [CreateIssuanceBranding1659463079429, FixCredentialClaimsReferencesUuid1741895822987]
30
- export const DataStoreStatusListMigrations = [CreateStatusList1693866470000, CreateBitstringStatusList1741895823000]
31
+ export const DataStoreStatusListMigrations = [
32
+ CreateStatusList1693866470000,
33
+ AddBitstringStatusListEnum1741895823000,
34
+ CreateBitstringStatusList1741895823000,
35
+ ]
31
36
  export const DataStoreEventLoggerMigrations = [CreateAuditEvents1701635835330]
32
37
  export const DataStoreDigitalCredentialMigrations = [CreateDigitalCredential1708525189000]
33
38
  export const DataStoreMachineStateMigrations = [CreateMachineStateStore1708098041262]
34
- export const DataStorePresentationDefinitionMigrations = [CreatePresentationDefinitions1716533767523]
39
+ export const DataStorePresentationDefinitionMigrations = [
40
+ CreatePresentationDefinitions1716533767523,
41
+ UpdatePresentationDefinitionItemNullable1741895824000,
42
+ ]
35
43
 
36
44
  // All migrations together
37
45
  export const DataStoreMigrations = [
@@ -1,13 +1,24 @@
1
1
  import { MigrationInterface, QueryRunner } from 'typeorm'
2
2
 
3
- export class CreateBitstringStatusListPG1741895823000 implements MigrationInterface {
4
- name = 'CreateBitstringStatusList1741895823000'
3
+ export class AddBitstringStatusListEnumPG1741895823000 implements MigrationInterface {
4
+ name = 'AddBitstringStatusListEnum1741895823000'
5
5
 
6
6
  public async up(queryRunner: QueryRunner): Promise<void> {
7
7
  await queryRunner.startTransaction()
8
8
  await queryRunner.query(`ALTER TYPE "StatusList_type_enum" ADD VALUE 'BitstringStatusList'`)
9
9
  await queryRunner.commitTransaction()
10
+ }
10
11
 
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+ public async down(queryRunner: QueryRunner): Promise<void> {
14
+ // Note: Cannot remove enum value in Postgres without recreating the type
15
+ }
16
+ }
17
+
18
+ export class CreateBitstringStatusListPG1741895823000 implements MigrationInterface {
19
+ name = 'CreateBitstringStatusList1741895823000'
20
+
21
+ public async up(queryRunner: QueryRunner): Promise<void> {
11
22
  // Add BitstringStatusList columns to StatusList table
12
23
  await queryRunner.query(`ALTER TABLE "StatusList" ADD COLUMN "ttl" integer`)
13
24
  await queryRunner.query(`ALTER TABLE "StatusList" ADD COLUMN "validFrom" TIMESTAMP`)
@@ -0,0 +1,15 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm'
2
+
3
+ export class UpdatePresentationDefinitionItemNullablePG1741895824000 implements MigrationInterface {
4
+ name = 'UpdatePresentationDefinitionItemNullable1741895824000'
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ // Make definition_payload nullable
8
+ await queryRunner.query(`ALTER TABLE "PresentationDefinitionItem" ALTER COLUMN "definition_payload" DROP NOT NULL`)
9
+ }
10
+
11
+ public async down(queryRunner: QueryRunner): Promise<void> {
12
+ // Make definition_payload NOT NULL again
13
+ await queryRunner.query(`ALTER TABLE "PresentationDefinitionItem" ALTER COLUMN "definition_payload" SET NOT NULL`)
14
+ }
15
+ }