@sphereon/ssi-sdk.data-store 0.19.0 → 0.19.1-next.100
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/machineState/MachineStateInfoEntity.d.ts +33 -0
- package/dist/entities/machineState/MachineStateInfoEntity.d.ts.map +1 -0
- package/dist/entities/machineState/MachineStateInfoEntity.js +85 -0
- package/dist/entities/machineState/MachineStateInfoEntity.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/machineState/IAbstractMachineStateStore.d.ts +52 -0
- package/dist/machineState/IAbstractMachineStateStore.d.ts.map +1 -0
- package/dist/machineState/IAbstractMachineStateStore.js +13 -0
- package/dist/machineState/IAbstractMachineStateStore.js.map +1 -0
- package/dist/machineState/MachineStateStore.d.ts +21 -0
- package/dist/machineState/MachineStateStore.d.ts.map +1 -0
- package/dist/machineState/MachineStateStore.js +139 -0
- package/dist/machineState/MachineStateStore.js.map +1 -0
- 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-CreateMachineStateStore.d.ts +7 -0
- package/dist/migrations/generic/7-CreateMachineStateStore.d.ts.map +1 -0
- package/dist/migrations/generic/7-CreateMachineStateStore.js +78 -0
- package/dist/migrations/generic/7-CreateMachineStateStore.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-CreateMachineStateStore.d.ts +7 -0
- package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.d.ts.map +1 -0
- package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.js +45 -0
- package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.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-CreateMachineStateStore.d.ts +7 -0
- package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.d.ts.map +1 -0
- package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.js +44 -0
- package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.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/machineState/IAbstractMachineStateStore.d.ts +58 -0
- package/dist/types/machineState/IAbstractMachineStateStore.d.ts.map +1 -0
- package/dist/types/machineState/IAbstractMachineStateStore.js +3 -0
- package/dist/types/machineState/IAbstractMachineStateStore.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/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__/machineState.entities.test.ts +51 -0
- package/src/__tests__/machineState.store.test.ts +174 -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/machineState/MachineStateInfoEntity.ts +58 -0
- package/src/index.ts +18 -0
- package/src/machineState/IAbstractMachineStateStore.ts +65 -0
- package/src/machineState/MachineStateStore.ts +149 -0
- package/src/migrations/generic/6-CreateDigitalCredential.ts +66 -0
- package/src/migrations/generic/7-CreateMachineStateStore.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-CreateMachineStateStore.ts +29 -0
- package/src/migrations/sqlite/1708525189002-CreateDigitalCredential.ts +34 -0
- package/src/migrations/sqlite/1708796002272-CreateMachineStateStore.ts +28 -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/machineState/IAbstractMachineStateStore.ts +68 -0
- package/src/utils/SortingUtils.ts +16 -0
- package/src/utils/digitalCredential/MappingUtils.ts +122 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { OrPromise } from '@sphereon/ssi-types'
|
|
2
|
+
import Debug from 'debug'
|
|
3
|
+
import { Brackets, DataSource, FindOptionsWhere, IsNull, LessThan, Not } from 'typeorm'
|
|
4
|
+
|
|
5
|
+
import { MachineStateInfoEntity } from '../entities/machineState/MachineStateInfoEntity'
|
|
6
|
+
import {
|
|
7
|
+
StoreFindMachineStatesArgs,
|
|
8
|
+
StoreMachineStateDeleteArgs,
|
|
9
|
+
StoreMachineStateDeleteExpiredArgs,
|
|
10
|
+
StoreMachineStateGetArgs,
|
|
11
|
+
StoreMachineStateInfo,
|
|
12
|
+
StoreMachineStatePersistArgs,
|
|
13
|
+
StoreMachineStatesFindActiveArgs,
|
|
14
|
+
} from '../types'
|
|
15
|
+
import { IAbstractMachineStateStore } from './IAbstractMachineStateStore'
|
|
16
|
+
|
|
17
|
+
const debug = Debug('sphereon:ssi-sdk:machine-state:store')
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Represents a data store for managing machine states.
|
|
21
|
+
*/
|
|
22
|
+
export class MachineStateStore extends IAbstractMachineStateStore {
|
|
23
|
+
private readonly _dbConnection: OrPromise<DataSource>
|
|
24
|
+
|
|
25
|
+
constructor(dbConnection: OrPromise<DataSource>) {
|
|
26
|
+
super()
|
|
27
|
+
this._dbConnection = dbConnection
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async persistMachineState(state: StoreMachineStatePersistArgs): Promise<StoreMachineStateInfo> {
|
|
31
|
+
const connection: DataSource = await this._dbConnection
|
|
32
|
+
const { machineName, instanceId, tenantId } = state
|
|
33
|
+
debug(`Executing persistMachineState for machine ${machineName}, instance ${instanceId}, tenantId: ${tenantId}...`)
|
|
34
|
+
const entity = MachineStateStore.machineStateInfoEntityFrom(state)
|
|
35
|
+
const existing = await connection.getRepository(MachineStateInfoEntity).findOne({
|
|
36
|
+
where: {
|
|
37
|
+
instanceId: state.instanceId,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
if (existing && existing.updatedCount > state.updatedCount) {
|
|
41
|
+
const error = `Updating machine state with an older version is not allowed. Machine ${existing.machineName}, last count: ${
|
|
42
|
+
existing.updatedCount
|
|
43
|
+
}, new count: ${existing.updatedCount}, last updated: ${existing.updatedAt}, current: ${new Date()}, instance: ${existing.instanceId}`
|
|
44
|
+
console.log(error)
|
|
45
|
+
return Promise.reject(new Error(error))
|
|
46
|
+
}
|
|
47
|
+
// No need for a transaction. This is a single entity. We don't want to be surprised by an isolation level hiding the state from others
|
|
48
|
+
const result = await connection.getRepository(MachineStateInfoEntity).save(entity, { transaction: false })
|
|
49
|
+
debug(`Done persistMachineState machine ${machineName}, instance ${instanceId}, tenantId: ${tenantId}`)
|
|
50
|
+
return MachineStateStore.machineInfoFrom(result)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async findActiveMachineStates(args: StoreMachineStatesFindActiveArgs): Promise<Array<StoreMachineStateInfo>> {
|
|
54
|
+
const { tenantId, machineName, instanceId } = args
|
|
55
|
+
const connection: DataSource = await this._dbConnection
|
|
56
|
+
debug(`Executing findActiveMachineStates query with machineName: ${machineName}, tenantId: ${tenantId}`)
|
|
57
|
+
const queryBuilder = connection
|
|
58
|
+
.getRepository(MachineStateInfoEntity)
|
|
59
|
+
.createQueryBuilder('state')
|
|
60
|
+
.where('state.completedAt IS NULL')
|
|
61
|
+
.andWhere(
|
|
62
|
+
new Brackets((qb) => {
|
|
63
|
+
qb.where('state.expiresAt IS NULL').orWhere('state.expiresAt > :now', { now: new Date() })
|
|
64
|
+
})
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if (instanceId) {
|
|
68
|
+
queryBuilder.andWhere('state.instanceId = :instanceId', { instanceId })
|
|
69
|
+
}
|
|
70
|
+
if (tenantId) {
|
|
71
|
+
queryBuilder.andWhere('state.tenantId = :tenantId', { tenantId })
|
|
72
|
+
}
|
|
73
|
+
if (machineName) {
|
|
74
|
+
queryBuilder.andWhere('state.machineName = :machineName', { machineName })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
(await queryBuilder
|
|
79
|
+
.orderBy('state.updatedAt', 'DESC')
|
|
80
|
+
.getMany()
|
|
81
|
+
.then((entities) => entities.map(MachineStateStore.machineInfoFrom))) ?? []
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async findMachineStates(args?: StoreFindMachineStatesArgs): Promise<Array<StoreMachineStateInfo>> {
|
|
86
|
+
const connection: DataSource = await this._dbConnection
|
|
87
|
+
debug('findMachineStates', args)
|
|
88
|
+
const result: Array<MachineStateInfoEntity> = await connection.getRepository(MachineStateInfoEntity).find({
|
|
89
|
+
...(args?.filter && { where: args?.filter }),
|
|
90
|
+
transaction: false,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return result.map((event: MachineStateInfoEntity) => MachineStateStore.machineInfoFrom(event))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async getMachineState(args: StoreMachineStateGetArgs): Promise<StoreMachineStateInfo> {
|
|
97
|
+
const connection: DataSource = await this._dbConnection
|
|
98
|
+
debug('getMachineState', args)
|
|
99
|
+
return connection.getRepository(MachineStateInfoEntity).findOneOrFail({ where: { instanceId: args.instanceId } })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async deleteMachineState(args: StoreMachineStateDeleteArgs): Promise<boolean> {
|
|
103
|
+
debug(`Executing deleteMachineState query with id: ${args.instanceId}`)
|
|
104
|
+
if (!args.instanceId) {
|
|
105
|
+
throw new Error('No instanceId parameter is provided.')
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const connection: DataSource = await this._dbConnection
|
|
109
|
+
|
|
110
|
+
const result = await connection.getRepository(MachineStateInfoEntity).delete(args.instanceId)
|
|
111
|
+
return result.affected != null && result.affected > 0
|
|
112
|
+
} catch (error) {
|
|
113
|
+
debug(`Error deleting state: ${error}`)
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async deleteExpiredMachineStates(args: StoreMachineStateDeleteExpiredArgs): Promise<number> {
|
|
119
|
+
const { machineName, tenantId, deleteDoneStates } = args
|
|
120
|
+
debug(`Executing deleteExpiredMachineStates query with params: ${JSON.stringify(args)}`)
|
|
121
|
+
try {
|
|
122
|
+
const connection: DataSource = await this._dbConnection
|
|
123
|
+
|
|
124
|
+
const deleteCriteria: FindOptionsWhere<MachineStateInfoEntity> = {
|
|
125
|
+
...(machineName && { machineName }),
|
|
126
|
+
...(tenantId && { tenantId }),
|
|
127
|
+
// When deleteOnDone state is set we only look at completedAt, in other cases we compare current time with expiresAt
|
|
128
|
+
...(!deleteDoneStates && { expiresAt: LessThan(new Date()) }),
|
|
129
|
+
...(deleteDoneStates && { completedAt: Not(IsNull()) }),
|
|
130
|
+
}
|
|
131
|
+
const result = await connection.getRepository(MachineStateInfoEntity).delete(deleteCriteria)
|
|
132
|
+
return result.affected ?? 0
|
|
133
|
+
} catch (error) {
|
|
134
|
+
debug(`Error deleting machine info: ${error}`)
|
|
135
|
+
return Promise.reject(new Error(`Error deleting expired machine states for machine type ${machineName}`))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
protected static machineInfoFrom = (machineStateInfoEntity: MachineStateInfoEntity): StoreMachineStateInfo => {
|
|
140
|
+
// We are making sure no entity function get copied
|
|
141
|
+
return JSON.parse(JSON.stringify(machineStateInfoEntity))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static machineStateInfoEntityFrom = (machineStateInfo: StoreMachineStateInfo | StoreMachineStatePersistArgs): MachineStateInfoEntity => {
|
|
145
|
+
const entity = new MachineStateInfoEntity()
|
|
146
|
+
Object.assign(entity, machineStateInfo)
|
|
147
|
+
return entity
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -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 { CreateMachineStateStore1708797018115 } from '../postgres/1708797018115-CreateMachineStateStore'
|
|
4
|
+
import { CreateMachineStateStore1708796002272 } from '../sqlite/1708796002272-CreateMachineStateStore'
|
|
5
|
+
|
|
6
|
+
const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations')
|
|
7
|
+
|
|
8
|
+
export class CreateMachineStateStore1708098041262 implements MigrationInterface {
|
|
9
|
+
name = 'CreateMachineStateStore1708098041262'
|
|
10
|
+
|
|
11
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
12
|
+
debug('migration: creating machine state 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: CreateMachineStateStore1708797018115 = new CreateMachineStateStore1708797018115()
|
|
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: CreateMachineStateStore1708796002272 = new CreateMachineStateStore1708796002272()
|
|
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 machine state 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: CreateMachineStateStore1708797018115 = new CreateMachineStateStore1708797018115()
|
|
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: CreateMachineStateStore1708796002272 = new CreateMachineStateStore1708796002272()
|
|
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 { CreateMachineStateStore1708098041262 } from './7-CreateMachineStateStore'
|
|
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 DataStoreMachineStateMigrations = [CreateMachineStateStore1708098041262]
|
|
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
|
+
...DataStoreMachineStateMigrations,
|
|
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
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class CreateMachineStateStore1708797018115 implements MigrationInterface {
|
|
4
|
+
name = 'CreateMachineStateStore1708797018115'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
CREATE TABLE "MachineStateInfoEntity" (
|
|
9
|
+
"instance_id" text NOT NULL,
|
|
10
|
+
"session_id" text,
|
|
11
|
+
"latest_state_name" text,
|
|
12
|
+
"machine_name" text NOT NULL,
|
|
13
|
+
"latest_event_type" text NOT NULL,
|
|
14
|
+
"state" text NOT NULL,
|
|
15
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
16
|
+
"updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
17
|
+
"updated_count" integer NOT NULL DEFAULT 0,
|
|
18
|
+
"expires_at" TIMESTAMP,
|
|
19
|
+
"completed_at" TIMESTAMP,
|
|
20
|
+
"tenant_id" text,
|
|
21
|
+
CONSTRAINT "PK_MachineStateInfoEntity_id" PRIMARY KEY ("instance_id")
|
|
22
|
+
)
|
|
23
|
+
`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
27
|
+
await queryRunner.query(`DROP TABLE "MachineStateInfoEntity"`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class CreateDigitalCredential1708525189002 implements MigrationInterface {
|
|
4
|
+
name = 'CreateDigitalCredential1708525189002'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
CREATE TABLE "DigitalCredential" (
|
|
9
|
+
"id" varchar PRIMARY KEY NOT NULL,
|
|
10
|
+
"document_type" varchar CHECK( "document_type" IN ('VC', 'VP', 'C', 'P') ) NOT NULL,
|
|
11
|
+
"document_format" varchar CHECK( "document_format" IN ('JSON_LD', 'JWT', 'SD_JWT', 'MDOC') ) NOT NULL,
|
|
12
|
+
"raw_document" text NOT NULL,
|
|
13
|
+
"uniform_document" text NOT NULL,
|
|
14
|
+
"hash" text NOT NULL UNIQUE,
|
|
15
|
+
"issuer_correlation_type" varchar CHECK( "issuer_correlation_type" IN ('DID') ) NOT NULL,
|
|
16
|
+
"subject_correlation_type" varchar CHECK( "subject_correlation_type" IN ('DID') ),
|
|
17
|
+
"issuer_correlation_id" text NOT NULL,
|
|
18
|
+
"subject_correlation_id" text,
|
|
19
|
+
"verified_state" varchar CHECK( "verified_state" IN ('REVOKED', 'VERIFIED', 'EXPIRED') ),
|
|
20
|
+
"tenant_id" text,
|
|
21
|
+
"created_at" datetime NOT NULL DEFAULT (datetime('now')),
|
|
22
|
+
"last_updated_at" datetime NOT NULL DEFAULT (datetime('now')),
|
|
23
|
+
"valid_from" datetime,
|
|
24
|
+
"valid_until" datetime,
|
|
25
|
+
"verified_at" datetime,
|
|
26
|
+
"revoked_at" datetime
|
|
27
|
+
)
|
|
28
|
+
`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
32
|
+
await queryRunner.query(`DROP TABLE "DigitalCredential"`)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class CreateMachineStateStore1708796002272 implements MigrationInterface {
|
|
4
|
+
name = 'CreateMachineStateStore1708796002272'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
CREATE TABLE "MachineStateInfoEntity" (
|
|
9
|
+
"instance_id" varchar PRIMARY KEY NOT NULL,
|
|
10
|
+
"session_id" varchar,
|
|
11
|
+
"machine_name" varchar NOT NULL,
|
|
12
|
+
"latest_state_name" varchar,
|
|
13
|
+
"latest_event_type" varchar NOT NULL,
|
|
14
|
+
"state" text NOT NULL,
|
|
15
|
+
"created_at" datetime NOT NULL DEFAULT (datetime('now')),
|
|
16
|
+
"updated_at" datetime NOT NULL DEFAULT (datetime('now')),
|
|
17
|
+
"updated_count" integer NOT NULL DEFAULT 0,
|
|
18
|
+
"expires_at" datetime,
|
|
19
|
+
"completed_at" datetime,
|
|
20
|
+
"tenant_id" varchar
|
|
21
|
+
)
|
|
22
|
+
`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
26
|
+
await queryRunner.query(`DROP TABLE "MachineStateInfoEntity"`)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CredentialCorrelationType, CredentialStateType, DigitalCredential } from './digitalCredential'
|
|
2
|
+
import { Hasher } from '@sphereon/ssi-types'
|
|
3
|
+
import { FindOptionsOrder } from 'typeorm'
|
|
4
|
+
import { DigitalCredentialEntity } from '../../entities/digitalCredential/DigitalCredentialEntity'
|
|
5
|
+
|
|
6
|
+
export type GetCredentialArgs = { id: string } | { hash: string }
|
|
7
|
+
|
|
8
|
+
export type FindDigitalCredentialArgs = Array<Partial<DigitalCredential>>
|
|
9
|
+
|
|
10
|
+
export type GetCredentialsArgs = {
|
|
11
|
+
filter?: FindDigitalCredentialArgs
|
|
12
|
+
offset?: number
|
|
13
|
+
limit?: number
|
|
14
|
+
order?: string | FindOptionsOrder<DigitalCredentialEntity>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type GetCredentialsResponse = {
|
|
18
|
+
data: Array<DigitalCredential>
|
|
19
|
+
total: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AddCredentialArgs = {
|
|
23
|
+
rawDocument: string
|
|
24
|
+
issuerCorrelationType: CredentialCorrelationType
|
|
25
|
+
subjectCorrelationType?: CredentialCorrelationType
|
|
26
|
+
issuerCorrelationId: string
|
|
27
|
+
subjectCorrelationId?: string
|
|
28
|
+
tenantId?: string
|
|
29
|
+
state?: CredentialStateType
|
|
30
|
+
verifiedAt?: Date
|
|
31
|
+
revokedAt?: Date
|
|
32
|
+
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type UpdateCredentialStateArgs = GetCredentialArgs & { verifiedState: CredentialStateType; verifiedAt?: Date; revokedAt?: Date }
|
|
36
|
+
|
|
37
|
+
export type RemoveCredentialArgs = GetCredentialArgs
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type NonPersistedDigitalCredential = Omit<DigitalCredential, 'id'>
|
|
2
|
+
|
|
3
|
+
export type DigitalCredential = {
|
|
4
|
+
id: string
|
|
5
|
+
documentType: DocumentType
|
|
6
|
+
documentFormat: CredentialDocumentFormat
|
|
7
|
+
rawDocument: string
|
|
8
|
+
uniformDocument: string
|
|
9
|
+
hash: string
|
|
10
|
+
issuerCorrelationType: CredentialCorrelationType
|
|
11
|
+
subjectCorrelationType?: CredentialCorrelationType
|
|
12
|
+
issuerCorrelationId: string
|
|
13
|
+
subjectCorrelationId?: string
|
|
14
|
+
verifiedState?: CredentialStateType
|
|
15
|
+
tenantId?: string
|
|
16
|
+
createdAt: Date
|
|
17
|
+
lastUpdatedAt: Date
|
|
18
|
+
validUntil?: Date
|
|
19
|
+
validFrom?: Date
|
|
20
|
+
verifiedAt?: Date
|
|
21
|
+
revokedAt?: Date
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export enum DocumentType {
|
|
25
|
+
VC = 'VC',
|
|
26
|
+
VP = 'VP',
|
|
27
|
+
P = 'P',
|
|
28
|
+
C = 'C',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export enum CredentialDocumentFormat {
|
|
32
|
+
JSON_LD = 'JSON_LD',
|
|
33
|
+
JWT = 'JWT',
|
|
34
|
+
SD_JWT = 'SD_JWT',
|
|
35
|
+
MDOC = 'MDOC',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export enum CredentialCorrelationType {
|
|
39
|
+
DID = 'DID',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export enum CredentialStateType {
|
|
43
|
+
REVOKED = 'REVOKED',
|
|
44
|
+
VERIFIED = 'VERIFIED',
|
|
45
|
+
EXPIRED = 'EXPIRED',
|
|
46
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export type StoreMachineStatePersistArgs = Omit<StoreMachineStateInfo, 'createdAt' | 'updatedAt'>
|
|
2
|
+
|
|
3
|
+
export type StoreMachineStatesFindActiveArgs = Partial<Pick<StoreMachineStateInfo, 'machineName' | 'tenantId' | 'instanceId'>>
|
|
4
|
+
|
|
5
|
+
export type FindMachineStatesFilterArgs = Array<Partial<Omit<StoreMachineStateInfo, 'state'>>>
|
|
6
|
+
|
|
7
|
+
export type StoreFindMachineStatesArgs = {
|
|
8
|
+
filter: FindMachineStatesFilterArgs
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type StoreMachineStateGetArgs = Pick<StoreMachineStateInfo, 'instanceId' | 'tenantId'>
|
|
12
|
+
|
|
13
|
+
export type StoreMachineStateDeleteArgs = StoreMachineStateGetArgs
|
|
14
|
+
export type StoreMachineStateDeleteExpiredArgs = { machineName?: string; tenantId?: string; deleteDoneStates?: boolean }
|
|
15
|
+
|
|
16
|
+
export interface StoreMachineStateInfo {
|
|
17
|
+
/**
|
|
18
|
+
* Unique instance ID of the machine
|
|
19
|
+
*/
|
|
20
|
+
instanceId: string
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Session Id of the machine. Not necessarily unique
|
|
24
|
+
*/
|
|
25
|
+
sessionId?: string
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Machine name
|
|
29
|
+
*/
|
|
30
|
+
machineName: string
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The latest state name. Can be empty for a newly initialize machine
|
|
34
|
+
*/
|
|
35
|
+
latestStateName?: string
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* event types like SET_TOC, SET_FIRSTNAME, .... Will be xstate.init on a newly initialized machine
|
|
39
|
+
*/
|
|
40
|
+
latestEventType: string
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Serialized Machine state
|
|
44
|
+
*/
|
|
45
|
+
state: string
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Represents the creation date
|
|
49
|
+
*/
|
|
50
|
+
createdAt: Date
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Represents the expiration date
|
|
54
|
+
*/
|
|
55
|
+
expiresAt?: Date
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Represents the update date
|
|
59
|
+
*/
|
|
60
|
+
updatedAt: Date
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Represents a counter for tracking updates.
|
|
64
|
+
*/
|
|
65
|
+
updatedCount: number
|
|
66
|
+
completedAt?: Date
|
|
67
|
+
tenantId?: string
|
|
68
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseEntity, FindOptionsOrder } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export const parseAndValidateOrderOptions = <T extends BaseEntity>(order: string): FindOptionsOrder<T> => {
|
|
4
|
+
const orderPairs = order.split(',').map((pair) => pair.trim().split('.'))
|
|
5
|
+
const orderOptions: FindOptionsOrder<T> = {}
|
|
6
|
+
|
|
7
|
+
orderPairs.forEach(([field, direction]) => {
|
|
8
|
+
const dir = direction.toUpperCase()
|
|
9
|
+
if (dir !== 'ASC' && dir !== 'DESC') {
|
|
10
|
+
throw new Error(`Invalid order direction: '${direction}'. Must be 'asc' or 'desc'.`)
|
|
11
|
+
}
|
|
12
|
+
;(orderOptions as any)[field] = dir
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
return orderOptions
|
|
16
|
+
}
|