Skip to content

Commit

Permalink
split to http server and client
Browse files Browse the repository at this point in the history
  • Loading branch information
idugalic committed Apr 5, 2024
1 parent 6abeb5d commit 0d74a07
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 89 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TypeScript library.
## Run the tests

We are using the `Given`-`When`-`Then` [structure](test_specification.ts) to
create a [testable specification](main_test.ts):
create a [testable specification](domain_test.ts):

- Given < some precondition(s) >
- When < an action/trigger occurs >
Expand All @@ -53,10 +53,14 @@ create a [testable specification](main_test.ts):
deno test
```

## Run the application
## Run the application (HTTP Server & Client)

```shell
deno run -A --unstable-kv main.ts
deno run --unstable-kv --allow-net server.ts
```

```shell
deno run --allow-net client.ts
```

## Deno KV as an event store
Expand Down
67 changes: 67 additions & 0 deletions client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

// This is a simple client that sends a create restaurant command and a change restaurant menu command to the server


// Create a restaurant command JSON
const createRestaurantCommandJson = `
{
"commandId": "691490bb-c4d3-45b8-99d0-efcf20e353ag",
"decider": "Restaurant",
"kind": "CreateRestaurantCommand",
"id": "691490bb-c4d3-45b8-99d0-efcf20e353ao",
"name": "Eat at Joes",
"menu": {
"menuItems": [
{"menuItemId": "1", "name": "Salad", "price": "8.99"},
{"menuItemId": "2", "name": "Soup", "price": "6.99"},
{"menuItemId": "3", "name": "Steak", "price": "19.99"}
],
"menuId": "34110e19-ca72-45e7-b969-61bebf54da08",
"cuisine": "SERBIAN"
}
}
`;

// Change restaurant menu command JSON
const changeRestaurantMenuCommandJson = `
{
"commandId": "691490bb-c4d3-45b8-99d0-efcf20e353ag",
"decider": "Restaurant",
"kind": "ChangeRestaurantMenuCommand",
"id": "691490bb-c4d3-45b8-99d0-efcf20e353ao",
"menu": {
"menuItems": [
{"menuItemId": "1", "name": "Salad", "price": "8.99"},
{"menuItemId": "2", "name": "Soup", "price": "6.99"},
{"menuItemId": "3", "name": "Steak", "price": "19.99"}
],
"menuId": "34110e19-ca72-45e7-b969-61bebf54da08",
"cuisine": "SERBIAN"
}
}
`;

// Send the create restaurant command to the server
const createRestaurantCommandResult = await fetch("http://localhost:8000", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: createRestaurantCommandJson,
});

console.log(createRestaurantCommandResult);

// Send the change restaurant menu command to the server
const changeRestaurantMenuCommandResult = await fetch("http://localhost:8000", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: changeRestaurantMenuCommandJson,
});

console.log(changeRestaurantMenuCommandResult);


// Run the client : `deno run --allow-net client.ts`
86 changes: 0 additions & 86 deletions main.ts

This file was deleted.

52 changes: 52 additions & 0 deletions server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { blue } from "std/fmt/colors.ts";
import {
Command,
Event,
Order,
orderDecider,
Restaurant,
restaurantDecider,
} from "./domain.ts";
import { Decider, EventSourcingAggregate } from "fmodel";
import { CommandMetadata, DenoEventRepository } from "./infrastructure.ts";
import { ApplicationAggregate } from "./application.ts";
import { commandAndMetadataSchema } from "./schema.ts";

// A simple HTTP server that handles commands of all types
Deno.serve(async (request: Request) => {
try {
// Parse the command and metadata from the request / Zod validation/parsing
const command: Command & CommandMetadata = commandAndMetadataSchema.parse(
await request.json(),
);

console.log(blue("Handling command: "), command);

// Open the key-value store
const kv = await Deno.openKv();
// Combine deciders to create a new decider that can handle both restaurant and order commands
const decider: Decider<Command, (Order & Restaurant) | null, Event> =
restaurantDecider.combine(orderDecider);
// Create a repository for the events / a Deno implementation of the IEventRepository
const eventRepository = new DenoEventRepository(kv);
// Create an aggregate to handle the commands of all types / Aggregate is composed of a decider and an event repository
const aggregate: ApplicationAggregate = new EventSourcingAggregate(
decider,
eventRepository,
);
// Handle the commands of all types
const result = await aggregate.handle(command);
console.log(blue("Result of command handling: "), result);
return new Response(JSON.stringify(result, null, 4), {
headers: { "Content-Type": "application/json" },
status: 200,
});
} catch (error) {
console.error("Error of command handling: ", error);
return new Response(error?.message ?? error, {
headers: { "Content-Type": "application/json" },
status: 500,
});
}
});
// Run the application server : `deno run --unstable-kv --allow-net server.ts`

0 comments on commit 0d74a07

Please sign in to comment.