Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-sa committed Aug 13, 2024
1 parent 1683620 commit 99a5b8b
Show file tree
Hide file tree
Showing 47 changed files with 723 additions and 186 deletions.
2 changes: 1 addition & 1 deletion accounting-service-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './lib/entities';
export * from './lib/service';
export * from './lib/services';
9 changes: 2 additions & 7 deletions accounting-service-api/src/lib/entities.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { entity, JSONEntity, JSONPartial, uuid, UUID } from '@deepkit/type';

import { Consumer } from '@ftgo/consumer-service-api';
import { entity, uuid, UUID } from '@deepkit/type';

@entity.name('account')
export class Account {
readonly id: UUID = uuid();
readonly consumerId: Consumer['id'];

static create(data: JSONPartial<Account>): Account {
return Object.assign(new Account(), data);
}
constructor(readonly consumerId: UUID) {}
}
23 changes: 0 additions & 23 deletions accounting-service-api/src/lib/service.ts

This file was deleted.

25 changes: 25 additions & 0 deletions accounting-service-api/src/lib/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { RestateService } from 'deepkit-restate';
import { UUID } from '@deepkit/type';

import { Consumer } from '@ftgo/consumer-service-api';
import { Money } from '@ftgo/common';

export interface AccountingServiceHandlers {
// Only required for handlers that need to be invoked directly using a Restate client
createAccount(consumer: Consumer): Promise<void>;
authorize(
consumerId: UUID,
orderId: UUID,
orderTotal: Money,
): Promise<unknown>;
reverseAuthorization(
consumerId: UUID,
orderId: UUID,
orderTotal: Money,
): Promise<unknown>;
}

export type AccountingServiceApi = RestateService<
'Accounting',
AccountingServiceHandlers
>;
14 changes: 12 additions & 2 deletions accounting-service/src/accounting.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { restate, RestateServiceContext } from 'deepkit-restate';
import { UUID } from '@deepkit/type';

import { Consumer, KafkaConsumerTopic } from '@ftgo/consumer-service-api';
import { Money } from '@ftgo/common';
import {
Account,
AccountingServiceApi,
AccountingServiceHandlers,
} from '@ftgo/accounting-service-api';
Expand All @@ -10,11 +13,18 @@ import { AccountRepository } from './account.repository';

@restate.service<AccountingServiceApi>()
export class AccountingService implements AccountingServiceHandlers {
constructor(private readonly accountRepository: AccountRepository) {}
constructor(private readonly account: AccountRepository) {}

// @ts-ignore
@(restate.kafka<KafkaConsumerTopic>().handler())
async createAccount(consumer: Consumer): Promise<void> {
await this.accountRepository.create({ consumerId: consumer.id });
await this.account.create(consumer.id);
}

@restate.handler()
async authorize(
consumerId: UUID,
orderId: UUID,
orderTotal: Money,
): Promise<unknown> {}
}
1 change: 1 addition & 0 deletions api-gateway/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Framework
SERVER_PORT=3000
SERVER_DEBUG=true
5 changes: 3 additions & 2 deletions api-gateway/src/accounting/accounting.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideAccountingServiceApi } from '@ftgo/accounting-service-api';
import { AccountingServiceApi } from '@ftgo/accounting-service-api';

import { AccountingController } from './accounting.controller';

export class AccountingModule extends createModule({
controllers: [AccountingController],
providers: [provideAccountingServiceApi()],
providers: [provideRestateServiceProxy<AccountingServiceApi>()],
}) {}
5 changes: 3 additions & 2 deletions api-gateway/src/consumer/consumer.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideConsumerServiceApi } from '@ftgo/consumer-service-api';
import { ConsumerServiceApi } from '@ftgo/consumer-service-api';

import { ConsumerController } from './consumer.controller';

export class ConsumerModule extends createModule({
controllers: [ConsumerController],
providers: [provideConsumerServiceApi()],
providers: [provideRestateServiceProxy<ConsumerServiceApi>()],
}) {}
5 changes: 3 additions & 2 deletions api-gateway/src/delivery/delivery.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideDeliveryServiceApi } from '@ftgo/delivery-service-api';
import { DeliveryServiceApi } from '@ftgo/delivery-service-api';

import { DeliveryController } from './delivery.controller';

export class DeliveryModule extends createModule({
controllers: [DeliveryController],
providers: [provideDeliveryServiceApi()],
providers: [provideRestateServiceProxy<DeliveryServiceApi>()],
}) {}
5 changes: 3 additions & 2 deletions api-gateway/src/kitchen/kitchen.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideKitchenServiceApi } from '@ftgo/kitchen-service-api';
import { KitchenServiceApi } from '@ftgo/kitchen-service-api';

import { KitchenController } from './kitchen.controller';

export class KitchenModule extends createModule({
controllers: [KitchenController],
providers: [provideKitchenServiceApi()],
providers: [provideRestateServiceProxy<KitchenServiceApi>()],
}) {}
33 changes: 31 additions & 2 deletions api-gateway/src/order/order.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
import { http } from '@deepkit/http';
import { http, HttpBody, HttpNotFoundError, HttpQuery } from '@deepkit/http';
import { RestateClient } from 'deepkit-restate';
import { UUID } from '@deepkit/type';

import {
CreateOrderRequest,
CreateOrderResponse,
OrderServiceApi,
} from '@ftgo/order-service-api';

@http.controller('order')
export class OrderController {}
export class OrderController {
constructor(
private readonly client: RestateClient,
private readonly service: OrderServiceApi,
) {}

@http.POST('')
async create(
request: HttpBody<CreateOrderRequest>,
): Promise<CreateOrderResponse> {}

@http.GET(':id')
async get(id: UUID) {
try {
} catch {
throw new HttpNotFoundError();
}
}

@http.POST('cancel/:id')
async cancel(id: UUID) {}
}
5 changes: 3 additions & 2 deletions api-gateway/src/order/order.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideOrderServiceApi } from '@ftgo/order-service-api';
import { OrderServiceApi } from '@ftgo/order-service-api';

import { OrderController } from './order.controller';

export class OrderModule extends createModule({
controllers: [OrderController],
providers: [provideOrderServiceApi()],
providers: [provideRestateServiceProxy<OrderServiceApi>()],
}) {}
5 changes: 3 additions & 2 deletions api-gateway/src/restaurant/restaurant.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createModule } from '@deepkit/app';
import { provideRestateServiceProxy } from 'deepkit-restate';

import { provideRestaurantServiceApi } from '@ftgo/restaurant-service-api';
import { RestaurantServiceApi } from '@ftgo/restaurant-service-api';

import { RestaurantController } from './restaurant.controller';

export class RestaurantModule extends createModule({
controllers: [RestaurantController],
providers: [provideRestaurantServiceApi()],
providers: [provideRestateServiceProxy<RestaurantServiceApi>()],
}) {}
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './lib/config';
export * from './lib/database';
export * from './lib/entities';
export * from './lib/errors';
export * from './lib/repository';
export * from './lib/types';
14 changes: 11 additions & 3 deletions common/src/lib/entities.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { float } from '@deepkit/type';
import { float, integer, Positive, UUID } from '@deepkit/type';

export class Money {
static ZERO = new Money(0);
static MAX = new Money(Number.MAX_SAFE_INTEGER);

constructor(readonly amount: float) {}

Expand All @@ -17,7 +18,14 @@ export class Money {
return this === other || this.amount === other.amount;
}

multiply(other: Money): Money {
return new Money(this.amount * other.amount);
multiply(amount: float): Money {
return new Money(this.amount * amount);
}
}

export class RevisedOrderLineItem {
constructor(
readonly quantity: integer & Positive,
readonly menuItemId: UUID,
) {}
}
1 change: 1 addition & 0 deletions common/src/lib/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class UnsupportedStateTransitionException extends Error {}
55 changes: 22 additions & 33 deletions common/src/lib/repository.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import { ClassType } from '@deepkit/core';
import {
ChangesInterface,
DeepPartial,
JSONEntity,
JSONPartial,
} from '@deepkit/type';
import {
RestateContextStorage,
RestateCustomContext,
RunAction,
} from 'deepkit-restate';
import { ChangesInterface, DeepPartial, JSONPartial } from '@deepkit/type';
import { RestateContextStorage, RestateCustomContext } from 'deepkit-restate';
import {
Database,
DatabaseQueryModel,
Expand All @@ -18,55 +9,53 @@ import {
PatchResult,
} from '@deepkit/orm';

export function RestateRepository<T extends OrmEntity>(
entity: ClassType<T> & { create(data: JSONPartial<T>): T },
) {
export function RestateRepository<E extends OrmEntity>(entity: ClassType<E>) {
return class Repository {
constructor(
readonly contextStorage: RestateContextStorage,
readonly database: Database,
) {}

get #ctx(): Pick<RestateCustomContext, 'run'> {
return (
this.contextStorage.getStore() || {
run: async (action: RunAction<any>) => action(),
}
);
return this.contextStorage.getStore()!;
}

// async findOne(filter: DatabaseQueryModel<T>['filter']): Promise<T> {
// async findOne(filter: DatabaseQueryModel<E>['filter']): Promise<E> {
// return await this.database.query(entity).filter(filter).findOne();
// }

async delete(
filter: DatabaseQueryModel<T>['filter'],
): Promise<DeleteResult<T>> {
return await this.#ctx.run<DeleteResult<T>>(() =>
filter: DatabaseQueryModel<E>['filter'],
): Promise<DeleteResult<E>> {
return await this.#ctx.run<DeleteResult<E>>(() =>
this.database.query(entity).filter(filter).deleteOne(),
);
}

// async find(filter: DatabaseQueryModel<T>['filter']): Promise<readonly T[]> {
// async find(filter: DatabaseQueryModel<E>['filter']): Promise<readonly E[]> {
// return await this.database.query(entity).filter(filter).find();
// }

async find(filter: DatabaseQueryModel<T>['filter']): Promise<T> {
async find(filter: DatabaseQueryModel<E>['filter']): Promise<E> {
return await this.database.query(entity).filter(filter).findOne();
}

async update(
filter: DatabaseQueryModel<T>['filter'],
changes: ChangesInterface<T> | DeepPartial<T>,
): Promise<PatchResult<T>> {
return await this.#ctx.run<PatchResult<T>>(() =>
async persist(entity: E): Promise<void> {
await this.#ctx.run(() => this.database.persist(entity));
}

async patch(
filter: DatabaseQueryModel<E>['filter'],
changes: ChangesInterface<E> | DeepPartial<E>,
): Promise<PatchResult<E>> {
return await this.#ctx.run<PatchResult<E>>(() =>
this.database.query(entity).filter(filter).patchOne(changes),
);
}

async create(data: JSONPartial<T>): Promise<T> {
return await this.#ctx.run<T>(async () => {
const et = entity.create(data);
async create(...args: ConstructorParameters<ClassType<E>>): Promise<E> {
return await this.#ctx.run<E>(async () => {
const et = new entity(...args);
await this.database.persist(et);
return et;
});
Expand Down
3 changes: 2 additions & 1 deletion consumer-service-api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/dtos';
export * from './lib/entities';
export * from './lib/service';
export * from './lib/services';
export * from './lib/topics';
9 changes: 9 additions & 0 deletions consumer-service-api/src/lib/dtos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { UUID } from '@deepkit/type';

import { Money } from '@ftgo/common';

export interface ValidateOrderRequest {
readonly consumerId: UUID;
readonly orderId: UUID;
readonly orderTotal: Money;
}
14 changes: 2 additions & 12 deletions consumer-service-api/src/lib/entities.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import {
entity,
JSONEntity,
JSONPartial,
PrimaryKey,
uuid,
UUID,
} from '@deepkit/type';
import { entity, PrimaryKey, uuid, UUID } from '@deepkit/type';

import { PersonName } from '@ftgo/common';

@entity.name('consumer')
export class Consumer {
readonly id: UUID & PrimaryKey = uuid();
readonly name: PersonName;

static create(data: JSONPartial<Consumer>) {
return Object.assign(new Consumer(), data);
}
constructor(readonly name: PersonName) {}
}
Loading

0 comments on commit 99a5b8b

Please sign in to comment.