UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

320 lines (278 loc) 7.68 kB
import setup from '../../setup'; import Aggregator, { Aggregation } from './Aggregator'; import FHEClient from '../../services/fhe'; import { get } from 'lodash'; describe('sdk/Aggregator', () => { let mongodb; let instance; let client; let aggregator; let uuid; beforeAll(async () => { [, mongodb, , , , client, , instance] = await setup.startApi({ features: { api: { admin: true, }, }, }); client.config.debug = true; uuid = setup.uuid(); }); beforeEach(() => { const datastores = new Map([['datastore', client]]); aggregator = new Aggregator(datastores); }); afterEach(() => { jest.restoreAllMocks(); }); afterAll(async () => { await setup.teardownDb(mongodb); await setup.stopApi(instance); }); describe('retrieve nested objects', () => { beforeAll(async () => { await client.createModel({ is_enabled: true, db: 'datastore', name: 'accounts', correlation_field: 'account_id', schema: { model: { type: 'object', properties: { firstname: { type: 'string' }, data: { type: 'string', }, }, }, }, }); await client.createModel({ is_enabled: true, db: 'datastore', name: 'profiles', correlation_field: 'profile_id', schema: { model: { type: 'object', properties: { account_id: { type: 'string' }, firstname: { type: 'string' }, }, }, }, }); }); it('returns all entities at once', async () => { const { data: account } = await client.create('accounts', { firstname: `Alice ${uuid}`, }); const { data: profile } = await client.create('profiles', { account_id: account.account_id, }); await client.update('accounts', account.account_id, { firstname: `Bernard ${uuid}`, }); const data = await aggregator.aggregate([ { type: 'fetch', datastore: 'datastore', model: 'accounts', destination: 'account', as_entity: true, query: { firstname: `Bernard ${uuid}`, }, }, { type: 'fetch', datastore: 'datastore', model: 'accounts', source: 'events', destination: 'account_events', map: [ { from: 'account.account_id', to: 'account_id', }, ], }, { type: 'fetch', datastore: 'datastore', model: 'profiles', map: [ { from: 'account.account_id', to: 'account_id', }, ], }, ]); expect(data).toMatchObject({ account: { firstname: `Bernard ${uuid}`, version: 1, }, account_events: [ { type: 'CREATED', version: 0, firstname: `Alice ${uuid}`, }, { type: 'UPDATED', version: 1, firstname: `Bernard ${uuid}`, }, ], profiles: [ { account_id: account.account_id, version: 0, }, ], }); }); it('returns timetravel entities from fetch', async () => { const { data: account } = await client.create('accounts', { firstname: `Alice ${uuid}`, }); const { data: profile } = await client.create('profiles', { account_id: account.account_id, firstname: `Alice ${uuid}`, }); await client.update('accounts', account.account_id, { firstname: `Bernard ${uuid}`, }); await client.update('profiles', profile.profile_id, { firstname: `Bernard ${uuid}`, }); const data = await aggregator.aggregate([ { type: 'fetch', datastore: 'datastore', model: 'profiles', source: 'events', destination: 'entity', as_entity: true, query: { type: 'CREATED', firstname: `Alice ${uuid}`, }, }, { type: 'fetch', datastore: 'datastore', model: 'accounts', source: 'entities', destination: 'account', as_entity: true, // timetravel timetravel: 'entity.created_at', correlation_field: 'account_id', // timetravel map: [ { from: 'entity.account_id', to: 'account_id', }, ], }, ]); expect(data).toMatchObject({ entity: { version: 0, firstname: `Alice ${uuid}`, }, account: { firstname: `Alice ${uuid}`, version: 0, }, }); }); it('performs FHE computations in aggregation', async () => { aggregator = new Aggregator(new Map([['datastore', client]])); const fhe = new FHEClient({}); await fhe.connect(); const fheStep = async ( step: { type: 'fhe'; script: string; args: Array<string> }, data: Aggregation = {}, ) => { const publicKey = data.public_key; const another = new FHEClient({}); await another.connect(); const UploadedPublicKey = another.seal.PublicKey(); UploadedPublicKey.load(another.context!, publicKey); another.keys!.public = UploadedPublicKey; const asyncFn = another.compile(step.script); const args = step.args.map((arg) => get(data, arg)); data.account.data = await another.compute(asyncFn, ...args); return data; }; const myStepDefinition = { handler: fheStep, }; aggregator.addStepType('fhe', myStepDefinition); const value = fhe.createCypher([1]).save(); const publicKey = fhe.keys.public.save(); const { data: account } = await client.create('accounts', { firstname: `Alice ${uuid}`, data: value, }); const data = await aggregator.aggregate( [ { type: 'fetch', datastore: 'datastore', model: 'accounts', destination: 'account', as_entity: true, query: { firstname: `Alice ${uuid}`, }, }, { type: 'fhe', name: 'FHE increment example', script: async function handler(a) { return a + 1; }.toString(), args: ['account.data'], }, { type: 'persist', datastore: 'datastore', model: 'accounts', correlation_field: 'account_id', destination: 'account', map: [ { from: 'account.account_id', to: 'account_id', }, { from: 'account.data', to: 'data', }, ], }, ], { public_key: publicKey, }, ); expect(data).toMatchObject({ account: { firstname: `Alice ${uuid}`, version: 1, }, }); const cipher = fhe.seal.CipherText(); cipher.load(fhe.context, data.account.data); expect(fhe.fromCypher(cipher).slice(0, 1)).toEqual([2]); }); }); });