Skip to content

Commit 8585ecd

Browse files
committed
feat: add services
0 parents  commit 8585ecd

26 files changed

+425
-0
lines changed

Diff for: monolith/main.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NestFactory } from '@nestjs/core';
2+
import { MonolithModule } from './monolith.module';
3+
4+
async function bootstrap() {
5+
const app = await NestFactory.create(MonolithModule);
6+
await app.listen(4040);
7+
}
8+
bootstrap();

Diff for: monolith/monolith.model.ts

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Field, ObjectType } from '@nestjs/graphql';
2+
3+
@ObjectType()
4+
export class Review {
5+
@Field()
6+
content: string;
7+
8+
@Field()
9+
productName: string;
10+
11+
@Field()
12+
rating: number;
13+
}
14+
15+
@ObjectType()
16+
export class Product {
17+
@Field()
18+
upc: string;
19+
20+
@Field()
21+
rating: number;
22+
}
23+
24+
@ObjectType()
25+
export class User {
26+
@Field()
27+
id: number;
28+
29+
@Field()
30+
username: string;
31+
32+
@Field()
33+
reviews: Review[];
34+
35+
@Field()
36+
basket: Product[];
37+
}

Diff for: monolith/monolith.module.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
ApolloFederationDriver,
3+
ApolloFederationDriverConfig,
4+
} from '@nestjs/apollo';
5+
import { Module } from '@nestjs/common';
6+
import { GraphQLModule } from '@nestjs/graphql';
7+
import { MonolithResolver } from './monolith.resolver';
8+
import { MonolithService } from './monolith.service';
9+
10+
11+
@Module({
12+
providers: [MonolithResolver, MonolithService],
13+
imports: [
14+
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
15+
driver: ApolloFederationDriver,
16+
typePaths: ['**/*.graphql'],
17+
}),
18+
],
19+
})
20+
export class MonolithModule {}

Diff for: monolith/monolith.resolver.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Args, Query, Resolver } from '@nestjs/graphql';
2+
import { MonolithService } from './monolith.service';
3+
import { Product, User } from './monolith.model';
4+
5+
@Resolver()
6+
export class MonolithResolver {
7+
constructor(private monolithService: MonolithService) {}
8+
9+
@Query(of => User)
10+
getUser(@Args({ name: 'id' }) id: number) {
11+
return this.monolithService.findById(id);
12+
}
13+
14+
@Query(of => Product)
15+
getProducts() {
16+
return this.monolithService.products;
17+
}
18+
}

Diff for: monolith/monolith.service.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { Product, Review, User } from './monolith.model';
3+
4+
@Injectable()
5+
export class MonolithService {
6+
private pokeball = { upc: 'potion', rating: 5.0 };
7+
private potion = { upc: 'potion', rating: 3.0 };
8+
private masterball = { upc: 'masterball', rating: null };
9+
private ashReviewOne: Review = { content: "wow! 20hp!", productName: 'potion', rating: 5 };
10+
private ashReviewTwo: Review = { content: "now I can catch more friends!", productName: 'pokeball', rating: 5 };
11+
private garyReviewOne: Review = { content: "20hp? Pathetic.", productName: 'potion', rating: 1 };
12+
13+
products: Product[] = [
14+
this.pokeball,
15+
this.potion,
16+
this.masterball,
17+
];
18+
19+
private users: User[] = [
20+
{ id: 1, username: 'AshKetchum', reviews: [this.ashReviewOne, this.ashReviewTwo], basket: [ this.pokeball, this.potion ] },
21+
{ id: 2, username: 'GaryOak', reviews: [this.garyReviewOne], basket: null },
22+
{ id: 3, username: 'ProfessorOak', reviews: [], basket: [this.masterball] },
23+
];
24+
25+
findById(id: number) {
26+
return this.users.find((user) => user.id === id);
27+
}
28+
}

Diff for: monolith/schema.graphql

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
type Query {
2+
getUser(id: Int!): User
3+
getProducts: [Product]!
4+
}
5+
6+
type Product {
7+
upc: ID!
8+
rating: Float
9+
}
10+
11+
type Review {
12+
productName: String!
13+
content: String!
14+
rating: Int!
15+
}
16+
17+
type User {
18+
id: Int!
19+
username: String!
20+
reviews: [Review!]!
21+
basket: [Product!]
22+
}

Diff for: package.json

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"scripts": {
3+
"start:monolith": "ts-node ./monolith/main.ts",
4+
"start:products": "ts-node ./products/main.ts",
5+
"start:users": "ts-node ./users/main.ts",
6+
"start:reviews": "ts-node ./reviews/main.ts",
7+
"start": "concurrently --kill-others-on-fail \"ts-node monolith/main.ts\" \"ts-node users/main.ts\" \"ts-node products/main.ts\" \"ts-node reviews/main.ts\""
8+
},
9+
"dependencies": {
10+
"@apollo/subgraph": "^2.6.2",
11+
"@nestjs/apollo": "^12.0.11",
12+
"@nestjs/cli": "^10.2.1",
13+
"@nestjs/common": "^10.2.10",
14+
"@nestjs/core": "^10.2.10",
15+
"@nestjs/graphql": "^12.0.11",
16+
"@nestjs/platform-express": "^10.2.10",
17+
"concurrently": "^8.2.2",
18+
"graphql": "^16.8.1",
19+
"ts-node": "^10.9.2"
20+
},
21+
"devDependencies": {
22+
"typescript": "^5.3.3"
23+
}
24+
}

Diff for: products/main.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NestFactory } from '@nestjs/core';
2+
import { ProductsModule } from './products.module';
3+
4+
async function bootstrap() {
5+
const app = await NestFactory.create(ProductsModule);
6+
await app.listen(4041);
7+
}
8+
bootstrap();

Diff for: products/products.model.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Field, ObjectType } from '@nestjs/graphql';
2+
3+
@ObjectType()
4+
export class Product {
5+
@Field()
6+
upc: string;
7+
8+
@Field()
9+
rating: number;
10+
}

Diff for: products/products.module.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
ApolloFederationDriver,
3+
ApolloFederationDriverConfig,
4+
} from '@nestjs/apollo';
5+
import { Module } from '@nestjs/common';
6+
import { GraphQLModule } from '@nestjs/graphql';
7+
import { ProductsResolver } from './products.resolver';
8+
import { ProductsService } from './products.service';
9+
10+
11+
@Module({
12+
providers: [ProductsResolver, ProductsService],
13+
imports: [
14+
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
15+
driver: ApolloFederationDriver,
16+
typePaths: ['**/*.graphql'],
17+
}),
18+
],
19+
})
20+
export class ProductsModule {}

Diff for: products/products.resolver.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Args, Query, Resolver } from '@nestjs/graphql';
2+
import { ProductsService } from './products.service';
3+
import { Product } from './products.model';
4+
5+
@Resolver()
6+
export class ProductsResolver {
7+
constructor(private productsService: ProductsService) {}
8+
9+
@Query(of => Product)
10+
getProducts() {
11+
return this.productsService.products;
12+
}
13+
}

Diff for: products/products.service.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { Product } from './products.model';
3+
4+
@Injectable()
5+
export class ProductsService {
6+
private pokeball = { upc: 'potion', rating: 5.0 };
7+
private potion = { upc: 'potion', rating: 3.0 };
8+
private masterball = { upc: 'masterball', rating: null };
9+
10+
products: Product[] = [
11+
this.pokeball,
12+
this.potion,
13+
this.masterball,
14+
];
15+
}

Diff for: products/schema.graphql

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@override", "@key", "@shareable"])
2+
3+
type Query {
4+
getProducts: [Product]! @override(from: "monolith")
5+
}
6+
7+
type Product @shareable {
8+
upc: ID!
9+
rating: Float
10+
}

Diff for: reviews/main.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NestFactory } from '@nestjs/core';
2+
import { ReviewsModule } from './reviews.module';
3+
4+
async function bootstrap() {
5+
const app = await NestFactory.create(ReviewsModule);
6+
await app.listen(4043);
7+
}
8+
bootstrap();

Diff for: reviews/reviews.model.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Field, ObjectType } from '@nestjs/graphql';
2+
3+
@ObjectType()
4+
export class Review {
5+
@Field()
6+
content: string;
7+
8+
@Field()
9+
productName: string;
10+
11+
@Field()
12+
rating: number;
13+
}
14+
15+
@ObjectType()
16+
export class User {
17+
@Field()
18+
id: number;
19+
20+
@Field()
21+
reviews: Review[] | null;
22+
}
23+

Diff for: reviews/reviews.module.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
ApolloFederationDriver,
3+
ApolloFederationDriverConfig,
4+
} from '@nestjs/apollo';
5+
import { Module } from '@nestjs/common';
6+
import { GraphQLModule } from '@nestjs/graphql';
7+
import { ReviewsResolver } from './reviews.resolver';
8+
import { ReviewsService } from './reviews.service';
9+
10+
11+
@Module({
12+
providers: [ReviewsResolver, ReviewsService],
13+
imports: [
14+
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
15+
driver: ApolloFederationDriver,
16+
typePaths: ['**/*.graphql'],
17+
}),
18+
],
19+
})
20+
export class ReviewsModule {}

Diff for: reviews/reviews.resolver.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Args, Query, Resolver } from '@nestjs/graphql';
2+
import { ReviewsService } from './reviews.service';
3+
import { User } from './reviews.model';
4+
5+
@Resolver()
6+
export class ReviewsResolver {
7+
constructor(private usersService: ReviewsService) {}
8+
9+
@Query(of => User)
10+
getUser(@Args({ name: 'id' }) id: number) {
11+
return this.usersService.findById(id);
12+
}
13+
}

Diff for: reviews/reviews.service.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { Review, User } from './reviews.model';
3+
4+
@Injectable()
5+
export class ReviewsService {
6+
private ashReviewOne: Review = { content: "wow! 20hp!", productName: 'potion', rating: 5 };
7+
private ashReviewTwo: Review = { content: "now I can catch more friends!", productName: 'pokeball', rating: 5 };
8+
private garyReviewOne: Review = { content: "20hp? Pathetic.", productName: 'potion', rating: 1 };
9+
10+
private users: User[] = [
11+
{ id: 1, reviews: [this.ashReviewOne, this.ashReviewTwo] },
12+
{ id: 2, reviews: [this.garyReviewOne] },
13+
{ id: 3, reviews: null },
14+
];
15+
16+
findById(id: number) {
17+
return this.users.find((user) => user.id === id);
18+
}
19+
}

Diff for: reviews/schema.graphql

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@override", "@key", "@shareable"])
2+
3+
type Query {
4+
getUser(id: Int!): User @shareable
5+
}
6+
7+
type User {
8+
id: Int! @shareable
9+
reviews: [Review!]! @override(from: "monolith")
10+
}
11+
12+
type Review {
13+
content: String! @override(from: "monolith")
14+
productName: String! @override(from: "monolith")
15+
rating: Int! @override(from: "monolith")
16+
}

Diff for: tsconfig.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"declaration": true,
5+
"removeComments": true,
6+
"emitDecoratorMetadata": true,
7+
"experimentalDecorators": true,
8+
"allowSyntheticDefaultImports": true,
9+
"target": "ES2021",
10+
"sourceMap": true,
11+
"outDir": "./dist",
12+
"baseUrl": "./",
13+
"incremental": true,
14+
"skipLibCheck": true
15+
},
16+
"include": ["monolith/**/*"]
17+
}

Diff for: users/main.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NestFactory } from '@nestjs/core';
2+
import { UsersModule } from './users.module';
3+
4+
async function bootstrap() {
5+
const app = await NestFactory.create(UsersModule);
6+
await app.listen(4042);
7+
}
8+
bootstrap();

0 commit comments

Comments
 (0)