@sphereon/ssi-sdk.data-store 0.19.1-next.2 → 0.19.1-next.75

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.
Files changed (110) hide show
  1. package/dist/digitalCredential/AbstractDigitalCredentialStore.d.ts +10 -0
  2. package/dist/digitalCredential/AbstractDigitalCredentialStore.d.ts.map +1 -0
  3. package/dist/digitalCredential/AbstractDigitalCredentialStore.js +7 -0
  4. package/dist/digitalCredential/AbstractDigitalCredentialStore.js.map +1 -0
  5. package/dist/digitalCredential/DigitalCredentialStore.d.ts +15 -0
  6. package/dist/digitalCredential/DigitalCredentialStore.d.ts.map +1 -0
  7. package/dist/digitalCredential/DigitalCredentialStore.js +118 -0
  8. package/dist/digitalCredential/DigitalCredentialStore.js.map +1 -0
  9. package/dist/entities/digitalCredential/DigitalCredentialEntity.d.ts +23 -0
  10. package/dist/entities/digitalCredential/DigitalCredentialEntity.d.ts.map +1 -0
  11. package/dist/entities/digitalCredential/DigitalCredentialEntity.js +93 -0
  12. package/dist/entities/digitalCredential/DigitalCredentialEntity.js.map +1 -0
  13. package/dist/entities/machineState/MachineStateInfoEntity.d.ts +33 -0
  14. package/dist/entities/machineState/MachineStateInfoEntity.d.ts.map +1 -0
  15. package/dist/entities/machineState/MachineStateInfoEntity.js +85 -0
  16. package/dist/entities/machineState/MachineStateInfoEntity.js.map +1 -0
  17. package/dist/index.d.ts +10 -3
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +19 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/machineState/IAbstractMachineStateStore.d.ts +52 -0
  22. package/dist/machineState/IAbstractMachineStateStore.d.ts.map +1 -0
  23. package/dist/machineState/IAbstractMachineStateStore.js +13 -0
  24. package/dist/machineState/IAbstractMachineStateStore.js.map +1 -0
  25. package/dist/machineState/MachineStateStore.d.ts +21 -0
  26. package/dist/machineState/MachineStateStore.d.ts.map +1 -0
  27. package/dist/machineState/MachineStateStore.js +137 -0
  28. package/dist/machineState/MachineStateStore.js.map +1 -0
  29. package/dist/migrations/generic/6-CreateDigitalCredential.d.ts +7 -0
  30. package/dist/migrations/generic/6-CreateDigitalCredential.d.ts.map +1 -0
  31. package/dist/migrations/generic/6-CreateDigitalCredential.js +78 -0
  32. package/dist/migrations/generic/6-CreateDigitalCredential.js.map +1 -0
  33. package/dist/migrations/generic/7-CreateMachineStateStore.d.ts +7 -0
  34. package/dist/migrations/generic/7-CreateMachineStateStore.d.ts.map +1 -0
  35. package/dist/migrations/generic/7-CreateMachineStateStore.js +78 -0
  36. package/dist/migrations/generic/7-CreateMachineStateStore.js.map +1 -0
  37. package/dist/migrations/generic/index.d.ts +4 -0
  38. package/dist/migrations/generic/index.d.ts.map +1 -1
  39. package/dist/migrations/generic/index.js +7 -1
  40. package/dist/migrations/generic/index.js.map +1 -1
  41. package/dist/migrations/index.d.ts +1 -1
  42. package/dist/migrations/index.d.ts.map +1 -1
  43. package/dist/migrations/index.js +3 -1
  44. package/dist/migrations/index.js.map +1 -1
  45. package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.d.ts +7 -0
  46. package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.d.ts.map +1 -0
  47. package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.js +59 -0
  48. package/dist/migrations/postgres/1708525189001-CreateDigitalCredential.js.map +1 -0
  49. package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.d.ts +7 -0
  50. package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.d.ts.map +1 -0
  51. package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.js +45 -0
  52. package/dist/migrations/postgres/1708797018115-CreateMachineStateStore.js.map +1 -0
  53. package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.d.ts +7 -0
  54. package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.d.ts.map +1 -0
  55. package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.js +50 -0
  56. package/dist/migrations/sqlite/1708525189002-CreateDigitalCredential.js.map +1 -0
  57. package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.d.ts +7 -0
  58. package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.d.ts.map +1 -0
  59. package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.js +44 -0
  60. package/dist/migrations/sqlite/1708796002272-CreateMachineStateStore.js.map +1 -0
  61. package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.d.ts +42 -0
  62. package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.d.ts.map +1 -0
  63. package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.js +3 -0
  64. package/dist/types/digitalCredential/IAbstractDigitalCredentialStore.js.map +1 -0
  65. package/dist/types/digitalCredential/digitalCredential.d.ts +42 -0
  66. package/dist/types/digitalCredential/digitalCredential.d.ts.map +1 -0
  67. package/dist/types/digitalCredential/digitalCredential.js +28 -0
  68. package/dist/types/digitalCredential/digitalCredential.js.map +1 -0
  69. package/dist/types/index.d.ts +1 -0
  70. package/dist/types/index.d.ts.map +1 -1
  71. package/dist/types/index.js +1 -0
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/types/machineState/IAbstractMachineStateStore.d.ts +58 -0
  74. package/dist/types/machineState/IAbstractMachineStateStore.d.ts.map +1 -0
  75. package/dist/types/machineState/IAbstractMachineStateStore.js +3 -0
  76. package/dist/types/machineState/IAbstractMachineStateStore.js.map +1 -0
  77. package/dist/utils/SortingUtils.d.ts +3 -0
  78. package/dist/utils/SortingUtils.d.ts.map +1 -0
  79. package/dist/utils/SortingUtils.js +18 -0
  80. package/dist/utils/SortingUtils.js.map +1 -0
  81. package/dist/utils/digitalCredential/MappingUtils.d.ts +7 -0
  82. package/dist/utils/digitalCredential/MappingUtils.d.ts.map +1 -0
  83. package/dist/utils/digitalCredential/MappingUtils.js +99 -0
  84. package/dist/utils/digitalCredential/MappingUtils.js.map +1 -0
  85. package/package.json +5 -4
  86. package/src/__tests__/digitalCredential.entities.test.ts +254 -0
  87. package/src/__tests__/digitalCredential.store.test.ts +294 -0
  88. package/src/__tests__/machineState.entities.test.ts +51 -0
  89. package/src/__tests__/machineState.store.test.ts +174 -0
  90. package/src/digitalCredential/AbstractDigitalCredentialStore.ts +17 -0
  91. package/src/digitalCredential/DigitalCredentialStore.ts +127 -0
  92. package/src/entities/digitalCredential/DigitalCredentialEntity.ts +64 -0
  93. package/src/entities/machineState/MachineStateInfoEntity.ts +58 -0
  94. package/src/index.ts +18 -0
  95. package/src/machineState/IAbstractMachineStateStore.ts +65 -0
  96. package/src/machineState/MachineStateStore.ts +151 -0
  97. package/src/migrations/generic/6-CreateDigitalCredential.ts +66 -0
  98. package/src/migrations/generic/7-CreateMachineStateStore.ts +66 -0
  99. package/src/migrations/generic/index.ts +6 -0
  100. package/src/migrations/index.ts +2 -0
  101. package/src/migrations/postgres/1708525189001-CreateDigitalCredential.ts +44 -0
  102. package/src/migrations/postgres/1708797018115-CreateMachineStateStore.ts +29 -0
  103. package/src/migrations/sqlite/1708525189002-CreateDigitalCredential.ts +34 -0
  104. package/src/migrations/sqlite/1708796002272-CreateMachineStateStore.ts +28 -0
  105. package/src/types/digitalCredential/IAbstractDigitalCredentialStore.ts +37 -0
  106. package/src/types/digitalCredential/digitalCredential.ts +46 -0
  107. package/src/types/index.ts +1 -0
  108. package/src/types/machineState/IAbstractMachineStateStore.ts +68 -0
  109. package/src/utils/SortingUtils.ts +16 -0
  110. package/src/utils/digitalCredential/MappingUtils.ts +122 -0
@@ -0,0 +1,151 @@
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
+ return Promise.reject(
42
+ new Error(
43
+ `Updating machine state with an older version is not allowed. Machine ${existing.machineName}, last count: ${
44
+ existing.updatedCount
45
+ }, new count: ${existing.updatedCount}, last updated: ${existing.updatedAt}, current: ${new Date()}, instance: ${existing.instanceId}`
46
+ )
47
+ )
48
+ }
49
+ // 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
50
+ const result = await connection.getRepository(MachineStateInfoEntity).save(entity, { transaction: false })
51
+ debug(`Done persistMachineState machine ${machineName}, instance ${instanceId}, tenantId: ${tenantId}`)
52
+ return MachineStateStore.machineInfoFrom(result)
53
+ }
54
+
55
+ async findActiveMachineStates(args: StoreMachineStatesFindActiveArgs): Promise<Array<StoreMachineStateInfo>> {
56
+ const { tenantId, machineName, instanceId } = args
57
+ const connection: DataSource = await this._dbConnection
58
+ debug(`Executing findActiveMachineStates query with machineName: ${machineName}, tenantId: ${tenantId}`)
59
+ const queryBuilder = connection
60
+ .getRepository(MachineStateInfoEntity)
61
+ .createQueryBuilder('state')
62
+ .where('state.completedAt IS NULL')
63
+ .andWhere(
64
+ new Brackets((qb) => {
65
+ qb.where('state.expiresAt IS NULL').orWhere('state.expiresAt > :now', { now: new Date() })
66
+ })
67
+ )
68
+
69
+ if (instanceId) {
70
+ queryBuilder.andWhere('state.instanceId = :instanceId', { instanceId })
71
+ }
72
+ if (tenantId) {
73
+ queryBuilder.andWhere('state.tenantId = :tenantId', { tenantId })
74
+ }
75
+ if (machineName) {
76
+ queryBuilder.andWhere('state.machineName = :machineName', { machineName })
77
+ }
78
+
79
+ return (
80
+ (await queryBuilder
81
+ .orderBy('state.updatedAt', 'DESC')
82
+ .getMany()
83
+ .then((entities) => entities.map(MachineStateStore.machineInfoFrom))) ?? []
84
+ )
85
+ }
86
+
87
+ async findMachineStates(args?: StoreFindMachineStatesArgs): Promise<Array<StoreMachineStateInfo>> {
88
+ const connection: DataSource = await this._dbConnection
89
+ debug('findMachineStates', args)
90
+ const result: Array<MachineStateInfoEntity> = await connection.getRepository(MachineStateInfoEntity).find({
91
+ ...(args?.filter && { where: args?.filter }),
92
+ transaction: false,
93
+ })
94
+
95
+ return result.map((event: MachineStateInfoEntity) => MachineStateStore.machineInfoFrom(event))
96
+ }
97
+
98
+ async getMachineState(args: StoreMachineStateGetArgs): Promise<StoreMachineStateInfo> {
99
+ const connection: DataSource = await this._dbConnection
100
+ debug('getMachineState', args)
101
+ return connection.getRepository(MachineStateInfoEntity).findOneOrFail({ where: { instanceId: args.instanceId } })
102
+ }
103
+
104
+ async deleteMachineState(args: StoreMachineStateDeleteArgs): Promise<boolean> {
105
+ debug(`Executing deleteMachineState query with id: ${args.instanceId}`)
106
+ if (!args.instanceId) {
107
+ throw new Error('No instanceId parameter is provided.')
108
+ }
109
+ try {
110
+ const connection: DataSource = await this._dbConnection
111
+
112
+ const result = await connection.getRepository(MachineStateInfoEntity).delete(args.instanceId)
113
+ return result.affected != null && result.affected > 0
114
+ } catch (error) {
115
+ debug(`Error deleting state: ${error}`)
116
+ return false
117
+ }
118
+ }
119
+
120
+ async deleteExpiredMachineStates(args: StoreMachineStateDeleteExpiredArgs): Promise<number> {
121
+ const { machineName, tenantId, deleteDoneStates } = args
122
+ debug(`Executing deleteExpiredMachineStates query with params: ${JSON.stringify(args)}`)
123
+ try {
124
+ const connection: DataSource = await this._dbConnection
125
+
126
+ const deleteCriteria: FindOptionsWhere<MachineStateInfoEntity> = {
127
+ ...(machineName && { machineName }),
128
+ ...(tenantId && { tenantId }),
129
+ // When deleteOnDone state is set we only look at completedAt, in other cases we compare current time with expiresAt
130
+ ...(!deleteDoneStates && { expiresAt: LessThan(new Date()) }),
131
+ ...(deleteDoneStates && { completedAt: Not(IsNull()) }),
132
+ }
133
+ const result = await connection.getRepository(MachineStateInfoEntity).delete(deleteCriteria)
134
+ return result.affected ?? 0
135
+ } catch (error) {
136
+ debug(`Error deleting machine info: ${error}`)
137
+ return Promise.reject(new Error(`Error deleting expired machine states for machine type ${machineName}`))
138
+ }
139
+ }
140
+
141
+ protected static machineInfoFrom = (machineStateInfoEntity: MachineStateInfoEntity): StoreMachineStateInfo => {
142
+ // We are making sure no entity function get copied
143
+ return JSON.parse(JSON.stringify(machineStateInfoEntity))
144
+ }
145
+
146
+ static machineStateInfoEntityFrom = (machineStateInfo: StoreMachineStateInfo | StoreMachineStatePersistArgs): MachineStateInfoEntity => {
147
+ const entity = new MachineStateInfoEntity()
148
+ Object.assign(entity, machineStateInfo)
149
+ return entity
150
+ }
151
+ }
@@ -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
  ]
@@ -4,4 +4,6 @@ export {
4
4
  DataStoreContactMigrations,
5
5
  DataStoreIssuanceBrandingMigrations,
6
6
  DataStoreStatusListMigrations,
7
+ DataStoreDigitalCredentialMigrations,
8
+ DataStoreMachineStateMigrations,
7
9
  } from './generic'
@@ -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
+ }
@@ -7,3 +7,4 @@ export * from './statusList/statusList'
7
7
  export * from './statusList/IAbstractStatusListStore'
8
8
  export * from './eventLogger/IAbstractEventLoggerStore'
9
9
  export * from './eventLogger/eventLogger'
10
+ export * from './machineState/IAbstractMachineStateStore'
@@ -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
+ }