Skip to content

Commit ff4af4a

Browse files
authored
Merge pull request #38 from MEITREX/misc_fixes
Miscellaneous Fixes & Improvements
2 parents fe6ec6f + 6947ba8 commit ff4af4a

5 files changed

Lines changed: 123 additions & 30 deletions

File tree

.meshrc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ additionalResolvers:
7676
- "./additionalResolvers/course.ts"
7777
- "./additionalResolvers/flashcard.ts"
7878
- "./additionalResolvers/quiz.ts"
79+
- "./additionalResolvers/user.ts"
7980
additionalEnvelopPlugins: "./envelopPlugins"
8081
transforms:
8182
- filterSchema:

additionalResolvers/user.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Resolvers } from "../.mesh";
2+
3+
const resolvers: Resolvers = {
4+
UserInfo: {
5+
availableCourseMemberships: {
6+
selectionSet: `{ id }`,
7+
async resolve(root, args, context, info) {
8+
return context.CourseService.Query._internal_noauth_courseMembershipsByUserId({
9+
root,
10+
args: {
11+
userId: root.id,
12+
availabilityFilter: true,
13+
},
14+
context,
15+
info,
16+
});
17+
}
18+
},
19+
unavailableCourseMemberships: {
20+
selectionSet: `{ id }`,
21+
async resolve(root, args, context, info) {
22+
return context.CourseService.Query._internal_noauth_courseMembershipsByUserId({
23+
root,
24+
args: {
25+
userId: root.id,
26+
availabilityFilter: false,
27+
},
28+
context,
29+
info,
30+
});
31+
}
32+
}
33+
}
34+
};
35+
36+
export default resolvers;

additionalTypeDefs/user.graphqls

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,9 @@ extend type UserInfo {
1212
}
1313
)
1414

15-
availableCourseMemberships: [CourseMembership!]! @resolveTo(
16-
sourceName: "CourseService",
17-
sourceTypeName: "Query",
18-
sourceFieldName: "_internal_noauth_courseMembershipsByUserId",
19-
requiredSelectionSet: "{ id }",
20-
sourceArgs: {
21-
userId: "{root.id}",
22-
availabilityFilter: true
23-
}
24-
)
15+
availableCourseMemberships: [CourseMembership!]! # resolved in user.ts
2516

26-
unavailableCourseMemberships: [CourseMembership!]! @resolveTo(
27-
sourceName: "CourseService",
28-
sourceTypeName: "Query",
29-
sourceFieldName: "_internal_noauth_courseMembershipsByUserId",
30-
requiredSelectionSet: "{ id }",
31-
sourceArgs: {
32-
userId: "{root.id}",
33-
availabilityFilter: false
34-
}
35-
)
17+
unavailableCourseMemberships: [CourseMembership!]! # resolved in user.ts
3618

3719
"""
3820
Media records of this user.

package.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7-
"start": "mesh dev",
8-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"start": "node run.mjs"
98
},
109
"keywords": [],
1110
"author": "",
@@ -14,13 +13,15 @@
1413
"@whatwg-node/server": "^0.9.14",
1514
"@envelop/core": "^4.0.1",
1615
"@envelop/generic-auth": "^6.0.0",
17-
"@graphql-mesh/runtime": "^0.96.4",
18-
"@graphql-mesh/cli": "^0.87.6",
19-
"@graphql-mesh/graphql": "^0.95.3",
20-
"@graphql-mesh/transform-type-merging": "^0.95.3",
21-
"@graphql-mesh/transform-hoist-field": "^0.95.3",
22-
"@graphql-mesh/transform-filter-schema": "^0.95.3",
23-
"graphql": "^16.8.0",
24-
"jose": "^4.14.4"
16+
"@graphql-mesh/runtime": "^0.106.6",
17+
"@graphql-mesh/cli": "^0.100.7",
18+
"@graphql-mesh/graphql": "^0.104.6",
19+
"@graphql-mesh/transform-type-merging": "^0.104.6",
20+
"@graphql-mesh/transform-hoist-field": "^0.105.7",
21+
"@graphql-mesh/transform-filter-schema": "^0.104.6",
22+
"graphql": "^16.11.0",
23+
"jose": "^4.14.4",
24+
"yaml": "^2.8.0",
25+
"node-fetch": "^3.3.2"
2526
}
2627
}

run.mjs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { spawn } from 'child_process';
2+
import yaml from 'yaml';
3+
import fs from 'fs';
4+
import fetch from 'node-fetch';
5+
6+
const sleep = ms => new Promise(r => setTimeout(r, ms));
7+
8+
async function checkReachable(url) {
9+
const res = await fetch(url, {
10+
method: 'POST',
11+
headers: { 'Content-Type': 'application/json' },
12+
body: `{ "query": "query {__schema {__typename}}" }`,
13+
});
14+
return res.ok;
15+
}
16+
17+
// get urls of services we need to wait for
18+
const meshRc = fs.readFileSync('./.meshrc.yaml', 'utf8');
19+
const config = yaml.parse(meshRc);
20+
21+
// replace env variables in urls
22+
const serviceEndpoints = []
23+
const reEnv = /{env\.(.+)}/g
24+
for (const service of config.sources) {
25+
let url = service.handler.graphql.endpoint;
26+
if (url) {
27+
url = url.replace(reEnv, (_, envVar) => {
28+
return process.env[envVar] || '';
29+
});
30+
serviceEndpoints.push({
31+
name: service.name,
32+
url: url,
33+
});
34+
}
35+
}
36+
37+
// wait for urls to be reachable
38+
while (true) {
39+
const notReachable = [];
40+
for(const service of serviceEndpoints) {
41+
try {
42+
const reachable = await checkReachable(service.url);
43+
if (!reachable) {
44+
notReachable.push(service.name);
45+
}
46+
} catch (error) {
47+
console.log('Failed trying to reach service:', error.message);
48+
notReachable.push(service.name);
49+
}
50+
}
51+
52+
if (notReachable.length === 0) {
53+
break;
54+
} else {
55+
console.log('Waiting for services to be reachable:', notReachable.join(', '));
56+
}
57+
console.log('Retrying in 5 seconds...');
58+
await sleep(5000);
59+
}
60+
61+
console.log('All services are reachable, starting mesh after 2 seconds...');
62+
await sleep(2000); // additional wait to ensure services are ready
63+
64+
// run mesh
65+
const meshProcess = spawn('npx', ['mesh', 'dev'], {
66+
stdio: 'inherit',
67+
shell: true,
68+
});
69+
70+
meshProcess.on('close', (code) => {
71+
console.log(`Mesh process exited with code ${code}`);
72+
process.exit(code ?? 0);
73+
});

0 commit comments

Comments
 (0)