@sphereon/ssi-sdk.vc-status-list-issuer-drivers 0.34.1-feature.SSISDK.17.bitstring.sl.13 → 0.34.1-feature.SSISDK.17.bitstring.sl.16
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/dist/index.cjs +114 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -3
- package/dist/index.d.ts +134 -3
- package/dist/index.js +115 -27
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/drivers.ts +169 -34
- package/src/types.ts +9 -4
package/src/drivers.ts
CHANGED
|
@@ -1,28 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusList Driver Implementation for TypeORM/Agent Data Sources
|
|
3
|
+
*
|
|
4
|
+
* This module provides the database-backed implementation of the IStatusListDriver interface,
|
|
5
|
+
* handling persistence and retrieval of status list credentials and entries using TypeORM.
|
|
6
|
+
* It delegates status list format-specific operations to the functions layer while managing
|
|
7
|
+
* database interactions, driver configuration, and entity lifecycle.
|
|
8
|
+
*
|
|
9
|
+
* Key responsibilities:
|
|
10
|
+
* - Database connection and store management
|
|
11
|
+
* - Status list CRUD operations
|
|
12
|
+
* - Status list entry management
|
|
13
|
+
* - Random index generation for new entries
|
|
14
|
+
* - Integration with multiple data sources
|
|
15
|
+
*
|
|
16
|
+
* @author Sphereon International B.V.
|
|
17
|
+
* @since 2024
|
|
18
|
+
*/
|
|
19
|
+
|
|
1
20
|
import { DataSources } from '@sphereon/ssi-sdk.agent-config'
|
|
2
21
|
import {
|
|
22
|
+
BitstringStatusListEntryCredentialStatus,
|
|
3
23
|
IAddStatusListArgs,
|
|
4
24
|
IAddStatusListEntryArgs,
|
|
5
25
|
IBitstringStatusListEntryEntity,
|
|
6
26
|
IGetStatusListEntryByCredentialIdArgs,
|
|
7
27
|
IGetStatusListEntryByIndexArgs,
|
|
8
|
-
IStatusListEntity,
|
|
9
28
|
IStatusListEntryEntity,
|
|
10
29
|
StatusListEntity,
|
|
11
30
|
StatusListStore,
|
|
12
31
|
} from '@sphereon/ssi-sdk.data-store'
|
|
13
32
|
import {
|
|
14
|
-
BitstringStatusListEntryCredentialStatus,
|
|
15
33
|
createCredentialStatusFromStatusList,
|
|
34
|
+
extractCredentialDetails,
|
|
16
35
|
StatusList2021EntryCredentialStatus,
|
|
17
|
-
statusListCredentialToDetails,
|
|
18
36
|
StatusListOAuthEntryCredentialStatus,
|
|
19
37
|
StatusListResult,
|
|
38
|
+
toStatusListDetails,
|
|
20
39
|
} from '@sphereon/ssi-sdk.vc-status-list'
|
|
21
40
|
import { StatusListCredential, StatusListCredentialIdMode, StatusListDriverType, StatusListType } from '@sphereon/ssi-types'
|
|
22
41
|
import { DataSource } from 'typeorm'
|
|
23
42
|
import { IStatusListDriver } from './types'
|
|
24
43
|
import { statusListResultToEntity } from './status-list-adapters'
|
|
25
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Configuration options for status list management
|
|
47
|
+
*/
|
|
26
48
|
export interface StatusListManagementOptions {
|
|
27
49
|
id?: string
|
|
28
50
|
correlationId?: string
|
|
@@ -32,14 +54,25 @@ export interface StatusListManagementOptions {
|
|
|
32
54
|
|
|
33
55
|
export type DriverOptions = TypeORMOptions
|
|
34
56
|
|
|
57
|
+
/**
|
|
58
|
+
* TypeORM-specific configuration options
|
|
59
|
+
*/
|
|
35
60
|
export interface TypeORMOptions {
|
|
36
61
|
dbName?: string
|
|
37
62
|
}
|
|
38
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Filesystem-specific configuration options
|
|
66
|
+
*/
|
|
39
67
|
export interface FilesystemOptions {
|
|
40
68
|
path: string // The base path where statusList Credentials will be persisted. Should be a folder and thus not include the VC/StatusList itself
|
|
41
69
|
}
|
|
42
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Creates status list management options for TypeORM driver
|
|
73
|
+
* @param args - Configuration parameters including id, correlationId, and database name
|
|
74
|
+
* @returns StatusListManagementOptions configured for TypeORM
|
|
75
|
+
*/
|
|
43
76
|
export function getOptions(args: { id?: string; correlationId?: string; dbName: string }): StatusListManagementOptions {
|
|
44
77
|
return {
|
|
45
78
|
id: args.id,
|
|
@@ -49,6 +82,11 @@ export function getOptions(args: { id?: string; correlationId?: string; dbName:
|
|
|
49
82
|
}
|
|
50
83
|
}
|
|
51
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Creates and initializes a status list driver instance
|
|
87
|
+
* @param args - Configuration parameters including database connection details
|
|
88
|
+
* @returns Promise resolving to initialized IStatusListDriver instance
|
|
89
|
+
*/
|
|
52
90
|
export async function getDriver(args: {
|
|
53
91
|
id?: string
|
|
54
92
|
correlationId?: string
|
|
@@ -70,15 +108,33 @@ export async function getDriver(args: {
|
|
|
70
108
|
)
|
|
71
109
|
}
|
|
72
110
|
|
|
111
|
+
/**
|
|
112
|
+
* TypeORM-based implementation of the IStatusListDriver interface
|
|
113
|
+
*
|
|
114
|
+
* Manages status list credentials and entries using a TypeORM data source.
|
|
115
|
+
* Handles database operations while delegating format-specific logic to the functions layer.
|
|
116
|
+
*/
|
|
73
117
|
export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
74
118
|
private _statusListLength: number | undefined
|
|
75
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new AgentDataSourceStatusListDriver instance
|
|
122
|
+
* @param _dataSource - TypeORM DataSource for database operations
|
|
123
|
+
* @param _statusListStore - StatusListStore for data persistence
|
|
124
|
+
* @param options - Driver configuration options
|
|
125
|
+
*/
|
|
76
126
|
constructor(
|
|
77
127
|
private _dataSource: DataSource,
|
|
78
128
|
private _statusListStore: StatusListStore,
|
|
79
129
|
private options: StatusListManagementOptions,
|
|
80
130
|
) {}
|
|
81
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Initializes and creates a new AgentDataSourceStatusListDriver instance
|
|
134
|
+
* @param options - Status list management configuration
|
|
135
|
+
* @param dbArgs - Database connection arguments
|
|
136
|
+
* @returns Promise resolving to initialized driver instance
|
|
137
|
+
*/
|
|
82
138
|
public static async init(
|
|
83
139
|
options: StatusListManagementOptions,
|
|
84
140
|
dbArgs?: {
|
|
@@ -109,6 +165,10 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
109
165
|
return new AgentDataSourceStatusListDriver(dataSource, statusListStore, options)
|
|
110
166
|
}
|
|
111
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Gets the TypeORM DataSource instance
|
|
170
|
+
* @returns DataSource instance for database operations
|
|
171
|
+
*/
|
|
112
172
|
get dataSource(): DataSource {
|
|
113
173
|
if (!this._dataSource) {
|
|
114
174
|
throw Error(`Datasource not available yet for ${this.options.driverOptions?.dbName}`)
|
|
@@ -116,6 +176,10 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
116
176
|
return this._dataSource
|
|
117
177
|
}
|
|
118
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Gets the StatusListStore instance
|
|
181
|
+
* @returns StatusListStore for data persistence operations
|
|
182
|
+
*/
|
|
119
183
|
get statusListStore(): StatusListStore {
|
|
120
184
|
if (!this._statusListStore) {
|
|
121
185
|
this._statusListStore = new StatusListStore(this.dataSource)
|
|
@@ -123,14 +187,27 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
123
187
|
return this._statusListStore
|
|
124
188
|
}
|
|
125
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Gets the driver configuration options
|
|
192
|
+
* @returns DriverOptions configuration
|
|
193
|
+
*/
|
|
126
194
|
getOptions(): DriverOptions {
|
|
127
195
|
return this.options.driverOptions ?? {}
|
|
128
196
|
}
|
|
129
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Gets the driver type
|
|
200
|
+
* @returns StatusListDriverType enum value
|
|
201
|
+
*/
|
|
130
202
|
getType(): StatusListDriverType {
|
|
131
203
|
return this.options.driverType
|
|
132
204
|
}
|
|
133
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Creates a new status list credential and stores it in the database
|
|
208
|
+
* @param args - Status list creation parameters
|
|
209
|
+
* @returns Promise resolving to StatusListResult
|
|
210
|
+
*/
|
|
134
211
|
async createStatusList(args: {
|
|
135
212
|
statusListType: StatusListType
|
|
136
213
|
statusListCredential: StatusListCredential
|
|
@@ -144,12 +221,13 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
144
221
|
}
|
|
145
222
|
const credentialIdMode = args.credentialIdMode ?? StatusListCredentialIdMode.ISSUANCE
|
|
146
223
|
|
|
147
|
-
//
|
|
148
|
-
const implementationResult = await
|
|
149
|
-
|
|
224
|
+
// Convert credential to implementation details using CREATE/READ context
|
|
225
|
+
const implementationResult = await toStatusListDetails({
|
|
226
|
+
statusListCredential: args.statusListCredential,
|
|
227
|
+
statusListType: args.statusListType,
|
|
228
|
+
bitsPerStatus: args.bitsPerStatus,
|
|
150
229
|
correlationId,
|
|
151
230
|
driverType: this.getType(),
|
|
152
|
-
bitsPerStatus: args.bitsPerStatus,
|
|
153
231
|
})
|
|
154
232
|
|
|
155
233
|
// Add driver-specific fields to create complete entity
|
|
@@ -164,29 +242,31 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
164
242
|
this._statusListLength = implementationResult.length
|
|
165
243
|
return implementationResult
|
|
166
244
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Updates an existing status list credential in the database
|
|
248
|
+
* @param args - Status list update parameters
|
|
249
|
+
* @returns Promise resolving to StatusListResult
|
|
250
|
+
*/
|
|
251
|
+
async updateStatusList(args: { statusListCredential: StatusListCredential; correlationId: string }): Promise<StatusListResult> {
|
|
172
252
|
const correlationId = args.correlationId ?? this.options.correlationId
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
{
|
|
179
|
-
id: details.id,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
correlationId,
|
|
183
|
-
},
|
|
184
|
-
],
|
|
253
|
+
|
|
254
|
+
const extractedDetails = await extractCredentialDetails(args.statusListCredential)
|
|
255
|
+
const entity = await this.statusListStore.getStatusList({
|
|
256
|
+
id: extractedDetails.id,
|
|
257
|
+
correlationId,
|
|
185
258
|
})
|
|
186
259
|
if (!entity) {
|
|
187
|
-
throw Error(`Status list ${
|
|
260
|
+
throw Error(`Status list ${extractedDetails.id}, correlationId ${correlationId} could not be found`)
|
|
188
261
|
}
|
|
189
262
|
|
|
263
|
+
entity.statusListCredential = args.statusListCredential
|
|
264
|
+
|
|
265
|
+
const details = await toStatusListDetails({
|
|
266
|
+
extractedDetails,
|
|
267
|
+
statusListEntity: entity,
|
|
268
|
+
})
|
|
269
|
+
|
|
190
270
|
// Merge details with existing entity and driver properties
|
|
191
271
|
const updateArgs = {
|
|
192
272
|
...entity,
|
|
@@ -200,11 +280,20 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
200
280
|
return { ...entity, ...details }
|
|
201
281
|
}
|
|
202
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Deletes the status list from the database
|
|
285
|
+
* @returns Promise resolving to boolean indicating success
|
|
286
|
+
*/
|
|
203
287
|
async deleteStatusList(): Promise<boolean> {
|
|
204
288
|
await this.statusListStore.removeStatusList({ id: this.options.id, correlationId: this.options.correlationId })
|
|
205
289
|
return Promise.resolve(true)
|
|
206
290
|
}
|
|
207
291
|
|
|
292
|
+
/**
|
|
293
|
+
* Updates a status list entry and returns the credential status
|
|
294
|
+
* @param args - Status list entry update parameters
|
|
295
|
+
* @returns Promise resolving to credential status and entry
|
|
296
|
+
*/
|
|
208
297
|
async updateStatusListEntry(args: IAddStatusListEntryArgs): Promise<{
|
|
209
298
|
credentialStatus: StatusList2021EntryCredentialStatus | StatusListOAuthEntryCredentialStatus | BitstringStatusListEntryCredentialStatus
|
|
210
299
|
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
@@ -228,18 +317,33 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
228
317
|
}
|
|
229
318
|
}
|
|
230
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Retrieves a status list entry by credential ID
|
|
322
|
+
* @param args - Query parameters including credential ID
|
|
323
|
+
* @returns Promise resolving to status list entry or undefined
|
|
324
|
+
*/
|
|
231
325
|
async getStatusListEntryByCredentialId(
|
|
232
326
|
args: IGetStatusListEntryByCredentialIdArgs,
|
|
233
327
|
): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity | undefined> {
|
|
234
328
|
return await this.statusListStore.getStatusListEntryByCredentialId(args)
|
|
235
329
|
}
|
|
236
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Retrieves a status list entry by index
|
|
333
|
+
* @param args - Query parameters including status list index
|
|
334
|
+
* @returns Promise resolving to status list entry or undefined
|
|
335
|
+
*/
|
|
237
336
|
async getStatusListEntryByIndex(
|
|
238
337
|
args: IGetStatusListEntryByIndexArgs,
|
|
239
338
|
): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity | undefined> {
|
|
240
339
|
return await this.statusListStore.getStatusListEntryByIndex(args)
|
|
241
340
|
}
|
|
242
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Generates a random available index for new status list entries
|
|
344
|
+
* @param args - Optional correlation ID parameter
|
|
345
|
+
* @returns Promise resolving to available index number
|
|
346
|
+
*/
|
|
243
347
|
async getRandomNewStatusListIndex(args?: { correlationId?: string }): Promise<number> {
|
|
244
348
|
let result = -1
|
|
245
349
|
let tries = 0
|
|
@@ -250,6 +354,12 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
250
354
|
return result
|
|
251
355
|
}
|
|
252
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Implementation for generating random status list indices with retry logic
|
|
359
|
+
* @param tries - Number of attempts made
|
|
360
|
+
* @param args - Optional correlation ID parameter
|
|
361
|
+
* @returns Promise resolving to available index or -1 if none found
|
|
362
|
+
*/
|
|
253
363
|
private async getRandomNewStatusListIndexImpl(tries: number, args?: { correlationId?: string }): Promise<number> {
|
|
254
364
|
const statusListId = this.options.id
|
|
255
365
|
const correlationId = args?.correlationId ?? this.options.correlationId
|
|
@@ -270,6 +380,11 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
270
380
|
return -1
|
|
271
381
|
}
|
|
272
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Gets the length of the status list
|
|
385
|
+
* @param args - Optional correlation ID parameter
|
|
386
|
+
* @returns Promise resolving to status list length
|
|
387
|
+
*/
|
|
273
388
|
async getStatusListLength(args?: { correlationId?: string }): Promise<number> {
|
|
274
389
|
if (!this._statusListLength) {
|
|
275
390
|
this._statusListLength = await this.getStatusList(args).then((details) => details.length)
|
|
@@ -277,30 +392,50 @@ export class AgentDataSourceStatusListDriver implements IStatusListDriver {
|
|
|
277
392
|
return this._statusListLength!
|
|
278
393
|
}
|
|
279
394
|
|
|
395
|
+
/**
|
|
396
|
+
* Retrieves the status list details
|
|
397
|
+
* @param args - Optional correlation ID parameter
|
|
398
|
+
* @returns Promise resolving to StatusListResult
|
|
399
|
+
*/
|
|
280
400
|
async getStatusList(args?: { correlationId?: string }): Promise<StatusListResult> {
|
|
281
401
|
const id = this.options.id
|
|
282
402
|
const correlationId = args?.correlationId ?? this.options.correlationId
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
403
|
+
|
|
404
|
+
const statusListEntity = await this.statusListStore.getStatusList({ id, correlationId })
|
|
405
|
+
|
|
406
|
+
// Convert entity to result using CREATE/READ context
|
|
407
|
+
return await toStatusListDetails({
|
|
408
|
+
statusListCredential: statusListEntity.statusListCredential!,
|
|
409
|
+
statusListType: statusListEntity.type,
|
|
410
|
+
bitsPerStatus: statusListEntity.bitsPerStatus,
|
|
411
|
+
correlationId: statusListEntity.correlationId,
|
|
412
|
+
driverType: statusListEntity.driverType,
|
|
413
|
+
})
|
|
290
414
|
}
|
|
291
415
|
|
|
416
|
+
/**
|
|
417
|
+
* Retrieves all status lists
|
|
418
|
+
* @returns Promise resolving to array of StatusListResult
|
|
419
|
+
*/
|
|
292
420
|
async getStatusLists(): Promise<Array<StatusListResult>> {
|
|
293
421
|
const statusLists = await this.statusListStore.getStatusLists({})
|
|
294
422
|
return Promise.all(
|
|
295
423
|
statusLists.map(async (statusListEntity) => {
|
|
296
|
-
return
|
|
297
|
-
statusListType: statusListEntity.type,
|
|
424
|
+
return toStatusListDetails({
|
|
298
425
|
statusListCredential: statusListEntity.statusListCredential!,
|
|
426
|
+
statusListType: statusListEntity.type,
|
|
427
|
+
bitsPerStatus: statusListEntity.bitsPerStatus,
|
|
428
|
+
correlationId: statusListEntity.correlationId,
|
|
429
|
+
driverType: statusListEntity.driverType,
|
|
299
430
|
})
|
|
300
431
|
}),
|
|
301
432
|
)
|
|
302
433
|
}
|
|
303
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Checks if a status list index is currently in use
|
|
437
|
+
* @returns Promise resolving to boolean indicating usage status
|
|
438
|
+
*/
|
|
304
439
|
isStatusListIndexInUse(): Promise<boolean> {
|
|
305
440
|
return Promise.resolve(false)
|
|
306
441
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
2
2
|
import {
|
|
3
|
+
BitstringStatusListEntryCredentialStatus,
|
|
3
4
|
IAddStatusListEntryArgs,
|
|
4
5
|
IGetStatusListEntryByCredentialIdArgs,
|
|
5
6
|
IGetStatusListEntryByIndexArgs,
|
|
@@ -7,13 +8,12 @@ import {
|
|
|
7
8
|
StatusListStore,
|
|
8
9
|
} from '@sphereon/ssi-sdk.data-store'
|
|
9
10
|
import {
|
|
10
|
-
BitstringStatusListEntryCredentialStatus,
|
|
11
11
|
IStatusListPlugin,
|
|
12
12
|
StatusList2021EntryCredentialStatus,
|
|
13
13
|
StatusListOAuthEntryCredentialStatus,
|
|
14
14
|
StatusListResult,
|
|
15
15
|
} from '@sphereon/ssi-sdk.vc-status-list'
|
|
16
|
-
import { StatusListCredential, StatusListDriverType } from '@sphereon/ssi-types'
|
|
16
|
+
import { StatusListCredential, StatusListDriverType, StatusListType } from '@sphereon/ssi-types'
|
|
17
17
|
import { IAgentContext, ICredentialIssuer, ICredentialVerifier, IDataStoreORM, IDIDManager, IKeyManager, IResolver } from '@veramo/core'
|
|
18
18
|
import { DriverOptions } from './drivers'
|
|
19
19
|
import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
|
|
@@ -38,7 +38,12 @@ export interface IStatusListDriver {
|
|
|
38
38
|
|
|
39
39
|
getStatusListLength(args?: { correlationId?: string }): Promise<number>
|
|
40
40
|
|
|
41
|
-
createStatusList(args: {
|
|
41
|
+
createStatusList(args: {
|
|
42
|
+
statusListType: StatusListType
|
|
43
|
+
statusListCredential: StatusListCredential
|
|
44
|
+
correlationId?: string
|
|
45
|
+
bitsPerStatus?: number
|
|
46
|
+
}): Promise<StatusListResult>
|
|
42
47
|
|
|
43
48
|
getStatusList(args?: { correlationId?: string }): Promise<StatusListResult>
|
|
44
49
|
|
|
@@ -53,7 +58,7 @@ export interface IStatusListDriver {
|
|
|
53
58
|
|
|
54
59
|
getStatusListEntryByIndex(args: IGetStatusListEntryByIndexArgs): Promise<IStatusListEntryEntity | undefined>
|
|
55
60
|
|
|
56
|
-
updateStatusList(args: { statusListCredential: StatusListCredential }): Promise<StatusListResult>
|
|
61
|
+
updateStatusList(args: { statusListCredential: StatusListCredential; correlationId: string }): Promise<StatusListResult>
|
|
57
62
|
|
|
58
63
|
deleteStatusList(): Promise<boolean>
|
|
59
64
|
|