Skip to content

Commit

Permalink
Exposed custom projection builders and ProjectionDefinition types
Browse files Browse the repository at this point in the history
It appeared that ProjectionDefinition types were not exposed and that caused issues with setting up custom projections.

Added builders to make that easier.

Reshaped also ProjectionDefnition helper method moving connection string and client to second context parameter. Thanks to that users that don't need it will have a simpler handle method definition.
  • Loading branch information
oskardudycz committed Aug 5, 2024
1 parent 462de81 commit 23904b8
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 41 deletions.
4 changes: 2 additions & 2 deletions samples/webApi/expressjs-with-postgresql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

![](./docs/public/logo.png)

# Emmett - Sample showing event-sourced WebApi with Express.js and EventStoreDB
# Emmett - Sample showing event-sourced WebApi with Express.js and PostgreSQL

Read more in [Emmett getting started guide](https://event-driven-io.github.io/emmett/getting-started.html).

## Prerequisities

Sample require EventStoreDB, you can start it by running
Sample require PostgreSQL, you can start it by running

```bash
docker-compose up
Expand Down
26 changes: 13 additions & 13 deletions src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/core",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - Event Sourcing development made simple",
"engines": {
"node": ">=20.11.1"
Expand Down
4 changes: 2 additions & 2 deletions src/packages/emmett-esdb/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett-esdb",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - EventStoreDB - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down Expand Up @@ -50,7 +50,7 @@
"@event-driven-io/emmett-testcontainers": "^0.5.0"
},
"peerDependencies": {
"@event-driven-io/emmett": "0.13.0",
"@event-driven-io/emmett": "0.14.0",
"@eventstore/db-client": "^6.1.0"
}
}
4 changes: 2 additions & 2 deletions src/packages/emmett-expressjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett-expressjs",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down Expand Up @@ -48,7 +48,7 @@
"dependencies": {},
"devDependencies": {},
"peerDependencies": {
"@event-driven-io/emmett": "0.13.0",
"@event-driven-io/emmett": "0.14.0",
"@types/express": "4.17.21",
"@types/supertest": "6.0.2",
"express": "4.19.2",
Expand Down
4 changes: 2 additions & 2 deletions src/packages/emmett-fastify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett-fastify",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down Expand Up @@ -52,7 +52,7 @@
"dependencies": {},
"devDependencies": {},
"peerDependencies": {
"@event-driven-io/emmett": "^0.13.0",
"@event-driven-io/emmett": "^0.14.0",
"fastify": "4.26.2",
"@fastify/compress": "7.0.0",
"@fastify/etag": "5.1.0",
Expand Down
4 changes: 2 additions & 2 deletions src/packages/emmett-postgresql/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett-postgresql",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - PostgreSQL - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down Expand Up @@ -52,7 +52,7 @@
"@event-driven-io/emmett-testcontainers": "^0.5.0"
},
"peerDependencies": {
"@event-driven-io/emmett": "0.13.0",
"@event-driven-io/emmett": "0.14.0",
"@types/pg": "^8.11.6",
"@types/pg-format": "^1.0.5",
"pg": "^8.12.0",
Expand Down
1 change: 1 addition & 0 deletions src/packages/emmett-postgresql/src/eventStore/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './postgreSQLEventStore';
export * from './projections';
export * from './schema';
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { assertDeepEqual, assertIsNotNull } from '@event-driven-io/emmett';
import {
assertDeepEqual,
assertEqual,
assertIsNotNull,
type ReadEvent,
} from '@event-driven-io/emmett';
import { pongoClient, type PongoClient } from '@event-driven-io/pongo';
import {
PostgreSqlContainer,
Expand All @@ -20,6 +25,7 @@ import {
getPostgreSQLEventStore,
type PostgresEventStore,
} from './postgreSQLEventStore';
import { inlineProjection } from './projections';
import { pongoSingleProjection } from './projections/pongo';

void describe('EventStoreDBEventStore', async () => {
Expand All @@ -32,7 +38,7 @@ void describe('EventStoreDBEventStore', async () => {
postgres = await new PostgreSqlContainer().start();
connectionString = postgres.getConnectionUri();
eventStore = getPostgreSQLEventStore(connectionString, {
projections: [shoppingCartShortInfoProjection],
projections: [shoppingCartShortInfoProjection, customProjection],
});
pongo = pongoClient(connectionString);
return eventStore;
Expand Down Expand Up @@ -60,6 +66,7 @@ void describe('EventStoreDBEventStore', async () => {
};
const discount = 10;
const shoppingCartId = `shopping_cart-${uuid()}`;
handledEventsInCustomProjection = [];

await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [
{ type: 'ProductItemAdded', data: { productItem } },
Expand Down Expand Up @@ -87,6 +94,8 @@ void describe('EventStoreDBEventStore', async () => {
totalAmount: 54,
},
);

assertEqual(3, handledEventsInCustomProjection.length);
});
});

Expand Down Expand Up @@ -126,3 +135,13 @@ const shoppingCartShortInfoProjection = pongoSingleProjection(
'ProductItemAdded',
'DiscountApplied',
);

let handledEventsInCustomProjection: ReadEvent<ShoppingCartEvent>[] = [];

const customProjection = inlineProjection<ShoppingCartEvent>({
name: 'customProjection',
canHandle: ['ProductItemAdded', 'DiscountApplied'],
handle: (events) => {
handledEventsInCustomProjection.push(...events);
},
});
18 changes: 15 additions & 3 deletions src/packages/emmett-postgresql/src/eventStore/projections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import {
import pg from 'pg';
import type { PostgresEventStoreOptions } from '../postgreSQLEventStore';

export type ProjectionHandlerContext = {
connectionString: string;
client: pg.PoolClient;
};

export type PostgresProjectionHandler<EventType extends Event = Event> = (
connectionString: string,
client: pg.PoolClient,
events: ReadEvent<EventType>[],
context: ProjectionHandlerContext,
) => Promise<void> | void;

export type ProjectionDefintion<EventType extends Event = Event> = {
Expand All @@ -36,6 +40,14 @@ export const handleProjections = async <EventType extends Event = Event>(
);

for (const projection of projections) {
await projection.handle(connectionString, client, events);
await projection.handle(events, { connectionString, client });
}
};

export const projection = <EventType extends Event>(
definition: ProjectionDefintion<EventType>,
): ProjectionDefintion => definition as unknown as ProjectionDefintion;

export const inlineProjection = <EventType extends Event>(
definition: Omit<ProjectionDefintion<EventType>, 'type'>,
): ProjectionDefintion => projection({ type: 'inline', ...definition });
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
type PongoDocument,
} from '@event-driven-io/pongo';
import pg from 'pg';
import { type ProjectionDefintion } from './';
import { inlineProjection, type ProjectionDefintion } from './';

export type PongoProjectionOptions<EventType extends Event> = {
documentId: (event: ReadEvent<EventType>) => string;
Expand Down Expand Up @@ -41,18 +41,14 @@ export const pongoProjection = <EventType extends Event>(
handle: (pongo: PongoClient, events: ReadEvent<EventType>[]) => Promise<void>,
...canHandle: EventTypeOf<EventType>[]
): ProjectionDefintion =>
({
type: 'inline',
inlineProjection<EventType>({
canHandle,
handle: async (
connectionString: string,
client: pg.PoolClient,
events: ReadEvent<EventType>[],
) => {
handle: async (events, context) => {
const { connectionString, client } = context;
const pongo = pongoClient(connectionString, { client });
await handle(pongo, events);
},
}) as unknown as ProjectionDefintion;
});

export const pongoMultiStreamProjection = <
Document extends PongoDocument,
Expand Down
4 changes: 2 additions & 2 deletions src/packages/emmett-testcontainers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett-testcontainers",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - TestContainers - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down Expand Up @@ -46,7 +46,7 @@
"dist"
],
"dependencies": {
"@event-driven-io/emmett": "0.13.0",
"@event-driven-io/emmett": "0.14.0",
"testcontainers": "^10.7.2"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/packages/emmett/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@event-driven-io/emmett",
"version": "0.13.0",
"version": "0.14.0",
"description": "Emmett - Event Sourcing development made simple",
"scripts": {
"build": "tsup",
Expand Down

0 comments on commit 23904b8

Please sign in to comment.