Skip to content

Commit fa052d4

Browse files
authored
API Dependency Updates (canada-ca#2633)
* update non breaking deps * update to apollo server v3 * update server with new setup * fix up create context and on connect * use new server setup on start up * update related tests
1 parent 3dce350 commit fa052d4

9 files changed

Lines changed: 614 additions & 1033 deletions

File tree

api-js/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const {
5858
}),
5959
}
6060

61-
Server({
61+
const server = await Server({
6262
maxDepth,
6363
complexityCost,
6464
scalarCost,
@@ -71,7 +71,9 @@ const {
7171
transaction,
7272
pubsubs,
7373
},
74-
}).listen(PORT, (err) => {
74+
})
75+
76+
await server.listen(PORT, (err) => {
7577
if (err) throw err
7678
console.log(`🚀 Server ready at http://localhost:${PORT}/graphql`)
7779
console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}/graphql`)

api-js/package-lock.json

Lines changed: 532 additions & 977 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-js/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
"lin-clean": "npx lingui extract --clean"
2424
},
2525
"dependencies": {
26+
"@graphql-tools/schema": "^7.1.5",
2627
"@lingui/core": "^3.10.4",
27-
"apollo-server": "^2.25.2",
28-
"apollo-server-express": "^2.25.2",
28+
"apollo-server": "^3.0.0",
29+
"apollo-server-core": "^3.0.0",
30+
"apollo-server-express": "^3.0.0",
2931
"arango-tools": "^0.5.0",
3032
"arangojs": "^7.5.0",
3133
"bcryptjs": "^2.4.3",
@@ -50,6 +52,7 @@
5052
"moment": "^2.29.1",
5153
"notifications-node-client": "^5.1.0",
5254
"psl": "^1.8.0",
55+
"subscriptions-transport-ws": "^0.9.19",
5356
"url-slug": "^3.0.2",
5457
"uuid": "^8.3.2",
5558
"validator": "^13.6.0"
@@ -77,7 +80,7 @@
7780
"jest": "^27.0.6",
7881
"jest-fetch-mock": "^3.0.3",
7982
"jest-matcher-utils": "^27.0.6",
80-
"nodemon": "^2.0.10",
83+
"nodemon": "^2.0.12",
8184
"prettier": "^2.3.2",
8285
"supertest": "^6.1.3"
8386
}

api-js/src/__tests__/create-context.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('given the create context function', () => {
3333
const context = await createContext({})({
3434
req: {},
3535
res: {},
36-
connection: { context: { authorization: token } },
36+
connection: { authorization: token },
3737
})
3838

3939
expect(context.userKey).toEqual('1234')
@@ -42,7 +42,7 @@ describe('given the create context function', () => {
4242
const context = await createContext({})({
4343
req: {},
4444
res: {},
45-
connection: { context: { language: 'en' } },
45+
connection: { language: 'en' },
4646
})
4747

4848
expect(context.request.language).toEqual('en')

api-js/src/__tests__/on-connect.test.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ensure, dbNameFromFile } from 'arango-tools'
22

3+
import { createContext } from '../create-context'
34
import { customOnConnect } from '../on-connect'
45
import { verifyToken, tokenize, userRequired } from '../auth'
56
import { createI18n } from '../create-i18n'
@@ -41,15 +42,16 @@ describe('given the customOnConnect function', () => {
4142
}
4243

4344
const onConnect = await customOnConnect({
44-
context: {},
45+
createContext,
46+
serverContext: {},
4547
createI18n,
4648
verifyToken,
4749
userRequired: mockedUserRequired,
4850
loadUserByKey: jest.fn(),
4951
verifiedRequired: jest.fn(),
50-
})(connectionParams, webSocket)
52+
})(connectionParams, webSocket, { request: {} })
5153

52-
expect(onConnect.language).toEqual('en')
54+
expect(onConnect.request.language).toEqual('en')
5355
expect(consoleOutput).toEqual([
5456
'User: 1234, connected to subscription.',
5557
])
@@ -72,15 +74,16 @@ describe('given the customOnConnect function', () => {
7274
}
7375

7476
const onConnect = await customOnConnect({
75-
context: {},
77+
createContext,
78+
serverContext: {},
7679
createI18n,
7780
verifyToken,
7881
userRequired: mockedUserRequired,
7982
loadUserByKey: jest.fn(),
8083
verifiedRequired: jest.fn(),
81-
})(connectionParams, webSocket)
84+
})(connectionParams, webSocket, { request: {} })
8285

83-
expect(onConnect.language).toEqual('fr')
86+
expect(onConnect.request.language).toEqual('fr')
8487
expect(consoleOutput).toEqual([
8588
'User: 1234, connected to subscription.',
8689
])
@@ -104,15 +107,16 @@ describe('given the customOnConnect function', () => {
104107
}
105108

106109
const onConnect = await customOnConnect({
107-
context: {},
110+
createContext,
111+
serverContext: {},
108112
createI18n,
109113
verifyToken,
110114
userRequired: mockedUserRequired,
111115
loadUserByKey: jest.fn(),
112116
verifiedRequired: jest.fn(),
113-
})(connectionParams, webSocket)
117+
})(connectionParams, webSocket, { request: {} })
114118

115-
expect(onConnect.authorization).toEqual(token)
119+
expect(onConnect.request.headers.authorization).toEqual(token)
116120
expect(consoleOutput).toEqual(['User: 1234, connected to subscription.'])
117121
})
118122
})
@@ -152,12 +156,13 @@ describe('given the customOnConnect function', () => {
152156

153157
try {
154158
await customOnConnect({
155-
context: { query },
159+
createContext,
160+
serverContext: { query },
156161
createI18n,
157162
verifyToken,
158163
userRequired,
159164
loadUserByKey: jest.fn().mockReturnValue({ load: jest.fn() }),
160-
})(connectionParams, webSocket)
165+
})(connectionParams, webSocket, { request: {} })
161166
} catch (err) {
162167
expect(err).toEqual(
163168
new Error('Authentication error. Please sign in.'),
@@ -183,12 +188,13 @@ describe('given the customOnConnect function', () => {
183188

184189
try {
185190
await customOnConnect({
186-
context: { query },
191+
createContext,
192+
serverContext: { query },
187193
createI18n,
188194
verifyToken,
189195
userRequired,
190196
loadUserByKey: jest.fn().mockReturnValue({ load: jest.fn() }),
191-
})(connectionParams, webSocket)
197+
})(connectionParams, webSocket, { request: {} })
192198
} catch (err) {
193199
expect(err).toEqual(
194200
new Error("Erreur d'authentification. Veuillez vous connecter."),

api-js/src/__tests__/server.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ describe('parse server', () => {
2424

2525
describe('/alive', () => {
2626
it('returns 200', async () => {
27-
const response = await request(Server({ query: jest.fn() })).get('/alive')
27+
const response = await request(await Server({ query: jest.fn() })).get('/alive')
2828
expect(response.status).toEqual(200)
2929
})
3030
})
3131

3232
describe('/ready', () => {
3333
it('returns 200', async () => {
34-
const response = await request(Server({ query: jest.fn() })).get('/ready')
34+
const response = await request(await Server({ query: jest.fn() })).get('/ready')
3535
expect(response.status).toEqual(200)
3636
})
3737
})
@@ -40,7 +40,7 @@ describe('parse server', () => {
4040
describe('endpoint is alive', () => {
4141
it('returns 200', async () => {
4242
const response = await request(
43-
Server({
43+
await Server({
4444
maxDepth,
4545
complexityCost,
4646
scalarCost,
@@ -65,7 +65,7 @@ describe('parse server', () => {
6565
describe('query cost is too high', () => {
6666
it('returns an error message', async () => {
6767
const response = await request(
68-
Server({
68+
await Server({
6969
maxDepth,
7070
complexityCost: 1,
7171
scalarCost: 100,
@@ -91,7 +91,7 @@ describe('parse server', () => {
9191
describe('query depth is too high', () => {
9292
it('returns an error message', async () => {
9393
const response = await request(
94-
Server({
94+
await Server({
9595
maxDepth: 1,
9696
complexityCost: 1000,
9797
scalarCost: 1,

api-js/src/create-context.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ export const createContext =
109109
if (connection) {
110110
req = {
111111
headers: {
112-
authorization: connection.context.authorization,
112+
authorization: connection.authorization,
113113
},
114-
language: connection.context.language,
114+
language: connection.language,
115115
}
116-
return createContextObject({ context, req, res })
116+
return createContextObject({ context, req })
117117
} else {
118118
return createContextObject({ context, req, res })
119119
}

api-js/src/on-connect.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
export const customOnConnect =
22
({
3-
context,
3+
createContext,
4+
serverContext,
45
createI18n,
56
verifyToken,
67
userRequired,
78
loadUserByKey,
89
verifiedRequired,
910
}) =>
10-
async (connectionParams, webSocket) => {
11+
async (connectionParams, webSocket, context) => {
12+
const expandedContext = { ...serverContext, ...context }
13+
14+
const factoryFunc = createContext(expandedContext)
15+
1116
const enLangPos = String(
1217
webSocket.upgradeReq.headers['accept-language'],
1318
).indexOf('en')
@@ -20,10 +25,7 @@ export const customOnConnect =
2025
language = 'fr'
2126
}
2227

23-
let authorization
24-
if (connectionParams.authorization) {
25-
authorization = connectionParams.authorization
26-
}
28+
const authorization = connectionParams?.authorization
2729

2830
const i18n = createI18n(language)
2931
const verify = verifyToken({ i18n })
@@ -34,7 +36,7 @@ export const customOnConnect =
3436
userKey = verify({ token }).userKey
3537
}
3638

37-
const { query } = context
39+
const { query } = serverContext
3840

3941
const user = await userRequired({
4042
i18n,
@@ -46,8 +48,7 @@ export const customOnConnect =
4648

4749
console.info(`User: ${userKey}, connected to subscription.`)
4850

49-
return {
50-
language,
51-
authorization,
52-
}
51+
const finalContext = await factoryFunc({ req: context.request, connection: { language, authorization } })
52+
53+
return finalContext
5354
}

api-js/src/server.js

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import cookieParser from 'cookie-parser'
22
import cors from 'cors'
33
import express from 'express'
44
import http from 'http'
5+
import { ApolloServerPluginLandingPageGraphQLPlayground as enablePlayground } from 'apollo-server-core'
56
import { ApolloServer } from 'apollo-server-express'
67
import requestLanguage from 'express-request-language'
7-
import { GraphQLSchema } from 'graphql'
8+
import { execute, subscribe, GraphQLSchema } from 'graphql'
89
import depthLimit from 'graphql-depth-limit'
910
import { createComplexityLimitRule } from 'graphql-validation-complexity'
11+
import { SubscriptionServer } from 'subscriptions-transport-ws'
1012

1113
import { createContext } from './create-context'
1214
import { createQuerySchema } from './query'
@@ -45,7 +47,7 @@ const createValidationRules = (
4547
]
4648
}
4749

48-
export const Server = ({
50+
export const Server = async ({
4951
maxDepth,
5052
complexityCost,
5153
scalarCost,
@@ -74,19 +76,13 @@ export const Server = ({
7476
res.json({ ok: 'yes' })
7577
})
7678

79+
const httpServer = http.createServer(app)
80+
81+
const schema = createSchema()
82+
7783
const server = new ApolloServer({
78-
schema: createSchema(),
84+
schema,
7985
context: createContext(context),
80-
subscriptions: {
81-
onConnect: customOnConnect({
82-
context,
83-
createI18n,
84-
verifyToken,
85-
userRequired,
86-
loadUserByKey,
87-
verifiedRequired,
88-
}),
89-
},
9086
validationRules: createValidationRules(
9187
maxDepth,
9288
complexityCost,
@@ -95,15 +91,33 @@ export const Server = ({
9591
listFactor,
9692
),
9793
introspection: true,
98-
playground: true,
9994
tracing,
95+
plugins: [enablePlayground()],
10096
})
10197

98+
await server.start()
10299
server.applyMiddleware({ app })
103100

104-
const httpServer = http.createServer(app)
105-
106-
server.installSubscriptionHandlers(httpServer)
101+
SubscriptionServer.create(
102+
{
103+
schema,
104+
execute,
105+
subscribe,
106+
onConnect: customOnConnect({
107+
createContext,
108+
serverContext: context,
109+
createI18n,
110+
verifyToken,
111+
userRequired,
112+
loadUserByKey,
113+
verifiedRequired,
114+
}),
115+
},
116+
{
117+
server: httpServer,
118+
path: server.graphqlPath,
119+
},
120+
)
107121

108122
return httpServer
109123
}

0 commit comments

Comments
 (0)