@sphereon/ssi-sdk.data-store 0.34.1-next.6 → 0.34.1-next.85
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 +982 -504
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -27
- package/dist/index.d.ts +112 -27
- package/dist/index.js +928 -450
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/statusList.entities.test.ts +58 -1
- package/src/__tests__/statusList.store.test.ts +64 -1
- package/src/entities/statusList/BitstringStatusListEntryEntity.ts +60 -0
- package/src/entities/statusList/StatusList2021EntryEntity.ts +4 -3
- package/src/entities/statusList/StatusListEntities.ts +54 -5
- package/src/index.ts +12 -2
- package/src/migrations/generic/12-CreateBitstringStatusList.ts +52 -0
- package/src/migrations/generic/index.ts +2 -1
- package/src/migrations/postgres/1737110469001-UpdateStatusList.ts +1 -1
- package/src/migrations/postgres/1741895823000-CreateBitstringStatusList.ts +55 -0
- package/src/migrations/sqlite/1741895823001-CreateBitstringStatusList.ts +145 -0
- package/src/statusList/IStatusListStore.ts +14 -11
- package/src/statusList/StatusListStore.ts +73 -35
- package/src/types/digitalCredential/enums.ts +1 -1
- package/src/types/statusList/IAbstractStatusListStore.ts +54 -4
- package/src/types/statusList/statusList.ts +50 -2
- package/src/utils/statusList/MappingUtils.ts +71 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/ssi-sdk.data-store",
|
|
3
|
-
"version": "0.34.1-next.
|
|
3
|
+
"version": "0.34.1-next.85+019802c5",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -28,11 +28,11 @@
|
|
|
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.
|
|
32
|
-
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.
|
|
33
|
-
"@sphereon/ssi-sdk.agent-config": "0.34.1-next.
|
|
34
|
-
"@sphereon/ssi-sdk.core": "0.34.1-next.
|
|
35
|
-
"@sphereon/ssi-types": "0.34.1-next.
|
|
31
|
+
"@sphereon/ssi-sdk-ext.did-utils": "0.34.1-next.85+019802c5",
|
|
32
|
+
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-next.85+019802c5",
|
|
33
|
+
"@sphereon/ssi-sdk.agent-config": "0.34.1-next.85+019802c5",
|
|
34
|
+
"@sphereon/ssi-sdk.core": "0.34.1-next.85+019802c5",
|
|
35
|
+
"@sphereon/ssi-types": "0.34.1-next.85+019802c5",
|
|
36
36
|
"@veramo/core": "4.2.0",
|
|
37
37
|
"@veramo/utils": "4.2.0",
|
|
38
38
|
"blakejs": "^1.2.1",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"PostgreSQL",
|
|
66
66
|
"Contact Store"
|
|
67
67
|
],
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "019802c57e9c1f9e3df4ecbb1d6a17f49e8fdbeb"
|
|
69
69
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource } from 'typeorm'
|
|
2
2
|
import { DataSources } from '@sphereon/ssi-sdk.agent-config'
|
|
3
|
-
import { DataStoreStatusListEntities, StatusListEntryEntity } from '../index'
|
|
3
|
+
import { BitstringStatusListEntity, BitstringStatusListEntryEntity, DataStoreStatusListEntities, StatusListEntryEntity } from '../index'
|
|
4
4
|
import { DataStoreStatusListMigrations } from '../migrations'
|
|
5
5
|
import { OAuthStatusListEntity, StatusList2021Entity } from '../entities/statusList/StatusListEntities'
|
|
6
6
|
import { IIssuer, StatusListCredentialIdMode, StatusListDriverType } from '@sphereon/ssi-types'
|
|
@@ -18,6 +18,8 @@ describe('Status list entities tests', () => {
|
|
|
18
18
|
migrations: DataStoreStatusListMigrations,
|
|
19
19
|
synchronize: false,
|
|
20
20
|
entities: [...DataStoreStatusListEntities],
|
|
21
|
+
logger: 'advanced-console',
|
|
22
|
+
logging: ['query', 'error', 'schema', 'warn', 'info', 'log', 'migration'],
|
|
21
23
|
}).initialize()
|
|
22
24
|
await dbConnection.runMigrations()
|
|
23
25
|
expect(await dbConnection.showMigrations()).toBeFalsy()
|
|
@@ -214,4 +216,59 @@ describe('Status list entities tests', () => {
|
|
|
214
216
|
})
|
|
215
217
|
expect(foundEntry).toBeNull()
|
|
216
218
|
})
|
|
219
|
+
|
|
220
|
+
it('should save bitstring status list to database', async () => {
|
|
221
|
+
const statusList = new BitstringStatusListEntity()
|
|
222
|
+
statusList.id = 'bitstring-list-1'
|
|
223
|
+
statusList.correlationId = 'correlation-bitstring-1'
|
|
224
|
+
statusList.driverType = StatusListDriverType.AGENT_TYPEORM
|
|
225
|
+
statusList.length = 131072
|
|
226
|
+
statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
|
|
227
|
+
statusList.proofFormat = 'lds'
|
|
228
|
+
statusList.statusPurpose = 'revocation'
|
|
229
|
+
statusList.bitsPerStatus = 1
|
|
230
|
+
statusList.ttl = 3600000
|
|
231
|
+
statusList.validFrom = new Date('2024-01-01T00:00:00Z')
|
|
232
|
+
statusList.validUntil = new Date('2025-01-01T00:00:00Z')
|
|
233
|
+
statusList.issuer = 'did:example:789'
|
|
234
|
+
|
|
235
|
+
const fromDb = await dbConnection.getRepository(BitstringStatusListEntity).save(statusList)
|
|
236
|
+
expect(fromDb).toBeDefined()
|
|
237
|
+
expect(fromDb.id).toEqual(statusList.id)
|
|
238
|
+
expect(fromDb.statusPurpose).toEqual(statusList.statusPurpose)
|
|
239
|
+
expect(fromDb.bitsPerStatus).toEqual(statusList.bitsPerStatus)
|
|
240
|
+
expect(fromDb.ttl).toEqual(statusList.ttl)
|
|
241
|
+
expect(fromDb.validFrom).toEqual(statusList.validFrom)
|
|
242
|
+
expect(fromDb.validUntil).toEqual(statusList.validUntil)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('should save bitstring status list entry to database', async () => {
|
|
246
|
+
const statusList = new BitstringStatusListEntity()
|
|
247
|
+
statusList.id = 'bitstring-list-1'
|
|
248
|
+
statusList.correlationId = 'correlation-bitstring-1'
|
|
249
|
+
statusList.driverType = StatusListDriverType.AGENT_TYPEORM
|
|
250
|
+
statusList.length = 131072
|
|
251
|
+
statusList.credentialIdMode = StatusListCredentialIdMode.ISSUANCE
|
|
252
|
+
statusList.proofFormat = 'lds'
|
|
253
|
+
statusList.statusPurpose = 'revocation'
|
|
254
|
+
statusList.issuer = 'did:example:789'
|
|
255
|
+
|
|
256
|
+
await dbConnection.getRepository(BitstringStatusListEntity).save(statusList)
|
|
257
|
+
|
|
258
|
+
const entry = new BitstringStatusListEntryEntity()
|
|
259
|
+
entry.statusList = statusList
|
|
260
|
+
entry.statusListIndex = 42
|
|
261
|
+
entry.credentialId = 'bitstring-credential-1'
|
|
262
|
+
entry.credentialHash = 'bitstring-hash-1'
|
|
263
|
+
entry.statusPurpose = 'revocation'
|
|
264
|
+
entry.bitsPerStatus = 1
|
|
265
|
+
entry.statusReference = 'https://example.org/status-ref'
|
|
266
|
+
|
|
267
|
+
const fromDb = await dbConnection.getRepository(BitstringStatusListEntryEntity).save(entry)
|
|
268
|
+
expect(fromDb).toBeDefined()
|
|
269
|
+
expect(fromDb.statusListIndex).toEqual(entry.statusListIndex)
|
|
270
|
+
expect(fromDb.statusPurpose).toEqual(entry.statusPurpose)
|
|
271
|
+
expect(fromDb.bitsPerStatus).toEqual(entry.bitsPerStatus)
|
|
272
|
+
expect(fromDb.statusReference).toEqual(entry.statusReference)
|
|
273
|
+
})
|
|
217
274
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource } from 'typeorm'
|
|
2
2
|
import { DataSources } from '@sphereon/ssi-sdk.agent-config'
|
|
3
|
-
import { DataStoreStatusListEntities } from '../index'
|
|
3
|
+
import { DataStoreStatusListEntities, IBitstringStatusListEntity } from '../index'
|
|
4
4
|
import { DataStoreStatusListMigrations } from '../migrations'
|
|
5
5
|
import { StatusListStore } from '../statusList/StatusListStore'
|
|
6
6
|
import { IOAuthStatusListEntity, IStatusList2021Entity, IStatusListEntryEntity } from '../types'
|
|
@@ -230,4 +230,67 @@ describe('Status list store tests', () => {
|
|
|
230
230
|
|
|
231
231
|
await expect(statusListStore.getStatusList({ id: statusList.id })).rejects.toThrow(`No status list found for id ${statusList.id}`)
|
|
232
232
|
})
|
|
233
|
+
|
|
234
|
+
it('should store bitstring status list', async () => {
|
|
235
|
+
const statusList: IBitstringStatusListEntity = {
|
|
236
|
+
id: 'bitstring-list-1',
|
|
237
|
+
correlationId: 'correlation-bitstring-1',
|
|
238
|
+
driverType: StatusListDriverType.AGENT_TYPEORM,
|
|
239
|
+
length: 131072,
|
|
240
|
+
credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
|
|
241
|
+
type: StatusListType.BitstringStatusList,
|
|
242
|
+
proofFormat: 'lds',
|
|
243
|
+
statusPurpose: 'revocation',
|
|
244
|
+
bitsPerStatus: 1,
|
|
245
|
+
ttl: 3600000,
|
|
246
|
+
validFrom: new Date('2024-01-01T00:00:00Z'),
|
|
247
|
+
validUntil: new Date('2025-01-01T00:00:00Z'),
|
|
248
|
+
issuer: 'did:example:789',
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const result = await statusListStore.addStatusList(statusList)
|
|
252
|
+
expect(result).toBeDefined()
|
|
253
|
+
expect(result.id).toEqual(statusList.id)
|
|
254
|
+
expect((result as IBitstringStatusListEntity).statusPurpose).toEqual(statusList.statusPurpose)
|
|
255
|
+
expect((result as IBitstringStatusListEntity).ttl).toEqual(statusList.ttl)
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
it('should store and retrieve all three types of status lists', async () => {
|
|
259
|
+
const statusList2021: IStatusList2021Entity = {
|
|
260
|
+
id: 'test-list-1',
|
|
261
|
+
correlationId: 'correlation-1',
|
|
262
|
+
driverType: StatusListDriverType.AGENT_TYPEORM,
|
|
263
|
+
length: 100000,
|
|
264
|
+
credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
|
|
265
|
+
type: StatusListType.StatusList2021,
|
|
266
|
+
proofFormat: 'jwt',
|
|
267
|
+
statusPurpose: 'revocation',
|
|
268
|
+
indexingDirection: 'rightToLeft',
|
|
269
|
+
issuer: 'did:example:123',
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const bitstringStatusList: IBitstringStatusListEntity = {
|
|
273
|
+
id: 'bitstring-list-1',
|
|
274
|
+
correlationId: 'correlation-bitstring-1',
|
|
275
|
+
driverType: StatusListDriverType.AGENT_TYPEORM,
|
|
276
|
+
length: 131072,
|
|
277
|
+
credentialIdMode: StatusListCredentialIdMode.ISSUANCE,
|
|
278
|
+
type: StatusListType.BitstringStatusList,
|
|
279
|
+
proofFormat: 'lds',
|
|
280
|
+
bitsPerStatus: 1,
|
|
281
|
+
statusPurpose: 'suspension',
|
|
282
|
+
ttl: 3600000,
|
|
283
|
+
issuer: 'did:example:789',
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
await statusListStore.addStatusList(statusList2021)
|
|
287
|
+
await statusListStore.addStatusList(bitstringStatusList)
|
|
288
|
+
|
|
289
|
+
const found2021 = await statusListStore.getStatusList({ id: statusList2021.id })
|
|
290
|
+
const foundBitstring = await statusListStore.getStatusList({ id: bitstringStatusList.id })
|
|
291
|
+
|
|
292
|
+
expect(found2021.type).toEqual(StatusListType.StatusList2021)
|
|
293
|
+
expect(foundBitstring.type).toEqual(StatusListType.BitstringStatusList)
|
|
294
|
+
expect((foundBitstring as IBitstringStatusListEntity).statusPurpose).toEqual('suspension')
|
|
295
|
+
})
|
|
233
296
|
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ChildEntity, Column } from 'typeorm'
|
|
2
|
+
import { StatusListEntryEntity } from './StatusList2021EntryEntity'
|
|
3
|
+
import { BitstringStatusMessage } from '../../types'
|
|
4
|
+
|
|
5
|
+
@ChildEntity('bitstring')
|
|
6
|
+
export class BitstringStatusListEntryEntity extends StatusListEntryEntity {
|
|
7
|
+
@Column({ type: 'varchar', name: 'statusPurpose', nullable: false })
|
|
8
|
+
statusPurpose!: string
|
|
9
|
+
|
|
10
|
+
@Column({ type: 'integer', name: 'bitsPerStatus', nullable: true, default: 1 })
|
|
11
|
+
bitsPerStatus?: number
|
|
12
|
+
|
|
13
|
+
@Column({
|
|
14
|
+
type: 'text',
|
|
15
|
+
name: 'statusMessage',
|
|
16
|
+
nullable: true,
|
|
17
|
+
transformer: {
|
|
18
|
+
from(value: string): Array<BitstringStatusMessage> | undefined {
|
|
19
|
+
if (!value) {
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
return JSON.parse(value)
|
|
23
|
+
},
|
|
24
|
+
to(value: Array<BitstringStatusMessage> | undefined): string | undefined {
|
|
25
|
+
if (!value) {
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
return JSON.stringify(value)
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
statusMessage?: Array<BitstringStatusMessage>
|
|
33
|
+
|
|
34
|
+
@Column({
|
|
35
|
+
type: 'text',
|
|
36
|
+
name: 'statusReference',
|
|
37
|
+
nullable: true,
|
|
38
|
+
transformer: {
|
|
39
|
+
from(value: string): string | string[] | undefined {
|
|
40
|
+
if (!value) {
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
if (value.startsWith('[')) {
|
|
44
|
+
return JSON.parse(value)
|
|
45
|
+
}
|
|
46
|
+
return value
|
|
47
|
+
},
|
|
48
|
+
to(value: string | string[] | undefined): string | undefined {
|
|
49
|
+
if (!value) {
|
|
50
|
+
return undefined
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(value)) {
|
|
53
|
+
return JSON.stringify(value)
|
|
54
|
+
}
|
|
55
|
+
return value
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
statusReference?: string | string[]
|
|
60
|
+
}
|
|
@@ -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
|
-
import { StatusListEntity } from './StatusListEntities'
|
|
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' })
|
|
@@ -15,7 +16,7 @@ export class StatusListEntryEntity extends BaseEntity {
|
|
|
15
16
|
@Validate(IsNonEmptyStringConstraint, { message: 'Status list index is required' })
|
|
16
17
|
statusListIndex!: number
|
|
17
18
|
|
|
18
|
-
@ManyToOne(() =>
|
|
19
|
+
@ManyToOne(() => StatusList2021Entity, (statusList) => statusList.statusListEntries)
|
|
19
20
|
@JoinColumn({ name: 'statusListId' })
|
|
20
21
|
statusList!: StatusListEntity
|
|
21
22
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type CredentialProofFormat,
|
|
2
3
|
type IIssuer,
|
|
3
4
|
type StatusListCredential,
|
|
4
5
|
StatusListCredentialIdMode,
|
|
@@ -6,12 +7,14 @@ import {
|
|
|
6
7
|
type StatusListIndexingDirection,
|
|
7
8
|
StatusListType,
|
|
8
9
|
type StatusPurpose2021,
|
|
9
|
-
type CredentialProofFormat,
|
|
10
10
|
} from '@sphereon/ssi-types'
|
|
11
|
+
|
|
11
12
|
import typeorm from 'typeorm'
|
|
12
|
-
const { BaseEntity, ChildEntity, Column, Entity, OneToMany, PrimaryColumn, TableInheritance, Unique } = typeorm
|
|
13
13
|
import { StatusListEntryEntity } from './StatusList2021EntryEntity'
|
|
14
14
|
import { typeOrmDateTime } from '@sphereon/ssi-sdk.agent-config'
|
|
15
|
+
import { BitstringStatusListEntryEntity } from './BitstringStatusListEntryEntity'
|
|
16
|
+
|
|
17
|
+
const { BaseEntity, ChildEntity, Column, Entity, OneToMany, PrimaryColumn, TableInheritance, Unique } = typeorm
|
|
15
18
|
|
|
16
19
|
@Entity('StatusList')
|
|
17
20
|
@Unique('UQ_correlationId', ['correlationId'])
|
|
@@ -26,6 +29,13 @@ export abstract class StatusListEntity extends BaseEntity {
|
|
|
26
29
|
@Column({ name: 'length', type: 'integer', nullable: false, unique: false })
|
|
27
30
|
length!: number
|
|
28
31
|
|
|
32
|
+
@Column('simple-enum', {
|
|
33
|
+
name: 'type',
|
|
34
|
+
enum: StatusListType,
|
|
35
|
+
nullable: false,
|
|
36
|
+
})
|
|
37
|
+
type!: StatusListType
|
|
38
|
+
|
|
29
39
|
@Column({
|
|
30
40
|
name: 'issuer',
|
|
31
41
|
type: 'text',
|
|
@@ -88,9 +98,6 @@ export abstract class StatusListEntity extends BaseEntity {
|
|
|
88
98
|
},
|
|
89
99
|
})
|
|
90
100
|
statusListCredential?: StatusListCredential
|
|
91
|
-
|
|
92
|
-
@OneToMany((type) => StatusListEntryEntity, (entry) => entry.statusList)
|
|
93
|
-
statusListEntries!: StatusListEntryEntity[]
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
@ChildEntity(StatusListType.StatusList2021)
|
|
@@ -106,6 +113,9 @@ export class StatusList2021Entity extends StatusListEntity {
|
|
|
106
113
|
|
|
107
114
|
@Column({ type: 'varchar', name: 'statusPurpose', nullable: false, default: 'revocation' })
|
|
108
115
|
statusPurpose!: StatusPurpose2021
|
|
116
|
+
|
|
117
|
+
@OneToMany((type) => StatusListEntryEntity, (entry) => entry.statusList)
|
|
118
|
+
statusListEntries!: StatusListEntryEntity[]
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
@ChildEntity(StatusListType.OAuthStatusList)
|
|
@@ -115,3 +125,42 @@ export class OAuthStatusListEntity extends StatusListEntity {
|
|
|
115
125
|
@Column({ name: 'expiresAt', nullable: true, type: typeOrmDateTime() })
|
|
116
126
|
expiresAt?: Date
|
|
117
127
|
}
|
|
128
|
+
|
|
129
|
+
@ChildEntity(StatusListType.BitstringStatusList)
|
|
130
|
+
export class BitstringStatusListEntity extends StatusListEntity {
|
|
131
|
+
@Column({
|
|
132
|
+
type: 'varchar',
|
|
133
|
+
name: 'statusPurpose',
|
|
134
|
+
nullable: false,
|
|
135
|
+
transformer: {
|
|
136
|
+
from(value: string): string | string[] {
|
|
137
|
+
if (value?.includes(',')) {
|
|
138
|
+
return value.split(',').map((v) => v.trim() as string)
|
|
139
|
+
}
|
|
140
|
+
return value as string
|
|
141
|
+
},
|
|
142
|
+
to(value: string | string[]): string {
|
|
143
|
+
if (Array.isArray(value)) {
|
|
144
|
+
return value.join(',')
|
|
145
|
+
}
|
|
146
|
+
return value
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
})
|
|
150
|
+
statusPurpose!: string | string[]
|
|
151
|
+
|
|
152
|
+
@Column({ type: 'integer', name: 'bitsPerStatus', nullable: false })
|
|
153
|
+
bitsPerStatus?: number
|
|
154
|
+
|
|
155
|
+
@Column({ name: 'validFrom', nullable: true, type: typeOrmDateTime() })
|
|
156
|
+
validFrom?: Date
|
|
157
|
+
|
|
158
|
+
@Column({ name: 'validUntil', nullable: true, type: typeOrmDateTime() })
|
|
159
|
+
validUntil?: Date
|
|
160
|
+
|
|
161
|
+
@Column({ type: 'integer', name: 'ttl', nullable: true })
|
|
162
|
+
ttl?: number
|
|
163
|
+
|
|
164
|
+
@OneToMany((type) => BitstringStatusListEntryEntity, (entry) => entry.statusList)
|
|
165
|
+
statusListEntries!: BitstringStatusListEntryEntity[]
|
|
166
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -16,8 +16,9 @@ import { ImageDimensionsEntity } from './entities/issuanceBranding/ImageDimensio
|
|
|
16
16
|
import { IssuerLocaleBrandingEntity } from './entities/issuanceBranding/IssuerLocaleBrandingEntity'
|
|
17
17
|
import { IssuerBrandingEntity } from './entities/issuanceBranding/IssuerBrandingEntity'
|
|
18
18
|
import { TextAttributesEntity } from './entities/issuanceBranding/TextAttributesEntity'
|
|
19
|
-
import { OAuthStatusListEntity, StatusList2021Entity, StatusListEntity } from './entities/statusList/StatusListEntities'
|
|
19
|
+
import { BitstringStatusListEntity, OAuthStatusListEntity, StatusList2021Entity, StatusListEntity } from './entities/statusList/StatusListEntities'
|
|
20
20
|
import { StatusListEntryEntity } from './entities/statusList/StatusList2021EntryEntity'
|
|
21
|
+
import { BitstringStatusListEntryEntity } from './entities/statusList/BitstringStatusListEntryEntity'
|
|
21
22
|
import { MachineStateInfoEntity } from './entities/machineState/MachineStateInfoEntity'
|
|
22
23
|
// import { IStatusListEntity, IStatusListEntryEntity } from './types.'
|
|
23
24
|
import { PartyRelationshipEntity } from './entities/contact/PartyRelationshipEntity'
|
|
@@ -100,7 +101,14 @@ export const DataStoreIssuanceBrandingEntities = [
|
|
|
100
101
|
|
|
101
102
|
export const DataStorePresentationDefinitionEntities = [PresentationDefinitionItemEntity]
|
|
102
103
|
|
|
103
|
-
export const DataStoreStatusListEntities = [
|
|
104
|
+
export const DataStoreStatusListEntities = [
|
|
105
|
+
StatusListEntity,
|
|
106
|
+
StatusList2021Entity,
|
|
107
|
+
OAuthStatusListEntity,
|
|
108
|
+
BitstringStatusListEntity,
|
|
109
|
+
BitstringStatusListEntryEntity,
|
|
110
|
+
StatusListEntryEntity,
|
|
111
|
+
]
|
|
104
112
|
|
|
105
113
|
export const DataStoreEventLoggerEntities = [AuditEventEntity]
|
|
106
114
|
|
|
@@ -143,8 +151,10 @@ export {
|
|
|
143
151
|
PhysicalAddressEntity,
|
|
144
152
|
StatusListEntity,
|
|
145
153
|
StatusListEntryEntity,
|
|
154
|
+
BitstringStatusListEntryEntity,
|
|
146
155
|
OAuthStatusListEntity,
|
|
147
156
|
StatusList2021Entity,
|
|
157
|
+
BitstringStatusListEntity,
|
|
148
158
|
AuditEventEntity,
|
|
149
159
|
DigitalCredentialEntity,
|
|
150
160
|
MachineStateInfoEntity,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
import Debug from 'debug'
|
|
3
|
+
import { CreateBitstringStatusListPG1741895823000 } from '../postgres/1741895823000-CreateBitstringStatusList'
|
|
4
|
+
import { CreateBitstringStatusListSqlite1741895823001 } from '../sqlite/1741895823001-CreateBitstringStatusList'
|
|
5
|
+
|
|
6
|
+
const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations')
|
|
7
|
+
|
|
8
|
+
export class CreateBitstringStatusList1741895823000 implements MigrationInterface {
|
|
9
|
+
name = 'CreateBitstringStatusList1741895823000'
|
|
10
|
+
|
|
11
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
12
|
+
debug('migration: creating bitstring status list tables')
|
|
13
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
14
|
+
switch (dbType) {
|
|
15
|
+
case 'postgres': {
|
|
16
|
+
const mig = new CreateBitstringStatusListPG1741895823000()
|
|
17
|
+
await mig.up(queryRunner)
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
case 'sqlite':
|
|
21
|
+
case 'expo':
|
|
22
|
+
case 'react-native': {
|
|
23
|
+
const mig = new CreateBitstringStatusListSqlite1741895823001()
|
|
24
|
+
await mig.up(queryRunner)
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
default:
|
|
28
|
+
return Promise.reject(`Migrations only supported for sqlite and postgres. Was ${dbType}`)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
33
|
+
debug('migration: dropping bitstring status list tables')
|
|
34
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
35
|
+
switch (dbType) {
|
|
36
|
+
case 'postgres': {
|
|
37
|
+
const mig = new CreateBitstringStatusListPG1741895823000()
|
|
38
|
+
await mig.down(queryRunner)
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
case 'sqlite':
|
|
42
|
+
case 'expo':
|
|
43
|
+
case 'react-native': {
|
|
44
|
+
const mig = new CreateBitstringStatusListSqlite1741895823001()
|
|
45
|
+
await mig.down(queryRunner)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
return Promise.reject(`Migrations only supported for sqlite and postgres. Was ${dbType}`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -9,6 +9,7 @@ import { CreateContacts1708525189000 } from './8-CreateContacts'
|
|
|
9
9
|
import { CreateContacts1715761125000 } from './9-CreateContacts'
|
|
10
10
|
import { CreatePresentationDefinitions1716533767523 } from './10-CreatePresentationDefinitions'
|
|
11
11
|
import { FixCredentialClaimsReferencesUuid1741895822987 } from './11-FixCredentialClaimsReferenceUuid'
|
|
12
|
+
import { CreateBitstringStatusList1741895823000 } from './12-CreateBitstringStatusList'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* The migrations array that SHOULD be used when initializing a TypeORM database connection.
|
|
@@ -26,7 +27,7 @@ export const DataStoreContactMigrations = [
|
|
|
26
27
|
CreateContacts1715761125000,
|
|
27
28
|
]
|
|
28
29
|
export const DataStoreIssuanceBrandingMigrations = [CreateIssuanceBranding1659463079429, FixCredentialClaimsReferencesUuid1741895822987]
|
|
29
|
-
export const DataStoreStatusListMigrations = [CreateStatusList1693866470000]
|
|
30
|
+
export const DataStoreStatusListMigrations = [CreateStatusList1693866470000, CreateBitstringStatusList1741895823000]
|
|
30
31
|
export const DataStoreEventLoggerMigrations = [CreateAuditEvents1701635835330]
|
|
31
32
|
export const DataStoreDigitalCredentialMigrations = [CreateDigitalCredential1708525189000]
|
|
32
33
|
export const DataStoreMachineStateMigrations = [CreateMachineStateStore1708098041262]
|
|
@@ -10,7 +10,7 @@ export class UpdateStatusList1737110469001 implements MigrationInterface {
|
|
|
10
10
|
// Make columns nullable and add new columns
|
|
11
11
|
await queryRunner.query(`ALTER TABLE "StatusList" ALTER COLUMN "indexingDirection" DROP NOT NULL`)
|
|
12
12
|
await queryRunner.query(`ALTER TABLE "StatusList" ALTER COLUMN "statusPurpose" DROP NOT NULL`)
|
|
13
|
-
await queryRunner.query(`ALTER TABLE "StatusList" ADD "bitsPerStatus" integer`)
|
|
13
|
+
await queryRunner.query(`ALTER TABLE "StatusList" ADD "bitsPerStatus" integer DEFAULT 1`)
|
|
14
14
|
await queryRunner.query(`ALTER TABLE "StatusList" ADD "expiresAt" timestamp with time zone`)
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class CreateBitstringStatusListPG1741895823000 implements MigrationInterface {
|
|
4
|
+
name = 'CreateBitstringStatusList1741895823000'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.startTransaction()
|
|
8
|
+
await queryRunner.query(`ALTER TYPE "StatusList_type_enum" ADD VALUE 'BitstringStatusList'`)
|
|
9
|
+
await queryRunner.commitTransaction()
|
|
10
|
+
|
|
11
|
+
// Add BitstringStatusList columns to StatusList table
|
|
12
|
+
await queryRunner.query(`ALTER TABLE "StatusList" ADD COLUMN "ttl" integer`)
|
|
13
|
+
await queryRunner.query(`ALTER TABLE "StatusList" ADD COLUMN "validFrom" TIMESTAMP`)
|
|
14
|
+
await queryRunner.query(`ALTER TABLE "StatusList" ADD COLUMN "validUntil" TIMESTAMP`)
|
|
15
|
+
|
|
16
|
+
// Update type enum constraint to include BitstringStatusList
|
|
17
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP CONSTRAINT IF EXISTS "CHK_StatusList_type"`)
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`ALTER TABLE "StatusList" ADD CONSTRAINT "CHK_StatusList_type" CHECK ("type" IN ('StatusList2021', 'OAuthStatusList', 'BitstringStatusList'))`,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
// Add inheritance discriminator column to StatusListEntry table
|
|
23
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "type" character varying NOT NULL DEFAULT 'StatusListEntryEntity'`)
|
|
24
|
+
|
|
25
|
+
// Add BitstringStatusListEntry specific columns to StatusListEntry table
|
|
26
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusPurpose" character varying`)
|
|
27
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusMessage" text`)
|
|
28
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" ADD COLUMN "statusReference" text`)
|
|
29
|
+
|
|
30
|
+
// Add constraint for entry type
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "StatusListEntry" ADD CONSTRAINT "CHK_StatusListEntry_type" CHECK ("type" IN ('StatusListEntryEntity', 'bitstring'))`,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
37
|
+
// Remove entry type constraint and columns
|
|
38
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP CONSTRAINT "CHK_StatusListEntry_type"`)
|
|
39
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusReference"`)
|
|
40
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusMessage"`)
|
|
41
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "bitsPerStatus"`)
|
|
42
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "statusPurpose"`)
|
|
43
|
+
await queryRunner.query(`ALTER TABLE "StatusListEntry" DROP COLUMN "type"`)
|
|
44
|
+
|
|
45
|
+
// Revert StatusList type constraint
|
|
46
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP CONSTRAINT "CHK_StatusList_type"`)
|
|
47
|
+
await queryRunner.query(`ALTER TABLE "StatusList" ADD CONSTRAINT "CHK_StatusList_type" CHECK ("type" IN ('StatusList2021', 'OAuthStatusList'))`)
|
|
48
|
+
|
|
49
|
+
// Remove BitstringStatusList columns from StatusList table
|
|
50
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "validUntil"`)
|
|
51
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "validFrom"`)
|
|
52
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "ttl"`)
|
|
53
|
+
await queryRunner.query(`ALTER TABLE "StatusList" DROP COLUMN "bitsPerStatus"`)
|
|
54
|
+
}
|
|
55
|
+
}
|