@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/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
- // Get implementation details
148
- const implementationResult = await statusListCredentialToDetails({
149
- ...args,
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
- async updateStatusList(args: {
168
- statusListCredential: StatusListCredential
169
- correlationId: string
170
- statusListType: StatusListType
171
- }): Promise<StatusListResult> {
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
- const details = await statusListCredentialToDetails({ ...args, correlationId, driverType: this.getType() })
174
- const entity = await (
175
- await this.statusListStore.getStatusListRepo(args.statusListType)
176
- ).findOne({
177
- where: [
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 ${details.id}, correlationId ${args.correlationId} could not be found`)
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
- return await this.statusListStore.getStatusList({ id, correlationId }).then((statusListEntity: IStatusListEntity) =>
284
- statusListCredentialToDetails({
285
- statusListType: statusListEntity.type,
286
- statusListCredential: statusListEntity.statusListCredential!,
287
- bitsPerStatus: statusListEntity.bitsPerStatus,
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 statusListCredentialToDetails({
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: { statusListCredential: StatusListCredential; correlationId?: string; bitsPerStatus?: number }): Promise<StatusListResult>
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