diff --git a/packages/data-store/src/__tests__/xstatePersistence.entities.test.ts b/packages/data-store/src/__tests__/xstatePersistence.entities.test.ts index 2f4ff8aa5..19437a316 100644 --- a/packages/data-store/src/__tests__/xstatePersistence.entities.test.ts +++ b/packages/data-store/src/__tests__/xstatePersistence.entities.test.ts @@ -1,45 +1,45 @@ -import {DataSource} from 'typeorm' -import {StateEntity, stateEntityFrom} from "../entities/xstatePersistence/StateEntity"; +import { DataSource } from 'typeorm' +import { StateEntity, stateEntityFrom } from '../entities/xstatePersistence/StateEntity' -import {DataStoreXStateStoreEntities, DataStoreXStateStoreMigrations, NonPersistedXStateStoreEvent} from '../index' +import { DataStoreXStateStoreEntities, DataStoreXStateStoreMigrations, NonPersistedXStateStoreEvent } from '../index' describe('Database entities tests', (): void => { - let dbConnection: DataSource + let dbConnection: DataSource - beforeEach(async (): Promise => { - dbConnection = await new DataSource({ - type: 'sqlite', - database: ':memory:', - //logging: 'all', - migrationsRun: false, - migrations: DataStoreXStateStoreMigrations, - synchronize: false, - entities: [...DataStoreXStateStoreEntities], - }).initialize() - await dbConnection.runMigrations() - expect(await dbConnection.showMigrations()).toBeFalsy() - }) + beforeEach(async (): Promise => { + dbConnection = await new DataSource({ + type: 'sqlite', + database: ':memory:', + //logging: 'all', + migrationsRun: false, + migrations: DataStoreXStateStoreMigrations, + synchronize: false, + entities: [...DataStoreXStateStoreEntities], + }).initialize() + await dbConnection.runMigrations() + expect(await dbConnection.showMigrations()).toBeFalsy() + }) - afterEach(async (): Promise => { - await dbConnection.destroy() - }) + afterEach(async (): Promise => { + await dbConnection.destroy() + }) - it('should save xstate event to database', async (): Promise => { - const xstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', - completedAt: new Date(), - tenantId: 'test_tenant_id' - } + it('should save xstate event to database', async (): Promise => { + const xstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', + completedAt: new Date(), + tenantId: 'test_tenant_id', + } - const xstateEventEntity: StateEntity = stateEntityFrom(xstateEvent) - const fromDb: StateEntity = await dbConnection.getRepository(StateEntity).save(xstateEventEntity) + const xstateEventEntity: StateEntity = stateEntityFrom(xstateEvent) + const fromDb: StateEntity = await dbConnection.getRepository(StateEntity).save(xstateEventEntity) - expect(fromDb).toBeDefined() - expect(fromDb?.id).not.toBeNull() - expect(fromDb?.type).toEqual(xstateEvent.type) - expect(fromDb?.state).toEqual(xstateEvent.state) - expect(fromDb?.tenantId).toEqual(xstateEvent.tenantId) - expect(fromDb?.completedAt).toEqual(xstateEvent.completedAt) - }) + expect(fromDb).toBeDefined() + expect(fromDb?.id).not.toBeNull() + expect(fromDb?.type).toEqual(xstateEvent.type) + expect(fromDb?.state).toEqual(xstateEvent.state) + expect(fromDb?.tenantId).toEqual(xstateEvent.tenantId) + expect(fromDb?.completedAt).toEqual(xstateEvent.completedAt) + }) }) diff --git a/packages/data-store/src/__tests__/xstatePersistence.store.test.ts b/packages/data-store/src/__tests__/xstatePersistence.store.test.ts index c732e0167..ba1551781 100644 --- a/packages/data-store/src/__tests__/xstatePersistence.store.test.ts +++ b/packages/data-store/src/__tests__/xstatePersistence.store.test.ts @@ -1,120 +1,121 @@ -import {DataSource} from 'typeorm' -import {DataStoreXStateStoreEntities, GetStateArgs, NonPersistedXStateStoreEvent, State, XStateStore} from '../index' -import {DataStoreXStateStoreMigrations} from '../migrations' +import { DataSource } from 'typeorm' +import { DataStoreXStateStoreEntities, GetStateArgs, NonPersistedXStateStoreEvent, State, XStateStore } from '../index' +import { DataStoreXStateStoreMigrations } from '../migrations' describe('Database entities tests', (): void => { - let dbConnection: DataSource - let xstateStore: XStateStore - - beforeEach(async (): Promise => { - dbConnection = await new DataSource({ - type: 'sqlite', - database: ':memory:', - logging: 'all', - migrationsRun: false, - migrations: DataStoreXStateStoreMigrations, - synchronize: false, - entities: DataStoreXStateStoreEntities, - }).initialize() - await dbConnection.runMigrations() - expect(await dbConnection.showMigrations()).toBeFalsy() - xstateStore = new XStateStore(dbConnection) + let dbConnection: DataSource + let xstateStore: XStateStore + + beforeEach(async (): Promise => { + dbConnection = await new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: 'all', + migrationsRun: false, + migrations: DataStoreXStateStoreMigrations, + synchronize: false, + entities: DataStoreXStateStoreEntities, + }).initialize() + await dbConnection.runMigrations() + expect(await dbConnection.showMigrations()).toBeFalsy() + xstateStore = new XStateStore(dbConnection) + }) + + afterEach(async (): Promise => { + await dbConnection.destroy() + }) + + it('should store xstate event', async (): Promise => { + const xstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', + createdAt: new Date(), + updatedAt: new Date(), + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + + const savedXStoreEvent: State = await xstateStore.saveState(xstateEvent) + expect(savedXStoreEvent).toBeDefined() + }) + + it('should get all state events', async (): Promise => { + const xstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + + const stateEvent1: NonPersistedXStateStoreEvent = await xstateStore.saveState({ ...xstateEvent }) + expect(stateEvent1).toBeDefined() + + const stateEvent2: NonPersistedXStateStoreEvent = await xstateStore.saveState({ ...xstateEvent }) + expect(stateEvent2).toBeDefined() + + const result: Array = await xstateStore.getStates() + expect(result).toHaveLength(2) + }) + + it('should retrieve an xstate event', async (): Promise => { + const xstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + + const savedXStoreEvent1: State = await xstateStore.saveState(xstateEvent) + expect(savedXStoreEvent1).toBeDefined() + + const result: State = await xstateStore.getState(xstateEvent) + expect(result).toBeDefined() + }) + + it('should return an error if type filter does not match', async (): Promise => { + const args: GetStateArgs = { + type: 'unknown_event', + } + + await expect(xstateStore.getState(args)).rejects.toEqual(Error('No state found for type: unknown_event')) + }) + + it('should delete the expired records', async () => { + const now = new Date() + const newestXstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'test_type_1', + createdAt: now, + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + const middleXstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'test_type_2', + createdAt: new Date(+now - 30000), + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + + const oldestXstateEvent: NonPersistedXStateStoreEvent = { + state: 'test_state', + type: 'test_type_3', + createdAt: new Date(+now - 60000), + completedAt: new Date(), + tenantId: 'test_tenant_id', + } + + await xstateStore.saveState(oldestXstateEvent) + await xstateStore.saveState(middleXstateEvent) + await xstateStore.saveState(newestXstateEvent) + + await xstateStore.deleteState({ + where: `created_at < datetime('now', :ttl)`, + parameters: { ttl: '-30 seconds' }, }) - afterEach(async (): Promise => { - await dbConnection.destroy() - }) - - it('should store xstate event', async (): Promise => { - const xstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', - createdAt: new Date(), - updatedAt: new Date(), - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - - const savedXStoreEvent: State = await xstateStore.saveState(xstateEvent) - expect(savedXStoreEvent).toBeDefined() - }) - - it('should get all state events', async (): Promise => { - const xstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - - const stateEvent1: NonPersistedXStateStoreEvent = await xstateStore.saveState({...xstateEvent}) - expect(stateEvent1).toBeDefined() - - const stateEvent2: NonPersistedXStateStoreEvent = await xstateStore.saveState({...xstateEvent}) - expect(stateEvent2).toBeDefined() - - const result: Array = await xstateStore.getStates() - expect(result).toHaveLength(2) - }) - - it('should retrieve an xstate event', async (): Promise => { - const xstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - - const savedXStoreEvent1: State = await xstateStore.saveState(xstateEvent) - expect(savedXStoreEvent1).toBeDefined() - - const result: State = await xstateStore.getState(xstateEvent) - expect(result).toBeDefined() - }) - - it('should return an error if type filter does not match', async (): Promise => { - const args: GetStateArgs = { - type: 'unknown_event' - } - - await expect(xstateStore.getState(args)).rejects.toEqual(Error('No state found for type: unknown_event')) - }) - - it('should delete the expired records', async () => { - const now = new Date() - const newestXstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'test_type_1', - createdAt: now, - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - const middleXstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'test_type_2', - createdAt: new Date(+now - 30000), - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - - const oldestXstateEvent: NonPersistedXStateStoreEvent = { - state: 'test_state', - type: 'test_type_3', - createdAt: new Date(+now - 60000), - completedAt: new Date(), - tenantId: 'test_tenant_id' - } - - await xstateStore.saveState(oldestXstateEvent) - await xstateStore.saveState(middleXstateEvent) - await xstateStore.saveState(newestXstateEvent) - - await xstateStore.deleteState({ - where: `created_at < datetime('now', :ttl)`, parameters: { ttl: '-30 seconds' } - }) - - await expect(xstateStore.getState({ type: 'test_type_1'})).resolves.toBeDefined() - await expect(xstateStore.getState({ type: 'test_type_2'})).resolves.toBeDefined() - await expect(xstateStore.getState({ type: 'test_type_3'})).rejects.toEqual(Error('No state found for type: test_type_3')) - }) + await expect(xstateStore.getState({ type: 'test_type_1' })).resolves.toBeDefined() + await expect(xstateStore.getState({ type: 'test_type_2' })).resolves.toBeDefined() + await expect(xstateStore.getState({ type: 'test_type_3' })).rejects.toEqual(Error('No state found for type: test_type_3')) + }) }) diff --git a/packages/data-store/src/entities/xstatePersistence/StateEntity.ts b/packages/data-store/src/entities/xstatePersistence/StateEntity.ts index 62e887b54..0cde43db9 100644 --- a/packages/data-store/src/entities/xstatePersistence/StateEntity.ts +++ b/packages/data-store/src/entities/xstatePersistence/StateEntity.ts @@ -1,35 +1,35 @@ -import {BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm" -import {NonPersistedXStateStoreEvent} from "../../types"; +import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' +import { NonPersistedXStateStoreEvent } from '../../types' @Entity('StateEntity') export class StateEntity extends BaseEntity { - @PrimaryGeneratedColumn('uuid', { name: 'id' }) - id!: string + @PrimaryGeneratedColumn('uuid', { name: 'id' }) + id!: string - @Column({ name: 'state', nullable: false }) - state!: string + @Column({ name: 'state', nullable: false }) + state!: string - @Column({ name: 'type', nullable: false }) - type!: string + @Column({ name: 'type', nullable: false }) + type!: string - @CreateDateColumn({ name: 'created_at', nullable: false }) - createdAt!: Date + @CreateDateColumn({ name: 'created_at', nullable: false }) + createdAt!: Date - @UpdateDateColumn({ name: 'updated_at', nullable: false }) - updatedAt!: Date + @UpdateDateColumn({ name: 'updated_at', nullable: false }) + updatedAt!: Date - @Column({ name: 'completed_at', type: 'datetime', nullable: true }) - completedAt?: Date + @Column({ name: 'completed_at', type: 'datetime', nullable: true }) + completedAt?: Date - @Column({ name: 'tenant_id', type: 'varchar', nullable: true }) - tenantId?: string + @Column({ name: 'tenant_id', type: 'varchar', nullable: true }) + tenantId?: string } export const stateEntityFrom = (args: NonPersistedXStateStoreEvent): StateEntity => { - const stateEntity = new StateEntity() - stateEntity.state = args.state - stateEntity.type = args.type - stateEntity.completedAt = args.completedAt - stateEntity.tenantId = args.tenantId - return stateEntity + const stateEntity = new StateEntity() + stateEntity.state = args.state + stateEntity.type = args.type + stateEntity.completedAt = args.completedAt + stateEntity.tenantId = args.tenantId + return stateEntity } diff --git a/packages/data-store/src/index.ts b/packages/data-store/src/index.ts index e7ce00f30..ab3dfa84f 100644 --- a/packages/data-store/src/index.ts +++ b/packages/data-store/src/index.ts @@ -18,7 +18,7 @@ import { IssuerBrandingEntity, issuerBrandingEntityFrom } from './entities/issua import { TextAttributesEntity, textAttributesEntityFrom } from './entities/issuanceBranding/TextAttributesEntity' import { StatusListEntity } from './entities/statusList2021/StatusList2021Entity' import { StatusListEntryEntity } from './entities/statusList2021/StatusList2021EntryEntity' -import { StateEntity } from "./entities/xstatePersistence/StateEntity"; +import { StateEntity } from './entities/xstatePersistence/StateEntity' import { IStatusListEntity, IStatusListEntryEntity } from './types' import { PartyRelationshipEntity } from './entities/contact/PartyRelationshipEntity' import { PartyTypeEntity } from './entities/contact/PartyTypeEntity' @@ -88,7 +88,7 @@ export const DataStoreEntities = [ ...DataStoreIssuanceBrandingEntities, ...DataStoreStatusListEntities, ...DataStoreEventLoggerEntities, - ...DataStoreXStateStoreEntities + ...DataStoreXStateStoreEntities, ] export { @@ -124,5 +124,5 @@ export { StatusListEntryEntity, AuditEventEntity, auditEventEntityFrom, - StateEntity + StateEntity, } diff --git a/packages/data-store/src/migrations/generic/6-CreateXStateStore.ts b/packages/data-store/src/migrations/generic/6-CreateXStateStore.ts index 51b8df8db..42acc8db1 100644 --- a/packages/data-store/src/migrations/generic/6-CreateXStateStore.ts +++ b/packages/data-store/src/migrations/generic/6-CreateXStateStore.ts @@ -6,61 +6,61 @@ import { CreateXStateStore1708096002272 } from '../sqlite/1708096002272-CreateXS const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:migrations') export class CreateXStateStore1708098041262 implements MigrationInterface { - name = 'CreateXStateStore1708098041262' + name = 'CreateXStateStore1708098041262' - public async up(queryRunner: QueryRunner): Promise { - debug('migration: creating contacts tables') - const dbType: DatabaseType = queryRunner.connection.driver.options.type + public async up(queryRunner: QueryRunner): Promise { + debug('migration: creating contacts tables') + const dbType: DatabaseType = queryRunner.connection.driver.options.type - switch (dbType) { - case 'postgres': { - debug('using postgres migration file') - const mig: CreateXStateStore1708097018115 = new CreateXStateStore1708097018115() - await mig.up(queryRunner) - debug('Migration statements executed') - return - } - case 'sqlite': - case 'expo': - case 'react-native': { - debug('using sqlite/react-native migration file') - const mig: CreateXStateStore1708096002272 = new CreateXStateStore1708096002272() - await mig.up(queryRunner) - debug('Migration statements executed') - return - } - default: - return Promise.reject( - `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` - ) - } + switch (dbType) { + case 'postgres': { + debug('using postgres migration file') + const mig: CreateXStateStore1708097018115 = new CreateXStateStore1708097018115() + await mig.up(queryRunner) + debug('Migration statements executed') + return + } + case 'sqlite': + case 'expo': + case 'react-native': { + debug('using sqlite/react-native migration file') + const mig: CreateXStateStore1708096002272 = new CreateXStateStore1708096002272() + await mig.up(queryRunner) + debug('Migration statements executed') + return + } + default: + return Promise.reject( + `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` + ) } + } - public async down(queryRunner: QueryRunner): Promise { - debug('migration: reverting contacts tables') - const dbType: DatabaseType = queryRunner.connection.driver.options.type + public async down(queryRunner: QueryRunner): Promise { + debug('migration: reverting contacts tables') + const dbType: DatabaseType = queryRunner.connection.driver.options.type - switch (dbType) { - case 'postgres': { - debug('using postgres migration file') - const mig: CreateXStateStore1708097018115 = new CreateXStateStore1708097018115() - await mig.down(queryRunner) - debug('Migration statements executed') - return - } - case 'sqlite': - case 'expo': - case 'react-native': { - debug('using sqlite/react-native migration file') - const mig: CreateXStateStore1708096002272 = new CreateXStateStore1708096002272() - await mig.down(queryRunner) - debug('Migration statements executed') - return - } - default: - return Promise.reject( - `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` - ) - } + switch (dbType) { + case 'postgres': { + debug('using postgres migration file') + const mig: CreateXStateStore1708097018115 = new CreateXStateStore1708097018115() + await mig.down(queryRunner) + debug('Migration statements executed') + return + } + case 'sqlite': + case 'expo': + case 'react-native': { + debug('using sqlite/react-native migration file') + const mig: CreateXStateStore1708096002272 = new CreateXStateStore1708096002272() + await mig.down(queryRunner) + debug('Migration statements executed') + return + } + default: + return Promise.reject( + `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` + ) } + } } diff --git a/packages/data-store/src/migrations/generic/index.ts b/packages/data-store/src/migrations/generic/index.ts index ce854224b..d95905d03 100644 --- a/packages/data-store/src/migrations/generic/index.ts +++ b/packages/data-store/src/migrations/generic/index.ts @@ -3,7 +3,7 @@ import { CreateIssuanceBranding1659463079429 } from './2-CreateIssuanceBranding' import { CreateContacts1690925872318 } from './3-CreateContacts' import { CreateStatusList1693866470000 } from './4-CreateStatusList' import { CreateAuditEvents1701635835330 } from './5-CreateAuditEvents' -import {CreateXStateStore1708098041262} from "./6-CreateXStateStore"; +import { CreateXStateStore1708098041262 } from './6-CreateXStateStore' /** * The migrations array that SHOULD be used when initializing a TypeORM database connection. @@ -26,5 +26,5 @@ export const DataStoreMigrations = [ ...DataStoreIssuanceBrandingMigrations, ...DataStoreStatusListMigrations, ...DataStoreEventLoggerMigrations, - ...DataStoreXStateStoreMigrations + ...DataStoreXStateStoreMigrations, ] diff --git a/packages/data-store/src/migrations/index.ts b/packages/data-store/src/migrations/index.ts index a346e1eca..e6c689af2 100644 --- a/packages/data-store/src/migrations/index.ts +++ b/packages/data-store/src/migrations/index.ts @@ -4,5 +4,5 @@ export { DataStoreContactMigrations, DataStoreIssuanceBrandingMigrations, DataStoreStatusListMigrations, - DataStoreXStateStoreMigrations + DataStoreXStateStoreMigrations, } from './generic' diff --git a/packages/data-store/src/migrations/postgres/1708097018115-CreateXStateStore.ts b/packages/data-store/src/migrations/postgres/1708097018115-CreateXStateStore.ts index ef1c0e313..bfbe1a02d 100644 --- a/packages/data-store/src/migrations/postgres/1708097018115-CreateXStateStore.ts +++ b/packages/data-store/src/migrations/postgres/1708097018115-CreateXStateStore.ts @@ -1,18 +1,18 @@ -import {enablePostgresUuidExtension} from "@sphereon/ssi-sdk.core"; -import {MigrationInterface, QueryRunner} from "typeorm"; +import { enablePostgresUuidExtension } from '@sphereon/ssi-sdk.core' +import { MigrationInterface, QueryRunner } from 'typeorm' export class CreateXStateStore1708097018115 implements MigrationInterface { - name = 'CreateXStateStore1708097018115' + name = 'CreateXStateStore1708097018115' - public async up(queryRunner: QueryRunner): Promise { - await enablePostgresUuidExtension(queryRunner) - await queryRunner.query( - `CREATE TABLE "StateEntity" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "state" varchar(255) NOT NULL, "type" varchar(255) NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "completed_at" TIMESTAMP, "tenant_id" varchar(255) NULL, "ttl" INTEGER NULL, CONSTRAINT PK_XStateStore_id PRIMARY KEY ("id"))` - ) - } + public async up(queryRunner: QueryRunner): Promise { + await enablePostgresUuidExtension(queryRunner) + await queryRunner.query( + `CREATE TABLE "StateEntity" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "state" varchar(255) NOT NULL, "type" varchar(255) NOT NULL, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "completed_at" TIMESTAMP, "tenant_id" varchar(255) NULL, "ttl" INTEGER NULL, CONSTRAINT PK_XStateStore_id PRIMARY KEY ("id"))` + ) + } - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "StateEntity" DROP CONSTRAINT "PK_StateStore_id"`) - await queryRunner.query(`DROP TABLE "StateEntity"`) - } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "StateEntity" DROP CONSTRAINT "PK_StateStore_id"`) + await queryRunner.query(`DROP TABLE "StateEntity"`) + } } diff --git a/packages/data-store/src/migrations/sqlite/1708096002272-CreateXStateStore.ts b/packages/data-store/src/migrations/sqlite/1708096002272-CreateXStateStore.ts index 5b14a98f2..90c127bed 100644 --- a/packages/data-store/src/migrations/sqlite/1708096002272-CreateXStateStore.ts +++ b/packages/data-store/src/migrations/sqlite/1708096002272-CreateXStateStore.ts @@ -1,16 +1,16 @@ -import {MigrationInterface, QueryRunner} from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm' export class CreateXStateStore1708096002272 implements MigrationInterface { - name = 'CreateXStateStore1708096002272' + name = 'CreateXStateStore1708096002272' - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "StateEntity" ("id" varchar PRIMARY KEY, "state" varchar(255) NOT NULL, "type" varchar(255) NOT NULL, "created_at" DATETIME NOT NULL DEFAULT (datetime('now')), "updated_at" DATETIME NOT NULL DEFAULT (datetime('now')), "completed_at" DATETIME, "tenant_id" varchar(255) NULL, "ttl" INTEGER NULL)` - ) - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "StateEntity" ("id" varchar PRIMARY KEY, "state" varchar(255) NOT NULL, "type" varchar(255) NOT NULL, "created_at" DATETIME NOT NULL DEFAULT (datetime('now')), "updated_at" DATETIME NOT NULL DEFAULT (datetime('now')), "completed_at" DATETIME, "tenant_id" varchar(255) NULL, "ttl" INTEGER NULL)` + ) + } - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "StateEntity"`) - await queryRunner.query(`DROP TABLE "StateEntity"`) - } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "StateEntity"`) + await queryRunner.query(`DROP TABLE "StateEntity"`) + } } diff --git a/packages/data-store/src/types/xstatePersistence/IAbstractXStateStore.ts b/packages/data-store/src/types/xstatePersistence/IAbstractXStateStore.ts index aa567e2b1..b5e18bf8d 100644 --- a/packages/data-store/src/types/xstatePersistence/IAbstractXStateStore.ts +++ b/packages/data-store/src/types/xstatePersistence/IAbstractXStateStore.ts @@ -1,12 +1,12 @@ -import {ObjectLiteral} from "typeorm"; +import { ObjectLiteral } from 'typeorm' export type SaveStateArgs = { - state: string - type: string - createdAt?: Date - updatedAt?: Date - completedAt?: Date - tenantId?: string + state: string + type: string + createdAt?: Date + updatedAt?: Date + completedAt?: Date + tenantId?: string } export type GetStateArgs = Pick @@ -14,20 +14,18 @@ export type GetStateArgs = Pick export type FindStatesArgs = Partial export type GetStatesArgs = { - filter: FindStatesArgs + filter: FindStatesArgs } export type NonPersistedXStateStoreEvent = SaveStateArgs -export type DeleteStateArgs = { where: string, parameters?: ObjectLiteral } - -export type VoidResult = void +export type DeleteStateArgs = { where: string; parameters?: ObjectLiteral } export type State = { - state: string - type: string - createdAt: Date - updatedAt: Date - completedAt?: Date - tenantId?: string + state: string + type: string + createdAt: Date + updatedAt: Date + completedAt?: Date + tenantId?: string } diff --git a/packages/data-store/src/xstatePersistence/IAbstractXStateStore.ts b/packages/data-store/src/xstatePersistence/IAbstractXStateStore.ts index 6ea94ac1c..59135a212 100644 --- a/packages/data-store/src/xstatePersistence/IAbstractXStateStore.ts +++ b/packages/data-store/src/xstatePersistence/IAbstractXStateStore.ts @@ -1,8 +1,8 @@ -import {DeleteStateArgs, GetStateArgs, GetStatesArgs, SaveStateArgs, State, VoidResult} from "../types"; +import { DeleteStateArgs, GetStateArgs, GetStatesArgs, SaveStateArgs, State } from '../types' export abstract class IAbstractXStateStore { - abstract saveState(state: SaveStateArgs): Promise - abstract getState(args: GetStateArgs): Promise - abstract getStates(args?: GetStatesArgs): Promise> - abstract deleteState(args: DeleteStateArgs): Promise + abstract saveState(state: SaveStateArgs): Promise + abstract getState(args: GetStateArgs): Promise + abstract getStates(args?: GetStatesArgs): Promise> + abstract deleteState(args: DeleteStateArgs): Promise } diff --git a/packages/data-store/src/xstatePersistence/XStateStore.ts b/packages/data-store/src/xstatePersistence/XStateStore.ts index dbfe705d1..d28ac20c3 100644 --- a/packages/data-store/src/xstatePersistence/XStateStore.ts +++ b/packages/data-store/src/xstatePersistence/XStateStore.ts @@ -1,68 +1,70 @@ -import {OrPromise} from "@sphereon/ssi-types"; +import { OrPromise } from '@sphereon/ssi-types' import Debug from 'debug' -import {DataSource} from "typeorm"; +import { DataSource, DeleteResult } from 'typeorm' -import {StateEntity} from "../entities/xstatePersistence/StateEntity"; -import {DeleteStateArgs, GetStateArgs, GetStatesArgs, SaveStateArgs, State, VoidResult,} from "../types"; -import {IAbstractXStateStore} from "./IAbstractXStateStore"; +import { StateEntity } from '../entities/xstatePersistence/StateEntity' +import { DeleteStateArgs, GetStateArgs, GetStatesArgs, SaveStateArgs, State } from '../types' +import { IAbstractXStateStore } from './IAbstractXStateStore' const debug = Debug('sphereon:ssi-sdk:xstatePersistence') export class XStateStore extends IAbstractXStateStore { - private readonly dbConnection: OrPromise + private readonly dbConnection: OrPromise - constructor(dbConnection: OrPromise) { - super() - this.dbConnection = dbConnection - } + constructor(dbConnection: OrPromise) { + super() + this.dbConnection = dbConnection + } - async saveState(state: SaveStateArgs): Promise { - const connection: DataSource = await this.dbConnection - debug(`Executing saveState with state: ${JSON.stringify(state)}`) - return connection.getRepository(StateEntity).save(state); - } + async saveState(state: SaveStateArgs): Promise { + const connection: DataSource = await this.dbConnection + debug(`Executing saveState with state: ${JSON.stringify(state)}`) + return connection.getRepository(StateEntity).save(state) + } - async getState(args: GetStateArgs): Promise { - const connection: DataSource = await this.dbConnection - debug(`Executing loadState query with type: ${args.type}`) - const result: StateEntity | null = await connection.getRepository(StateEntity) - .findOne({ - where: { type: args.type } - }) - if (!result) { - return Promise.reject(Error(`No state found for type: ${args.type}`)) - } - return this.stateFrom(result) + async getState(args: GetStateArgs): Promise { + const connection: DataSource = await this.dbConnection + debug(`Executing loadState query with type: ${args.type}`) + const result: StateEntity | null = await connection.getRepository(StateEntity).findOne({ + where: { type: args.type }, + }) + if (!result) { + return Promise.reject(Error(`No state found for type: ${args.type}`)) } + return this.stateFrom(result) + } - async getStates(args?: GetStatesArgs): Promise> { - const connection: DataSource = await this.dbConnection // TODO apply everywhere - debug('Getting states', args) - const result: Array = await connection.getRepository(StateEntity).find({ - ...(args?.filter && { where: args?.filter }), - }) + async getStates(args?: GetStatesArgs): Promise> { + const connection: DataSource = await this.dbConnection // TODO apply everywhere + debug('Getting states', args) + const result: Array = await connection.getRepository(StateEntity).find({ + ...(args?.filter && { where: args?.filter }), + }) - return result.map((event: StateEntity) => this.stateFrom(event)) - } + return result.map((event: StateEntity) => this.stateFrom(event)) + } + + async deleteState(args: DeleteStateArgs): Promise { + try { + const connection: DataSource = await this.dbConnection + debug(`Executing deleteState query with where clause: ${args.where} and params: ${JSON.stringify(args.parameters)}`) + const result: DeleteResult = await connection.createQueryBuilder().delete().from(StateEntity).where(args.where, args.parameters).execute() - async deleteState(args: DeleteStateArgs): Promise { - const connection: DataSource = await this.dbConnection - debug(`Executing deleteState query with where clause: ${args.where} and params: ${JSON.stringify(args.parameters)}`) - await connection.createQueryBuilder() - .delete() - .from(StateEntity) - .where(args.where, args.parameters) - .execute() + return result.affected != null && result.affected > 0 + } catch (error) { + debug(`Error deleting state: ${error}`) + return false } + } - private stateFrom = (state: StateEntity): State => { - return { - state: state.id, - type: state.type, - createdAt: state.createdAt, - updatedAt: state.updatedAt, - completedAt: state.completedAt, - tenantId: state.tenantId - } + private stateFrom = (state: StateEntity): State => { + return { + state: state.id, + type: state.type, + createdAt: state.createdAt, + updatedAt: state.updatedAt, + completedAt: state.completedAt, + tenantId: state.tenantId, } + } } diff --git a/packages/event-logger/agent.yml b/packages/event-logger/agent.yml index cfbabc005..c835894be 100644 --- a/packages/event-logger/agent.yml +++ b/packages/event-logger/agent.yml @@ -4,9 +4,8 @@ constants: baseUrl: http://localhost:3335 port: 3335 methods: - - persistState - - loadState - - deleteExpiredStates + - loggerGetAuditEvents + - loggerLogAuditEvent dbConnection: $require: typeorm?t=function#createConnection @@ -18,7 +17,7 @@ dbConnection: migrations: $require: './packages/data-store?t=object#DataStoreMigrations' entities: - $require: './packages/data-store?t=object#DataStoreXStateStoreEntities' + $require: './packages/data-store?t=object#DataStoreEventLoggerEntities' server: baseUrl: @@ -82,9 +81,9 @@ agent: $args: - schemaValidation: false plugins: - - $require: ./packages/xstate-persistence/dist#XStatePersistence + - $require: ./packages/event-logger/dist#EventLogger $args: - store: - $require: './packages/data-store/dist#XStateStore' + $require: './packages/data-store/dist#EventLoggerStore' $args: - $ref: /dbConnection diff --git a/packages/xstate-persistence/agent.yml b/packages/xstate-persistence/agent.yml index 2debeaf30..028d1b9f3 100644 --- a/packages/xstate-persistence/agent.yml +++ b/packages/xstate-persistence/agent.yml @@ -6,10 +6,20 @@ constants: # please use your own X25519 key, this is only an example secretKey: 29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c methods: - - createVerifiableCredentialLDLocal - createVerifiablePresentationLDLocal - verifyPresentationLDLocal - verifyCredentialLDLocal + - persistState + - loadState + - deleteExpiredStates +dbConnection: + $require: typeorm?t=function#createConnection + $args: + - type: sqlite + database: ':memory:' + synchronize: false + migrationsRun: true + migrations: + $require: './packages/data-store?t=object#DataStoreMigrations' + entities: + $require: './packages/data-store?t=object#DataStoreXStateStoreEntities' server: baseUrl: @@ -73,14 +83,9 @@ agent: $args: - schemaValidation: false plugins: - - $require: '@veramo/credential-ld/build#VeramoLdSignature' - # - # - $require: '@veramo/credential-ld/build#CredentialIssuerLD' - # $args: - # - contextMaps: [] - # suites: [] - - $require: ./packages/vc-handler-ld-local/dist#CredentialHandlerLDLocal + - $require: ./packages/xstate-persistence/dist#XStatePersistence $args: - - contextMaps: [] - suites: [] - bindingOverrides: [] + - store: + $require: './packages/data-store/dist#XStateStore' + $args: + - $ref: /dbConnection diff --git a/packages/xstate-persistence/package.json b/packages/xstate-persistence/package.json index acb740b90..2b7407a61 100644 --- a/packages/xstate-persistence/package.json +++ b/packages/xstate-persistence/package.json @@ -14,7 +14,6 @@ "build:clean": "tsc --build --clean && tsc --build", "generate-plugin-schema": "ts-node ../../packages/dev/bin/sphereon.js dev generate-plugin-schema" }, - "devDependencies": { "@sphereon/ssi-sdk.agent-config": "workspace:*", "@sphereon/ssi-sdk.core": "workspace:*", diff --git a/packages/xstate-persistence/plugin.schema.json b/packages/xstate-persistence/plugin.schema.json index f97d81b5e..3271bfeea 100644 --- a/packages/xstate-persistence/plugin.schema.json +++ b/packages/xstate-persistence/plugin.schema.json @@ -25,10 +25,7 @@ ] }, "DeleteStateResult": { - "$ref": "#/components/schemas/VoidResult" - }, - "VoidResult": { - "type": "null" + "type": "boolean" }, "LoadStateArgs": { "$ref": "#/components/schemas/GetStateArgs" diff --git a/packages/xstate-persistence/src/__tests__/localAgent.test.ts b/packages/xstate-persistence/src/__tests__/localAgent.test.ts index fda85a4ec..0c8a32b75 100644 --- a/packages/xstate-persistence/src/__tests__/localAgent.test.ts +++ b/packages/xstate-persistence/src/__tests__/localAgent.test.ts @@ -9,7 +9,7 @@ let dbConnection: Promise let agent: any const setup = async (): Promise => { - const config = await getConfig('packages/event-logger/agent.yml') + const config = await getConfig('packages/xstate-persistence/agent.yml') const { localAgent, db } = await createObjects(config, { localAgent: '/agent', db: '/dbConnection' }) agent = localAgent dbConnection = db diff --git a/packages/xstate-persistence/src/__tests__/restAgent.test.ts b/packages/xstate-persistence/src/__tests__/restAgent.test.ts index 0b7066e28..bee356668 100644 --- a/packages/xstate-persistence/src/__tests__/restAgent.test.ts +++ b/packages/xstate-persistence/src/__tests__/restAgent.test.ts @@ -1,13 +1,13 @@ import 'cross-fetch/polyfill' -import {createAgent, IAgent, IAgentOptions} from '@veramo/core' -import {AgentRestClient} from '@veramo/remote-client' -import {AgentRouter, RequestWithAgentRouter} from '@veramo/remote-server' +import { createAgent, IAgent, IAgentOptions } from '@veramo/core' +import { AgentRestClient } from '@veramo/remote-client' +import { AgentRouter, RequestWithAgentRouter } from '@veramo/remote-server' // @ts-ignore -import express, {Router} from 'express' -import {Server} from 'http' -import {DataSource} from 'typeorm' -import {createObjects, getConfig} from '@sphereon/ssi-sdk.agent-config' -import {IXStatePersistence} from "../index"; +import express, { Router } from 'express' +import { Server } from 'http' +import { DataSource } from 'typeorm' +import { createObjects, getConfig } from '@sphereon/ssi-sdk.agent-config' +import { IXStatePersistence } from '../index' import xStatePersistenceAgentLogic from './shared/xStatePersistenceAgentLogic' jest.setTimeout(60000) @@ -32,7 +32,7 @@ const getAgent = (options?: IAgentOptions) => }) const setup = async (): Promise => { - const config = await getConfig('packages/event-logger/agent.yml') + const config = await getConfig('packages/xstate-persistence/agent.yml') const { agent, db } = await createObjects(config, { agent: '/agent', db: '/dbConnection' }) serverAgent = agent dbConnection = db diff --git a/packages/xstate-persistence/src/__tests__/shared/xStatePersistenceAgentLogic.ts b/packages/xstate-persistence/src/__tests__/shared/xStatePersistenceAgentLogic.ts index 49ae0d990..1bf409da9 100644 --- a/packages/xstate-persistence/src/__tests__/shared/xStatePersistenceAgentLogic.ts +++ b/packages/xstate-persistence/src/__tests__/shared/xStatePersistenceAgentLogic.ts @@ -1,11 +1,11 @@ -import {NonPersistedXStateStoreEvent, State} from "@sphereon/ssi-sdk.data-store"; -import {TAgent} from '@veramo/core' -import {IXStatePersistence, SQLDialect} from '../../index' +import { NonPersistedXStateStoreEvent, State } from '@sphereon/ssi-sdk.data-store' +import { TAgent } from '@veramo/core' +import { IXStatePersistence, SQLDialect } from '../../index' type ConfiguredAgent = TAgent export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Promise; tearDown: () => Promise }): void => { - describe('Event Logger Agent Plugin', (): void => { + describe('xstate-persistence agent plugin', (): void => { let agent: ConfiguredAgent beforeAll(async (): Promise => { @@ -21,8 +21,8 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', createdAt: new Date(), updatedAt: new Date(), - completedAt: new Date(), - tenantId: 'test_tenant_id' + completedAt: new Date(), + tenantId: 'test_tenant_id', } const savedXStoreEvent: State = await agent.persistState(xstateEvent) @@ -35,11 +35,11 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro type: 'b40b8474-58a2-4b23-9fde-bd6ee1902cdb', createdAt: new Date(), updatedAt: new Date(), - completedAt: new Date(), - tenantId: 'test_tenant_id' + completedAt: new Date(), + tenantId: 'test_tenant_id', } - const savedXStoreEvent: State = await agent.persistState({...xstateEvent}) + const savedXStoreEvent: State = await agent.persistState({ ...xstateEvent }) expect(savedXStoreEvent).toBeDefined() const result: State = await agent.loadState({ type: savedXStoreEvent.type }) @@ -53,14 +53,14 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro type: 'test_type_1', createdAt: now, completedAt: new Date(), - tenantId: 'test_tenant_id' + tenantId: 'test_tenant_id', } const middleXstateEvent: NonPersistedXStateStoreEvent = { state: 'test_state', type: 'test_type_2', createdAt: new Date(+now - 30000), - completedAt: new Date(), - tenantId: 'test_tenant_id' + completedAt: new Date(), + tenantId: 'test_tenant_id', } const oldestXstateEvent: NonPersistedXStateStoreEvent = { @@ -68,7 +68,7 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro type: 'test_type_3', createdAt: new Date(+now - 60000), completedAt: new Date(), - tenantId: 'test_tenant_id' + tenantId: 'test_tenant_id', } await agent.persistState(newestXstateEvent) @@ -77,9 +77,9 @@ export default (testContext: { getAgent: () => ConfiguredAgent; setup: () => Pro await agent.deleteExpiredStates({ duration: 40000, dialect: SQLDialect.SQLite3 }) - await expect(agent.loadState({ type: 'test_type_1'})).resolves.toBeDefined() - await expect(agent.loadState({ type: 'test_type_2'})).resolves.toBeDefined() - await expect(agent.loadState({ type: 'test_type_3'})).rejects.toEqual(Error('No state found for type: test_type_3')) + await expect(agent.loadState({ type: 'test_type_1' })).resolves.toBeDefined() + await expect(agent.loadState({ type: 'test_type_2' })).resolves.toBeDefined() + await expect(agent.loadState({ type: 'test_type_3' })).rejects.toEqual(Error('No state found for type: test_type_3')) }) }) } diff --git a/packages/xstate-persistence/src/agent/XStatePersistence.ts b/packages/xstate-persistence/src/agent/XStatePersistence.ts index 89b6286fa..64f36505f 100644 --- a/packages/xstate-persistence/src/agent/XStatePersistence.ts +++ b/packages/xstate-persistence/src/agent/XStatePersistence.ts @@ -1,18 +1,18 @@ -import {DeleteStateArgs, IAbstractXStateStore, State} from "@sphereon/ssi-sdk.data-store"; -import {IAgentPlugin,} from '@veramo/core' +import { DeleteStateArgs, IAbstractXStateStore, State } from '@sphereon/ssi-sdk.data-store' +import { IAgentPlugin } from '@veramo/core' import { - DeleteExpiredStatesArgs, - DeleteStateResult, - NonPersistedXStatePersistenceEvent, - RequiredContext, - schema, - SQLDialect, - XStatePersistenceEvent, - XStatePersistenceEventType, - XStateStateManagerOptions + DeleteExpiredStatesArgs, + DeleteStateResult, + NonPersistedXStatePersistenceEvent, + RequiredContext, + schema, + SQLDialect, + XStatePersistenceEvent, + XStatePersistenceEventType, + XStateStateManagerOptions, } from '../index' -import {IXStatePersistence, LoadStateArgs, LoadStateResult} from "../types"; +import { IXStatePersistence, LoadStateArgs, LoadStateResult } from '../types' /** * This class implements the IXStateStateManager interface using a TypeORM compatible database. @@ -22,72 +22,72 @@ import {IXStatePersistence, LoadStateArgs, LoadStateResult} from "../types"; * @beta This API may change without a BREAKING CHANGE notice. */ export class XStatePersistence implements IAgentPlugin { - readonly schema = schema.IXStatePersistence - readonly methods: IXStatePersistence - readonly eventTypes: Array - readonly store: IAbstractXStateStore + readonly schema = schema.IXStatePersistence + readonly methods: IXStatePersistence + readonly eventTypes: Array + readonly store: IAbstractXStateStore - constructor(opts: XStateStateManagerOptions) { - const { store, eventTypes } = opts + constructor(opts: XStateStateManagerOptions) { + const { store, eventTypes } = opts - this.store = store - this.eventTypes = eventTypes - - this.methods = { - loadState: this.loadState.bind(this), - deleteExpiredStates: this.deleteExpiredStates.bind(this), - persistState: this.persistState.bind(this) - } + this.store = store + this.eventTypes = eventTypes + + this.methods = { + loadState: this.loadState.bind(this), + deleteExpiredStates: this.deleteExpiredStates.bind(this), + persistState: this.persistState.bind(this), } + } - public async onEvent(event: XStatePersistenceEvent, context: RequiredContext): Promise { - switch (event.type) { - case XStatePersistenceEventType.EVERY: - // Calling the context of the agent to make sure the REST client is called when configured - await context.agent.persistState({...event.data}) - break - default: - return Promise.reject(Error('Event type not supported')) - } + public async onEvent(event: XStatePersistenceEvent, context: RequiredContext): Promise { + switch (event.type) { + case XStatePersistenceEventType.EVERY: + // Calling the context of the agent to make sure the REST client is called when configured + await context.agent.persistState({ ...event.data }) + break + default: + return Promise.reject(Error('Event type not supported')) } + } - private async persistState(args: NonPersistedXStatePersistenceEvent): Promise { - if (!this.store) { - return Promise.reject(Error('No store available in options')) - } - return this.store.saveState(args) + private async persistState(args: NonPersistedXStatePersistenceEvent): Promise { + if (!this.store) { + return Promise.reject(Error('No store available in options')) } + return this.store.saveState(args) + } - private async loadState(args: LoadStateArgs): Promise { - if (!this.store) { - return Promise.reject(Error('No store available in options')) - } - return this.store.getState(args) + private async loadState(args: LoadStateArgs): Promise { + if (!this.store) { + return Promise.reject(Error('No store available in options')) } + return this.store.getState(args) + } - private async deleteExpiredStates(args: DeleteExpiredStatesArgs): Promise { - if (!this.store) { - return Promise.reject(Error('No store available in options')) - } - const sqLiteParams: DeleteStateArgs = { - where: `created_at < datetime('now', :duration)`, - parameters: { - duration: `-${args.duration / 1000} seconds` - } - } - const postgreSQLParams: DeleteStateArgs = { - where: 'created_at < :duration', - parameters: { - duration: `NOW() - ${args.duration / 1000} seconds::interval` - } - } - switch (args.dialect) { - case SQLDialect.SQLite3: - return this.store.deleteState(sqLiteParams) - case SQLDialect.PostgreSQL: - return this.store.deleteState(postgreSQLParams) - default: - return Promise.reject(Error('Invalid database dialect')) - } + private async deleteExpiredStates(args: DeleteExpiredStatesArgs): Promise { + if (!this.store) { + return Promise.reject(Error('No store available in options')) + } + const sqLiteParams: DeleteStateArgs = { + where: `created_at < datetime('now', :duration)`, + parameters: { + duration: `-${args.duration / 1000} seconds`, + }, + } + const postgreSQLParams: DeleteStateArgs = { + where: 'created_at < :duration', + parameters: { + duration: `NOW() - ${args.duration / 1000} seconds::interval`, + }, + } + switch (args.dialect) { + case SQLDialect.SQLite3: + return this.store.deleteState(sqLiteParams) + case SQLDialect.PostgreSQL: + return this.store.deleteState(postgreSQLParams) + default: + return Promise.reject(Error('Invalid database dialect')) } + } } diff --git a/packages/xstate-persistence/src/types/IXStatePersistence.ts b/packages/xstate-persistence/src/types/IXStatePersistence.ts index 5f86c2d03..ab440eee1 100644 --- a/packages/xstate-persistence/src/types/IXStatePersistence.ts +++ b/packages/xstate-persistence/src/types/IXStatePersistence.ts @@ -1,13 +1,14 @@ -import {State} from "@sphereon/ssi-sdk.data-store"; -import {IPluginMethodMap} from '@veramo/core' +import { State } from '@sphereon/ssi-sdk.data-store' +import { IPluginMethodMap } from '@veramo/core' import { DeleteExpiredStatesArgs, DeleteStateResult, LoadStateArgs, LoadStateResult, - NonPersistedXStatePersistenceEvent, RequiredContext -} from "./types"; + NonPersistedXStatePersistenceEvent, + RequiredContext, +} from './types' /** * The interface definition for a plugin that can issue and verify Verifiable Credentials and Presentations @@ -30,7 +31,6 @@ export interface IXStatePersistence extends IPluginMethodMap { */ loadState(args: LoadStateArgs): Promise - /** * Deletes the state of an xstate machine in the database. * diff --git a/packages/xstate-persistence/src/types/types.ts b/packages/xstate-persistence/src/types/types.ts index ec2b4049b..e58298d54 100644 --- a/packages/xstate-persistence/src/types/types.ts +++ b/packages/xstate-persistence/src/types/types.ts @@ -1,22 +1,22 @@ -import {GetStateArgs, IAbstractXStateStore, SaveStateArgs, State, VoidResult} from "@sphereon/ssi-sdk.data-store"; -import {IAgentContext} from "@veramo/core"; +import { GetStateArgs, IAbstractXStateStore, SaveStateArgs, State } from '@sphereon/ssi-sdk.data-store' +import { IAgentContext } from '@veramo/core' -import {IXStatePersistence} from "./IXStatePersistence"; +import { IXStatePersistence } from './IXStatePersistence' -export type XStateStateManagerOptions = { store: IAbstractXStateStore, eventTypes: Array } +export type XStateStateManagerOptions = { store: IAbstractXStateStore; eventTypes: Array } export enum XStatePersistenceEventType { - EVERY = 'every' + EVERY = 'every', } export enum SQLDialect { - SQLite3 = 'SQLite3', - PostgreSQL = 'PostgreSQL', + SQLite3 = 'SQLite3', + PostgreSQL = 'PostgreSQL', } export type DeleteExpiredStatesArgs = { - duration: number, - dialect: SQLDialect, + duration: number + dialect: SQLDialect } export type NonPersistedXStatePersistenceEvent = SaveStateArgs @@ -25,11 +25,11 @@ export type LoadStateArgs = GetStateArgs export type LoadStateResult = State -export type DeleteStateResult = VoidResult +export type DeleteStateResult = boolean export type XStatePersistenceEvent = { - type: XStatePersistenceEventType, - data: NonPersistedXStatePersistenceEvent + type: XStatePersistenceEventType + data: NonPersistedXStatePersistenceEvent } export type RequiredContext = IAgentContext