@sphereon/ssi-sdk.data-store 0.32.1-next.12 → 0.32.1-next.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 (85) hide show
  1. package/dist/entities/presentationDefinition/PresentationDefinitionItemEntity.d.ts +1 -0
  2. package/dist/entities/presentationDefinition/PresentationDefinitionItemEntity.d.ts.map +1 -1
  3. package/dist/entities/presentationDefinition/PresentationDefinitionItemEntity.js +8 -2
  4. package/dist/entities/presentationDefinition/PresentationDefinitionItemEntity.js.map +1 -1
  5. package/dist/entities/{statusList2021 → statusList}/StatusList2021EntryEntity.d.ts +1 -1
  6. package/dist/entities/statusList/StatusList2021EntryEntity.d.ts.map +1 -0
  7. package/dist/entities/{statusList2021 → statusList}/StatusList2021EntryEntity.js +3 -3
  8. package/dist/entities/statusList/StatusList2021EntryEntity.js.map +1 -0
  9. package/dist/entities/statusList/StatusListEntities.d.ts +23 -0
  10. package/dist/entities/statusList/StatusListEntities.d.ts.map +1 -0
  11. package/dist/entities/{statusList2021/StatusList2021Entity.js → statusList/StatusListEntities.js} +44 -16
  12. package/dist/entities/statusList/StatusListEntities.js.map +1 -0
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +4 -4
  16. package/dist/index.js.map +1 -1
  17. package/dist/migrations/generic/4-CreateStatusList.d.ts.map +1 -1
  18. package/dist/migrations/generic/4-CreateStatusList.js +22 -12
  19. package/dist/migrations/generic/4-CreateStatusList.js.map +1 -1
  20. package/dist/migrations/postgres/1693866470001-CreateStatusList.d.ts.map +1 -1
  21. package/dist/migrations/postgres/1693866470001-CreateStatusList.js +43 -7
  22. package/dist/migrations/postgres/1693866470001-CreateStatusList.js.map +1 -1
  23. package/dist/migrations/postgres/1716475165345-CreatePresentationDefinitions.d.ts.map +1 -1
  24. package/dist/migrations/postgres/1716475165345-CreatePresentationDefinitions.js +1 -0
  25. package/dist/migrations/postgres/1716475165345-CreatePresentationDefinitions.js.map +1 -1
  26. package/dist/migrations/postgres/1737110469001-UpdateStatusList.d.ts +7 -0
  27. package/dist/migrations/postgres/1737110469001-UpdateStatusList.d.ts.map +1 -0
  28. package/dist/migrations/postgres/1737110469001-UpdateStatusList.js +39 -0
  29. package/dist/migrations/postgres/1737110469001-UpdateStatusList.js.map +1 -0
  30. package/dist/migrations/sqlite/1693866470000-CreateStatusList.d.ts.map +1 -1
  31. package/dist/migrations/sqlite/1693866470000-CreateStatusList.js +45 -5
  32. package/dist/migrations/sqlite/1693866470000-CreateStatusList.js.map +1 -1
  33. package/dist/migrations/sqlite/1716475165344-CreatePresentationDefinitions.d.ts.map +1 -1
  34. package/dist/migrations/sqlite/1716475165344-CreatePresentationDefinitions.js +1 -0
  35. package/dist/migrations/sqlite/1716475165344-CreatePresentationDefinitions.js.map +1 -1
  36. package/dist/migrations/sqlite/1737110469000-UpdateStatusList.d.ts +7 -0
  37. package/dist/migrations/sqlite/1737110469000-UpdateStatusList.d.ts.map +1 -0
  38. package/dist/migrations/sqlite/1737110469000-UpdateStatusList.js +88 -0
  39. package/dist/migrations/sqlite/1737110469000-UpdateStatusList.js.map +1 -0
  40. package/dist/statusList/IStatusListStore.d.ts +2 -2
  41. package/dist/statusList/IStatusListStore.d.ts.map +1 -1
  42. package/dist/statusList/StatusListStore.d.ts +8 -7
  43. package/dist/statusList/StatusListStore.d.ts.map +1 -1
  44. package/dist/statusList/StatusListStore.js +53 -31
  45. package/dist/statusList/StatusListStore.js.map +1 -1
  46. package/dist/types/presentationDefinition/presentationDefinition.d.ts +3 -1
  47. package/dist/types/presentationDefinition/presentationDefinition.d.ts.map +1 -1
  48. package/dist/types/statusList/IAbstractStatusListStore.d.ts +2 -2
  49. package/dist/types/statusList/IAbstractStatusListStore.d.ts.map +1 -1
  50. package/dist/types/statusList/statusList.d.ts +9 -4
  51. package/dist/types/statusList/statusList.d.ts.map +1 -1
  52. package/dist/utils/presentationDefinition/MappingUtils.d.ts.map +1 -1
  53. package/dist/utils/presentationDefinition/MappingUtils.js +2 -0
  54. package/dist/utils/presentationDefinition/MappingUtils.js.map +1 -1
  55. package/dist/utils/statusList/MappingUtils.d.ts +5 -0
  56. package/dist/utils/statusList/MappingUtils.d.ts.map +1 -0
  57. package/dist/utils/statusList/MappingUtils.js +69 -0
  58. package/dist/utils/statusList/MappingUtils.js.map +1 -0
  59. package/package.json +6 -5
  60. package/src/__tests__/pd-manager.entities.test.ts +77 -0
  61. package/src/__tests__/statusList.entities.test.ts +215 -0
  62. package/src/__tests__/statusList.store.test.ts +232 -0
  63. package/src/entities/presentationDefinition/PresentationDefinitionItemEntity.ts +6 -2
  64. package/src/entities/{statusList2021 → statusList}/StatusList2021EntryEntity.ts +1 -1
  65. package/src/entities/{statusList2021/StatusList2021Entity.ts → statusList/StatusListEntities.ts} +37 -18
  66. package/src/index.ts +3 -3
  67. package/src/migrations/generic/4-CreateStatusList.ts +22 -12
  68. package/src/migrations/postgres/1693866470001-CreateStatusList.ts +45 -9
  69. package/src/migrations/postgres/1716475165345-CreatePresentationDefinitions.ts +1 -0
  70. package/src/migrations/postgres/1737110469001-UpdateStatusList.ts +25 -0
  71. package/src/migrations/sqlite/1693866470000-CreateStatusList.ts +45 -5
  72. package/src/migrations/sqlite/1716475165344-CreatePresentationDefinitions.ts +1 -0
  73. package/src/migrations/sqlite/1737110469000-UpdateStatusList.ts +84 -0
  74. package/src/statusList/IStatusListStore.ts +2 -2
  75. package/src/statusList/StatusListStore.ts +66 -40
  76. package/src/types/presentationDefinition/presentationDefinition.ts +3 -1
  77. package/src/types/statusList/IAbstractStatusListStore.ts +2 -2
  78. package/src/types/statusList/statusList.ts +12 -4
  79. package/src/utils/presentationDefinition/MappingUtils.ts +3 -0
  80. package/src/utils/statusList/MappingUtils.ts +82 -0
  81. package/dist/entities/statusList2021/StatusList2021Entity.d.ts +0 -19
  82. package/dist/entities/statusList2021/StatusList2021Entity.d.ts.map +0 -1
  83. package/dist/entities/statusList2021/StatusList2021Entity.js.map +0 -1
  84. package/dist/entities/statusList2021/StatusList2021EntryEntity.d.ts.map +0 -1
  85. package/dist/entities/statusList2021/StatusList2021EntryEntity.js.map +0 -1
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.statusListFrom = exports.statusListEntityFrom = void 0;
4
+ const StatusListEntities_1 = require("../../entities/statusList/StatusListEntities");
5
+ const ssi_types_1 = require("@sphereon/ssi-types");
6
+ const FormattingUtils_1 = require("../FormattingUtils");
7
+ const statusListEntityFrom = (args) => {
8
+ if (args.type === ssi_types_1.StatusListType.StatusList2021) {
9
+ const entity = new StatusListEntities_1.StatusList2021Entity();
10
+ const sl2021 = args;
11
+ entity.indexingDirection = sl2021.indexingDirection;
12
+ entity.statusPurpose = sl2021.statusPurpose;
13
+ setBaseFields(entity, args);
14
+ Object.defineProperty(entity, 'type', {
15
+ value: ssi_types_1.StatusListType.StatusList2021,
16
+ enumerable: true,
17
+ configurable: true,
18
+ });
19
+ return entity;
20
+ }
21
+ if (args.type === ssi_types_1.StatusListType.OAuthStatusList) {
22
+ const entity = new StatusListEntities_1.OAuthStatusListEntity();
23
+ const oauthSl = args;
24
+ entity.bitsPerStatus = oauthSl.bitsPerStatus;
25
+ entity.expiresAt = oauthSl.expiresAt;
26
+ setBaseFields(entity, args);
27
+ Object.defineProperty(entity, 'type', {
28
+ value: ssi_types_1.StatusListType.OAuthStatusList,
29
+ enumerable: true,
30
+ configurable: true,
31
+ });
32
+ return entity;
33
+ }
34
+ throw new Error(`Invalid status list type ${args.type}`);
35
+ };
36
+ exports.statusListEntityFrom = statusListEntityFrom;
37
+ const statusListFrom = (entity) => {
38
+ if (entity instanceof StatusListEntities_1.StatusList2021Entity) {
39
+ const result = Object.assign(Object.assign({}, getBaseFields(entity)), { type: ssi_types_1.StatusListType.StatusList2021, indexingDirection: entity.indexingDirection, statusPurpose: entity.statusPurpose });
40
+ return (0, FormattingUtils_1.replaceNullWithUndefined)(result);
41
+ }
42
+ if (entity instanceof StatusListEntities_1.OAuthStatusListEntity) {
43
+ const result = Object.assign(Object.assign({}, getBaseFields(entity)), { type: ssi_types_1.StatusListType.OAuthStatusList, bitsPerStatus: entity.bitsPerStatus, expiresAt: entity.expiresAt });
44
+ return (0, FormattingUtils_1.replaceNullWithUndefined)(result);
45
+ }
46
+ throw new Error(`Invalid status list type ${typeof entity}`);
47
+ };
48
+ exports.statusListFrom = statusListFrom;
49
+ const setBaseFields = (entity, args) => {
50
+ entity.id = args.id;
51
+ entity.correlationId = args.correlationId;
52
+ entity.length = args.length;
53
+ entity.issuer = args.issuer;
54
+ entity.driverType = args.driverType;
55
+ entity.credentialIdMode = args.credentialIdMode;
56
+ entity.proofFormat = args.proofFormat;
57
+ entity.statusListCredential = args.statusListCredential;
58
+ };
59
+ const getBaseFields = (entity) => ({
60
+ id: entity.id,
61
+ correlationId: entity.correlationId,
62
+ length: entity.length,
63
+ issuer: entity.issuer,
64
+ driverType: entity.driverType,
65
+ credentialIdMode: entity.credentialIdMode,
66
+ proofFormat: entity.proofFormat,
67
+ statusListCredential: entity.statusListCredential,
68
+ });
69
+ //# sourceMappingURL=MappingUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MappingUtils.js","sourceRoot":"","sources":["../../../src/utils/statusList/MappingUtils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.data-store",
3
- "version": "0.32.1-next.12+cd321acb",
3
+ "version": "0.32.1-next.141+5862bf90",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,13 +18,14 @@
18
18
  "@sphereon/pex": "5.0.0-unstable.28",
19
19
  "@sphereon/ssi-sdk-ext.did-utils": "0.27.0",
20
20
  "@sphereon/ssi-sdk-ext.identifier-resolution": "0.27.0",
21
- "@sphereon/ssi-sdk.agent-config": "0.32.1-next.12+cd321acb",
22
- "@sphereon/ssi-sdk.core": "0.32.1-next.12+cd321acb",
23
- "@sphereon/ssi-types": "0.32.1-next.12+cd321acb",
21
+ "@sphereon/ssi-sdk.agent-config": "0.32.1-next.141+5862bf90",
22
+ "@sphereon/ssi-sdk.core": "0.32.1-next.141+5862bf90",
23
+ "@sphereon/ssi-types": "0.32.1-next.141+5862bf90",
24
24
  "@veramo/core": "4.2.0",
25
25
  "@veramo/utils": "4.2.0",
26
26
  "blakejs": "^1.2.1",
27
27
  "class-validator": "^0.14.1",
28
+ "dcql": "0.2.19",
28
29
  "debug": "^4.3.5",
29
30
  "typeorm": "^0.3.20"
30
31
  },
@@ -53,5 +54,5 @@
53
54
  "Contact Store"
54
55
  ],
55
56
  "nx": {},
56
- "gitHead": "cd321acb679d70af853b7bad5548baa2345a4291"
57
+ "gitHead": "5862bf90d03a6d50882f12d5e4be150a3d53f823"
57
58
  }
@@ -24,6 +24,83 @@ describe('PresentationDefinitionItemEntity tests', (): void => {
24
24
  await dbConnection.destroy()
25
25
  })
26
26
 
27
+ it('should create and retrieve PresentationDefinitionItemEntity with dcqlPayload', async (): Promise<void> => {
28
+ const repository = dbConnection.getRepository(PresentationDefinitionItemEntity)
29
+ const entity = new PresentationDefinitionItemEntity()
30
+ entity.definitionId = 'definition1'
31
+ entity.version = '1.0'
32
+ entity.definitionPayload = JSON.stringify({ id: 'definition1', input_descriptors: [] })
33
+ entity.dcqlPayload = JSON.stringify({
34
+ credentials: [
35
+ {
36
+ id: 'credential1',
37
+ format: 'jwt_vc',
38
+ claims: [
39
+ {
40
+ namespace: 'test',
41
+ claim_name: 'testClaim',
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ })
47
+
48
+ const savedEntity = await repository.save(entity)
49
+ expect(savedEntity).toBeDefined()
50
+ expect(savedEntity.id).toBeDefined()
51
+ expect(savedEntity.dcqlPayload).toBeDefined()
52
+
53
+ const retrievedEntity = await repository.findOneBy({ id: savedEntity.id })
54
+ expect(retrievedEntity).toBeDefined()
55
+ expect(retrievedEntity!.dcqlPayload).toBeDefined()
56
+ const parsedDcql = JSON.parse(retrievedEntity!.dcqlPayload)
57
+ expect(parsedDcql.credentials[0].id).toEqual('credential1')
58
+ })
59
+
60
+ it('should update PresentationDefinitionItemEntity dcqlPayload', async (): Promise<void> => {
61
+ const repository = dbConnection.getRepository(PresentationDefinitionItemEntity)
62
+ const entity = new PresentationDefinitionItemEntity()
63
+ entity.definitionId = 'definition1'
64
+ entity.version = '1.0'
65
+ entity.definitionPayload = JSON.stringify({ id: 'definition1', input_descriptors: [] })
66
+ entity.dcqlPayload = JSON.stringify({
67
+ credentials: [
68
+ {
69
+ id: 'credential1',
70
+ format: 'jwt_vc',
71
+ claims: [
72
+ {
73
+ namespace: 'test',
74
+ claim_name: 'testClaim',
75
+ },
76
+ ],
77
+ },
78
+ ],
79
+ })
80
+
81
+ const savedEntity = await repository.save(entity)
82
+ expect(savedEntity).toBeDefined()
83
+
84
+ const updatedDcql = {
85
+ credentials: [
86
+ {
87
+ id: 'credential2',
88
+ format: 'jwt_vc',
89
+ claims: [
90
+ {
91
+ namespace: 'test',
92
+ claim_name: 'updatedClaim',
93
+ },
94
+ ],
95
+ },
96
+ ],
97
+ }
98
+ savedEntity.dcqlPayload = JSON.stringify(updatedDcql)
99
+ const updatedEntity = await repository.save(savedEntity)
100
+ expect(updatedEntity).toBeDefined()
101
+ expect(JSON.parse(updatedEntity.dcqlPayload).credentials[0].id).toEqual('credential2')
102
+ })
103
+
27
104
  it('should create and retrieve PresentationDefinitionItemEntity', async (): Promise<void> => {
28
105
  const repository = dbConnection.getRepository(PresentationDefinitionItemEntity)
29
106
  const entity = new PresentationDefinitionItemEntity()
@@ -0,0 +1,215 @@
1
+ import { DataSource } from 'typeorm'
2
+ import { DataSources } from '@sphereon/ssi-sdk.agent-config'
3
+ import { DataStoreStatusListEntities, StatusListEntryEntity } from '../index'
4
+ import { DataStoreStatusListMigrations } from '../migrations'
5
+ import { OAuthStatusListEntity, StatusList2021Entity } from '../entities/statusList/StatusListEntities'
6
+ import { IIssuer, StatusListCredentialIdMode, StatusListDriverType } from '@sphereon/ssi-types'
7
+
8
+ describe('Status list entities tests', () => {
9
+ let dbConnection: DataSource
10
+
11
+ beforeEach(async () => {
12
+ DataSources.singleInstance().defaultDbType = 'sqlite'
13
+ dbConnection = await new DataSource({
14
+ type: 'sqlite',
15
+ database: ':memory:',
16
+ migrationsRun: false,
17
+ migrations: DataStoreStatusListMigrations,
18
+ synchronize: false,
19
+ entities: [...DataStoreStatusListEntities],
20
+ }).initialize()
21
+ await dbConnection.runMigrations()
22
+ expect(await dbConnection.showMigrations()).toBeFalsy()
23
+ })
24
+
25
+ afterEach(async () => {
26
+ await dbConnection.destroy()
27
+ })
28
+
29
+ it('should save status list to database', async () => {
30
+ const statusList = new StatusList2021Entity()
31
+ statusList.id = 'test-list-1'
32
+ statusList.correlationId = 'correlation-1'
33
+ statusList.driverType = StatusListDriverType.AGENT_TYPEORM
34
+ statusList.length = 100000
35
+ statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
36
+ statusList.proofFormat = 'jwt'
37
+ statusList.statusPurpose = 'revocation'
38
+ statusList.indexingDirection = 'rightToLeft'
39
+ statusList.issuer = 'did:example:123'
40
+
41
+ const fromDb = await dbConnection.getRepository(StatusList2021Entity).save(statusList)
42
+ expect(fromDb).toBeDefined()
43
+ expect(fromDb.id).toEqual(statusList.id)
44
+ expect(fromDb.correlationId).toEqual(statusList.correlationId)
45
+ expect(fromDb.length).toEqual(statusList.length)
46
+ expect(fromDb.credentialIdMode).toEqual(statusList.credentialIdMode)
47
+ expect(fromDb.statusPurpose).toEqual(statusList.statusPurpose)
48
+ expect(fromDb.indexingDirection).toEqual(statusList.indexingDirection)
49
+ expect(fromDb.issuer).toEqual(statusList.issuer)
50
+ })
51
+
52
+ it('should save status list entry to database', async () => {
53
+ const statusList = new StatusList2021Entity()
54
+ statusList.id = 'test-list-1'
55
+ statusList.correlationId = 'correlation-1'
56
+ statusList.driverType = StatusListDriverType.AGENT_TYPEORM
57
+ statusList.length = 100000
58
+ statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
59
+ statusList.proofFormat = 'jwt'
60
+ statusList.statusPurpose = 'revocation'
61
+ statusList.indexingDirection = 'rightToLeft'
62
+ statusList.issuer = 'did:example:123'
63
+
64
+ await dbConnection.getRepository(StatusList2021Entity).save(statusList)
65
+
66
+ const entry = new StatusListEntryEntity()
67
+ entry.statusList = statusList
68
+ entry.statusListIndex = 1
69
+ entry.credentialId = 'credential-1'
70
+ entry.credentialHash = 'hash-1'
71
+ entry.correlationId = 'correlation-1'
72
+ entry.value = '1'
73
+
74
+ const fromDb = await dbConnection.getRepository(StatusListEntryEntity).save(entry)
75
+ expect(fromDb).toBeDefined()
76
+ expect(fromDb.statusListIndex).toEqual(entry.statusListIndex)
77
+ expect(fromDb.credentialId).toEqual(entry.credentialId)
78
+ expect(fromDb.credentialHash).toEqual(entry.credentialHash)
79
+ expect(fromDb.correlationId).toEqual(entry.correlationId)
80
+ expect(fromDb.value).toEqual(entry.value)
81
+ })
82
+
83
+ it('should handle complex issuer object', async () => {
84
+ const statusList = new StatusList2021Entity()
85
+ statusList.id = 'test-list-1'
86
+ statusList.correlationId = 'correlation-1'
87
+ statusList.driverType = StatusListDriverType.AGENT_TYPEORM
88
+ statusList.length = 100000
89
+ statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
90
+ statusList.proofFormat = 'jwt'
91
+ statusList.statusPurpose = 'revocation'
92
+ statusList.indexingDirection = 'rightToLeft'
93
+ statusList.issuer = { id: 'did:example:123', name: 'Test Issuer' }
94
+
95
+ const fromDb = await dbConnection.getRepository(StatusList2021Entity).save(statusList)
96
+ expect(fromDb).toBeDefined()
97
+ expect(fromDb.issuer).toEqual(statusList.issuer)
98
+ expect(typeof fromDb.issuer).toEqual('object')
99
+ expect((fromDb.issuer as IIssuer).id).toEqual('did:example:123')
100
+ expect((fromDb.issuer as IIssuer).name).toEqual('Test Issuer')
101
+ })
102
+
103
+ it('should save OAuth status list to database', async () => {
104
+ const statusList = new OAuthStatusListEntity()
105
+ statusList.id = 'oauth-list-1'
106
+ statusList.correlationId = 'correlation-oauth-1'
107
+ statusList.driverType = StatusListDriverType.AGENT_TYPEORM
108
+ statusList.length = 100000
109
+ statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
110
+ statusList.proofFormat = 'jwt'
111
+ statusList.bitsPerStatus = 1
112
+ statusList.expiresAt = new Date('2025-01-01T00:00:00Z')
113
+ statusList.issuer = 'did:example:123'
114
+
115
+ const fromDb = await dbConnection.getRepository(OAuthStatusListEntity).save(statusList)
116
+ expect(fromDb).toBeDefined()
117
+ expect(fromDb.id).toEqual(statusList.id)
118
+ expect(fromDb.correlationId).toEqual(statusList.correlationId)
119
+ expect(fromDb.length).toEqual(statusList.length)
120
+ expect(fromDb.credentialIdMode).toEqual(statusList.credentialIdMode)
121
+ expect(fromDb.bitsPerStatus).toEqual(statusList.bitsPerStatus)
122
+ expect(fromDb.expiresAt).toEqual(statusList.expiresAt)
123
+ expect(fromDb.issuer).toEqual(statusList.issuer)
124
+ })
125
+
126
+ it('should handle both status list types having entries', async () => {
127
+ const statusList2021 = new StatusList2021Entity()
128
+ statusList2021.id = 'test-list-1'
129
+ statusList2021.correlationId = 'correlation-1'
130
+ statusList2021.driverType = StatusListDriverType.AGENT_TYPEORM
131
+ statusList2021.length = 100000
132
+ statusList2021.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
133
+ statusList2021.proofFormat = 'jwt'
134
+ statusList2021.statusPurpose = 'revocation'
135
+ statusList2021.indexingDirection = 'rightToLeft'
136
+ statusList2021.issuer = 'did:example:123'
137
+ await dbConnection.getRepository(StatusList2021Entity).save(statusList2021)
138
+
139
+ const oauthStatusList = new OAuthStatusListEntity()
140
+ oauthStatusList.id = 'oauth-list-1'
141
+ oauthStatusList.correlationId = 'correlation-oauth-1'
142
+ oauthStatusList.driverType = StatusListDriverType.AGENT_TYPEORM
143
+ oauthStatusList.length = 100000
144
+ oauthStatusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
145
+ oauthStatusList.proofFormat = 'jwt'
146
+ oauthStatusList.bitsPerStatus = 1
147
+ oauthStatusList.issuer = 'did:example:456'
148
+ await dbConnection.getRepository(OAuthStatusListEntity).save(oauthStatusList)
149
+
150
+ const entry2021 = new StatusListEntryEntity()
151
+ entry2021.statusList = statusList2021
152
+ entry2021.statusListIndex = 1
153
+ entry2021.credentialId = 'credential-1'
154
+ entry2021.credentialHash = 'hash-1'
155
+ entry2021.value = '1'
156
+ await dbConnection.getRepository(StatusListEntryEntity).save(entry2021)
157
+
158
+ const entryOAuth = new StatusListEntryEntity()
159
+ entryOAuth.statusList = oauthStatusList
160
+ entryOAuth.statusListIndex = 1
161
+ entryOAuth.credentialId = 'credential-2'
162
+ entryOAuth.credentialHash = 'hash-2'
163
+ entryOAuth.value = '1'
164
+ await dbConnection.getRepository(StatusListEntryEntity).save(entryOAuth)
165
+
166
+ const found2021Entry = await dbConnection.getRepository(StatusListEntryEntity).findOne({
167
+ where: { statusList: statusList2021.id, statusListIndex: 1 },
168
+ })
169
+ const foundOAuthEntry = await dbConnection.getRepository(StatusListEntryEntity).findOne({
170
+ where: { statusList: oauthStatusList.id, statusListIndex: 1 },
171
+ })
172
+
173
+ expect(found2021Entry).toBeDefined()
174
+ expect(found2021Entry?.credentialId).toEqual('credential-1')
175
+ expect(foundOAuthEntry).toBeDefined()
176
+ expect(foundOAuthEntry?.credentialId).toEqual('credential-2')
177
+ })
178
+
179
+ it('should cascade delete entries when status list is deleted', async () => {
180
+ const statusList = new StatusList2021Entity()
181
+ statusList.id = 'test-list-1'
182
+ statusList.correlationId = 'correlation-1'
183
+ statusList.driverType = StatusListDriverType.AGENT_TYPEORM
184
+ statusList.length = 100000
185
+ statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
186
+ statusList.proofFormat = 'jwt'
187
+ statusList.statusPurpose = 'revocation'
188
+ statusList.indexingDirection = 'rightToLeft'
189
+ statusList.issuer = 'did:example:123'
190
+
191
+ const savedStatusList = await dbConnection.getRepository(StatusList2021Entity).save(statusList)
192
+
193
+ const entry = new StatusListEntryEntity()
194
+ entry.statusList = statusList
195
+ entry.statusListIndex = 1
196
+ entry.credentialId = 'credential-1'
197
+ entry.credentialHash = 'hash-1'
198
+ entry.correlationId = 'correlation-1'
199
+ entry.value = '1'
200
+
201
+ await dbConnection.getRepository(StatusListEntryEntity).save(entry)
202
+
203
+ // First delete entry, otherwise constraint fails
204
+ await dbConnection.getRepository(StatusListEntryEntity).delete({ statusList: savedStatusList.id })
205
+ await dbConnection.getRepository(StatusList2021Entity).remove(savedStatusList)
206
+
207
+ const foundEntry = await dbConnection.getRepository(StatusListEntryEntity).findOne({
208
+ where: {
209
+ statusList: statusList.id,
210
+ statusListIndex: entry.statusListIndex,
211
+ },
212
+ })
213
+ expect(foundEntry).toBeNull()
214
+ })
215
+ })
@@ -0,0 +1,232 @@
1
+ import { DataSource } from 'typeorm'
2
+ import { DataSources } from '@sphereon/ssi-sdk.agent-config'
3
+ import { DataStoreStatusListEntities } from '../index'
4
+ import { DataStoreStatusListMigrations } from '../migrations'
5
+ import { StatusListStore } from '../statusList/StatusListStore'
6
+ import { IStatusList2021Entity, IStatusListEntryEntity, IOAuthStatusListEntity } from '../types'
7
+ import { StatusListCredentialIdMode, StatusListDriverType, StatusListType } from '@sphereon/ssi-types'
8
+
9
+ describe('Status list store tests', () => {
10
+ let dbConnection: DataSource
11
+ let statusListStore: StatusListStore
12
+
13
+ beforeEach(async () => {
14
+ DataSources.singleInstance().defaultDbType = 'sqlite'
15
+ dbConnection = await new DataSource({
16
+ type: 'sqlite',
17
+ database: ':memory:',
18
+ migrationsRun: false,
19
+ migrations: DataStoreStatusListMigrations,
20
+ synchronize: false,
21
+ entities: DataStoreStatusListEntities,
22
+ }).initialize()
23
+ await dbConnection.runMigrations()
24
+ expect(await dbConnection.showMigrations()).toBeFalsy()
25
+ statusListStore = new StatusListStore(dbConnection)
26
+ })
27
+
28
+ afterEach(async () => {
29
+ await dbConnection.destroy()
30
+ })
31
+
32
+ it('should store status list', async () => {
33
+ const statusList: IStatusList2021Entity = {
34
+ id: 'test-list-1',
35
+ correlationId: 'correlation-1',
36
+ driverType: StatusListDriverType.AGENT_TYPEORM,
37
+ length: 100000,
38
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
39
+ type: StatusListType.StatusList2021,
40
+ proofFormat: 'jwt',
41
+ statusPurpose: 'revocation',
42
+ indexingDirection: 'rightToLeft',
43
+ issuer: 'did:example:123',
44
+ }
45
+
46
+ const result = await statusListStore.addStatusList(statusList)
47
+ expect(result).toBeDefined()
48
+ expect(result.id).toEqual(statusList.id)
49
+ expect(result.correlationId).toEqual(statusList.correlationId)
50
+ })
51
+
52
+ it('should store status list entry', async () => {
53
+ const statusList: IStatusList2021Entity = {
54
+ id: 'test-list-1',
55
+ correlationId: 'correlation-1',
56
+ driverType: StatusListDriverType.AGENT_TYPEORM,
57
+ length: 100000,
58
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
59
+ type: StatusListType.StatusList2021,
60
+ proofFormat: 'jwt',
61
+ statusPurpose: 'revocation',
62
+ indexingDirection: 'rightToLeft',
63
+ issuer: 'did:example:123',
64
+ }
65
+
66
+ await statusListStore.addStatusList(statusList)
67
+
68
+ const entry: IStatusListEntryEntity = {
69
+ statusList: statusList.id,
70
+ statusListIndex: 1,
71
+ credentialId: 'credential-1',
72
+ credentialHash: 'hash-1',
73
+ correlationId: 'correlation-1',
74
+ value: '1',
75
+ }
76
+
77
+ const result = await statusListStore.addStatusListEntry(entry)
78
+ expect(result).toBeDefined()
79
+ expect(result.statusListIndex).toEqual(entry.statusListIndex)
80
+ expect(result.credentialId).toEqual(entry.credentialId)
81
+ })
82
+
83
+ it('should store OAuth status list', async () => {
84
+ const statusList: IOAuthStatusListEntity = {
85
+ id: 'oauth-list-1',
86
+ correlationId: 'correlation-oauth-1',
87
+ driverType: StatusListDriverType.AGENT_TYPEORM,
88
+ length: 100000,
89
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
90
+ type: StatusListType.OAuthStatusList,
91
+ proofFormat: 'jwt',
92
+ bitsPerStatus: 1,
93
+ expiresAt: new Date('2025-01-01T00:00:00Z'),
94
+ issuer: 'did:example:123',
95
+ }
96
+
97
+ const result = (await statusListStore.addStatusList(statusList)) as IOAuthStatusListEntity
98
+ expect(result).toBeDefined()
99
+ expect(result.id).toEqual(statusList.id)
100
+ expect(result.correlationId).toEqual(statusList.correlationId)
101
+ expect(result.bitsPerStatus).toEqual(statusList.bitsPerStatus)
102
+ expect(result.expiresAt).toEqual(statusList.expiresAt)
103
+ })
104
+
105
+ it('should store and retrieve both types of status lists', async () => {
106
+ const statusList2021: IStatusList2021Entity = {
107
+ id: 'test-list-1',
108
+ correlationId: 'correlation-1',
109
+ driverType: StatusListDriverType.AGENT_TYPEORM,
110
+ length: 100000,
111
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
112
+ type: StatusListType.StatusList2021,
113
+ proofFormat: 'jwt',
114
+ statusPurpose: 'revocation',
115
+ indexingDirection: 'rightToLeft',
116
+ issuer: 'did:example:123',
117
+ }
118
+
119
+ const oauthStatusList: IOAuthStatusListEntity = {
120
+ id: 'oauth-list-1',
121
+ correlationId: 'correlation-oauth-1',
122
+ driverType: StatusListDriverType.AGENT_TYPEORM,
123
+ length: 100000,
124
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
125
+ type: StatusListType.OAuthStatusList,
126
+ proofFormat: 'jwt',
127
+ bitsPerStatus: 1,
128
+ issuer: 'did:example:456',
129
+ }
130
+
131
+ await statusListStore.addStatusList(statusList2021)
132
+ await statusListStore.addStatusList(oauthStatusList)
133
+
134
+ const found2021 = (await statusListStore.getStatusList({ id: statusList2021.id })) as IStatusList2021Entity
135
+ const foundOAuth = (await statusListStore.getStatusList({ id: oauthStatusList.id })) as IOAuthStatusListEntity
136
+
137
+ expect(found2021.type).toEqual(StatusListType.StatusList2021)
138
+ expect(found2021.statusPurpose).toEqual('revocation')
139
+ expect(foundOAuth.type).toEqual(StatusListType.OAuthStatusList)
140
+ expect((foundOAuth as IOAuthStatusListEntity).bitsPerStatus).toEqual(1)
141
+ })
142
+
143
+ it('should get status list by id', async () => {
144
+ const statusList: IStatusList2021Entity = {
145
+ id: 'test-list-1',
146
+ correlationId: 'correlation-1',
147
+ driverType: StatusListDriverType.AGENT_TYPEORM,
148
+ length: 100000,
149
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
150
+ type: StatusListType.StatusList2021,
151
+ proofFormat: 'jwt',
152
+ statusPurpose: 'revocation',
153
+ indexingDirection: 'rightToLeft',
154
+ issuer: 'did:example:123',
155
+ }
156
+
157
+ await statusListStore.addStatusList(statusList)
158
+
159
+ const result = await statusListStore.getStatusList({ id: statusList.id })
160
+ expect(result).toBeDefined()
161
+ expect(result.id).toEqual(statusList.id)
162
+ })
163
+
164
+ it('should get status lists with filter', async () => {
165
+ const statusList1: IStatusList2021Entity = {
166
+ id: 'test-list-1',
167
+ correlationId: 'correlation-1',
168
+ driverType: StatusListDriverType.AGENT_TYPEORM,
169
+ length: 100000,
170
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
171
+ type: StatusListType.StatusList2021,
172
+ proofFormat: 'jwt',
173
+ statusPurpose: 'revocation',
174
+ indexingDirection: 'rightToLeft',
175
+ issuer: 'did:example:123',
176
+ }
177
+
178
+ const statusList2: IStatusList2021Entity = {
179
+ id: 'test-list-2',
180
+ correlationId: 'correlation-2',
181
+ driverType: StatusListDriverType.AGENT_TYPEORM,
182
+ length: 100000,
183
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
184
+ type: StatusListType.StatusList2021,
185
+ proofFormat: 'jwt',
186
+ statusPurpose: 'suspension',
187
+ indexingDirection: 'rightToLeft',
188
+ issuer: 'did:example:456',
189
+ }
190
+
191
+ await statusListStore.addStatusList(statusList1)
192
+ await statusListStore.addStatusList(statusList2)
193
+
194
+ const result = await statusListStore.getStatusLists({
195
+ filter: [{ statusPurpose: 'revocation' }],
196
+ })
197
+
198
+ expect(result.length).toEqual(1)
199
+ expect(result[0].id).toEqual(statusList1.id)
200
+ })
201
+
202
+ it('should delete status list', async () => {
203
+ const statusList: IStatusList2021Entity = {
204
+ id: 'test-list-1',
205
+ correlationId: 'correlation-1',
206
+ driverType: StatusListDriverType.AGENT_TYPEORM,
207
+ length: 100000,
208
+ credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
209
+ type: StatusListType.StatusList2021,
210
+ proofFormat: 'jwt',
211
+ statusPurpose: 'revocation',
212
+ indexingDirection: 'rightToLeft',
213
+ issuer: 'did:example:123',
214
+ }
215
+
216
+ await statusListStore.addStatusList(statusList)
217
+ const entry: IStatusListEntryEntity = {
218
+ statusList: statusList.id,
219
+ statusListIndex: 1,
220
+ credentialId: 'credential-1',
221
+ credentialHash: 'hash-1',
222
+ correlationId: 'correlation-1',
223
+ value: '1',
224
+ }
225
+ await statusListStore.addStatusListEntry(entry)
226
+
227
+ const result = await statusListStore.removeStatusList({ id: statusList.id })
228
+ expect(result).toEqual(true)
229
+
230
+ await expect(statusListStore.getStatusList({ id: statusList.id })).rejects.toThrow(`No status list found for id ${statusList.id}`)
231
+ })
232
+ })
@@ -25,10 +25,14 @@ 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 })
29
- @IsNotEmpty({ message: 'A blank definition payload field is not allowed' })
28
+ @Column({ name: 'definition_payload', type: 'text', nullable: false, unique: false }) // TODO should this become nullable now we have dcqlPayload?
29
+ @IsNotEmpty({ message: 'A blank PD definition payload field is not allowed' })
30
30
  definitionPayload!: string
31
31
 
32
+ @Column({ name: 'dcql_payload', type: 'text', nullable: true, unique: false })
33
+ @IsNotEmpty({ message: 'A blank dcql definition payload field is not allowed' })
34
+ dcqlPayload!: string
35
+
32
36
  @CreateDateColumn({ name: 'created_at', nullable: false, type: typeOrmDateTime() })
33
37
  createdAt!: Date
34
38
 
@@ -1,7 +1,7 @@
1
1
  import { Validate } from 'class-validator'
2
2
  import { BaseEntity, Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
3
3
  import { IsNonEmptyStringConstraint } from '../validators'
4
- import { StatusListEntity } from './StatusList2021Entity'
4
+ import { StatusListEntity } from './StatusListEntities'
5
5
 
6
6
  @Entity('StatusListEntry')
7
7
  // @Unique('uq_credential_statuslist', ['statusList', 'credentialId']) // disabled because one prop can be null