Skip to content

Commit 2d934fa

Browse files
committed
Fixed error handling
1 parent 26adddd commit 2d934fa

File tree

7 files changed

+50
-49
lines changed

7 files changed

+50
-49
lines changed

samples/from_crud_to_eventsourcing/src/core/http.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ export const isWeakETag = (etag: ETag): etag is WeakETag => {
3434

3535
export const getWeakETagValue = (etag: ETag): WeakETag => {
3636
const weak = WeakETagRegex.exec(etag);
37-
if (weak == null || weak.length == 0) throw ETagErrors.WRONG_WEAK_ETAG_FORMAT;
37+
if (weak == null || weak.length == 0)
38+
throw new Error(ETagErrors.WRONG_WEAK_ETAG_FORMAT);
3839
return weak[1] as WeakETag;
3940
};
4041

@@ -66,7 +67,7 @@ export const getWeakETagValueFromHeader = (
6667
}
6768

6869
if (!isWeakETag(etag)) {
69-
throw ETagErrors.WRONG_WEAK_ETAG_FORMAT;
70+
throw new Error(ETagErrors.WRONG_WEAK_ETAG_FORMAT);
7071
}
7172

7273
return getWeakETagValue(etag);
@@ -89,7 +90,7 @@ export const getExpectedRevisionFromIfMatch = (request: ApiRequest): bigint => {
8990
const revision = getExpectedRevision(request, HeaderNames.IF_MATCH);
9091

9192
if (revision === undefined) {
92-
throw ETagErrors.MISSING_HEADER;
93+
throw new Error(ETagErrors.MISSING_HEADER);
9394
}
9495

9596
return revision;

samples/from_crud_to_eventsourcing/src/core/postgres.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ let db: ConnectionPool;
1212
export const getPostgres = (): ConnectionPool => {
1313
if (!db) {
1414
if (!config.postgres.connectionString) {
15-
throw 'Postgres connection string not set. Please define "DATABASE_URL" environment variable';
15+
throw new Error(
16+
'Postgres connection string not set. Please define "DATABASE_URL" environment variable'
17+
);
1618
}
1719

1820
if (!config.postgres.schemaName) {
19-
throw 'Postgres schema name string not set. Please define "DATABASE_SCHEMA" environment variable';
21+
throw new Error(
22+
'Postgres schema name string not set. Please define "DATABASE_SCHEMA" environment variable'
23+
);
2024
}
2125

2226
db = createConnectionPool({
@@ -65,7 +69,7 @@ export const assertUpdated = async <T>(
6569
const result = await update();
6670

6771
if (result.length === 0) {
68-
throw PostgresErrors.FAILED_TO_UPDATE_ROW;
72+
throw new Error(PostgresErrors.FAILED_TO_UPDATE_ROW);
6973
}
7074

7175
return result;
@@ -77,7 +81,7 @@ export const assertFound = async <T>(
7781
const result = await find();
7882

7983
if (result === null) {
80-
throw PostgresErrors.ROW_NOT_FOUND;
84+
throw new Error(PostgresErrors.ROW_NOT_FOUND);
8185
}
8286

8387
return result;

samples/from_crud_to_eventsourcing/src/core/validation.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ export const enum ValidationErrors {
1414

1515
export const assertNotEmptyString = (value: unknown): string => {
1616
if (typeof value !== 'string' || value.length === 0) {
17-
throw ValidationErrors.NOT_A_NONEMPTY_STRING;
17+
throw new Error(ValidationErrors.NOT_A_NONEMPTY_STRING);
1818
}
1919
return value;
2020
};
2121

2222
export const assertStringOrUndefined = (value: unknown): string | undefined => {
2323
if (value != null && typeof value !== 'string') {
24-
throw ValidationErrors.NOT_A_STRING_OR_UNDEFINED;
24+
throw new Error(ValidationErrors.NOT_A_STRING_OR_UNDEFINED);
2525
}
2626
return value ?? undefined;
2727
};
2828

2929
export const assertPositiveNumber = (value: unknown): number => {
3030
if (typeof value !== 'number' || value <= 0) {
31-
throw ValidationErrors.NOT_A_POSITIVE_NUMBER;
31+
throw new Error(ValidationErrors.NOT_A_POSITIVE_NUMBER);
3232
}
3333
return value;
3434
};
@@ -41,26 +41,26 @@ export const assertPositiveNumberOrUndefined = (
4141

4242
export const assertUnsignedBigInt = (value: string): bigint => {
4343
if (value === undefined) {
44-
throw ValidationErrors.NOT_AN_UNSIGNED_BIGINT;
44+
throw new Error(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);
4545
}
4646

4747
const number = BigInt(value);
4848
if (number < 0) {
49-
throw ValidationErrors.NOT_AN_UNSIGNED_BIGINT;
49+
throw new Error(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);
5050
}
5151
return number;
5252
};
5353

5454
export const assertDateOrUndefined = (value: unknown): Date | undefined => {
5555
if (value != null && typeof value !== 'string') {
56-
throw ValidationErrors.NOT_A_DATE_OR_UNDEFINED;
56+
throw new Error(ValidationErrors.NOT_A_DATE_OR_UNDEFINED);
5757
}
5858
return value ? new Date(value) : undefined;
5959
};
6060

6161
export const assertArray = (value: unknown): [] => {
6262
if (!Array.isArray(value)) {
63-
throw ValidationErrors.NOT_AN_ARRAY;
63+
throw new Error(ValidationErrors.NOT_AN_ARRAY);
6464
}
6565
return value as [];
6666
};

samples/from_crud_to_eventsourcing/src/eventsourced/core/streams.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,18 @@ import {
1111
StreamingRead,
1212
} from '@eventstore/db-client';
1313

14-
export type ApplyEvent<Entity, E extends EventType> = (
15-
currentState: Entity | undefined,
16-
event: RecordedEvent<E>
17-
) => Entity;
18-
1914
export const StreamAggregator =
2015
<Entity, StreamEvents extends EventType>(
21-
when: ApplyEvent<Entity, StreamEvents>
16+
when: (currentState: Entity, event: RecordedEvent<StreamEvents>) => Entity
2217
) =>
2318
async (
2419
eventStream: StreamingRead<ResolvedEvent<StreamEvents>>
2520
): Promise<Entity> => {
26-
let currentState: Entity | undefined = undefined;
21+
let currentState = {} as Entity;
2722
for await (const { event } of eventStream) {
2823
if (!event) continue;
2924
currentState = when(currentState, event);
3025
}
31-
if (currentState == null) throw 'oh no';
3226
return currentState;
3327
};
3428

@@ -40,7 +34,9 @@ let eventStore: EventStoreDBClient;
4034

4135
export function getEventStore(): EventStoreDBClient {
4236
if (!config.eventStoreDB.connectionString) {
43-
throw 'EventStoreDB connection string not set. Please define "ESDB_CONNECTION_STRING" environment variable';
37+
throw new Error(
38+
'EventStoreDB connection string not set. Please define "ESDB_CONNECTION_STRING" environment variable'
39+
);
4440
}
4541

4642
if (!eventStore) {

samples/from_crud_to_eventsourcing/src/eventsourced/shoppingCarts/productItem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export const assertProductItemExists = (
7272
const current = findProductItem(productItems, productId);
7373

7474
if (!current || current.quantity < quantity) {
75-
throw ShoppingCartErrors.PRODUCT_ITEM_NOT_FOUND;
75+
throw new Error(ShoppingCartErrors.PRODUCT_ITEM_NOT_FOUND);
7676
}
7777

7878
return current;

samples/from_crud_to_eventsourcing/src/eventsourced/shoppingCarts/shoppingCart.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,25 @@ export interface ShoppingCart {
101101

102102
export const enum ShoppingCartErrors {
103103
OPENED_EXISTING_CART = 'OPENED_EXISTING_CART',
104-
CART_IS_ALREADY_CLOSED = 'CART_IS_ALREADY_CLOSED',
105-
CART_NOT_FOUND = 'CART_NOT_FOUND',
104+
CART_IS_NOT_OPENED = 'CART_IS_NOT_OPENED',
106105
USER_DOES_NOT_EXISTS = 'USER_DOES_NOT_EXISTS',
106+
NO_PRODUCTS_ITEMS = 'NO_PRODUCTS_ITEMS',
107107
PRODUCT_ITEM_NOT_FOUND = 'PRODUCT_ITEM_NOT_FOUND',
108108
UNKNOWN_EVENT_TYPE = 'UNKNOWN_EVENT_TYPE',
109109
}
110110

111111
export const toShoppingCartStreamName = (shoppingCartId: string) =>
112112
`shopping_cart-${shoppingCartId}`;
113113

114-
export const assertShoppingCartIsNotClosed = (shoppingCart: ShoppingCart) => {
115-
if (
116-
(shoppingCart.status & ShoppingCartStatus.Closed) ===
117-
ShoppingCartStatus.Closed
118-
) {
119-
throw ShoppingCartErrors.CART_IS_ALREADY_CLOSED;
114+
export const assertShoppingCartIsOpened = (shoppingCart: ShoppingCart) => {
115+
if (shoppingCart.status !== ShoppingCartStatus.Opened) {
116+
throw new Error(ShoppingCartErrors.CART_IS_NOT_OPENED);
117+
}
118+
};
119+
120+
export const assertHasProductItems = (shoppingCart: ShoppingCart) => {
121+
if (shoppingCart.productItems.length === 0) {
122+
throw new Error(ShoppingCartErrors.NO_PRODUCTS_ITEMS);
120123
}
121124
};
122125

@@ -128,19 +131,14 @@ export const getShoppingCart = StreamAggregator<
128131
ShoppingCart,
129132
ShoppingCartEvent
130133
>((currentState, event) => {
131-
if (event.type === 'shopping-cart-opened') {
132-
if (currentState != null) throw ShoppingCartErrors.OPENED_EXISTING_CART;
133-
return {
134-
id: event.data.shoppingCartId,
135-
openedAt: new Date(event.data.openedAt),
136-
productItems: [],
137-
status: ShoppingCartStatus.Opened,
138-
};
139-
}
140-
141-
if (currentState == null) throw ShoppingCartErrors.CART_NOT_FOUND;
142-
143134
switch (event.type) {
135+
case 'shopping-cart-opened':
136+
return {
137+
id: event.data.shoppingCartId,
138+
openedAt: new Date(event.data.openedAt),
139+
productItems: [],
140+
status: ShoppingCartStatus.Opened,
141+
};
144142
case 'product-item-added-to-shopping-cart':
145143
return {
146144
...currentState,
@@ -164,7 +162,8 @@ export const getShoppingCart = StreamAggregator<
164162
};
165163
default: {
166164
const _: never = event;
167-
throw ShoppingCartErrors.UNKNOWN_EVENT_TYPE;
165+
console.error(`Unknown event type %s`, event);
166+
return currentState;
168167
}
169168
}
170169
});
@@ -205,7 +204,7 @@ export const addProductItemToShoppingCart = async (
205204
): Promise<ProductItemAddedToShoppingCart> => {
206205
const shoppingCart = await getShoppingCart(events);
207206

208-
assertShoppingCartIsNotClosed(shoppingCart);
207+
assertShoppingCartIsOpened(shoppingCart);
209208

210209
const pricedProductItem = await getPricedProduct(productItem);
211210

@@ -234,7 +233,7 @@ export const removeProductItemFromShoppingCart = async (
234233
): Promise<ProductItemRemovedFromShoppingCart> => {
235234
const shoppingCart = await getShoppingCart(events);
236235

237-
assertShoppingCartIsNotClosed(shoppingCart);
236+
assertShoppingCartIsOpened(shoppingCart);
238237

239238
const current = assertProductItemExists(
240239
shoppingCart.productItems,
@@ -272,7 +271,8 @@ export const confirmShoppingCart = async (
272271
): Promise<ShoppingCartConfirmed> => {
273272
const shoppingCart = await getShoppingCart(events);
274273

275-
assertShoppingCartIsNotClosed(shoppingCart);
274+
assertShoppingCartIsOpened(shoppingCart);
275+
assertHasProductItems(shoppingCart);
276276

277277
const user = await getUserData(userId);
278278

samples/from_crud_to_eventsourcing/src/eventsourced/shoppingCarts/shoppingCartDetails.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const projectToShoppingCartItem = (
4747
return projectShoppingCartConfirmed(db, event, streamRevision);
4848
default: {
4949
const _: never = event;
50-
throw ShoppingCartErrors.UNKNOWN_EVENT_TYPE;
50+
throw new Error(ShoppingCartErrors.UNKNOWN_EVENT_TYPE);
5151
}
5252
}
5353
};

0 commit comments

Comments
 (0)