Skip to content

Commit bb0f316

Browse files
committed
feat: ts and bun router plugin example
1 parent 33739df commit bb0f316

27 files changed

+8282
-449
lines changed

cosmo-router/graph.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ subgraphs:
66
file: ../subgraphs/products/schema.graphql
77
- plugin:
88
version: 0.0.1
9-
path: plugins/users
9+
path: plugins/users
10+
- plugin:
11+
version: 0.0.1
12+
path: plugins/courses

cosmo-router/package.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,19 @@
66
"type": "module",
77
"scripts": {
88
"compose": "wgc router compose -i graph.yaml -o config.json",
9-
"build": "wgc router plugin build plugins/users --debug && npm run compose",
10-
"test": "wgc router plugin test plugins/users",
11-
"generate": "wgc router plugin build plugins/users --generate-only",
9+
10+
"build:users": "wgc router plugin build plugins/users --debug",
11+
"build:courses": "wgc router plugin build plugins/courses --debug",
12+
"build": "npm run build:users && npm run build:courses && npm run compose",
13+
14+
"test:users": "wgc router plugin test plugins/users",
15+
"test:courses": "wgc router plugin test plugins/courses",
16+
"test": "npm run test:users && npm run test:courses",
17+
18+
"generate:users": "wgc router plugin build plugins/users --generate-only",
19+
"generate:courses": "wgc router plugin build plugins/courses --generate-only",
20+
"generate": "npm run generate:users && npm run generate:courses",
21+
1222
"postinstall": "rm -rf release && wgc router download-binary -o release && chmod +x release/router",
1323
"start": "./release/router"
1424
},
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Ignore the binary files
2+
bin/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
.PHONY: build test generate install-wgc
3+
4+
install-wgc:
5+
@which wgc > /dev/null 2>&1 || npm install -g wgc@latest
6+
7+
make: build
8+
9+
test: install-wgc
10+
wgc router plugin test .
11+
12+
generate: install-wgc
13+
wgc router plugin generate .
14+
15+
publish: generate
16+
wgc router plugin publish .
17+
18+
build: install-wgc
19+
wgc router plugin build . --debug
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Courses Plugin
2+
3+
A Cosmo Router plugin for course management and enrollment. This plugin provides a GraphQL API for managing courses, instructors, and student enrollments using gRPC service implementation.
4+
5+
## Features
6+
7+
- Course creation and management
8+
- Instructor course assignments
9+
- In-memory data storage with mock data
10+
11+
## Testing
12+
13+
The tests validate all functionality of the plugin including:
14+
15+
- Course querying (all courses and by ID)
16+
- User lookup by ID (instructors and students)
17+
- Course creation
18+
- Student enrollment in courses
19+
20+
### Running Tests
21+
22+
```bash
23+
cd cosmo-router/plugins/courses
24+
make test
25+
```
26+
27+
## Directory Structure
28+
29+
```
30+
courses/
31+
├── bin/ # Compiled plugin binaries
32+
├── generated/ # Auto-generated gRPC code from schema
33+
│ ├── service.pb.js
34+
│ ├── service_grpc_pb.js
35+
│ └── service.proto
36+
├── src/ # Source code
37+
│ ├── plugin.ts # Plugin implementation
38+
│ ├── plugin.test.ts # Integration tests
39+
│ ├── plugin-server.ts # gRPC server setup
40+
│ └── schema.graphql # GraphQL schema definition
41+
└── package.json # Dependencies
42+
```
43+
44+
## GraphQL API
45+
46+
### Queries
47+
48+
- `courses`: List all courses
49+
- `course(id: ID!)`: Get a course by ID
50+
51+
### Mutations
52+
53+
- `createCourse(input: CourseInput!)`: Create a new course
54+
- `enrollUser(userId: ID!, courseId: ID!)`: Enroll a user in a course
55+
56+
57+
## Example GraphQL Operations
58+
59+
```graphql
60+
# Get all courses
61+
query {
62+
courses {
63+
id
64+
title
65+
description
66+
instructor {
67+
id
68+
}
69+
durationHours
70+
published
71+
}
72+
}
73+
74+
# Get a specific course
75+
query {
76+
course(id: "course-1") {
77+
id
78+
title
79+
description
80+
instructor {
81+
id
82+
}
83+
durationHours
84+
published
85+
}
86+
}
87+
88+
# Create a new course
89+
mutation {
90+
createCourse(input: {
91+
title: "Advanced GraphQL"
92+
description: "Master GraphQL concepts"
93+
instructorId: "1"
94+
durationHours: 30
95+
published: true
96+
}) {
97+
id
98+
title
99+
description
100+
instructor {
101+
id
102+
}
103+
}
104+
}
105+
106+
# Enroll a user in a course
107+
mutation {
108+
enrollUser(userId: "user-1", courseId: "course-1") {
109+
id
110+
user {
111+
id
112+
}
113+
course {
114+
id
115+
title
116+
}
117+
progress
118+
}
119+
}
120+
```

cosmo-router/plugins/courses/bun.lock

Lines changed: 236 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
{
2+
"version": 1,
3+
"service": "CoursesService",
4+
"operationMappings": [
5+
{
6+
"type": "OPERATION_TYPE_QUERY",
7+
"original": "courses",
8+
"mapped": "QueryCourses",
9+
"request": "QueryCoursesRequest",
10+
"response": "QueryCoursesResponse"
11+
},
12+
{
13+
"type": "OPERATION_TYPE_QUERY",
14+
"original": "course",
15+
"mapped": "QueryCourse",
16+
"request": "QueryCourseRequest",
17+
"response": "QueryCourseResponse"
18+
},
19+
{
20+
"type": "OPERATION_TYPE_MUTATION",
21+
"original": "createCourse",
22+
"mapped": "MutationCreateCourse",
23+
"request": "MutationCreateCourseRequest",
24+
"response": "MutationCreateCourseResponse"
25+
},
26+
{
27+
"type": "OPERATION_TYPE_MUTATION",
28+
"original": "enrollUser",
29+
"mapped": "MutationEnrollUser",
30+
"request": "MutationEnrollUserRequest",
31+
"response": "MutationEnrollUserResponse"
32+
}
33+
],
34+
"entityMappings": [
35+
{
36+
"typeName": "User",
37+
"kind": "entity",
38+
"key": "id",
39+
"rpc": "LookupUserById",
40+
"request": "LookupUserByIdRequest",
41+
"response": "LookupUserByIdResponse"
42+
}
43+
],
44+
"typeFieldMappings": [
45+
{
46+
"type": "Query",
47+
"fieldMappings": [
48+
{
49+
"original": "courses",
50+
"mapped": "courses",
51+
"argumentMappings": []
52+
},
53+
{
54+
"original": "course",
55+
"mapped": "course",
56+
"argumentMappings": [
57+
{
58+
"original": "id",
59+
"mapped": "id"
60+
}
61+
]
62+
}
63+
]
64+
},
65+
{
66+
"type": "Mutation",
67+
"fieldMappings": [
68+
{
69+
"original": "createCourse",
70+
"mapped": "create_course",
71+
"argumentMappings": [
72+
{
73+
"original": "input",
74+
"mapped": "input"
75+
}
76+
]
77+
},
78+
{
79+
"original": "enrollUser",
80+
"mapped": "enroll_user",
81+
"argumentMappings": [
82+
{
83+
"original": "userId",
84+
"mapped": "user_id"
85+
},
86+
{
87+
"original": "courseId",
88+
"mapped": "course_id"
89+
}
90+
]
91+
}
92+
]
93+
},
94+
{
95+
"type": "User",
96+
"fieldMappings": [
97+
{
98+
"original": "id",
99+
"mapped": "id",
100+
"argumentMappings": []
101+
},
102+
{
103+
"original": "instructorCourses",
104+
"mapped": "instructor_courses",
105+
"argumentMappings": []
106+
},
107+
{
108+
"original": "enrollments",
109+
"mapped": "enrollments",
110+
"argumentMappings": []
111+
}
112+
]
113+
},
114+
{
115+
"type": "Course",
116+
"fieldMappings": [
117+
{
118+
"original": "id",
119+
"mapped": "id",
120+
"argumentMappings": []
121+
},
122+
{
123+
"original": "title",
124+
"mapped": "title",
125+
"argumentMappings": []
126+
},
127+
{
128+
"original": "description",
129+
"mapped": "description",
130+
"argumentMappings": []
131+
},
132+
{
133+
"original": "instructor",
134+
"mapped": "instructor",
135+
"argumentMappings": []
136+
},
137+
{
138+
"original": "durationHours",
139+
"mapped": "duration_hours",
140+
"argumentMappings": []
141+
},
142+
{
143+
"original": "published",
144+
"mapped": "published",
145+
"argumentMappings": []
146+
},
147+
{
148+
"original": "enrollments",
149+
"mapped": "enrollments",
150+
"argumentMappings": []
151+
}
152+
]
153+
},
154+
{
155+
"type": "Enrollment",
156+
"fieldMappings": [
157+
{
158+
"original": "id",
159+
"mapped": "id",
160+
"argumentMappings": []
161+
},
162+
{
163+
"original": "user",
164+
"mapped": "user",
165+
"argumentMappings": []
166+
},
167+
{
168+
"original": "course",
169+
"mapped": "course",
170+
"argumentMappings": []
171+
},
172+
{
173+
"original": "progress",
174+
"mapped": "progress",
175+
"argumentMappings": []
176+
},
177+
{
178+
"original": "enrolledAt",
179+
"mapped": "enrolled_at",
180+
"argumentMappings": []
181+
}
182+
]
183+
},
184+
{
185+
"type": "CourseInput",
186+
"fieldMappings": [
187+
{
188+
"original": "title",
189+
"mapped": "title",
190+
"argumentMappings": []
191+
},
192+
{
193+
"original": "description",
194+
"mapped": "description",
195+
"argumentMappings": []
196+
},
197+
{
198+
"original": "instructorId",
199+
"mapped": "instructor_id",
200+
"argumentMappings": []
201+
},
202+
{
203+
"original": "durationHours",
204+
"mapped": "duration_hours",
205+
"argumentMappings": []
206+
},
207+
{
208+
"original": "published",
209+
"mapped": "published",
210+
"argumentMappings": []
211+
}
212+
]
213+
}
214+
],
215+
"enumMappings": [],
216+
"resolveMappings": []
217+
}

0 commit comments

Comments
 (0)