@sphereon/ssi-sdk.data-store 0.34.1-feature.SSISDK.17.bitstring.sl.9 → 0.34.1-next.29

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.data-store",
3
- "version": "0.34.1-feature.SSISDK.17.bitstring.sl.9+a052acba",
3
+ "version": "0.34.1-next.29+2593a430",
4
4
  "source": "src/index.ts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,15 +28,15 @@
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.29.0",
32
- "@sphereon/ssi-sdk-ext.identifier-resolution": "0.29.0",
33
- "@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.17.bitstring.sl.9+a052acba",
34
- "@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.17.bitstring.sl.9+a052acba",
35
- "@sphereon/ssi-types": "0.34.1-feature.SSISDK.17.bitstring.sl.9+a052acba",
31
+ "@sphereon/ssi-sdk-ext.did-utils": "0.29.1-next.3",
32
+ "@sphereon/ssi-sdk-ext.identifier-resolution": "0.29.1-next.3",
33
+ "@sphereon/ssi-sdk.agent-config": "0.34.1-next.29+2593a430",
34
+ "@sphereon/ssi-sdk.core": "0.34.1-next.29+2593a430",
35
+ "@sphereon/ssi-types": "0.34.1-next.29+2593a430",
36
36
  "@veramo/core": "4.2.0",
37
37
  "@veramo/utils": "4.2.0",
38
38
  "blakejs": "^1.2.1",
39
- "class-validator": "^0.14.1",
39
+ "class-validator": "0.14.1",
40
40
  "dcql": "0.2.19",
41
41
  "debug": "^4.3.5",
42
42
  "typeorm": "0.3.20"
@@ -65,5 +65,5 @@
65
65
  "PostgreSQL",
66
66
  "Contact Store"
67
67
  ],
68
- "gitHead": "a052acbaa88acf4be22236ca3afaadd5b2821fe1"
68
+ "gitHead": "2593a430ac4faca47b620a3e12b297899518f2af"
69
69
  }
@@ -277,6 +277,7 @@ describe('Status list store tests', () => {
277
277
  credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
278
278
  type: StatusListType.BitstringStatusList,
279
279
  proofFormat: 'lds',
280
+ bitsPerStatus: 1,
280
281
  statusPurpose: 'suspension',
281
282
  ttl: 3600000,
282
283
  issuer: 'did:example:789',
@@ -1,31 +1,9 @@
1
- import { Validate } from 'class-validator'
2
- import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'
3
- import { IsNonEmptyStringConstraint } from '../validators'
4
- import { BitstringStatusListEntity } from './StatusListEntities'
5
- import { BitstringStatus } from '../../types/statusList/bitstringTypes'
6
-
7
- @Entity('BitstringStatusListEntry')
8
- export class BitstringStatusListEntryEntity extends BaseEntity {
9
- @PrimaryColumn({ name: 'statusListId', type: 'varchar', nullable: false, unique: false })
10
- @Validate(IsNonEmptyStringConstraint, { message: 'Status list id is required' })
11
- statusListId!: string
12
-
13
- @PrimaryColumn({ name: 'statusListIndex', type: 'integer', nullable: false, unique: false })
14
- statusListIndex!: number
15
-
16
- @ManyToOne(() => BitstringStatusListEntity, (statusList) => statusList.statusListEntries)
17
- @JoinColumn({ name: 'statusListId' })
18
- statusList!: BitstringStatusListEntity
19
-
20
- @Column({ name: 'credentialId', type: 'text', nullable: true })
21
- credentialId?: string
22
-
23
- @Column({ name: 'credentialHash', length: 128, type: 'varchar', nullable: true, unique: false })
24
- credentialHash?: string
25
-
26
- @Column({ name: 'correlationId', length: 255, type: 'varchar', nullable: true, unique: false })
27
- entryCorrelationId?: string
1
+ import { ChildEntity, Column } from 'typeorm'
2
+ import { StatusListEntryEntity } from './StatusList2021EntryEntity'
3
+ import { BitstringStatusMessage } from '../../types'
28
4
 
5
+ @ChildEntity('bitstring')
6
+ export class BitstringStatusListEntryEntity extends StatusListEntryEntity {
29
7
  @Column({ type: 'varchar', name: 'statusPurpose', nullable: false })
30
8
  statusPurpose!: string
31
9
 
@@ -37,13 +15,13 @@ export class BitstringStatusListEntryEntity extends BaseEntity {
37
15
  name: 'statusMessage',
38
16
  nullable: true,
39
17
  transformer: {
40
- from(value: string): Array<BitstringStatus> | undefined {
18
+ from(value: string): Array<BitstringStatusMessage> | undefined {
41
19
  if (!value) {
42
20
  return undefined
43
21
  }
44
22
  return JSON.parse(value)
45
23
  },
46
- to(value: Array<BitstringStatus> | undefined): string | undefined {
24
+ to(value: Array<BitstringStatusMessage> | undefined): string | undefined {
47
25
  if (!value) {
48
26
  return undefined
49
27
  }
@@ -51,7 +29,7 @@ export class BitstringStatusListEntryEntity extends BaseEntity {
51
29
  },
52
30
  },
53
31
  })
54
- statusMessage?: Array<BitstringStatus>
32
+ statusMessage?: Array<BitstringStatusMessage>
55
33
 
56
34
  @Column({
57
35
  type: 'text',
@@ -1,11 +1,12 @@
1
1
  import { Validate } from 'class-validator'
2
- import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'
2
+ import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, TableInheritance } from 'typeorm'
3
3
  import { IsNonEmptyStringConstraint } from '../validators'
4
4
  import { StatusList2021Entity, StatusListEntity } from './StatusListEntities'
5
5
 
6
6
  @Entity('StatusListEntry')
7
7
  // @Unique('uq_credential_statuslist', ['statusList', 'credentialId']) // disabled because one prop can be null
8
8
  // @Unique('uq_credentialHash_statuslistId', ['statusList', 'credentialHash']) // disabled because one prop can be null
9
+ @TableInheritance({ column: { type: 'varchar', name: 'type' } })
9
10
  export class StatusListEntryEntity extends BaseEntity {
10
11
  @PrimaryColumn({ name: 'statusListId', type: 'varchar', nullable: false, unique: false })
11
12
  @Validate(IsNonEmptyStringConstraint, { message: 'Status list id is required' })
@@ -29,6 +29,13 @@ export abstract class StatusListEntity extends BaseEntity {
29
29
  @Column({ name: 'length', type: 'integer', nullable: false, unique: false })
30
30
  length!: number
31
31
 
32
+ @Column('simple-enum', {
33
+ name: 'type',
34
+ enum: StatusListType,
35
+ nullable: false,
36
+ })
37
+ type!: StatusListType
38
+
32
39
  @Column({
33
40
  name: 'issuer',
34
41
  type: 'text',
@@ -16,36 +16,35 @@ export class CreateBitstringStatusListPG1741895823000 implements MigrationInterf
16
16
  `ALTER TABLE "StatusList" ADD CONSTRAINT "CHK_StatusList_type" CHECK ("type" IN ('StatusList2021', 'OAuthStatusList', 'BitstringStatusList'))`,
17
17
  )
18
18
 
19
- // Create BitstringStatusListEntry table
20
- await queryRunner.query(`
21
- CREATE TABLE "BitstringStatusListEntry" (
22
- "statusListId" character varying NOT NULL,
23
- "statusListIndex" integer NOT NULL,
24
- "credentialId" text,
25
- "credentialHash" character varying(128),
26
- "correlationId" character varying(255),
27
- "statusPurpose" character varying NOT NULL,
28
- "bitsPerStatus" integer DEFAULT 1,
29
- "statusMessage" text,
30
- "statusReference" text,
31
- CONSTRAINT "PK_BitstringStatusListEntry" PRIMARY KEY ("statusListId", "statusListIndex")
32
- )
33
- `)
34
-
35
- await queryRunner.query(`
36
- ALTER TABLE "BitstringStatusListEntry"
37
- ADD CONSTRAINT "FK_BitstringStatusListEntry_statusListId"
38
- FOREIGN KEY ("statusListId") REFERENCES "StatusList"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
39
- `)
19
+ // Add inheritance discriminator column to StatusListEntry table
20
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "type" character varying NOT NULL DEFAULT 'StatusListEntryEntity'`)
21
+
22
+ // Add BitstringStatusListEntry specific columns to StatusListEntry table
23
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusPurpose" character varying`)
24
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "bitsPerStatus" integer DEFAULT 1`)
25
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusMessage" text`)
26
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusReference" text`)
27
+
28
+ // Add constraint for entry type
29
+ await queryRunner.query(
30
+ `ALTER TABLE "StatusListEntry" ADD CONSTRAINT "CHK_StatusListEntry_type" CHECK ("type" IN ('StatusListEntryEntity', 'bitstring'))`,
31
+ )
40
32
  }
41
33
 
42
34
  public async down(queryRunner: QueryRunner): Promise<void> {
43
- await queryRunner.query(`ALTER TABLE "BitstringStatusListEntry" DROP CONSTRAINT "FK_BitstringStatusListEntry_statusListId"`)
44
- await queryRunner.query(`DROP TABLE "BitstringStatusListEntry"`)
45
-
35
+ // Remove entry type constraint and columns
36
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP CONSTRAINT "CHK_StatusListEntry_type"`)
37
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusReference"`)
38
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusMessage"`)
39
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "bitsPerStatus"`)
40
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusPurpose"`)
41
+ await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "type"`)
42
+
43
+ // Revert StatusList type constraint
46
44
  await queryRunner.query(`ALTER TABLE "StatusList" DROP CONSTRAINT "CHK_StatusList_type"`)
47
45
  await queryRunner.query(`ALTER TABLE "StatusList" ADD CONSTRAINT "CHK_StatusList_type" CHECK ("type" IN ('StatusList2021', 'OAuthStatusList'))`)
48
46
 
47
+ // Remove BitstringStatusList columns from StatusList table
49
48
  await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "validUntil"`)
50
49
  await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "validFrom"`)
51
50
  await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "ttl"`)
@@ -14,7 +14,7 @@ export class CreateBitstringStatusListSqlite1741895823001 implements MigrationIn
14
14
  "type" varchar CHECK( "type" IN ('StatusList2021', 'OAuthStatusList', 'BitstringStatusList') ) NOT NULL DEFAULT ('StatusList2021'),
15
15
  "driverType" varchar CHECK( "driverType" IN ('agent_typeorm','agent_kv_store','github','agent_filesystem') ) NOT NULL DEFAULT ('agent_typeorm'),
16
16
  "credentialIdMode" varchar CHECK( "credentialIdMode" IN ('ISSUANCE','PERSISTENCE','NEVER') ) NOT NULL DEFAULT ('ISSUANCE'),
17
- "proofFormat" varchar CHECK( "proofFormat" IN ('lds','jwt') ) NOT NULL DEFAULT ('lds'),
17
+ "proofFormat" varchar CHECK( "proofFormat" IN ('lds','jwt', 'vc+jwt') ) NOT NULL DEFAULT ('lds'),
18
18
  "indexingDirection" varchar CHECK( "indexingDirection" IN ('rightToLeft') ),
19
19
  "statusPurpose" varchar,
20
20
  "statusListCredential" text,
@@ -43,26 +43,69 @@ export class CreateBitstringStatusListSqlite1741895823001 implements MigrationIn
43
43
  await queryRunner.query(`DROP TABLE "StatusList"`)
44
44
  await queryRunner.query(`ALTER TABLE "temporary_StatusList" RENAME TO "StatusList"`)
45
45
 
46
- // Create BitstringStatusListEntry table
46
+ // Update StatusListEntry table with inheritance and bitstring columns
47
47
  await queryRunner.query(`
48
- CREATE TABLE "BitstringStatusListEntry" (
48
+ CREATE TABLE "temporary_StatusListEntry" (
49
49
  "statusListId" varchar NOT NULL,
50
50
  "statusListIndex" integer NOT NULL,
51
51
  "credentialId" text,
52
52
  "credentialHash" varchar(128),
53
53
  "correlationId" varchar(255),
54
- "statusPurpose" varchar NOT NULL,
54
+ "value" varchar(50),
55
+ "type" varchar CHECK( "type" IN ('StatusListEntryEntity', 'bitstring') ) NOT NULL DEFAULT ('StatusListEntryEntity'),
56
+ "statusPurpose" varchar,
55
57
  "bitsPerStatus" integer DEFAULT (1),
56
58
  "statusMessage" text,
57
59
  "statusReference" text,
58
60
  PRIMARY KEY ("statusListId", "statusListIndex")
59
61
  )
60
62
  `)
63
+
64
+ await queryRunner.query(`
65
+ INSERT INTO "temporary_StatusListEntry"(
66
+ "statusListId", "statusListIndex", "credentialId", "credentialHash",
67
+ "correlationId", "value", "type"
68
+ )
69
+ SELECT
70
+ "statusListId", "statusListIndex", "credentialId", "credentialHash",
71
+ "correlationId", "value", 'StatusListEntryEntity'
72
+ FROM "StatusListEntry"
73
+ `)
74
+
75
+ await queryRunner.query(`DROP TABLE "StatusListEntry"`)
76
+ await queryRunner.query(`ALTER TABLE "temporary_StatusListEntry" RENAME TO "StatusListEntry"`)
61
77
  }
62
78
 
63
79
  public async down(queryRunner: QueryRunner): Promise<void> {
64
- await queryRunner.query(`DROP TABLE "BitstringStatusListEntry"`)
80
+ // Revert StatusListEntry table changes
81
+ await queryRunner.query(`
82
+ CREATE TABLE "temporary_StatusListEntry" (
83
+ "statusListId" varchar NOT NULL,
84
+ "statusListIndex" integer NOT NULL,
85
+ "credentialId" text,
86
+ "credentialHash" varchar(128),
87
+ "correlationId" varchar(255),
88
+ "value" varchar(50),
89
+ PRIMARY KEY ("statusListId", "statusListIndex")
90
+ )
91
+ `)
92
+
93
+ await queryRunner.query(`
94
+ INSERT INTO "temporary_StatusListEntry"(
95
+ "statusListId", "statusListIndex", "credentialId", "credentialHash",
96
+ "correlationId", "value"
97
+ )
98
+ SELECT
99
+ "statusListId", "statusListIndex", "credentialId", "credentialHash",
100
+ "correlationId", "value"
101
+ FROM "StatusListEntry"
102
+ WHERE "type" = 'StatusListEntryEntity'
103
+ `)
104
+
105
+ await queryRunner.query(`DROP TABLE "StatusListEntry"`)
106
+ await queryRunner.query(`ALTER TABLE "temporary_StatusListEntry" RENAME TO "StatusListEntry"`)
65
107
 
108
+ // Revert StatusList table changes
66
109
  await queryRunner.query(`
67
110
  CREATE TABLE "temporary_StatusList" (
68
111
  "id" varchar PRIMARY KEY NOT NULL,
@@ -72,7 +115,7 @@ export class CreateBitstringStatusListSqlite1741895823001 implements MigrationIn
72
115
  "type" varchar CHECK( "type" IN ('StatusList2021', 'OAuthStatusList') ) NOT NULL DEFAULT ('StatusList2021'),
73
116
  "driverType" varchar CHECK( "driverType" IN ('agent_typeorm','agent_kv_store','github','agent_filesystem') ) NOT NULL DEFAULT ('agent_typeorm'),
74
117
  "credentialIdMode" varchar CHECK( "credentialIdMode" IN ('ISSUANCE','PERSISTENCE','NEVER') ) NOT NULL DEFAULT ('ISSUANCE'),
75
- "proofFormat" varchar CHECK( "proofFormat" IN ('lds','jwt') ) NOT NULL DEFAULT ('lds'),
118
+ "proofFormat" varchar CHECK( "proofFormat" IN ('lds','jwt', 'vc+jwt') ) NOT NULL DEFAULT ('lds'),
76
119
  "indexingDirection" varchar CHECK( "indexingDirection" IN ('rightToLeft') ),
77
120
  "statusPurpose" varchar,
78
121
  "statusListCredential" text,
@@ -2,6 +2,8 @@ import { StatusListEntryEntity } from '../entities/statusList/StatusList2021Entr
2
2
  import type {
3
3
  IAddStatusListArgs,
4
4
  IAddStatusListEntryArgs,
5
+ IBitstringStatusListEntity,
6
+ IBitstringStatusListEntryEntity,
5
7
  IGetStatusListArgs,
6
8
  IGetStatusListEntriesArgs,
7
9
  IGetStatusListEntryByCredentialIdArgs,
@@ -12,33 +14,34 @@ import type {
12
14
  IUpdateStatusListIndexArgs,
13
15
  } from '../types'
14
16
  import { IStatusListEntity, IStatusListEntryEntity } from '../types'
17
+ import { BitstringStatusListEntryEntity } from '../entities/statusList/BitstringStatusListEntryEntity'
15
18
 
16
19
  export interface IStatusListStore {
17
- getStatusList(args: IGetStatusListArgs): Promise<IStatusListEntity>
20
+ getStatusList(args: IGetStatusListArgs): Promise<IStatusListEntity | IBitstringStatusListEntity>
18
21
 
19
- getStatusLists(args: IGetStatusListsArgs): Promise<Array<IStatusListEntity>>
22
+ getStatusLists(args: IGetStatusListsArgs): Promise<Array<IStatusListEntity | IBitstringStatusListEntity>>
20
23
 
21
24
  removeStatusList(args: IRemoveStatusListArgs): Promise<boolean>
22
25
 
23
- addStatusList(args: IAddStatusListArgs): Promise<IStatusListEntity>
26
+ addStatusList(args: IAddStatusListArgs): Promise<IStatusListEntity | IBitstringStatusListEntity>
24
27
 
25
- updateStatusList(args: IUpdateStatusListIndexArgs): Promise<IStatusListEntity>
28
+ updateStatusList(args: IUpdateStatusListIndexArgs): Promise<IStatusListEntity | IBitstringStatusListEntity>
26
29
 
27
30
  availableStatusListEntries(args: IStatusListEntryAvailableArgs): Promise<number[]>
28
31
 
29
- addStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity>
32
+ addStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity>
30
33
 
31
- updateStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity>
34
+ updateStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity>
32
35
 
33
- getStatusListEntryByIndex(args: IGetStatusListEntryByIndexArgs): Promise<StatusListEntryEntity | undefined>
36
+ getStatusListEntryByIndex(args: IGetStatusListEntryByIndexArgs): Promise<StatusListEntryEntity | BitstringStatusListEntryEntity | undefined>
34
37
 
35
- getStatusListEntryByCredentialId(args: IGetStatusListEntryByCredentialIdArgs): Promise<StatusListEntryEntity | undefined>
38
+ getStatusListEntryByCredentialId(
39
+ args: IGetStatusListEntryByCredentialIdArgs,
40
+ ): Promise<StatusListEntryEntity | BitstringStatusListEntryEntity | undefined>
36
41
 
37
42
  removeStatusListEntryByIndex(args: IGetStatusListEntryByIndexArgs): Promise<boolean>
38
43
 
39
44
  removeStatusListEntryByCredentialId(args: IGetStatusListEntryByCredentialIdArgs): Promise<boolean>
40
45
 
41
- getStatusListEntries(args: IGetStatusListEntriesArgs): Promise<IStatusListEntryEntity[]>
42
-
43
- getStatusList(args: IGetStatusListArgs): Promise<IStatusListEntity>
46
+ getStatusListEntries(args: IGetStatusListEntriesArgs): Promise<Array<IStatusListEntryEntity | IBitstringStatusListEntryEntity>>
44
47
  }
@@ -3,9 +3,12 @@ import Debug from 'debug'
3
3
  import { DataSource, In, type Repository } from 'typeorm'
4
4
  import { BitstringStatusListEntity, OAuthStatusListEntity, StatusList2021Entity, StatusListEntity } from '../entities/statusList/StatusListEntities'
5
5
  import { StatusListEntryEntity } from '../entities/statusList/StatusList2021EntryEntity'
6
- import type {
6
+ import { BitstringStatusListEntryEntity } from '../entities/statusList/BitstringStatusListEntryEntity'
7
+ import {
7
8
  IAddStatusListArgs,
8
9
  IAddStatusListEntryArgs,
10
+ IBitstringStatusListEntity,
11
+ IBitstringStatusListEntryEntity,
9
12
  IGetStatusListArgs,
10
13
  IGetStatusListEntriesArgs,
11
14
  IGetStatusListEntryByCredentialIdArgs,
@@ -41,7 +44,7 @@ export class StatusListStore implements IStatusListStore {
41
44
  async availableStatusListEntries(args: IStatusListEntryAvailableArgs): Promise<number[]> {
42
45
  const statusListIndex = Array.isArray(args.statusListIndex) ? args.statusListIndex : [args.statusListIndex]
43
46
  const statusList = await this.getStatusList({ ...args, id: args.statusListId })
44
- const repo = await this.getStatusListEntryRepo()
47
+ const repo = await this.getStatusListEntryRepo(statusList.type)
45
48
  const results = (
46
49
  await repo.find({
47
50
  where: {
@@ -53,33 +56,42 @@ export class StatusListStore implements IStatusListStore {
53
56
  return statusListIndex.filter((index) => !results.includes(index))
54
57
  }
55
58
 
56
- async addStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity> {
57
- return (await this.getStatusListEntryRepo()).save(args)
59
+ async addStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity> {
60
+ if (!args.statusListId) {
61
+ throw new Error('statusListId is required')
62
+ }
63
+
64
+ const statusList = await this.getStatusList({ id: args.statusListId })
65
+ return await (await this.getStatusListEntryRepo(statusList.type)).save(args)
58
66
  }
59
67
 
60
- async updateStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity> {
61
- const statusListId = args.statusListId ?? args.statusList?.id
68
+ async updateStatusListEntry(args: IAddStatusListEntryArgs): Promise<IStatusListEntryEntity | IBitstringStatusListEntryEntity> {
69
+ const statusListId = args.statusListId
70
+ if (!statusListId) {
71
+ throw new Error('statusListId is required')
72
+ }
73
+
74
+ const statusList = await this.getStatusList({ id: statusListId })
62
75
  const result = await this.getStatusListEntryByIndex({ ...args, statusListId, errorOnNotFound: false })
63
76
  const updatedEntry: Partial<IStatusListEntryEntity> = {
64
- value: args.value,
65
- correlationId: args.correlationId,
66
- credentialHash: args.credentialHash,
67
- credentialId: args.credentialId,
77
+ ...result,
78
+ ...args,
79
+ statusListId,
68
80
  }
69
81
 
70
82
  const updStatusListId = result?.statusListId ?? statusListId
71
83
  const updateResult = await (
72
- await this.getStatusListEntryRepo()
84
+ await this.getStatusListEntryRepo(statusList.type)
73
85
  ).upsert(
74
86
  { ...(result ?? { statusListId: updStatusListId, statusListIndex: args.statusListIndex }), ...updatedEntry },
75
87
  { conflictPaths: ['statusList', 'statusListIndex'] },
76
88
  )
77
- console.log(updateResult)
89
+ debug(updateResult)
78
90
  return (await this.getStatusListEntryByIndex({
79
91
  ...args,
80
92
  statusListId: updStatusListId,
81
93
  errorOnNotFound: true,
82
- })) as IStatusListEntryEntity
94
+ }))!
83
95
  }
84
96
 
85
97
  async getStatusListEntryByIndex({
@@ -88,7 +100,7 @@ export class StatusListStore implements IStatusListStore {
88
100
  statusListIndex,
89
101
  entryCorrelationId,
90
102
  errorOnNotFound,
91
- }: IGetStatusListEntryByIndexArgs): Promise<StatusListEntryEntity | undefined> {
103
+ }: IGetStatusListEntryByIndexArgs): Promise<StatusListEntryEntity | BitstringStatusListEntryEntity | undefined> {
92
104
  if (!statusListId && !statusListCorrelationId) {
93
105
  throw Error(`Cannot get statusList entry without either a statusList id or statusListCorrelationId`)
94
106
  }
@@ -97,8 +109,12 @@ export class StatusListStore implements IStatusListStore {
97
109
  throw Error(`Cannot get statusList entry without either a statusListIndex or entryCorrelationId`)
98
110
  }
99
111
 
112
+ const statusList = statusListId
113
+ ? await this.getStatusList({ id: statusListId })
114
+ : await this.getStatusList({ correlationId: statusListCorrelationId })
115
+
100
116
  const result = await (
101
- await this.getStatusListEntryRepo()
117
+ await this.getStatusListEntryRepo(statusList.type)
102
118
  ).findOne({
103
119
  where: {
104
120
  ...(statusListId && { statusListId }),
@@ -118,7 +134,9 @@ export class StatusListStore implements IStatusListStore {
118
134
  return result ?? undefined
119
135
  }
120
136
 
121
- async getStatusListEntryByCredentialId(args: IGetStatusListEntryByCredentialIdArgs): Promise<StatusListEntryEntity | undefined> {
137
+ async getStatusListEntryByCredentialId(
138
+ args: IGetStatusListEntryByCredentialIdArgs,
139
+ ): Promise<StatusListEntryEntity | BitstringStatusListEntryEntity | undefined> {
122
140
  const credentialId = args.credentialId
123
141
  if (!credentialId) {
124
142
  throw Error('Can only get a credential by credentialId when a credentialId is supplied')
@@ -132,8 +150,8 @@ export class StatusListStore implements IStatusListStore {
132
150
  ...(args.entryCorrelationId && { correlationId: args.entryCorrelationId }),
133
151
  credentialId,
134
152
  }
135
- console.log(`Entries: ${JSON.stringify(await (await this.getStatusListEntryRepo()).find(), null, 2)}`)
136
- const result = await (await this.getStatusListEntryRepo()).findOne({ where })
153
+ debug(`Entries: ${JSON.stringify(await (await this.getStatusListEntryRepo(statusList.type)).find(), null, 2)}`)
154
+ const result = await (await this.getStatusListEntryRepo(statusList.type)).findOne({ where })
137
155
 
138
156
  if (!result && args.errorOnNotFound) {
139
157
  throw Error(`Could not find status list credential id ${credentialId} for status list id ${statusList.id}`)
@@ -149,8 +167,12 @@ export class StatusListStore implements IStatusListStore {
149
167
  error = true
150
168
  }
151
169
  if (!error) {
170
+ const statusList = await this.getStatusList({
171
+ id: args.statusListId,
172
+ correlationId: args.statusListCorrelationId,
173
+ })
152
174
  const result = await (
153
- await this.getStatusListEntryRepo()
175
+ await this.getStatusListEntryRepo(statusList.type)
154
176
  ).delete({
155
177
  ...(args.statusListId && { statusList: args.statusListId }),
156
178
  ...(args.entryCorrelationId && { correlationId: args.entryCorrelationId }),
@@ -169,10 +191,11 @@ export class StatusListStore implements IStatusListStore {
169
191
  error = true
170
192
  }
171
193
  if (error) {
172
- console.log(`Could not delete statusList ${args.statusListId} entry by index ${args.statusListIndex}`)
194
+ console.error(`Could not delete statusList ${args.statusListId} entry by index ${args.statusListIndex}`)
173
195
  } else {
196
+ const statusList = await this.getStatusList({ id: args.statusListId })
174
197
  const result = await (
175
- await this.getStatusListEntryRepo()
198
+ await this.getStatusListEntryRepo(statusList.type)
176
199
  ).delete({
177
200
  ...(args.statusListId && { statusList: args.statusListId }),
178
201
  ...(args.entryCorrelationId && { correlationId: args.entryCorrelationId }),
@@ -183,12 +206,14 @@ export class StatusListStore implements IStatusListStore {
183
206
  return !error
184
207
  }
185
208
 
186
- async getStatusListEntries(args: IGetStatusListEntriesArgs): Promise<StatusListEntryEntity[]> {
187
- return (await this.getStatusListEntryRepo()).find({ where: { ...args?.filter, statusList: args.statusListId } })
188
- }
189
-
190
- async getStatusList(args: IGetStatusListArgs): Promise<IStatusListEntity> {
191
- return statusListFrom(await this.getStatusListEntity(args))
209
+ async getStatusListEntries(args: IGetStatusListEntriesArgs): Promise<Array<IStatusListEntryEntity | IBitstringStatusListEntryEntity>> {
210
+ const statusList = await this.getStatusList({ id: args.statusListId })
211
+ const results = await (
212
+ await this.getStatusListEntryRepo(statusList.type)
213
+ ).find({
214
+ where: { ...args?.filter, statusList: args.statusListId },
215
+ })
216
+ return results as Array<IStatusListEntryEntity | IBitstringStatusListEntryEntity>
192
217
  }
193
218
 
194
219
  private async getStatusListEntity(args: IGetStatusListArgs): Promise<StatusListEntity> {
@@ -208,7 +233,12 @@ export class StatusListStore implements IStatusListStore {
208
233
  return result
209
234
  }
210
235
 
211
- async getStatusLists(args: IGetStatusListsArgs): Promise<Array<IStatusListEntity>> {
236
+ async getStatusList(args: IGetStatusListArgs): Promise<IStatusListEntity | IBitstringStatusListEntity> {
237
+ const entity = await this.getStatusListEntity(args)
238
+ return statusListFrom(entity) as IStatusListEntity | IBitstringStatusListEntity
239
+ }
240
+
241
+ async getStatusLists(args: IGetStatusListsArgs): Promise<Array<IStatusListEntity | IBitstringStatusListEntity>> {
212
242
  const result = await (
213
243
  await this.getStatusListRepo()
214
244
  ).find({
@@ -219,7 +249,7 @@ export class StatusListStore implements IStatusListStore {
219
249
  return []
220
250
  }
221
251
 
222
- return result.map((entity) => statusListFrom(entity))
252
+ return result.map((entity) => statusListFrom(entity) as IStatusListEntity | IBitstringStatusListEntity)
223
253
  }
224
254
 
225
255
  async addStatusList(args: IAddStatusListArgs): Promise<IStatusListEntity> {
@@ -240,7 +270,7 @@ export class StatusListStore implements IStatusListStore {
240
270
  return statusListFrom(createdResult)
241
271
  }
242
272
 
243
- async updateStatusList(args: IUpdateStatusListIndexArgs): Promise<IStatusListEntity> {
273
+ async updateStatusList(args: IUpdateStatusListIndexArgs): Promise<IStatusListEntity | IBitstringStatusListEntity> {
244
274
  const result = await this.getStatusList(args)
245
275
  debug('Updating status list', result)
246
276
  const entity = statusListEntityFrom(args)
@@ -251,7 +281,7 @@ export class StatusListStore implements IStatusListStore {
251
281
  async removeStatusList(args: IRemoveStatusListArgs): Promise<boolean> {
252
282
  const result = await this.getStatusListEntity(args)
253
283
 
254
- await (await this.getStatusListEntryRepo()).delete({ statusListId: result.id })
284
+ await (await this.getStatusListEntryRepo(result.type)).delete({ statusListId: result.id })
255
285
  const deletedEntity = await (await this.getStatusListRepo()).remove(result)
256
286
 
257
287
  return Boolean(deletedEntity)
@@ -275,7 +305,13 @@ export class StatusListStore implements IStatusListStore {
275
305
  }
276
306
  }
277
307
 
278
- async getStatusListEntryRepo(): Promise<Repository<StatusListEntryEntity>> {
279
- return (await this.getDS()).getRepository(StatusListEntryEntity)
308
+ async getStatusListEntryRepo(type?: StatusListType): Promise<Repository<StatusListEntryEntity | BitstringStatusListEntryEntity>> {
309
+ const dataSource = await this.getDS()
310
+ switch (type) {
311
+ case StatusListType.BitstringStatusList:
312
+ return dataSource.getRepository(BitstringStatusListEntryEntity)
313
+ default:
314
+ return dataSource.getRepository(StatusListEntryEntity)
315
+ }
280
316
  }
281
317
  }
@@ -6,7 +6,6 @@ export * from './presentationDefinition/presentationDefinition'
6
6
  export * from './presentationDefinition/IAbstractPDStore'
7
7
  export * from './validation/validation'
8
8
  export * from './statusList/statusList'
9
- export * from './statusList/bitstringTypes'
10
9
  export * from './statusList/IAbstractStatusListStore'
11
10
  export * from './eventLogger/IAbstractEventLoggerStore'
12
11
  export * from './eventLogger/eventLogger'
@@ -1,5 +1,21 @@
1
1
  import { FindOptionsWhere } from 'typeorm'
2
- import { IOAuthStatusListEntity, IStatusList2021Entity, IStatusListEntity, IStatusListEntryEntity } from './statusList'
2
+ import {
3
+ BitstringStatusPurpose,
4
+ IBitstringStatusListEntryEntity,
5
+ IOAuthStatusListEntity,
6
+ IStatusList2021Entity,
7
+ IStatusListEntryEntity,
8
+ } from './statusList'
9
+ import {
10
+ CredentialProofFormat,
11
+ IIssuer,
12
+ StatusListCredential,
13
+ StatusListCredentialIdMode,
14
+ StatusListDriverType,
15
+ StatusListIndexingDirection,
16
+ StatusListType,
17
+ StatusPurpose2021,
18
+ } from '@sphereon/ssi-types'
3
19
 
4
20
  export type FindStatusListArgs = FindOptionsWhere<IStatusList2021Entity | IOAuthStatusListEntity>[]
5
21
  export type FindStatusListEntryArgs = FindOptionsWhere<IStatusListEntryEntity>[] | FindOptionsWhere<IStatusListEntryEntity>
@@ -30,7 +46,7 @@ export interface IGetStatusListEntriesArgs {
30
46
  filter?: FindStatusListEntryArgs
31
47
  }
32
48
 
33
- export type IAddStatusListEntryArgs = IStatusListEntryEntity
49
+ export type IAddStatusListEntryArgs = IStatusListEntryEntity | IBitstringStatusListEntryEntity
34
50
 
35
51
  export interface IGetStatusListArgs {
36
52
  id?: string
@@ -43,6 +59,40 @@ export interface IGetStatusListsArgs {
43
59
  filter?: FindStatusListArgs
44
60
  }
45
61
 
46
- export type IAddStatusListArgs = IStatusListEntity
62
+ interface IBaseStatusListArgs {
63
+ id: string
64
+ correlationId: string
65
+ driverType: StatusListDriverType
66
+ credentialIdMode: StatusListCredentialIdMode
67
+ length: number
68
+ issuer: string | IIssuer
69
+ type: StatusListType
70
+ proofFormat: CredentialProofFormat
71
+ statusListCredential?: StatusListCredential
72
+ bitsPerStatus?: number
73
+ }
74
+
75
+ export type IStatusList2021Args = IBaseStatusListArgs & {
76
+ type: StatusListType.StatusList2021
77
+ indexingDirection: StatusListIndexingDirection
78
+ statusPurpose: StatusPurpose2021
79
+ }
80
+
81
+ export type IOAuthStatusListArgs = IBaseStatusListArgs & {
82
+ type: StatusListType.OAuthStatusList
83
+ bitsPerStatus: number
84
+ expiresAt?: Date
85
+ }
86
+
87
+ export type IBitstringStatusListArgs = IBaseStatusListArgs & {
88
+ type: StatusListType.BitstringStatusList
89
+ statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
90
+ bitsPerStatus?: number
91
+ validFrom?: Date
92
+ validUntil?: Date
93
+ ttl?: number
94
+ }
95
+
96
+ export type IAddStatusListArgs = IStatusList2021Args | IOAuthStatusListArgs | IBitstringStatusListArgs
47
97
 
48
- export type IUpdateStatusListIndexArgs = IStatusListEntity
98
+ export type IUpdateStatusListIndexArgs = IAddStatusListArgs