### Application Setup with Pongo Client Source: https://event-driven-io.github.io/emmett/getting-started.html Inject the Pongo client when setting up the application's APIs. This example shows the necessary import and how to pass the Pongo client instance to the shoppingCartApi configuration. ```typescript import { pongoClient } from '@event-driven-io/pongo'; const connectionString = process.env.POSTGRESQL_CONNECTION_STRING ?? 'postgresql://localhost:5432/postgres'; const pongo = pongoClient(connectionString); const eventStore = getPostgreSQLEventStore(connectionString, { projections: projections.inline([ shoppingCartSummaryProjection, clientShoppingSummaryProjection, ]), }); const application = getApplication({ apis: [ shoppingCartApi( eventStore, pongo, // 👈 getUnitPrice, ), ], }); ``` -------------------------------- ### Typical Project Setup: API with PostgreSQL Source: https://event-driven-io.github.io/emmett/resources/packages.html Installs the necessary packages for an API project using Emmett with PostgreSQL as the event store and Express.js for the web framework. It also includes the testcontainers package for E2E testing. ```bash npm install @event-driven-io/emmett \ @event-driven-io/emmett-postgresql \ @event-driven-io/emmett-expressjs npm install -D @event-driven-io/emmett-testcontainers ``` -------------------------------- ### Typical Project Setup: API with EventStoreDB Source: https://event-driven-io.github.io/emmett/resources/packages.html Installs the packages for an API project using Emmett with EventStoreDB as the event store and Fastify for the web framework. It also includes the testcontainers package for E2E testing. ```bash npm install @event-driven-io/emmett \ @event-driven-io/emmett-esdb \ @event-driven-io/emmett-fastify npm install -D @event-driven-io/emmett-testcontainers ``` -------------------------------- ### Manual API Testing with .http File Source: https://event-driven-io.github.io/emmett/samples Example HTTP requests for testing API endpoints, including adding a product item, getting cart details, and confirming a shopping cart. ```http ### Add product item POST http://localhost:3000/clients/client-1/shopping-carts/cart-1/product-items Content-Type: application/json { "productId": "shoes-123", "quantity": 2 } ### Get shopping cart GET http://localhost:3000/clients/client-1/shopping-carts/cart-1 ### Confirm shopping cart POST http://localhost:3000/clients/client-1/shopping-carts/cart-1/confirm ``` -------------------------------- ### Typical Project Setup: API with MongoDB Source: https://event-driven-io.github.io/emmett/resources/packages.html Installs the packages for an API project using Emmett with MongoDB as the event store and Express.js for the web framework. It also includes the testcontainers package for E2E testing. ```bash npm install @event-driven-io/emmett \ @event-driven-io/emmett-mongodb \ @event-driven-io/emmett-expressjs npm install -D @event-driven-io/emmett-testcontainers ``` -------------------------------- ### Run the Application Source: https://event-driven-io.github.io/emmett/quick-intro.html Executes the application's start script defined in package.json. ```sh npm run start ``` -------------------------------- ### E2E PostgreSQL Setup with Testcontainers Source: https://event-driven-io.github.io/emmett/guides/testing.html Set up end-to-end tests against a real PostgreSQL database using Testcontainers. This requires starting a PostgreSQL container and configuring the event store to use its connection URI. ```typescript import { ApiE2ESpecification } from '@event-driven-io/emmett-expressjs'; import { getPostgreSQLEventStore } from '@event-driven-io/emmett-postgresql'; import { PostgreSqlContainer, StartedPostgreSqlContainer, } from '@testcontainers/postgresql'; describe('Shopping Cart API (E2E)', () => { let postgres: StartedPostgreSqlContainer; let given: ApiE2ESpecification; beforeAll(async () => { // Start PostgreSQL container postgres = await new PostgreSqlContainer().start(); const eventStore = getPostgreSQLEventStore(postgres.getConnectionUri()); given = ApiE2ESpecification.for(() => getApplication({ apis: [shoppingCartApi(eventStore, getProductPrice)], }), ); }); afterAll(async () => { await eventStore.close(); await postgres.stop(); }); }); ``` -------------------------------- ### Shopping Cart API Endpoint Setup Source: https://event-driven-io.github.io/emmett/getting-started.html Sets up a POST endpoint for adding product items to a shopping cart. It handles request parsing, command creation, and interaction with the event store. Requires an event store and a function to get unit prices. ```typescript const handle = CommandHandler({ evolve, initialState }); type AddProductItemRequest = Request< Partial<{ clientId: string; shoppingCartId: string }>, unknown, Partial<{ productId: string; quantity: number }> >; //////////////////////////////////////////////////// // Web Api //////////////////////////////////////////////////// export const shoppingCartApi = ( // external dependencies eventStore: EventStore, getUnitPrice: (productId: string) => Promise, ): WebApiSetup => (router: Router): void => { //////////////////////////////////////////////////// // Endpoint //////////////////////////////////////////////////// router.post( '/clients/:clientId/shopping-carts/current/product-items', on(async (request: AddProductItemRequest) => { const shoppingCartId = getShoppingCartId( assertNotEmptyString(request.params.clientId), ); const productId = assertNotEmptyString(request.body.productId); const command: AddProductItemToShoppingCart = { type: 'AddProductItemToShoppingCart', data: { shoppingCartId, productItem: { productId, quantity: assertPositiveNumber(request.body.quantity), unitPrice: await getUnitPrice(productId), }, }, }; await handle(eventStore, shoppingCartId, (state) => addProductItem(command, state), ); return NoContent(); }), ); // (...) other endpoints }; ``` -------------------------------- ### Add Start Script to package.json Source: https://event-driven-io.github.io/emmett/quick-intro.html Configures the 'start' script in package.json to run the application using tsx. ```json { "name": "emmett-quick-intro", "version": "1.0.0", "type": "module", "description": "", "scripts": { "start": "tsx ./index.ts" }, "author": "", "license": "ISC", "devDependencies": { "@types/node": "^25.0.10", "tsx": "^4.19.3", "typescript": "^5.8.2" }, "dependencies": { "@event-driven-io/emmett": "^0.43.0-beta.14" } } ``` -------------------------------- ### Initialize bun Project Source: https://event-driven-io.github.io/emmett/quick-intro.html Initializes a new bun project. Accept the defaults for a quick setup. ```sh bun init ``` -------------------------------- ### Install PostgreSQL Event Store Source: https://event-driven-io.github.io/emmett/event-stores/postgresql.html Install the PostgreSQL adapter for Emmett. Peer dependencies for Emmett and Pongo are also required. ```bash npm install @event-driven-io/emmett-postgresql ``` ```bash npm install @event-driven-io/emmett @event-driven-io/pongo ``` -------------------------------- ### Initialize npm Project Source: https://event-driven-io.github.io/emmett/quick-intro.html Initializes a new npm project. Accept the defaults for a quick setup. ```sh npm init ``` -------------------------------- ### Run Express + PostgreSQL Sample Source: https://event-driven-io.github.io/emmett/samples Instructions to clone the repository, set up PostgreSQL using Docker, install dependencies, and run the Express.js application. ```bash # Clone the repository git clone https://github.com/event-driven-io/emmett.git cd emmett/samples/webApi/expressjs-with-postgresql # Start PostgreSQL docker-compose up -d # Install dependencies npm install # Run the application npm run start ``` -------------------------------- ### Example AddItem Command Source: https://event-driven-io.github.io/emmett/quick-intro.html An example 'AddItem' command to add 'Pizza' to the cart. ```typescript const addPizza: AddItem = { type: 'AddItem', data: { name: 'Pizza', }, }; ``` -------------------------------- ### Test Discount Application with Emmett Helpers Source: https://event-driven-io.github.io/emmett/getting-started.html Assert that a 'DiscountApplied' event correctly updates the total amount in the read model for an existing shopping cart. This example utilizes `eventsInStream` and `newEventsInStream` helpers for concise event setup. ```typescript import { eventsInStream, newEventsInStream, } from '@event-driven-io/emmett-postgresql'; void describe('Shopping carts summary', () => { // (...) test setup void it('applies discount for existing shopping cart with product', () => { const couponId = uuid(); return given( eventsInStream(shoppingCartId, [ { type: 'ProductItemAddedToShoppingCart', data: { productItem: { unitPrice: 100, productId: 'shoes', quantity: 100 }, }, }, ]), ) .when( newEventsInStream(shoppingCartId, [ { type: 'DiscountApplied', data: { percent: 10, couponId }, }, ]), ) .then( expectPongoDocuments .fromCollection( shoppingCartShortInfoCollectionName, ) .withId(shoppingCartId) .toBeEqual({ productItemsCount: 100, totalAmount: 9000, }), ); }); }); ``` -------------------------------- ### Initialize pnpm Project Source: https://event-driven-io.github.io/emmett/quick-intro.html Initializes a new pnpm project. Accept the defaults for a quick setup. ```sh pnpm init ``` -------------------------------- ### Install Pongo Package Source: https://event-driven-io.github.io/emmett/resources/packages.html Install the Pongo package, which provides PostgreSQL as a Document Database with a MongoDB-like API. ```bash npm install @event-driven-io/pongo ``` -------------------------------- ### Install Peer Dependencies Source: https://event-driven-io.github.io/emmett/event-stores/mongodb.html Install the necessary peer dependencies for the MongoDB event store. ```bash npm install @event-driven-io/emmett mongodb ``` -------------------------------- ### Initialize yarn Project Source: https://event-driven-io.github.io/emmett/quick-intro.html Initializes a new yarn project. Accept the defaults for a quick setup. ```sh yarn init ``` -------------------------------- ### Installation Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Install the Emmett Express.js package and its peer dependencies. ```APIDOC ## Installation ### Package Installation ```bash npm install @event-driven-io/emmett-expressjs ``` ### Peer Dependencies ```bash npm install @event-driven-io/emmett express npm install -D @types/express ``` ``` -------------------------------- ### Install Peer Dependencies Source: https://event-driven-io.github.io/emmett/event-stores/esdb.html Install the necessary peer dependencies for the Emmett EventStoreDB adapter. ```bash npm install @event-driven-io/emmett @eventstore/db-client ``` -------------------------------- ### PostgreSQL Projection Testing Setup Source: https://event-driven-io.github.io/emmett/api-reference/projections.html Sets up a PostgreSQL projection specification for testing. Requires a connection string and the projection definition. ```typescript import { PostgreSQLProjectionSpec, expectPongoDocuments, eventsInStream, newEventsInStream, } from '@event-driven-io/emmett-postgresql'; describe('Cart Summary Projection', () => { let given: PostgreSQLProjectionSpec; beforeAll(async () => { given = PostgreSQLProjectionSpec.for({ projection: cartSummaryProjection, connectionString: testConnectionString, }); }); it('creates summary on first product', () => given([]) .when([ { type: 'ProductItemAdded', data: { productId: 'shoes', quantity: 2, price: 100 }, metadata: { streamName: 'shopping_cart-123' }, }, ]) .then( expectPongoDocuments .fromCollection('cart_summaries') .withId('123') .toBeEqual({ totalItems: 2, totalAmount: 200 }), )); it('updates summary on additional products', () => given( eventsInStream('shopping_cart-123', [ { type: 'ProductItemAdded', data: { productId: 'shoes', quantity: 2, price: 100 }, }, ]), ) .when( newEventsInStream('shopping_cart-123', [ { type: 'ProductItemAdded', data: { productId: 'shirt', quantity: 1, price: 50 }, }, ]), ) .then( expectPongoDocuments .fromCollection('cart_summaries') .withId('123') .toBeEqual({ totalItems: 3, totalAmount: 250 }), )); }); ``` -------------------------------- ### Install Emmett Fastify Package Source: https://event-driven-io.github.io/emmett/frameworks/fastify.html Install the main package for Emmett's Fastify integration. ```bash npm install @event-driven-io/emmett-fastify ``` -------------------------------- ### WebAPI Setup Pattern Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Organizes API routes by defining them within a WebApiSetup function, which is then passed to getApplication. ```typescript // api/shoppingCartApi.ts import { WebApiSetup } from '@event-driven-io/emmett-expressjs'; export const shoppingCartApi = ( eventStore: EventStore, getPrice: (productId: string) => Promise, ): WebApiSetup => (router) => { // All routes defined here router.get('/carts/:id' /* ... */); router.post('/carts/:id/items' /* ... */); router.post('/carts/:id/confirm' /* ... */); }; // main.ts import { getApplication, startAPI } from '@event-driven-io/emmett-expressjs'; const app = getApplication({ apis: [ shoppingCartApi(eventStore, priceService.getPrice), orderApi(eventStore), userApi(userService), ], }); startAPI(app); ``` -------------------------------- ### Example AddItem Command for Ice Cream Source: https://event-driven-io.github.io/emmett/quick-intro.html An example 'AddItem' command to add 'Ice Cream' to the cart. ```typescript const addIceCream: AddItem = { type: 'AddItem', data: { name: 'Ice Cream', }, }; ``` -------------------------------- ### Quick Setup: In-Memory Event Store Source: https://event-driven-io.github.io/emmett/event-stores Initializes the in-memory event store. This is a simple, non-persistent store suitable for testing and development. ```typescript import { getInMemoryEventStore } from '@event-driven-io/emmett'; const eventStore = getInMemoryEventStore(); ``` -------------------------------- ### Install Emmett Core and Event Store Packages Source: https://event-driven-io.github.io/emmett/resources/faq.html Install the core Emmett package along with the desired event store package using npm. Optional packages for web frameworks and testing utilities can also be installed. ```bash # Core package (required) npm install @event-driven-io/emmett # Choose your event store npm install @event-driven-io/emmett-postgresql # PostgreSQL npm install @event-driven-io/emmett-esdb # EventStoreDB npm install @event-driven-io/emmett-mongodb # MongoDB npm install @event-driven-io/emmett-sqlite # SQLite # Optional: Web framework integration npm install @event-driven-io/emmett-expressjs # Express.js npm install @event-driven-io/emmett-fastify # Fastify # Optional: Testing utilities npm install @event-driven-io/emmett-testcontainers ``` -------------------------------- ### Setup with Existing MongoClient Source: https://event-driven-io.github.io/emmett/event-stores/mongodb.html Initialize the MongoDB event store using an existing MongoClient instance. ```typescript import { MongoClient } from 'mongodb'; import { getMongoDBEventStore } from '@event-driven-io/emmett-mongodb'; const client = new MongoClient('mongodb://localhost:27017'); await client.connect(); const eventStore = getMongoDBEventStore({ client, database: 'events', }); ``` -------------------------------- ### Application Setup Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Set up your Express.js application with Emmett, including sensible defaults and API configurations. ```APIDOC ## Application Setup ```typescript import { getApplication, startAPI } from '@event-driven-io/emmett-expressjs'; import { getInMemoryEventStore } from '@event-driven-io/emmett'; const eventStore = getInMemoryEventStore(); const app = getApplication({ apis: [shoppingCartApi(eventStore)], }); startAPI(app, 3000); ``` ``` -------------------------------- ### Complete Emmett Fastify Example with PostgreSQL Source: https://event-driven-io.github.io/emmett/frameworks/fastify.html A full example demonstrating Emmett's Fastify integration with PostgreSQL for event storage, including defining a decider, creating an event store, and setting up API routes. ```typescript import { startAPI, getFastifyApp } from '@event-driven-io/emmett-fastify'; import { getPostgreSQLEventStore } from '@event-driven-io/emmett-postgresql'; import { CommandHandler } from '@event-driven-io/emmett'; // Define your decider const shoppingCartDecider = { decide, evolve, initialState, mapToStreamId: (id: string) => `shopping_cart-${id}`, }; // Create event store const eventStore = getPostgreSQLEventStore(process.env.DATABASE_URL!); // Define API const shoppingCartApi = (eventStore: EventStore) => async (fastify: FastifyInstance) => { const handle = CommandHandler(shoppingCartDecider, eventStore); fastify.post<{ Params: { cartId: string }; Body: { productId: string; quantity: number }; }>('/carts/:cartId/items', async (request, reply) => { const { cartId } = request.params; const { productId, quantity } = request.body; const price = await getPriceFromCatalog(productId); const result = await handle(cartId, { type: 'AddProductItem', data: { productId, quantity, price }, }); return reply .header('ETag', `"${result.nextExpectedStreamVersion}" `) .status(200) .send({ added: true }); }); }; // Start server const app = getFastifyApp({ apis: [shoppingCartApi(eventStore)], }); await startAPI(app, { port: 3000 }); ``` -------------------------------- ### Install PostgreSQL Event Store Source: https://event-driven-io.github.io/emmett/event-stores Installs the PostgreSQL event store package using npm. This is suitable for production applications requiring full ACID compliance. ```bash npm install @event-driven-io/emmett-postgresql ``` -------------------------------- ### Install In-Memory Event Store Source: https://event-driven-io.github.io/emmett/event-stores The in-memory event store is included in the core package and does not require a separate installation. It's suitable for testing purposes. ```bash # Included in core package npm install @event-driven-io/emmett ``` -------------------------------- ### Run Emmett Documentation Locally Source: https://event-driven-io.github.io/emmett/resources/contributing.html Commands to install dependencies and run the documentation development server locally. ```bash cd src/docs npm install npm run dev ``` -------------------------------- ### Install Peer Dependencies Source: https://event-driven-io.github.io/emmett/event-stores/sqlite.html Install necessary peer dependencies for the SQLite event store, including Emmett and better-sqlite3. ```bash npm install @event-driven-io/emmett better-sqlite3 npm install -D @types/better-sqlite3 ``` -------------------------------- ### Install EventStoreDB Event Store Source: https://event-driven-io.github.io/emmett/event-stores Installs the EventStoreDB event store package using npm. This is ideal for native event sourcing scenarios and offers cluster scaling. ```bash npm install @event-driven-io/emmett-esdb ``` -------------------------------- ### Install PostgreSQL Testcontainers for bun Source: https://event-driven-io.github.io/emmett/getting-started.html Add the PostgreSQL Testcontainers package to your project using bun. ```sh $ bun add @testcontainers/postgresql ``` -------------------------------- ### Evolve Pattern Implementation Example Source: https://event-driven-io.github.io/emmett/api-reference/projections.html An example implementation of the 'evolve' pattern for a shopping cart projection. It demonstrates how to handle adding items and confirming the cart, including document creation and deletion. ```typescript const evolve = (document: CartSummary | null, event: ShoppingCartEvent) => { switch (event.type) { case 'ProductItemAdded': const current = document ?? { totalItems: 0, totalAmount: 0 }; return { ...current, totalItems: current.totalItems + event.data.quantity, }; case 'ShoppingCartConfirmed': return null; // Delete document default: return document; } }; ``` -------------------------------- ### Install SQLite Event Store Source: https://event-driven-io.github.io/emmett/event-stores Installs the SQLite event store package using npm. This is recommended for development and embedded applications, providing full ACID compliance on a single node. ```bash npm install @event-driven-io/emmett-sqlite ``` -------------------------------- ### Install MongoDB Event Store Source: https://event-driven-io.github.io/emmett/event-stores Installs the MongoDB event store package using npm. This option is best for document-centric applications and scales horizontally. ```bash npm install @event-driven-io/emmett-mongodb ``` -------------------------------- ### Integration Test Setup: Shopping Cart API Source: https://event-driven-io.github.io/emmett/guides/testing.html Sets up integration tests for the Shopping Cart API using `ApiSpecification` and an in-memory event store. This snippet shows the initial setup before testing specific endpoints. ```typescript import { ApiSpecification } from '@event-driven-io/emmett-expressjs'; import { getInMemoryEventStore } from '@event-driven-io/emmett'; import { shoppingCartApi, getApplication } from './api'; describe('Shopping Cart API', () => { let given: ApiSpecification; beforeAll(() => { const eventStore = getInMemoryEventStore(); given = ApiSpecification.for(() => getApplication({ apis: [ shoppingCartApi( eventStore, () => Promise.resolve(100), // Mock price lookup ), ], }), ); }); }); ``` -------------------------------- ### Install PostgreSQL Testcontainers for npm Source: https://event-driven-io.github.io/emmett/getting-started.html Add the PostgreSQL Testcontainers package to your project using npm. ```sh $ npm add @testcontainers/postgresql ``` -------------------------------- ### Read Stream Example Source: https://event-driven-io.github.io/emmett/api-reference/eventstore.html Demonstrates how to read events from a specific stream and access the results. ```typescript const result = await eventStore.readStream('shopping_cart-123'); console.log(result.events); // Array of events console.log(result.currentStreamVersion); // Current stream version (bigint) console.log(result.streamExists); // true if stream exists ``` -------------------------------- ### Install PostgreSQL Testcontainers for pnpm Source: https://event-driven-io.github.io/emmett/getting-started.html Add the PostgreSQL Testcontainers package to your project using pnpm. ```sh $ pnpm add @testcontainers/postgresql ``` -------------------------------- ### Run Express + EventStoreDB Sample Source: https://event-driven-io.github.io/emmett/samples Instructions to navigate to the sample directory, set up EventStoreDB using Docker, install dependencies, and run the Express.js application. ```bash cd emmett/samples/webApi/expressjs-with-esdb # Start EventStoreDB docker-compose up -d # Install and run npm install npm run start ``` -------------------------------- ### Isolated Test Database Setup for Event Store Source: https://event-driven-io.github.io/emmett/event-stores/sqlite.html Set up an isolated, in-memory SQLite database for each test using `getSQLiteEventStore(':memory:')`. This ensures tests do not interfere with each other and start with a clean state. ```typescript import { v4 as uuid } from 'uuid'; describe('Shopping Cart', () => { let eventStore: SQLiteEventStore; beforeEach(() => { // Each test gets fresh in-memory database eventStore = getSQLiteEventStore(':memory:'); }); it('adds products', async () => { await eventStore.appendToStream('cart-1', [ { type: 'ProductItemAdded', data: { productId: 'p1', quantity: 1, price: 10 }, }, ]); const { events } = await eventStore.readStream('cart-1'); expect(events).toHaveLength(1); }); }); ``` -------------------------------- ### Run Express + MongoDB Sample Source: https://event-driven-io.github.io/emmett/samples Instructions to navigate to the sample directory, set up MongoDB using Docker, install dependencies, and run the Express.js application. ```bash cd emmett/samples/webApi/expressjs-with-mongodb # Start MongoDB docker-compose up -d # Install and run npm install npm run start ``` -------------------------------- ### Registering Projections with Event Store Source: https://event-driven-io.github.io/emmett/getting-started.html Example of how to register the `shoppingCartSummaryProjection` and `clientShoppingSummaryProjection` with the event store configuration using `projections.inline`. ```typescript const eventStore = getPostgreSQLEventStore(connectionString, { projections: projections.inline([ shoppingCartSummaryProjection, clientShoppingSummaryProjection, // 👈 ]), }); ``` -------------------------------- ### Isolate Tests Source: https://event-driven-io.github.io/emmett/guides/testing.html Demonstrates the principle of test isolation using `beforeEach` to ensure each test starts with a clean state. Contrasts this with a bad example where tests depend on each other due to shared mutable state. ```typescript // ✅ Good: Each test is independent beforeEach(() => { cartId = `cart-${uuid()}`; }); // ❌ Bad: Tests depend on each other let cartId = 'shared-cart'; // Mutations leak between tests ``` -------------------------------- ### Quick Setup: EventStoreDB Event Store Source: https://event-driven-io.github.io/emmett/event-stores Initializes the EventStoreDB event store using the EventStoreDBClient. Requires the EventStoreDB server to be running and accessible. ```typescript import { getEventStoreDBEventStore } from '@event-driven-io/emmett-esdb'; import { EventStoreDBClient } from '@eventstore/db-client'; const client = EventStoreDBClient.connectionString( 'esdb://localhost:2113?tls=false', ); const eventStore = getEventStoreDBEventStore(client); ``` -------------------------------- ### Default Application Setup Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Uses getApplication with sensible defaults for setting up an Express application, including JSON parsing, URL encoding, and error handling. ```typescript const app = getApplication({ apis: [myApi], }); // Includes: // - JSON body parsing // - URL encoding // - Problem Details error handling // - ETag support ``` -------------------------------- ### Quick Setup: MongoDB Event Store Source: https://event-driven-io.github.io/emmett/event-stores Initializes the MongoDB event store with connection details and a database name. The MongoDB server must be running. ```typescript import { getMongoDBEventStore } from '@event-driven-io/emmett-mongodb'; const eventStore = getMongoDBEventStore({ connectionString: 'mongodb://localhost:27017', database: 'events', }); ``` -------------------------------- ### Integrating Pongo Queries into API Routes Source: https://event-driven-io.github.io/emmett/guides/projections.html Wire Pongo queries into Express route handlers to serve read models. This example demonstrates setting up GET endpoints for retrieving shopping cart details and short info. ```typescript const shoppingCartApi = (readStore: PongoDb): WebApiSetup => (router: Router) => { router.get( '/clients/:clientId/shopping-carts/current', on(async (request: Request) => { const shoppingCartId = `shopping_cart:${request.params.clientId}:current`; const result = await getDetailsById(readStore, shoppingCartId); if (result === null) return NotFound(); if (result.status !== 'Opened') return NotFound(); return OK({ body: result }); }), ); router.get( '/clients/:clientId/shopping-carts/current/short-info', on(async (request: Request) => { const shoppingCartId = `shopping_cart:${request.params.clientId}:current`; const result = await getShortInfoById(readStore, shoppingCartId); if (result === null) return NotFound(); return OK({ body: result }); }), ); }; ``` -------------------------------- ### Quick Setup: PostgreSQL Event Store Source: https://event-driven-io.github.io/emmett/event-stores Initializes the PostgreSQL event store using a connection string. Ensure your PostgreSQL server is running and accessible. ```typescript import { getPostgreSQLEventStore } from '@event-driven-io/emmett-postgresql'; const eventStore = getPostgreSQLEventStore( 'postgresql://user:password@localhost:5432/mydb', ); ``` -------------------------------- ### Example RemoveItem Command for Pizza Source: https://event-driven-io.github.io/emmett/quick-intro.html An example 'RemoveItem' command to remove 'Pizza' from the cart. ```typescript const removePizza: RemoveItem = { type: 'RemoveItem', data: { name: 'Pizza', }, }; ``` -------------------------------- ### Install TypeScript and tsx Source: https://event-driven-io.github.io/emmett/quick-intro.html Installs TypeScript and tsx as development dependencies for running TypeScript code. ```sh npm install typescript @types/node tsx --save-dev ``` -------------------------------- ### Quick Setup: SQLite Event Store Source: https://event-driven-io.github.io/emmett/event-stores Initializes the SQLite event store, specifying the database file path. An in-memory option is also available using ':memory:'. ```typescript import { getSQLiteEventStore } from '@event-driven-io/emmett-sqlite'; const eventStore = getSQLiteEventStore('./events.db'); // or in-memory: getSQLiteEventStore(':memory:') ``` -------------------------------- ### Install Emmett Peer Dependencies Source: https://event-driven-io.github.io/emmett/frameworks/fastify.html Install the core Emmett package and Fastify as peer dependencies. ```bash npm install @event-driven-io/emmett fastify ``` -------------------------------- ### Handle Example Commands Source: https://event-driven-io.github.io/emmett/quick-intro.html Demonstrates handling a sequence of commands ('AddItem' for Pizza, 'AddItem' for Ice Cream, 'RemoveItem' for Ice Cream) against a specific shopping cart ID using the 'handle' function. ```typescript // Use a constant cart id for this example. // In real life applications, this should be a real cart id. const shoppingCartId = '1'; // 2. Handle command await handle(eventStore, shoppingCartId, (state) => decide(addPizza, state)); console.log('---'); await handle(eventStore, shoppingCartId, (state) => decide(addIceCream, state)); console.log('---'); await handle(eventStore, shoppingCartId, ( state, ) => decide(removeIceCream, state), ); ``` -------------------------------- ### Clone and Install Emmett Dependencies Source: https://event-driven-io.github.io/emmett/resources/contributing.html Clone the Emmett repository and install project dependencies using npm. ```bash git clone https://github.com/event-driven-io/emmett.git cd emmett npm install npm run build npm run test ``` -------------------------------- ### Install Peer Dependencies Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Install necessary peer dependencies for Emmett and Express.js, including TypeScript types. ```bash npm install @event-driven-io/emmett-expressjs npm install @event-driven-io/emmett express npm install -D @types/express ``` -------------------------------- ### Define Example Commands Source: https://event-driven-io.github.io/emmett/quick-intro.html Define sample commands for a shopping cart application, including adding and removing items. These commands represent actions that can change the application's state. ```typescript const addPizza: AddItem = { type: 'AddItem', data: { name: 'Pizza', }, }; const addIceCream: AddItem = { type: 'AddItem', data: { name: 'Ice Cream', }, }; const removePizza: RemoveItem = { type: 'RemoveItem', data: { name: 'Pizza', }, }; const removeIceCream: RemoveItem = { type: 'RemoveItem', data: { name: 'Ice Cream', }, }; ``` -------------------------------- ### Example RemoveItem Command for Ice Cream Source: https://event-driven-io.github.io/emmett/quick-intro.html An example 'RemoveItem' command to remove 'Ice Cream' from the cart. ```typescript const removeIceCream: RemoveItem = { type: 'RemoveItem', data: { name: 'Ice Cream', }, }; ``` -------------------------------- ### Setup Shopping Cart WebAPI Source: https://event-driven-io.github.io/emmett/getting-started.html Sets up the Shopping Cart WebAPI by defining external dependencies like event store and product price query. It returns a WebApiSetup function that configures the Express router. ```typescript import type { WebApiSetup } from '@event-driven-io/emmett-expressjs'; import { Router } from 'express'; import { evolve, initialState } from '../shoppingCart'; // Let's setup the command handler, we'll use it in endpoints const handle = CommandHandler({ evolve, initialState }); export const shoppingCartApi = ( // external dependencies eventStore: EventStore, getUnitPrice: (productId: string) => Promise, ): WebApiSetup => (router: Router): void => { // We'll setup routes here }; ``` -------------------------------- ### Set up PostgreSQL Testcontainer and Event Store Source: https://event-driven-io.github.io/emmett/getting-started.html Configure a PostgreSQL container and initialize the event store for end-to-end testing. Ensure the event store is closed and the container stopped after all tests. ```typescript import { getPostgreSQLEventStore, type PostgresEventStore, } from '@event-driven-io/emmett-postgresql'; import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql'; import { PostgreSqlContainer } from '@testcontainers/postgresql'; void describe('ShoppingCart E2E', () => { let postgreSQLContainer: StartedPostgreSqlContainer; let eventStore: PostgresEventStore; // Set up a container and event store before all tests beforeAll(async () => { postgreSQLContainer = await new PostgreSqlContainer( 'postgres:18.1', ).start(); eventStore = getPostgreSQLEventStore( postgreSQLContainer.getConnectionUri(), ); }); // Close PostgreSQL connection and stop container once we finished testing afterAll(async () => { await eventStore.close(); return postgreSQLContainer.stop(); }); // (...) Tests will go here }); ``` -------------------------------- ### Install Emmett Express.js Package Source: https://event-driven-io.github.io/emmett/frameworks/expressjs.html Install the main package for Emmett's Express.js integration using npm. ```bash npm install @event-driven-io/emmett-expressjs ``` -------------------------------- ### Basic EventStoreDB Setup Source: https://event-driven-io.github.io/emmett/event-stores/esdb.html Initialize the EventStoreDB client and obtain the Emmett event store instance. Ensure the connection string is correctly configured for your EventStoreDB instance. ```typescript import { getEventStoreDBEventStore } from '@event-driven-io/emmett-esdb'; import { EventStoreDBClient } from '@eventstore/db-client'; const client = EventStoreDBClient.connectionString( 'esdb://localhost:2113?tls=false', ); const eventStore = getEventStoreDBEventStore(client); ``` -------------------------------- ### Direct Command Handler Setup Source: https://event-driven-io.github.io/emmett/api-reference/command.html Sets up a direct command handler using the CommandHandler factory. Requires an event store, decision logic, state evolution, initial state, and a stream ID mapping function. ```typescript import { CommandHandler } from '@event-driven-io/emmett'; const handle = CommandHandler(eventStore, { decide, evolve, initialState, mapToStreamId: (command) => `shopping_cart-${command.data.cartId}`, }); ``` -------------------------------- ### Install Emmett with bun Source: https://event-driven-io.github.io/emmett/getting-started.html Add the Emmett package to your project using bun. This command installs the necessary types and tooling for streamlined development. ```bash $ bun add @event-driven-io/emmett ``` -------------------------------- ### Initialize Pongo Client and Query Shopping Cart Summary Source: https://event-driven-io.github.io/emmett/getting-started.html Initializes the Pongo client with a connection string and queries for a specific shopping cart summary document. Ensure the POSTGRESQL_CONNECTION_STRING environment variable is set or provide a default. ```typescript import { pongoClient } from '@event-driven-io/pongo'; const connectionString = process.env.POSTGRESQL_CONNECTION_STRING ?? 'postgresql://localhost:5432/postgres'; const pongo = pongoClient(connectionString); const shoppingCartsSummary = pongo.db().collection('shopping_carts_summary'); const summary = await shoppingCartsSummary.findOne({ _id: 'shopping_cart-123', }); ``` -------------------------------- ### Install Emmett with yarn Source: https://event-driven-io.github.io/emmett/getting-started.html Add the Emmett package to your project using yarn. This command installs the necessary types and tooling for streamlined development. ```bash $ yarn add @event-driven-io/emmett ``` -------------------------------- ### Build and Run Application with Docker Compose Source: https://event-driven-io.github.io/emmett/samples Use these commands to build the application image and then run the application within Docker containers. Ensure Docker is installed and configured. ```bash # Build application docker-compose --profile app build # Run application docker-compose --profile app up ``` -------------------------------- ### Install Emmett with pnpm Source: https://event-driven-io.github.io/emmett/getting-started.html Add the Emmett package to your project using pnpm. This command installs the necessary types and tooling for streamlined development. ```bash $ pnpm add @event-driven-io/emmett ``` -------------------------------- ### Install Emmett with npm Source: https://event-driven-io.github.io/emmett/getting-started.html Add the Emmett package to your project using npm. This command installs the necessary types and tooling for streamlined development. ```bash $ npm add @event-driven-io/emmett ``` -------------------------------- ### Set up PostgreSQL Testcontainer and Projection Spec Source: https://event-driven-io.github.io/emmett/getting-started.html Initialize a PostgreSQL test container and configure the projection specification for testing. This setup is crucial before running any projection tests. ```typescript import { PostgreSQLProjectionSpec, } from '@event-driven-io/emmett-postgresql'; import { PostgreSqlContainer, StartedPostgreSqlContainer, } from '@testcontainers/postgresql'; import { after, before, beforeEach, describe, it } from 'vitest'; import { v4 as uuid } from 'uuid'; void describe('Shopping carts summary', () => { let postgres: StartedPostgreSqlContainer; let connectionString: string; let given: PostgreSQLProjectionSpec< ProductItemAdded | ProductItemRemoved | DiscountApplied >; let shoppingCartId: string; before(async () => { postgres = await new PostgreSqlContainer().start(); connectionString = postgres.getConnectionUri(); given = PostgreSQLProjectionSpec.for({ projection: shoppingCartShortInfoProjection, connectionString, }); }); beforeEach(() => (shoppingCartId = `shoppingCart-${uuid()}`)); }); ``` -------------------------------- ### Installing Emmett Express.js Package Source: https://event-driven-io.github.io/emmett/getting-started.html Installs the `@event-driven-io/emmett-expressjs` package using npm, pnpm, yarn, or bun. This package provides integration with Express.js applications. ```sh $ npm add @event-driven-io/emmett-expressjs ``` ```sh $ pnpm add @event-driven-io/emmett-expressjs ``` ```sh $ yarn add @event-driven-io/emmett-expressjs ``` ```sh $ bun add @event-driven-io/emmett-expressjs ```