@sphereon/ssi-sdk.data-store 0.19.1-next.2 → 0.19.1-unstable.63
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/digitalCredential/AbstractDigitalCredentialStore.d.ts +10 -0
- package/dist/digitalCredential/AbstractDigitalCredentialStore.d.ts.map +1 -0
- package/dist/digitalCredential/AbstractDigitalCredentialStore.js +7 -0
- package/dist/digitalCredential/AbstractDigitalCredentialStore.js.map +1 -0
- package/dist/digitalCredential/DigitalCredentialStore.d.ts +15 -0
- package/dist/digitalCredential/DigitalCredentialStore.d.ts.map +1 -0
- package/dist/digitalCredential/DigitalCredentialStore.js +118 -0
- package/dist/digitalCredential/DigitalCredentialStore.js.map +1 -0
- package/dist/entities/digitalCredential/DigitalCredentialEntity.d.ts +23 -0
- package/dist/entities/digitalCredential/DigitalCredentialEntity.d.ts.map +1 -0
- package/dist/entities/digitalCredential/DigitalCredentialEntity.js +93 -0
- package/dist/entities/digitalCredential/DigitalCredentialEntity.js.map +1 -0
- package/dist/entities/xstate/StateEntity.d.ts +14 -0
- package/dist/entities/xstate/StateEntity.d.ts.map +1 -0
- package/dist/entities/xstate/StateEntity.js +60 -0
- package/dist/entities/xstate/StateEntity.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations/generic/6-CreateDigitalCredential.d.ts +7 -0
- package/dist/migrations/generic/6-CreateDigitalCredential.d.ts.map +1 -0
- package/dist/migrations/generic/6-CreateDigitalCredential.js +78 -0
- package/dist/migrations/generic/6-CreateDigitalCredential.js.map +1 -0
- package/dist/migrations/generic/7-CreateXStateStore.d.ts +7 -0
- package/dist/migrations/generic/7-CreateXStateStore.d.ts.map +1 -0
- package/dist/migrations/generic/7-CreateXStateStore.js +78 -0
- package/dist/migrations/generic/7-CreateXStateStore.js.map +1 -0
- package/dist/migrations/generic/index.d.ts +4 -0
- package/dist/migrations/generic/index.d.ts.map +1 -1
- package/dist/migrations/generic/index.js +7 -1
- package/dist/migrations/generic/index.js.map +1 -1
- package/dist/migrations/index.d.ts +1 -1
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +3 -1
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.d.ts +7 -0
- package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.d.ts.map +1 -0
- package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.js +59 -0
- package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.js.map +1 -0
- package/dist/migrations/postgres/1708797018115-CreateXStateStore.d.ts +7 -0
- package/dist/migrations/postgres/1708797018115-CreateXStateStore.d.ts.map +1 -0
- package/dist/migrations/postgres/1708797018115-CreateXStateStore.js +45 -0
- package/dist/migrations/postgres/1708797018115-CreateXStateStore.js.map +1 -0
- package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.d.ts +7 -0
- package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.d.ts.map +1 -0
- package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.js +50 -0
- package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.js.map +1 -0
- package/dist/migrations/sqlite/1708796002272-CreateXStateStore.d.ts +7 -0
- package/dist/migrations/sqlite/1708796002272-CreateXStateStore.d.ts.map +1 -0
- package/dist/migrations/sqlite/1708796002272-CreateXStateStore.js +42 -0
- package/dist/migrations/sqlite/1708796002272-CreateXStateStore.js.map +1 -0
- package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.d.ts +42 -0
- package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.d.ts.map +1 -0
- package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.js +3 -0
- package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.js.map +1 -0
- package/dist/types/digitalCredential/digitalCredential.d.ts +42 -0
- package/dist/types/digitalCredential/digitalCredential.d.ts.map +1 -0
- package/dist/types/digitalCredential/digitalCredential.js +28 -0
- package/dist/types/digitalCredential/digitalCredential.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/xstate/IAbstractXStateStore.d.ts +38 -0
- package/dist/types/xstate/IAbstractXStateStore.d.ts.map +1 -0
- package/dist/types/xstate/IAbstractXStateStore.js +3 -0
- package/dist/types/xstate/IAbstractXStateStore.js.map +1 -0
- package/dist/utils/SortingUtils.d.ts +3 -0
- package/dist/utils/SortingUtils.d.ts.map +1 -0
- package/dist/utils/SortingUtils.js +18 -0
- package/dist/utils/SortingUtils.js.map +1 -0
- package/dist/utils/digitalCredential/MappingUtils.d.ts +7 -0
- package/dist/utils/digitalCredential/MappingUtils.d.ts.map +1 -0
- package/dist/utils/digitalCredential/MappingUtils.js +99 -0
- package/dist/utils/digitalCredential/MappingUtils.js.map +1 -0
- package/dist/xstate/IAbstractXStateStore.d.ts +9 -0
- package/dist/xstate/IAbstractXStateStore.d.ts.map +1 -0
- package/dist/xstate/IAbstractXStateStore.js +7 -0
- package/dist/xstate/IAbstractXStateStore.js.map +1 -0
- package/dist/xstate/XStateStore.d.ts +17 -0
- package/dist/xstate/XStateStore.d.ts.map +1 -0
- package/dist/xstate/XStateStore.js +110 -0
- package/dist/xstate/XStateStore.js.map +1 -0
- package/package.json +5 -4
- package/src/__tests__/digitalCredential.entities.test.ts +254 -0
- package/src/__tests__/digitalCredential.store.test.ts +294 -0
- package/src/__tests__/xstate.entities.test.ts +47 -0
- package/src/__tests__/xstate.store.test.ts +158 -0
- package/src/digitalCredential/AbstractDigitalCredentialStore.ts +17 -0
- package/src/digitalCredential/DigitalCredentialStore.ts +127 -0
- package/src/entities/digitalCredential/DigitalCredentialEntity.ts +64 -0
- package/src/entities/xstate/StateEntity.ts +34 -0
- package/src/index.ts +18 -0
- package/src/migrations/generic/6-CreateDigitalCredential.ts +66 -0
- package/src/migrations/generic/7-CreateXStateStore.ts +66 -0
- package/src/migrations/generic/index.ts +6 -0
- package/src/migrations/index.ts +2 -0
- package/src/migrations/postgres/1708525189001-CreateDigitalCredential.ts +44 -0
- package/src/migrations/postgres/1708797018115-CreateXStateStore.ts +29 -0
- package/src/migrations/sqlite/1708525189002-CreateDigitalCredential.ts +34 -0
- package/src/migrations/sqlite/1708796002272-CreateXStateStore.ts +26 -0
- package/src/types/digitalCredential/IAbstractDigitalCredentialStore.ts +37 -0
- package/src/types/digitalCredential/digitalCredential.ts +46 -0
- package/src/types/index.ts +1 -0
- package/src/types/xstate/IAbstractXStateStore.ts +39 -0
- package/src/utils/SortingUtils.ts +16 -0
- package/src/utils/digitalCredential/MappingUtils.ts +122 -0
- package/src/xstate/IAbstractXStateStore.ts +9 -0
- package/src/xstate/XStateStore.ts +107 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { DataSource } from 'typeorm'
|
|
2
|
+
import {
|
|
3
|
+
DataStoreXStateStoreEntities,
|
|
4
|
+
GetActiveStateArgs,
|
|
5
|
+
NonPersistedXStateStoreEvent,
|
|
6
|
+
SaveStateArgs,
|
|
7
|
+
State,
|
|
8
|
+
XStateStore,
|
|
9
|
+
} from '../index'
|
|
10
|
+
import { DataStoreXStateStoreMigrations } from '../migrations'
|
|
11
|
+
|
|
12
|
+
describe('Database entities tests', (): void => {
|
|
13
|
+
let dbConnection: DataSource
|
|
14
|
+
let xstateStore: XStateStore
|
|
15
|
+
|
|
16
|
+
beforeEach(async (): Promise<void> => {
|
|
17
|
+
dbConnection = await new DataSource({
|
|
18
|
+
type: 'sqlite',
|
|
19
|
+
database: ':memory:',
|
|
20
|
+
logging: 'all',
|
|
21
|
+
migrationsRun: false,
|
|
22
|
+
migrations: DataStoreXStateStoreMigrations,
|
|
23
|
+
synchronize: false,
|
|
24
|
+
entities: DataStoreXStateStoreEntities,
|
|
25
|
+
}).initialize()
|
|
26
|
+
await dbConnection.runMigrations()
|
|
27
|
+
expect(await dbConnection.showMigrations()).toBeFalsy()
|
|
28
|
+
xstateStore = new XStateStore(dbConnection)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
afterEach(async (): Promise<void> => {
|
|
32
|
+
await dbConnection.destroy()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('should store xstate event', async (): Promise<void> => {
|
|
36
|
+
const xstateEvent: NonPersistedXStateStoreEvent = {
|
|
37
|
+
stateName: 'enterPersonalDetails',
|
|
38
|
+
machineType: 'Onboarding',
|
|
39
|
+
xStateEventType: 'SET_PERSONAL_DATA',
|
|
40
|
+
state: 'test_state',
|
|
41
|
+
expiresAt: new Date(new Date().getDate() + 100000),
|
|
42
|
+
tenantId: 'test_tenant_id',
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const savedXStoreEvent: State = await xstateStore.saveState(xstateEvent)
|
|
46
|
+
expect(savedXStoreEvent).toBeDefined()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should get all state events', async (): Promise<void> => {
|
|
50
|
+
const xstateEvent: NonPersistedXStateStoreEvent = {
|
|
51
|
+
stateName: 'enterPersonalDetails',
|
|
52
|
+
machineType: 'Onboarding',
|
|
53
|
+
xStateEventType: 'SET_PERSONAL_DATA',
|
|
54
|
+
state: 'test_state',
|
|
55
|
+
expiresAt: new Date(new Date().getDate() + 100000),
|
|
56
|
+
tenantId: 'test_tenant_id',
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const stateEvent1: NonPersistedXStateStoreEvent = await xstateStore.saveState({ ...xstateEvent })
|
|
60
|
+
expect(stateEvent1).toBeDefined()
|
|
61
|
+
|
|
62
|
+
const stateEvent2: NonPersistedXStateStoreEvent = await xstateStore.saveState({ ...xstateEvent })
|
|
63
|
+
expect(stateEvent2).toBeDefined()
|
|
64
|
+
|
|
65
|
+
const result: Array<State> = await xstateStore.getStates()
|
|
66
|
+
expect(result).toHaveLength(2)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should retrieve an xstate event', async (): Promise<void> => {
|
|
70
|
+
const expiresAt = new Date()
|
|
71
|
+
expiresAt.setTime(expiresAt.getTime() + 100000)
|
|
72
|
+
const xstateEvent: SaveStateArgs = {
|
|
73
|
+
stateName: 'enterPersonalDetails',
|
|
74
|
+
machineType: 'Onboarding',
|
|
75
|
+
xStateEventType: 'SET_PERSONAL_DATA',
|
|
76
|
+
state: 'test_state',
|
|
77
|
+
expiresAt,
|
|
78
|
+
tenantId: 'test_tenant_id',
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const savedXStoreEvent1: State = await xstateStore.saveState(xstateEvent)
|
|
82
|
+
expect(savedXStoreEvent1).toBeDefined()
|
|
83
|
+
const result: State = await xstateStore.getActiveState({ machineType: xstateEvent.machineType, tenantId: xstateEvent.tenantId })
|
|
84
|
+
expect(result).toBeDefined()
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should delete an xstate event', async (): Promise<void> => {
|
|
88
|
+
const xstateEvent: NonPersistedXStateStoreEvent = {
|
|
89
|
+
stateName: 'enterPersonalDetails',
|
|
90
|
+
machineType: 'Onboarding',
|
|
91
|
+
xStateEventType: 'SET_PERSONAL_DATA',
|
|
92
|
+
state: 'test_state',
|
|
93
|
+
expiresAt: new Date(new Date().getDate() + 100000),
|
|
94
|
+
tenantId: 'test_tenant_id',
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const savedXStoreEvent: State = await xstateStore.saveState(xstateEvent)
|
|
98
|
+
expect(savedXStoreEvent).toBeDefined()
|
|
99
|
+
|
|
100
|
+
const result: boolean = await xstateStore.deleteState({ id: savedXStoreEvent.id })
|
|
101
|
+
expect(result).toBeTruthy()
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('should return an error if type filter does not match', async (): Promise<void> => {
|
|
105
|
+
const args: GetActiveStateArgs = {
|
|
106
|
+
machineType: 'unknown_machine',
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await expect(xstateStore.getActiveState(args)).rejects.toEqual(
|
|
110
|
+
Error('No active state found for machineType: unknown_machine, tenantId: undefined')
|
|
111
|
+
)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('should delete the expired records', async () => {
|
|
115
|
+
const futureExpiresAt = new Date()
|
|
116
|
+
futureExpiresAt.setTime(futureExpiresAt.getTime() + 100000) // Future expiration
|
|
117
|
+
|
|
118
|
+
const pastExpiresAt = new Date()
|
|
119
|
+
pastExpiresAt.setTime(pastExpiresAt.getTime() - 100000) // Past expiration, already expired
|
|
120
|
+
|
|
121
|
+
const oldestXstateEvent: SaveStateArgs = {
|
|
122
|
+
stateName: 'acceptAgreement',
|
|
123
|
+
machineType: 'Onboarding1',
|
|
124
|
+
xStateEventType: 'SET_TOC',
|
|
125
|
+
state: 'test_state',
|
|
126
|
+
expiresAt: futureExpiresAt,
|
|
127
|
+
tenantId: 'test_tenant_id',
|
|
128
|
+
}
|
|
129
|
+
const middleXstateEvent: SaveStateArgs = {
|
|
130
|
+
stateName: 'acceptAgreement',
|
|
131
|
+
machineType: 'Onboarding2',
|
|
132
|
+
xStateEventType: 'SET_POLICY2',
|
|
133
|
+
state: 'test_state',
|
|
134
|
+
expiresAt: futureExpiresAt,
|
|
135
|
+
tenantId: 'test_tenant_id',
|
|
136
|
+
}
|
|
137
|
+
const newestXstateEvent: SaveStateArgs = {
|
|
138
|
+
stateName: 'enterPersonalDetails',
|
|
139
|
+
machineType: 'Onboarding3',
|
|
140
|
+
xStateEventType: 'SET_PERSONAL_DATA',
|
|
141
|
+
state: 'test_state',
|
|
142
|
+
expiresAt: pastExpiresAt, // This event should be already expired
|
|
143
|
+
tenantId: 'test_tenant_id',
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
await xstateStore.saveState(oldestXstateEvent)
|
|
147
|
+
await xstateStore.saveState(middleXstateEvent)
|
|
148
|
+
await xstateStore.saveState(newestXstateEvent)
|
|
149
|
+
|
|
150
|
+
await xstateStore.deleteExpiredStates({})
|
|
151
|
+
|
|
152
|
+
await expect(xstateStore.getActiveState({ machineType: 'Onboarding1' })).resolves.toBeDefined()
|
|
153
|
+
await expect(xstateStore.getActiveState({ machineType: 'Onboarding2' })).resolves.toBeDefined()
|
|
154
|
+
await expect(xstateStore.getActiveState({ machineType: 'Onboarding3' })).rejects.toEqual(
|
|
155
|
+
Error('No active state found for machineType: Onboarding3, tenantId: undefined')
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AddCredentialArgs,
|
|
3
|
+
GetCredentialArgs,
|
|
4
|
+
GetCredentialsArgs,
|
|
5
|
+
GetCredentialsResponse,
|
|
6
|
+
RemoveCredentialArgs,
|
|
7
|
+
UpdateCredentialStateArgs,
|
|
8
|
+
} from '../types/digitalCredential/IAbstractDigitalCredentialStore'
|
|
9
|
+
import { DigitalCredentialEntity } from '../entities/digitalCredential/DigitalCredentialEntity'
|
|
10
|
+
|
|
11
|
+
export abstract class AbstractDigitalCredentialStore {
|
|
12
|
+
abstract getCredential(args: GetCredentialArgs): Promise<DigitalCredentialEntity>
|
|
13
|
+
abstract getCredentials(args?: GetCredentialsArgs): Promise<GetCredentialsResponse>
|
|
14
|
+
abstract addCredential(args: AddCredentialArgs): Promise<DigitalCredentialEntity>
|
|
15
|
+
abstract updateCredentialState(args: UpdateCredentialStateArgs): Promise<DigitalCredentialEntity>
|
|
16
|
+
abstract removeCredential(args: RemoveCredentialArgs): Promise<boolean>
|
|
17
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { AbstractDigitalCredentialStore } from './AbstractDigitalCredentialStore'
|
|
2
|
+
import {
|
|
3
|
+
AddCredentialArgs,
|
|
4
|
+
GetCredentialArgs,
|
|
5
|
+
GetCredentialsArgs,
|
|
6
|
+
GetCredentialsResponse,
|
|
7
|
+
RemoveCredentialArgs,
|
|
8
|
+
UpdateCredentialStateArgs,
|
|
9
|
+
} from '../types/digitalCredential/IAbstractDigitalCredentialStore'
|
|
10
|
+
import { OrPromise } from '@sphereon/ssi-types'
|
|
11
|
+
import { DataSource, FindOptionsOrder, Repository } from 'typeorm'
|
|
12
|
+
import Debug from 'debug'
|
|
13
|
+
import { DigitalCredentialEntity } from '../entities/digitalCredential/DigitalCredentialEntity'
|
|
14
|
+
import { nonPersistedDigitalCredentialEntityFromAddArgs } from '../utils/digitalCredential/MappingUtils'
|
|
15
|
+
import { FindOptionsWhere } from 'typeorm/find-options/FindOptionsWhere'
|
|
16
|
+
import { CredentialStateType, DigitalCredential, NonPersistedDigitalCredential } from '../types/digitalCredential/digitalCredential'
|
|
17
|
+
import { parseAndValidateOrderOptions } from '../utils/SortingUtils'
|
|
18
|
+
|
|
19
|
+
const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:credential-store')
|
|
20
|
+
|
|
21
|
+
export class DigitalCredentialStore extends AbstractDigitalCredentialStore {
|
|
22
|
+
private readonly dbConnection: OrPromise<DataSource>
|
|
23
|
+
|
|
24
|
+
constructor(dbConnection: OrPromise<DataSource>) {
|
|
25
|
+
super()
|
|
26
|
+
this.dbConnection = dbConnection
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addCredential = async (args: AddCredentialArgs): Promise<DigitalCredentialEntity> => {
|
|
30
|
+
debug('Adding credential', args)
|
|
31
|
+
const digitalCredentialEntityRepository: Repository<DigitalCredentialEntity> = (await this.dbConnection).getRepository(DigitalCredentialEntity)
|
|
32
|
+
const credentialEntity: NonPersistedDigitalCredential = nonPersistedDigitalCredentialEntityFromAddArgs(args)
|
|
33
|
+
const createdResult: DigitalCredentialEntity = await digitalCredentialEntityRepository.save(credentialEntity)
|
|
34
|
+
return Promise.resolve(createdResult)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getCredential = async (args: GetCredentialArgs): Promise<DigitalCredentialEntity> => {
|
|
38
|
+
const result: DigitalCredentialEntity | null = await (await this.dbConnection).getRepository(DigitalCredentialEntity).findOne({
|
|
39
|
+
where: args,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (!result) {
|
|
43
|
+
return Promise.reject(Error(`No credential found for arg: ${args.toString()}`))
|
|
44
|
+
}
|
|
45
|
+
return result
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getCredentials = async (args?: GetCredentialsArgs): Promise<GetCredentialsResponse> => {
|
|
49
|
+
const { filter = {}, offset, limit, order = 'id.asc' } = args ?? {}
|
|
50
|
+
const sortOptions: FindOptionsOrder<DigitalCredentialEntity> =
|
|
51
|
+
order && typeof order === 'string'
|
|
52
|
+
? parseAndValidateOrderOptions<DigitalCredentialEntity>(order)
|
|
53
|
+
: <FindOptionsOrder<DigitalCredentialEntity>>order
|
|
54
|
+
const [result, total] = await (await this.dbConnection).getRepository(DigitalCredentialEntity).findAndCount({
|
|
55
|
+
where: filter,
|
|
56
|
+
skip: offset,
|
|
57
|
+
take: limit,
|
|
58
|
+
order: sortOptions,
|
|
59
|
+
})
|
|
60
|
+
return {
|
|
61
|
+
data: result,
|
|
62
|
+
total,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
removeCredential = async (args: RemoveCredentialArgs): Promise<boolean> => {
|
|
67
|
+
if (!args) {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let query: FindOptionsWhere<DigitalCredentialEntity> = {}
|
|
72
|
+
|
|
73
|
+
if ('id' in args) {
|
|
74
|
+
query.id = args.id
|
|
75
|
+
} else if ('hash' in args) {
|
|
76
|
+
query.hash = args.hash
|
|
77
|
+
} else {
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const connection = await this.dbConnection
|
|
82
|
+
const result = await connection.getRepository(DigitalCredentialEntity).delete(query)
|
|
83
|
+
return result.affected === 1
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Error removing digital credential:', error)
|
|
86
|
+
return false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
updateCredentialState = async (args: UpdateCredentialStateArgs): Promise<DigitalCredentialEntity> => {
|
|
91
|
+
const credentialRepository: Repository<DigitalCredentialEntity> = (await this.dbConnection).getRepository(DigitalCredentialEntity)
|
|
92
|
+
const whereClause: Record<string, any> = {}
|
|
93
|
+
if ('id' in args) {
|
|
94
|
+
whereClause.id = args.id
|
|
95
|
+
} else if ('hash' in args) {
|
|
96
|
+
whereClause.hash = args.hash
|
|
97
|
+
} else {
|
|
98
|
+
throw new Error('No id or hash param is provided.')
|
|
99
|
+
}
|
|
100
|
+
if (!args.verifiedState) {
|
|
101
|
+
throw new Error('No verifiedState param is provided.')
|
|
102
|
+
}
|
|
103
|
+
if (args.verifiedState === CredentialStateType.REVOKED && !args.revokedAt) {
|
|
104
|
+
throw new Error('No revokedAt param is provided.')
|
|
105
|
+
}
|
|
106
|
+
if (args.verifiedState !== CredentialStateType.REVOKED && !args.verifiedAt) {
|
|
107
|
+
throw new Error('No verifiedAt param is provided.')
|
|
108
|
+
}
|
|
109
|
+
const credential: DigitalCredentialEntity | null = await credentialRepository.findOne({
|
|
110
|
+
where: whereClause,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
if (!credential) {
|
|
114
|
+
return Promise.reject(Error(`No credential found for args: ${whereClause}`))
|
|
115
|
+
}
|
|
116
|
+
const updatedCredential: DigitalCredential = {
|
|
117
|
+
...credential,
|
|
118
|
+
...(args.verifiedState !== CredentialStateType.REVOKED && { verifiedAt: args.verifiedAt }),
|
|
119
|
+
...(args.verifiedState === CredentialStateType.REVOKED && { revokedAt: args.revokedAt }),
|
|
120
|
+
lastUpdatedAt: new Date(),
|
|
121
|
+
verifiedState: args.verifiedState,
|
|
122
|
+
}
|
|
123
|
+
debug('Updating credential', credential)
|
|
124
|
+
const updatedResult: DigitalCredentialEntity = await credentialRepository.save(updatedCredential, { transaction: true })
|
|
125
|
+
return updatedResult
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
|
2
|
+
import {
|
|
3
|
+
CredentialCorrelationType,
|
|
4
|
+
CredentialDocumentFormat,
|
|
5
|
+
CredentialStateType,
|
|
6
|
+
DocumentType,
|
|
7
|
+
} from '../../types/digitalCredential/digitalCredential'
|
|
8
|
+
|
|
9
|
+
@Entity('DigitalCredential')
|
|
10
|
+
export class DigitalCredentialEntity extends BaseEntity {
|
|
11
|
+
@PrimaryGeneratedColumn('uuid')
|
|
12
|
+
id!: string
|
|
13
|
+
|
|
14
|
+
@Column('simple-enum', { name: 'document_type', enum: DocumentType, nullable: false })
|
|
15
|
+
documentType!: DocumentType
|
|
16
|
+
|
|
17
|
+
@Column('simple-enum', { name: 'document_format', enum: CredentialDocumentFormat, nullable: false })
|
|
18
|
+
documentFormat!: CredentialDocumentFormat
|
|
19
|
+
|
|
20
|
+
@Column('text', { name: 'raw_document', nullable: false })
|
|
21
|
+
rawDocument!: string
|
|
22
|
+
|
|
23
|
+
@Column('text', { name: 'uniform_document', nullable: false })
|
|
24
|
+
uniformDocument!: string
|
|
25
|
+
|
|
26
|
+
@Column('text', { name: 'hash', nullable: false, unique: true })
|
|
27
|
+
hash!: string
|
|
28
|
+
|
|
29
|
+
@Column('simple-enum', { name: 'issuer_correlation_type', enum: CredentialCorrelationType, nullable: false })
|
|
30
|
+
issuerCorrelationType!: CredentialCorrelationType
|
|
31
|
+
|
|
32
|
+
@Column('simple-enum', { name: 'subject_correlation_type', enum: CredentialCorrelationType, nullable: true })
|
|
33
|
+
subjectCorrelationType?: CredentialCorrelationType
|
|
34
|
+
|
|
35
|
+
@Column('text', { name: 'issuer_correlation_id', nullable: false })
|
|
36
|
+
issuerCorrelationId!: string
|
|
37
|
+
|
|
38
|
+
@Column('text', { name: 'subject_correlation_id', nullable: true })
|
|
39
|
+
subjectCorrelationId?: string
|
|
40
|
+
|
|
41
|
+
@Column('simple-enum', { name: 'verified_state', enum: CredentialStateType, nullable: true })
|
|
42
|
+
verifiedState?: CredentialStateType
|
|
43
|
+
|
|
44
|
+
@Column('text', { name: 'tenant_id', nullable: true })
|
|
45
|
+
tenantId?: string
|
|
46
|
+
|
|
47
|
+
@CreateDateColumn({ name: 'created_at', nullable: false })
|
|
48
|
+
createdAt!: Date
|
|
49
|
+
|
|
50
|
+
@UpdateDateColumn({ name: 'last_updated_at', nullable: false })
|
|
51
|
+
lastUpdatedAt!: Date
|
|
52
|
+
|
|
53
|
+
@Column('date', { name: 'valid_until', nullable: true })
|
|
54
|
+
validUntil?: Date
|
|
55
|
+
|
|
56
|
+
@Column('date', { name: 'valid_from', nullable: true })
|
|
57
|
+
validFrom?: Date
|
|
58
|
+
|
|
59
|
+
@Column('date', { name: 'verified_at', nullable: true })
|
|
60
|
+
verifiedAt?: Date
|
|
61
|
+
|
|
62
|
+
@Column('date', { name: 'revoked_at', nullable: true })
|
|
63
|
+
revokedAt?: Date
|
|
64
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
@Entity('StateEntity')
|
|
4
|
+
export class StateEntity extends BaseEntity {
|
|
5
|
+
@PrimaryGeneratedColumn('uuid', { name: 'id' })
|
|
6
|
+
id!: string
|
|
7
|
+
|
|
8
|
+
@Column({ name: 'state_name', nullable: false })
|
|
9
|
+
stateName!: string
|
|
10
|
+
|
|
11
|
+
@Column({ name: 'machine_type', nullable: false })
|
|
12
|
+
machineType!: string
|
|
13
|
+
|
|
14
|
+
@Column({ name: 'xstate_event_type', nullable: false })
|
|
15
|
+
xStateEventType!: string
|
|
16
|
+
|
|
17
|
+
@Column({ name: 'state', nullable: false })
|
|
18
|
+
state!: string
|
|
19
|
+
|
|
20
|
+
@CreateDateColumn({ name: 'created_at', nullable: false })
|
|
21
|
+
createdAt!: Date
|
|
22
|
+
|
|
23
|
+
@UpdateDateColumn({ name: 'updated_at', nullable: false })
|
|
24
|
+
updatedAt!: Date
|
|
25
|
+
|
|
26
|
+
@Column({ name: 'expires_at', type: 'datetime', nullable: true })
|
|
27
|
+
expiresAt?: Date
|
|
28
|
+
|
|
29
|
+
@Column({ name: 'completed_at', type: 'datetime', nullable: true })
|
|
30
|
+
completedAt?: Date
|
|
31
|
+
|
|
32
|
+
@Column({ name: 'tenant_id', type: 'varchar', nullable: true })
|
|
33
|
+
tenantId?: string
|
|
34
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { IssuerBrandingEntity, issuerBrandingEntityFrom } from './entities/issua
|
|
|
18
18
|
import { TextAttributesEntity, textAttributesEntityFrom } from './entities/issuanceBranding/TextAttributesEntity'
|
|
19
19
|
import { StatusListEntity } from './entities/statusList2021/StatusList2021Entity'
|
|
20
20
|
import { StatusListEntryEntity } from './entities/statusList2021/StatusList2021EntryEntity'
|
|
21
|
+
import { StateEntity } from './entities/xstate/StateEntity'
|
|
21
22
|
import { IStatusListEntity, IStatusListEntryEntity } from './types'
|
|
22
23
|
import { PartyRelationshipEntity } from './entities/contact/PartyRelationshipEntity'
|
|
23
24
|
import { PartyTypeEntity } from './entities/contact/PartyTypeEntity'
|
|
@@ -31,14 +32,20 @@ export { AbstractIssuanceBrandingStore } from './issuanceBranding/AbstractIssuan
|
|
|
31
32
|
export { IssuanceBrandingStore } from './issuanceBranding/IssuanceBrandingStore'
|
|
32
33
|
export { StatusListStore } from './statusList/StatusListStore'
|
|
33
34
|
import { AuditEventEntity, auditEventEntityFrom } from './entities/eventLogger/AuditEventEntity'
|
|
35
|
+
import { DigitalCredentialEntity } from './entities/digitalCredential/DigitalCredentialEntity'
|
|
36
|
+
import { digitalCredentialFrom, digitalCredentialsFrom, nonPersistedDigitalCredentialEntityFromAddArgs } from './utils/digitalCredential/MappingUtils'
|
|
34
37
|
export { AbstractEventLoggerStore } from './eventLogger/AbstractEventLoggerStore'
|
|
35
38
|
export { EventLoggerStore } from './eventLogger/EventLoggerStore'
|
|
39
|
+
export { IAbstractXStateStore } from './xstate/IAbstractXStateStore'
|
|
40
|
+
export { XStateStore } from './xstate/XStateStore'
|
|
41
|
+
|
|
36
42
|
export {
|
|
37
43
|
DataStoreMigrations,
|
|
38
44
|
DataStoreEventLoggerMigrations,
|
|
39
45
|
DataStoreContactMigrations,
|
|
40
46
|
DataStoreIssuanceBrandingMigrations,
|
|
41
47
|
DataStoreStatusListMigrations,
|
|
48
|
+
DataStoreXStateStoreMigrations,
|
|
42
49
|
} from './migrations'
|
|
43
50
|
export * from './types'
|
|
44
51
|
export * from './utils/contact/MappingUtils'
|
|
@@ -77,12 +84,18 @@ export const DataStoreStatusListEntities = [StatusListEntity, StatusListEntryEnt
|
|
|
77
84
|
|
|
78
85
|
export const DataStoreEventLoggerEntities = [AuditEventEntity]
|
|
79
86
|
|
|
87
|
+
export const DataStoreDigitalCredentialEntities = [DigitalCredentialEntity]
|
|
88
|
+
|
|
89
|
+
export const DataStoreXStateStoreEntities = [StateEntity]
|
|
90
|
+
|
|
80
91
|
// All entities combined if a party wants to enable them all at once
|
|
81
92
|
export const DataStoreEntities = [
|
|
82
93
|
...DataStoreContactEntities,
|
|
83
94
|
...DataStoreIssuanceBrandingEntities,
|
|
84
95
|
...DataStoreStatusListEntities,
|
|
85
96
|
...DataStoreEventLoggerEntities,
|
|
97
|
+
...DataStoreDigitalCredentialEntities,
|
|
98
|
+
...DataStoreXStateStoreEntities,
|
|
86
99
|
]
|
|
87
100
|
|
|
88
101
|
export {
|
|
@@ -119,4 +132,9 @@ export {
|
|
|
119
132
|
StatusListEntryEntity,
|
|
120
133
|
AuditEventEntity,
|
|
121
134
|
auditEventEntityFrom,
|
|
135
|
+
DigitalCredentialEntity,
|
|
136
|
+
digitalCredentialFrom,
|
|
137
|
+
digitalCredentialsFrom,
|
|
138
|
+
nonPersistedDigitalCredentialEntityFromAddArgs,
|
|
139
|
+
StateEntity,
|
|
122
140
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
import Debug, { Debugger } from 'debug'
|
|
3
|
+
import { CreateDigitalCredential1708525189001 } from '../postgres/1708525189001-CreateDigitalCredential'
|
|
4
|
+
import { CreateDigitalCredential1708525189002 } from '../sqlite/1708525189002-CreateDigitalCredential'
|
|
5
|
+
|
|
6
|
+
const debug: Debugger = Debug('sphereon:ssi-sdk:migrations')
|
|
7
|
+
|
|
8
|
+
export class CreateDigitalCredential1708525189000 implements MigrationInterface {
|
|
9
|
+
name: string = 'CreateDigitalCredential1708525189000'
|
|
10
|
+
|
|
11
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
12
|
+
debug('migration: creating DigitalCredential tables')
|
|
13
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
14
|
+
|
|
15
|
+
switch (dbType) {
|
|
16
|
+
case 'postgres': {
|
|
17
|
+
debug('using postgres migration file for DigitalCredential')
|
|
18
|
+
const mig: CreateDigitalCredential1708525189001 = new CreateDigitalCredential1708525189001()
|
|
19
|
+
await mig.up(queryRunner)
|
|
20
|
+
debug('Postgres Migration statements for DigitalCredential executed')
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
case 'sqlite':
|
|
24
|
+
case 'expo':
|
|
25
|
+
case 'react-native': {
|
|
26
|
+
debug('using sqlite/react-native migration file for DigitalCredential')
|
|
27
|
+
const mig: CreateDigitalCredential1708525189002 = new CreateDigitalCredential1708525189002()
|
|
28
|
+
await mig.up(queryRunner)
|
|
29
|
+
debug('SQLite Migration statements for DigitalCredential executed')
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
default:
|
|
33
|
+
return Promise.reject(
|
|
34
|
+
`Migrations are currently only supported for sqlite, react-native, expo, and postgres for UniformCredential. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
40
|
+
debug('migration: reverting DigitalCredential tables')
|
|
41
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
42
|
+
|
|
43
|
+
switch (dbType) {
|
|
44
|
+
case 'postgres': {
|
|
45
|
+
debug('using postgres migration file for DigitalCredential')
|
|
46
|
+
const mig: CreateDigitalCredential1708525189001 = new CreateDigitalCredential1708525189001()
|
|
47
|
+
await mig.down(queryRunner)
|
|
48
|
+
debug('Postgres Migration statements for DigitalCredential reverted')
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
case 'sqlite':
|
|
52
|
+
case 'expo':
|
|
53
|
+
case 'react-native': {
|
|
54
|
+
debug('using sqlite/react-native migration file for DigitalCredential')
|
|
55
|
+
const mig: CreateDigitalCredential1708525189002 = new CreateDigitalCredential1708525189002()
|
|
56
|
+
await mig.down(queryRunner)
|
|
57
|
+
debug('SQLite Migration statements for DigitalCredential reverted')
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
return Promise.reject(
|
|
62
|
+
`Migrations are currently only supported for sqlite, react-native, expo, and postgres for DigitalCredential. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
import Debug from 'debug'
|
|
3
|
+
import { CreateXStateStore1708797018115 } from '../postgres/1708797018115-CreateXStateStore'
|
|
4
|
+
import { CreateXStateStore1708796002272 } from '../sqlite/1708796002272-CreateXStateStore'
|
|
5
|
+
|
|
6
|
+
const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations')
|
|
7
|
+
|
|
8
|
+
export class CreateXStateStore1708098041262 implements MigrationInterface {
|
|
9
|
+
name = 'CreateXStateStore1708098041262'
|
|
10
|
+
|
|
11
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
12
|
+
debug('migration: creating contacts tables')
|
|
13
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
14
|
+
|
|
15
|
+
switch (dbType) {
|
|
16
|
+
case 'postgres': {
|
|
17
|
+
debug('using postgres migration file')
|
|
18
|
+
const mig: CreateXStateStore1708797018115 = new CreateXStateStore1708797018115()
|
|
19
|
+
await mig.up(queryRunner)
|
|
20
|
+
debug('Migration statements executed')
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
case 'sqlite':
|
|
24
|
+
case 'expo':
|
|
25
|
+
case 'react-native': {
|
|
26
|
+
debug('using sqlite/react-native migration file')
|
|
27
|
+
const mig: CreateXStateStore1708796002272 = new CreateXStateStore1708796002272()
|
|
28
|
+
await mig.up(queryRunner)
|
|
29
|
+
debug('Migration statements executed')
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
default:
|
|
33
|
+
return Promise.reject(
|
|
34
|
+
`Migrations are currently only supported for sqlite, react-native, expo and postgres. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
40
|
+
debug('migration: reverting contacts tables')
|
|
41
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
42
|
+
|
|
43
|
+
switch (dbType) {
|
|
44
|
+
case 'postgres': {
|
|
45
|
+
debug('using postgres migration file')
|
|
46
|
+
const mig: CreateXStateStore1708797018115 = new CreateXStateStore1708797018115()
|
|
47
|
+
await mig.down(queryRunner)
|
|
48
|
+
debug('Migration statements executed')
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
case 'sqlite':
|
|
52
|
+
case 'expo':
|
|
53
|
+
case 'react-native': {
|
|
54
|
+
debug('using sqlite/react-native migration file')
|
|
55
|
+
const mig: CreateXStateStore1708796002272 = new CreateXStateStore1708796002272()
|
|
56
|
+
await mig.down(queryRunner)
|
|
57
|
+
debug('Migration statements executed')
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
return Promise.reject(
|
|
62
|
+
`Migrations are currently only supported for sqlite, react-native, expo and postgres. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -3,6 +3,8 @@ import { CreateIssuanceBranding1659463079429 } from './2-CreateIssuanceBranding'
|
|
|
3
3
|
import { CreateContacts1690925872318 } from './3-CreateContacts'
|
|
4
4
|
import { CreateStatusList1693866470000 } from './4-CreateStatusList'
|
|
5
5
|
import { CreateAuditEvents1701635835330 } from './5-CreateAuditEvents'
|
|
6
|
+
import { CreateDigitalCredential1708525189000 } from './6-CreateDigitalCredential'
|
|
7
|
+
import { CreateXStateStore1708098041262 } from './7-CreateXStateStore'
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The migrations array that SHOULD be used when initializing a TypeORM database connection.
|
|
@@ -17,6 +19,8 @@ export const DataStoreContactMigrations = [CreateContacts1659463079429, CreateCo
|
|
|
17
19
|
export const DataStoreIssuanceBrandingMigrations = [CreateIssuanceBranding1659463079429]
|
|
18
20
|
export const DataStoreStatusListMigrations = [CreateStatusList1693866470000]
|
|
19
21
|
export const DataStoreEventLoggerMigrations = [CreateAuditEvents1701635835330]
|
|
22
|
+
export const DataStoreDigitalCredentialMigrations = [CreateDigitalCredential1708525189000]
|
|
23
|
+
export const DataStoreXStateStoreMigrations = [CreateXStateStore1708098041262]
|
|
20
24
|
|
|
21
25
|
// All migrations together
|
|
22
26
|
export const DataStoreMigrations = [
|
|
@@ -24,4 +28,6 @@ export const DataStoreMigrations = [
|
|
|
24
28
|
...DataStoreIssuanceBrandingMigrations,
|
|
25
29
|
...DataStoreStatusListMigrations,
|
|
26
30
|
...DataStoreEventLoggerMigrations,
|
|
31
|
+
...DataStoreDigitalCredentialMigrations,
|
|
32
|
+
...DataStoreXStateStoreMigrations,
|
|
27
33
|
]
|
package/src/migrations/index.ts
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class CreateDigitalCredential1708525189001 implements MigrationInterface {
|
|
4
|
+
name = 'CreateDigitalCredential1708525189001'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`CREATE TYPE "digital_document_type" AS ENUM('VC', 'VP', 'C', 'P')`)
|
|
8
|
+
await queryRunner.query(`CREATE TYPE "digital_credential_document_format" AS ENUM('JSON_LD', 'JWT', 'SD_JWT', 'MDOC')`)
|
|
9
|
+
await queryRunner.query(`CREATE TYPE "digital_credential_correlation_type" AS ENUM('DID')`)
|
|
10
|
+
await queryRunner.query(`CREATE TYPE "digital_credential_state_type" AS ENUM('REVOKED', 'VERIFIED', 'EXPIRED')`)
|
|
11
|
+
|
|
12
|
+
await queryRunner.query(`
|
|
13
|
+
CREATE TABLE "DigitalCredential" (
|
|
14
|
+
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
|
15
|
+
"document_type" "digital_document_type" NOT NULL,
|
|
16
|
+
"document_format" "digital_credential_document_format" NOT NULL,
|
|
17
|
+
"raw_document" text NOT NULL,
|
|
18
|
+
"uniform_document" text NOT NULL,
|
|
19
|
+
"hash" text NOT NULL UNIQUE,
|
|
20
|
+
"issuer_correlation_type" "digital_credential_correlation_type" NOT NULL,
|
|
21
|
+
"subject_correlation_type" "digital_credential_correlation_type",
|
|
22
|
+
"issuer_correlation_id" text NOT NULL,
|
|
23
|
+
"subject_correlation_id" text,
|
|
24
|
+
"verified_state" "digital_credential_state_type",
|
|
25
|
+
"tenant_id" text,
|
|
26
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
27
|
+
"last_updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
28
|
+
"valid_from" DATE,
|
|
29
|
+
"valid_until" DATE,
|
|
30
|
+
"verified_at" DATE,
|
|
31
|
+
"revoked_at" DATE,
|
|
32
|
+
PRIMARY KEY ("id")
|
|
33
|
+
)
|
|
34
|
+
`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
38
|
+
await queryRunner.query(`DROP TABLE "DigitalCredential"`)
|
|
39
|
+
await queryRunner.query(`DROP TYPE "digital_credential_state_type"`)
|
|
40
|
+
await queryRunner.query(`DROP TYPE "digital_credential_correlation_type"`)
|
|
41
|
+
await queryRunner.query(`DROP TYPE "digital_credential_document_format"`)
|
|
42
|
+
await queryRunner.query(`DROP TYPE "digital_document_type"`)
|
|
43
|
+
}
|
|
44
|
+
}
|