Skip to content

Commit

Permalink
ci: add coveralls
Browse files Browse the repository at this point in the history
fix(proto): fix proto generation
feat: add basic app endpoint functions
feat: add zod validation
fix(microservices): fix port assignments when running locally
  • Loading branch information
Zyzle committed Jun 6, 2023
1 parent e45ae2d commit 170b6f4
Show file tree
Hide file tree
Showing 35 changed files with 817 additions and 74 deletions.
5 changes: 4 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/not-a-real-shop"
GATEWAY_PORT=3000
GATEWAY_PORT=3000
ORDERS_PORT=5001
PRODUCTS_PORT=5002
USERS_PORT=5003
9 changes: 8 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,12 @@ jobs:

- run: npx nx format:check
- run: npx nx affected -t lint --parallel=3
- run: npx nx affected -t test --parallel=3 --configuration=ci
- run: npx nx affected -t test --parallel=3 --configuration=ci --coverage --coverageReporters=lcov
- run: node ./tools/coverageMerger.js
- run: npx nx affected -t build --parallel=3

- name: Coveralls
uses: coverallsapp/github-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage/lcov.info
4 changes: 3 additions & 1 deletion apps/gateway/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';

import { ProductsModule } from './products/products.module';
import { OrdersModule } from './orders/orders.module';
import { UsersModule } from './users/users.module';

@Module({
imports: [ProductsModule],
imports: [ProductsModule, OrdersModule, UsersModule],
controllers: [],
providers: [],
})
Expand Down
27 changes: 27 additions & 0 deletions apps/gateway/src/orders/orders.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Test, TestingModule } from '@nestjs/testing';
import { createMock } from '@golevelup/ts-jest';

import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';

describe('OrdersController', () => {
let controller: OrdersController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: OrdersService,
useValue: createMock<OrdersService>(),
},
],
controllers: [OrdersController],
}).compile();

controller = module.get<OrdersController>(OrdersController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
23 changes: 23 additions & 0 deletions apps/gateway/src/orders/orders.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Controller, Get, Param } from '@nestjs/common';

import { OrdersService } from './orders.service';

@Controller('orders')
export class OrdersController {
constructor(private ordersService: OrdersService) {}

@Get()
getAllOrders() {
return this.ordersService.getAllOrders();
}

@Get(':id')
getOrder(@Param('id') id: string) {
return this.ordersService.getOrder(id);
}

@Get('user/:userId')
getUserOrders(@Param('userId') userId: string) {
return this.ordersService.getUserOrders(userId);
}
}
26 changes: 26 additions & 0 deletions apps/gateway/src/orders/orders.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';

import { Orders } from '@not-a-real-shop/rpc';

import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';

@Module({
imports: [
ClientsModule.register([
{
name: Orders.ORDERS_PACKAGE_NAME,
transport: Transport.GRPC,
options: {
url: `localhost:${process.env.ORDERS_PORT}`,
package: Orders.ORDERS_PACKAGE_NAME,
protoPath: './proto/orders.proto',
},
},
]),
],
controllers: [OrdersController],
providers: [OrdersService],
})
export class OrdersModule {}
32 changes: 32 additions & 0 deletions apps/gateway/src/orders/orders.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ClientGrpc } from '@nestjs/microservices';
import { createMock } from '@golevelup/ts-jest';

import { Orders } from '@not-a-real-shop/rpc';

import { OrdersService } from './orders.service';

describe('OrdersService', () => {
let service: OrdersService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
OrdersService,
{
provide: Orders.ORDERS_PACKAGE_NAME,
useValue:
createMock<ClientGrpc>().getService<Orders.OrdersServiceClient>(
Orders.ORDERS_SERVICE_NAME
),
},
],
}).compile();

service = module.get<OrdersService>(OrdersService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
29 changes: 29 additions & 0 deletions apps/gateway/src/orders/orders.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';

import { Orders } from '@not-a-real-shop/rpc';

@Injectable()
export class OrdersService implements OnModuleInit {
private ordersRpcService: Orders.OrdersServiceClient;

constructor(@Inject(Orders.ORDERS_PACKAGE_NAME) private client: ClientGrpc) {}

onModuleInit() {
this.ordersRpcService = this.client.getService<Orders.OrdersServiceClient>(
Orders.ORDERS_SERVICE_NAME
);
}

getAllOrders() {
return this.ordersRpcService.getAllOrders({});
}

getOrder(id: string) {
return this.ordersRpcService.getOrder({ id });
}

getUserOrders(userId: string) {
return this.ordersRpcService.getUserOrders({ userId });
}
}
9 changes: 9 additions & 0 deletions apps/gateway/src/products/products.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing';
import { createMock } from '@golevelup/ts-jest';

import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';

describe('ProductsController', () => {
let controller: ProductsController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: ProductsService,
useValue: createMock<ProductsService>(),
},
],
controllers: [ProductsController],
}).compile();

Expand Down
24 changes: 23 additions & 1 deletion apps/gateway/src/products/products.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Controller, Get, Param } from '@nestjs/common';
import { Body, Controller, Get, Param, Post } from '@nestjs/common';

import { ProductsService } from './products.service';
import { ReserveStockDto } from './products.dto';
import { ApiBody } from '@nestjs/swagger';

@Controller('products')
export class ProductsController {
Expand All @@ -15,4 +17,24 @@ export class ProductsController {
getProduct(@Param('id') id: string) {
return this.productsService.getProduct(id);
}

@Post(':id/reserve')
@ApiBody({ type: ReserveStockDto })
reserveStock(@Param('id') productId: string, @Body() body: ReserveStockDto) {
return this.productsService.reserveStock(
productId,
body.quantity,
body.cartItemId
);
}

@Post(':id/release')
@ApiBody({ type: ReserveStockDto })
releaseStock(@Param('id') productId: string, @Body() body: ReserveStockDto) {
return this.productsService.releaseStock(
productId,
body.quantity,
body.cartItemId
);
}
}
9 changes: 9 additions & 0 deletions apps/gateway/src/products/products.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createZodDto } from 'nestjs-zod';
import { z } from 'nestjs-zod/z';

export const ReserveStockSchema = z.object({
quantity: z.number().int().positive(),
cartItemId: z.string().uuid(),
});

export class ReserveStockDto extends createZodDto(ReserveStockSchema) {}
11 changes: 10 additions & 1 deletion apps/gateway/src/products/products.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Module } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
import { ClientsModule, Transport } from '@nestjs/microservices';

import { Products } from '@not-a-real-shop/rpc';

import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';
import { ZodValidationPipe } from 'nestjs-zod';

@Module({
imports: [
Expand All @@ -13,13 +15,20 @@ import { ProductsService } from './products.service';
name: Products.PRODUCTS_PACKAGE_NAME,
transport: Transport.GRPC,
options: {
url: `localhost:${process.env.PRODUCTS_PORT}`,
package: Products.PRODUCTS_PACKAGE_NAME,
protoPath: './proto/products.proto',
},
},
]),
],
controllers: [ProductsController],
providers: [ProductsService],
providers: [
{
provide: APP_PIPE,
useClass: ZodValidationPipe,
},
ProductsService,
],
})
export class ProductsModule {}
16 changes: 15 additions & 1 deletion apps/gateway/src/products/products.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ClientGrpc } from '@nestjs/microservices';
import { createMock } from '@golevelup/ts-jest';

import { Products } from '@not-a-real-shop/rpc';

import { ProductsService } from './products.service';

describe('ProductsService', () => {
let service: ProductsService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ProductsService],
providers: [
ProductsService,
{
provide: Products.PRODUCTS_PACKAGE_NAME,
useValue:
createMock<ClientGrpc>().getService<Products.ProductsServiceClient>(
Products.PRODUCTS_SERVICE_NAME
),
},
],
}).compile();

service = module.get<ProductsService>(ProductsService);
Expand Down
19 changes: 18 additions & 1 deletion apps/gateway/src/products/products.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';

import { Products } from '@not-a-real-shop/rpc';
Expand All @@ -23,6 +23,23 @@ export class ProductsService implements OnModuleInit {
}

getProducts() {
Logger.debug('Getting products');
return this.productsRpcService.getProducts({});
}

reserveStock(productId: string, quantity: number, cartItemId: string) {
return this.productsRpcService.reserveStock({
productId,
quantity,
cartItemId,
});
}

releaseStock(productId: string, quantity: number, cartItemId: string) {
return this.productsRpcService.releaseStock({
productId,
quantity,
cartItemId,
});
}
}
27 changes: 27 additions & 0 deletions apps/gateway/src/users/users.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Test, TestingModule } from '@nestjs/testing';
import { createMock } from '@golevelup/ts-jest';

import { UsersController } from './users.controller';
import { UsersService } from './users.service';

describe('UsersController', () => {
let controller: UsersController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: UsersService,
useValue: createMock<UsersService>(),
},
],
controllers: [UsersController],
}).compile();

controller = module.get<UsersController>(UsersController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
13 changes: 13 additions & 0 deletions apps/gateway/src/users/users.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Controller, Get, Param } from '@nestjs/common';

import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}

@Get(':id')
getUser(@Param('id') id: string) {
return this.usersService.getUser(id);
}
}
Loading

0 comments on commit 170b6f4

Please sign in to comment.