@common-stack/server-stack 9.0.2-alpha.3 → 9.0.2-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/MainStackServer.cjs +75 -24
- package/lib/MainStackServer.cjs.map +1 -1
- package/lib/MainStackServer.mjs +75 -24
- package/lib/MainStackServer.mjs.map +1 -1
- package/lib/config/env-config.cjs +3 -0
- package/lib/config/env-config.cjs.map +1 -1
- package/lib/config/env-config.mjs +3 -0
- package/lib/config/env-config.mjs.map +1 -1
- package/lib/express-adapter.cjs +73 -0
- package/lib/express-adapter.cjs.map +1 -0
- package/lib/express-adapter.mjs +73 -0
- package/lib/express-adapter.mjs.map +1 -0
- package/lib/servers/ExpressApp.cjs +4 -4
- package/lib/servers/ExpressApp.cjs.map +1 -1
- package/lib/servers/ExpressApp.mjs +3 -3
- package/lib/servers/ExpressApp.mjs.map +1 -1
- package/lib/servers/GraphqlServer.cjs +30 -18
- package/lib/servers/GraphqlServer.cjs.map +1 -1
- package/lib/servers/GraphqlServer.mjs +29 -17
- package/lib/servers/GraphqlServer.mjs.map +1 -1
- package/lib/servers/GraphqlWs.cjs +10 -1
- package/lib/servers/GraphqlWs.cjs.map +1 -1
- package/lib/servers/GraphqlWs.mjs +10 -1
- package/lib/servers/GraphqlWs.mjs.map +1 -1
- package/lib/servers/WebsocketMultipathUpdate.cjs +39 -38
- package/lib/servers/WebsocketMultipathUpdate.cjs.map +1 -1
- package/lib/servers/WebsocketMultipathUpdate.mjs +38 -37
- package/lib/servers/WebsocketMultipathUpdate.mjs.map +1 -1
- package/package.json +7 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var expressAdapter=require('../express-adapter.cjs'),error=require('../middleware/error.cjs'),services=require('../middleware/services.cjs');require('../middleware/sentry.cjs');var redisClient=require('../middleware/redis-client.cjs'),cors=require('../middleware/cors.cjs'),Sentry=require('@sentry/node');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var Sentry__namespace=/*#__PURE__*/_interopNamespaceDefault(Sentry);/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
2
|
function expressApp(modules, options, middlewares, http, redisClient$1) {
|
|
3
|
-
const app = express();
|
|
3
|
+
const app = expressAdapter.express();
|
|
4
4
|
// FIRST PRIORITY: Add Redis client middleware at the very top
|
|
5
5
|
// This ensures req.redisClient is available to ALL downstream middleware
|
|
6
6
|
if (redisClient$1) {
|
|
@@ -29,14 +29,14 @@ function expressApp(modules, options, middlewares, http, redisClient$1) {
|
|
|
29
29
|
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, X-CSP-Nonce, Content-Type, Accept');
|
|
30
30
|
next();
|
|
31
31
|
});
|
|
32
|
-
app.use(
|
|
32
|
+
app.use(expressAdapter.jsonParser({
|
|
33
33
|
limit: '50mb',
|
|
34
34
|
verify: (req, res, buf) => {
|
|
35
35
|
// #Todo: Find some proper solution for it
|
|
36
36
|
req.rawBody = buf;
|
|
37
37
|
},
|
|
38
38
|
}));
|
|
39
|
-
app.use(
|
|
39
|
+
app.use(expressAdapter.urlencodedParser({ limit: '50mb', extended: true, parameterLimit: 50000 }));
|
|
40
40
|
for (const applyMiddleware of modules.middlewares) {
|
|
41
41
|
applyMiddleware(app);
|
|
42
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressApp.cjs","sources":["../../src/servers/ExpressApp.ts"],"sourcesContent":[null],"names":["redisClient","redisClientMiddleware","phasedContextMiddleware","corsMiddleware","Sentry","errorMiddleware"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpressApp.cjs","sources":["../../src/servers/ExpressApp.ts"],"sourcesContent":[null],"names":["redisClient","express","redisClientMiddleware","phasedContextMiddleware","corsMiddleware","jsonParser","urlencodedParser","Sentry","errorMiddleware"],"mappings":"gqBAAA;AAUM,SAAU,UAAU,CAAC,OAAgB,EAAE,OAAuB,EAAE,WAAW,EAAE,IAAK,EAAEA,aAAY,EAAA;AAClG,IAAA,MAAM,GAAG,GAAGC,sBAAO,EAAE,CAAC;;;IAItB,IAAID,aAAW,EAAE;QACb,GAAG,CAAC,GAAG,CAACE,iCAAqB,CAACF,aAAW,CAAC,CAAC,CAAC;KAC/C;;;;IAKD,GAAG,CAAC,GAAG,CAACG,gCAAuB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;;AAG5D,IAAA,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE;QAC/C,eAAe,CAAC,GAAG,CAAC,CAAC;KACxB;;;IAID,GAAG,CAAC,GAAG,CAACA,gCAAuB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;;AAG5D,IAAA,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAE1B,IAAA,IAAI,WAAW,KAAK,IAAI,EAAE;AACtB,QAAA,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;KACxB;AAED,IAAA,GAAG,CAAC,GAAG,CAACC,mBAAc,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,KAAI;AACvB,QAAA,GAAG,CAAC,MAAM,CAAC,kCAAkC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,QAAA,GAAG,CAAC,MAAM,CAAC,8BAA8B,EAAE,qBAAqB,CAAC,CAAC;AAClE,QAAA,GAAG,CAAC,MAAM,CACN,8BAA8B,EAC9B,6EAA6E,CAChF,CAAC;AACF,QAAA,IAAI,EAAE,CAAC;AACX,KAAC,CAAC,CAAC;AAEH,IAAA,GAAG,CAAC,GAAG,CACHC,yBAAU,CAAC;AACP,QAAA,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,KAAI;;AAErB,YAAA,GAAW,CAAC,OAAO,GAAG,GAAG,CAAC;SAC9B;AACJ,KAAA,CAAC,CACL,CAAC;IACF,GAAG,CAAC,GAAG,CAACC,+BAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAEpF,IAAA,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE;QAC/C,eAAe,CAAC,GAAG,CAAC,CAAC;KACxB;;;;IAKD,GAAG,CAAC,GAAG,CAACH,gCAAuB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;;AAG7D,IAAAI,iBAAM,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,OAAO,EAAE;AACT,QAAA,GAAG,CAAC,GAAG,CAACC,qBAAe,CAAC,CAAC;KAC5B;AAED,IAAA,OAAO,GAAG,CAAC;AACf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import express
|
|
1
|
+
import {express,jsonParser,urlencodedParser}from'../express-adapter.mjs';import {errorMiddleware}from'../middleware/error.mjs';import {phasedContextMiddleware}from'../middleware/services.mjs';import'../middleware/sentry.mjs';import {redisClientMiddleware}from'../middleware/redis-client.mjs';import {corsMiddleware}from'../middleware/cors.mjs';import*as Sentry from'@sentry/node';/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
2
|
function expressApp(modules, options, middlewares, http, redisClient) {
|
|
3
3
|
const app = express();
|
|
4
4
|
// FIRST PRIORITY: Add Redis client middleware at the very top
|
|
@@ -29,14 +29,14 @@ function expressApp(modules, options, middlewares, http, redisClient) {
|
|
|
29
29
|
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, X-CSP-Nonce, Content-Type, Accept');
|
|
30
30
|
next();
|
|
31
31
|
});
|
|
32
|
-
app.use(
|
|
32
|
+
app.use(jsonParser({
|
|
33
33
|
limit: '50mb',
|
|
34
34
|
verify: (req, res, buf) => {
|
|
35
35
|
// #Todo: Find some proper solution for it
|
|
36
36
|
req.rawBody = buf;
|
|
37
37
|
},
|
|
38
38
|
}));
|
|
39
|
-
app.use(
|
|
39
|
+
app.use(urlencodedParser({ limit: '50mb', extended: true, parameterLimit: 50000 }));
|
|
40
40
|
for (const applyMiddleware of modules.middlewares) {
|
|
41
41
|
applyMiddleware(app);
|
|
42
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressApp.mjs","sources":["../../src/servers/ExpressApp.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpressApp.mjs","sources":["../../src/servers/ExpressApp.ts"],"sourcesContent":[null],"names":[],"mappings":"4XAAA;AAUM,SAAU,UAAU,CAAC,OAAgB,EAAE,OAAuB,EAAE,WAAW,EAAE,IAAK,EAAE,WAAY,EAAA;AAClG,IAAA,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;;;IAItB,IAAI,WAAW,EAAE;QACb,GAAG,CAAC,GAAG,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC;KAC/C;;;;IAKD,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;;AAG5D,IAAA,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE;QAC/C,eAAe,CAAC,GAAG,CAAC,CAAC;KACxB;;;IAID,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;;AAG5D,IAAA,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAE1B,IAAA,IAAI,WAAW,KAAK,IAAI,EAAE;AACtB,QAAA,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;KACxB;AAED,IAAA,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,KAAI;AACvB,QAAA,GAAG,CAAC,MAAM,CAAC,kCAAkC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,QAAA,GAAG,CAAC,MAAM,CAAC,8BAA8B,EAAE,qBAAqB,CAAC,CAAC;AAClE,QAAA,GAAG,CAAC,MAAM,CACN,8BAA8B,EAC9B,6EAA6E,CAChF,CAAC;AACF,QAAA,IAAI,EAAE,CAAC;AACX,KAAC,CAAC,CAAC;AAEH,IAAA,GAAG,CAAC,GAAG,CACH,UAAU,CAAC;AACP,QAAA,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,KAAI;;AAErB,YAAA,GAAW,CAAC,OAAO,GAAG,GAAG,CAAC;SAC9B;AACJ,KAAA,CAAC,CACL,CAAC;IACF,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAEpF,IAAA,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,WAAW,EAAE;QAC/C,eAAe,CAAC,GAAG,CAAC,CAAC;KACxB;;;;IAKD,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;;AAG7D,IAAA,MAAM,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,OAAO,EAAE;AACT,QAAA,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;KAC5B;AAED,IAAA,OAAO,GAAG,CAAC;AACf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var server=require('@apollo/server'),express4=require('@apollo/server/express4'),cacheControl=require('@apollo/server/plugin/cacheControl')
|
|
1
|
+
'use strict';var server=require('@apollo/server'),express4=require('@apollo/server/express4'),cacheControl=require('@apollo/server/plugin/cacheControl');require('isomorphic-fetch');var expressAdapter=require('../express-adapter.cjs'),cors=require('../middleware/cors.cjs'),Keyv=require('keyv'),KeyvRedis=require('@keyv/redis'),utils_keyvadapter=require('@apollo/utils.keyvadapter'),storeRedis=require('@common-stack/store-redis'),GraphqlWs=require('./GraphqlWs.cjs'),envConfig=require('../config/env-config.cjs');if ((process.env.LOG_LEVEL && process.env.LOG_LEVEL === 'trace') || process.env.LOG_LEVEL === 'debug') ;
|
|
2
2
|
// @workaround as the `dataSources` not available in Subscription (websocket) Context.
|
|
3
3
|
// https://github.com/apollographql/apollo-server/issues/1526 need to revisit in Apollo-Server v3.
|
|
4
4
|
const constructDataSourcesForSubscriptions = (context, cache, dataSources) => {
|
|
@@ -12,7 +12,7 @@ const constructDataSourcesForSubscriptions = (context, cache, dataSources) => {
|
|
|
12
12
|
};
|
|
13
13
|
class GraphqlServer {
|
|
14
14
|
app;
|
|
15
|
-
|
|
15
|
+
wsServerHost;
|
|
16
16
|
redisClient;
|
|
17
17
|
moduleService;
|
|
18
18
|
enableSubscription;
|
|
@@ -21,9 +21,10 @@ class GraphqlServer {
|
|
|
21
21
|
plugins;
|
|
22
22
|
logger;
|
|
23
23
|
graphqlWsServer;
|
|
24
|
-
constructor(app,
|
|
24
|
+
constructor(app, wsServerHost, // ultimate-express app or http.Server
|
|
25
|
+
redisClient, moduleService, enableSubscription = true, cacheKeyGenerator, invalidateCacheKeyGenerator, plugins) {
|
|
25
26
|
this.app = app;
|
|
26
|
-
this.
|
|
27
|
+
this.wsServerHost = wsServerHost;
|
|
27
28
|
this.redisClient = redisClient;
|
|
28
29
|
this.moduleService = moduleService;
|
|
29
30
|
this.enableSubscription = enableSubscription;
|
|
@@ -32,8 +33,11 @@ class GraphqlServer {
|
|
|
32
33
|
this.plugins = plugins;
|
|
33
34
|
this.logger = this.moduleService.logger.child({ className: 'GraphqlServer' });
|
|
34
35
|
if (enableSubscription) {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
// WebSocketServer binds to different hosts depending on engine:
|
|
37
|
+
// - ultimate-express: pass the app as 'server' (ultimate-ws)
|
|
38
|
+
// - classic express: pass the httpServer as 'server' (ws)
|
|
39
|
+
const wsServer = new expressAdapter.WebSocketServer({
|
|
40
|
+
server: this.wsServerHost,
|
|
37
41
|
path: envConfig.config.GRAPHQL_ENDPOINT,
|
|
38
42
|
});
|
|
39
43
|
this.graphqlWsServer = new GraphqlWs.GraphqlWs(wsServer, this.moduleService, this.redisClient);
|
|
@@ -46,11 +50,7 @@ class GraphqlServer {
|
|
|
46
50
|
}
|
|
47
51
|
const apolloServer = this.configureApolloServer();
|
|
48
52
|
await apolloServer.start();
|
|
49
|
-
|
|
50
|
-
origin: [envConfig.config.CLIENT_URL],
|
|
51
|
-
credentials: true,
|
|
52
|
-
};
|
|
53
|
-
this.app.use(__GRAPHQL_ENDPOINT__, cors(corsOptions), express.json(), express4.expressMiddleware(apolloServer, {
|
|
53
|
+
this.app.use(__GRAPHQL_ENDPOINT__, cors.corsMiddleware, expressAdapter.express.json(), express4.expressMiddleware(apolloServer, {
|
|
54
54
|
context: async ({ req, res, connection }) => {
|
|
55
55
|
let context;
|
|
56
56
|
let addons = {};
|
|
@@ -117,17 +117,29 @@ class GraphqlServer {
|
|
|
117
117
|
const cacheSet = cacheAdapter.set.bind(cacheAdapter);
|
|
118
118
|
cacheAdapter.set = (key, value, opts) => cacheSet(key.replaceAll('fqc:', ''), value, opts);
|
|
119
119
|
const { cacheKeyGenerator, invalidateCacheKeyGenerator, logger } = this;
|
|
120
|
+
const serverPlugins = [
|
|
121
|
+
cacheControl.ApolloServerPluginCacheControl(),
|
|
122
|
+
storeRedis.invalidateCachePlugin({ cache: this.redisClient, invalidateCacheKeyGenerator }),
|
|
123
|
+
storeRedis.responseCachePlugin({ logger, cacheKeyGenerator }),
|
|
124
|
+
...(this.plugins ?? []),
|
|
125
|
+
];
|
|
126
|
+
// For classic express, add drain plugin to gracefully close the HTTP server.
|
|
127
|
+
// ultimate-express (uWebSockets.js) handles connection draining natively.
|
|
128
|
+
if (!expressAdapter.isUltimateEngine && this.wsServerHost) {
|
|
129
|
+
try {
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
131
|
+
const { ApolloServerPluginDrainHttpServer } = require('@apollo/server/plugin/drainHttpServer');
|
|
132
|
+
serverPlugins.push(ApolloServerPluginDrainHttpServer({ httpServer: this.wsServerHost }));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Plugin not available — skip
|
|
136
|
+
}
|
|
137
|
+
}
|
|
120
138
|
const serverConfig = {
|
|
121
139
|
schema: this.moduleService.schema,
|
|
122
140
|
allowBatchedHttpRequests: true,
|
|
123
141
|
cache: cacheAdapter,
|
|
124
|
-
plugins:
|
|
125
|
-
drainHttpServer.ApolloServerPluginDrainHttpServer({ httpServer: this.httpServer }),
|
|
126
|
-
cacheControl.ApolloServerPluginCacheControl(),
|
|
127
|
-
storeRedis.invalidateCachePlugin({ cache: this.redisClient, invalidateCacheKeyGenerator }),
|
|
128
|
-
storeRedis.responseCachePlugin({ logger, cacheKeyGenerator }),
|
|
129
|
-
...(this.plugins ?? []),
|
|
130
|
-
],
|
|
142
|
+
plugins: serverPlugins,
|
|
131
143
|
};
|
|
132
144
|
if (this.enableSubscription) {
|
|
133
145
|
serverConfig.plugins.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlServer.cjs","sources":["../../src/servers/GraphqlServer.ts"],"sourcesContent":[null],"names":["WebSocketServer","config","GraphqlWs","
|
|
1
|
+
{"version":3,"file":"GraphqlServer.cjs","sources":["../../src/servers/GraphqlServer.ts"],"sourcesContent":[null],"names":["WebSocketServer","config","GraphqlWs","corsMiddleware","express","expressMiddleware","KeyvAdapter","ApolloServerPluginCacheControl","invalidateCachePlugin","responseCachePlugin","isUltimateEngine","ApolloServer"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {ApolloServer}from'@apollo/server';import {expressMiddleware}from'@apollo/server/express4';import {ApolloServerPluginCacheControl}from'@apollo/server/plugin/cacheControl';import
|
|
1
|
+
import {ApolloServer}from'@apollo/server';import {expressMiddleware}from'@apollo/server/express4';import {ApolloServerPluginCacheControl}from'@apollo/server/plugin/cacheControl';import'isomorphic-fetch';import {WebSocketServer,express,isUltimateEngine}from'../express-adapter.mjs';import {corsMiddleware}from'../middleware/cors.mjs';import Keyv from'keyv';import KeyvRedis from'@keyv/redis';import {KeyvAdapter}from'@apollo/utils.keyvadapter';import {invalidateCachePlugin,responseCachePlugin}from'@common-stack/store-redis';import {GraphqlWs}from'./GraphqlWs.mjs';import {config}from'../config/env-config.mjs';if ((process.env.LOG_LEVEL && process.env.LOG_LEVEL === 'trace') || process.env.LOG_LEVEL === 'debug') ;
|
|
2
2
|
// @workaround as the `dataSources` not available in Subscription (websocket) Context.
|
|
3
3
|
// https://github.com/apollographql/apollo-server/issues/1526 need to revisit in Apollo-Server v3.
|
|
4
4
|
const constructDataSourcesForSubscriptions = (context, cache, dataSources) => {
|
|
@@ -12,7 +12,7 @@ const constructDataSourcesForSubscriptions = (context, cache, dataSources) => {
|
|
|
12
12
|
};
|
|
13
13
|
class GraphqlServer {
|
|
14
14
|
app;
|
|
15
|
-
|
|
15
|
+
wsServerHost;
|
|
16
16
|
redisClient;
|
|
17
17
|
moduleService;
|
|
18
18
|
enableSubscription;
|
|
@@ -21,9 +21,10 @@ class GraphqlServer {
|
|
|
21
21
|
plugins;
|
|
22
22
|
logger;
|
|
23
23
|
graphqlWsServer;
|
|
24
|
-
constructor(app,
|
|
24
|
+
constructor(app, wsServerHost, // ultimate-express app or http.Server
|
|
25
|
+
redisClient, moduleService, enableSubscription = true, cacheKeyGenerator, invalidateCacheKeyGenerator, plugins) {
|
|
25
26
|
this.app = app;
|
|
26
|
-
this.
|
|
27
|
+
this.wsServerHost = wsServerHost;
|
|
27
28
|
this.redisClient = redisClient;
|
|
28
29
|
this.moduleService = moduleService;
|
|
29
30
|
this.enableSubscription = enableSubscription;
|
|
@@ -32,8 +33,11 @@ class GraphqlServer {
|
|
|
32
33
|
this.plugins = plugins;
|
|
33
34
|
this.logger = this.moduleService.logger.child({ className: 'GraphqlServer' });
|
|
34
35
|
if (enableSubscription) {
|
|
36
|
+
// WebSocketServer binds to different hosts depending on engine:
|
|
37
|
+
// - ultimate-express: pass the app as 'server' (ultimate-ws)
|
|
38
|
+
// - classic express: pass the httpServer as 'server' (ws)
|
|
35
39
|
const wsServer = new WebSocketServer({
|
|
36
|
-
server: this.
|
|
40
|
+
server: this.wsServerHost,
|
|
37
41
|
path: config.GRAPHQL_ENDPOINT,
|
|
38
42
|
});
|
|
39
43
|
this.graphqlWsServer = new GraphqlWs(wsServer, this.moduleService, this.redisClient);
|
|
@@ -46,11 +50,7 @@ class GraphqlServer {
|
|
|
46
50
|
}
|
|
47
51
|
const apolloServer = this.configureApolloServer();
|
|
48
52
|
await apolloServer.start();
|
|
49
|
-
|
|
50
|
-
origin: [config.CLIENT_URL],
|
|
51
|
-
credentials: true,
|
|
52
|
-
};
|
|
53
|
-
this.app.use(__GRAPHQL_ENDPOINT__, cors(corsOptions), express.json(), expressMiddleware(apolloServer, {
|
|
53
|
+
this.app.use(__GRAPHQL_ENDPOINT__, corsMiddleware, express.json(), expressMiddleware(apolloServer, {
|
|
54
54
|
context: async ({ req, res, connection }) => {
|
|
55
55
|
let context;
|
|
56
56
|
let addons = {};
|
|
@@ -117,17 +117,29 @@ class GraphqlServer {
|
|
|
117
117
|
const cacheSet = cacheAdapter.set.bind(cacheAdapter);
|
|
118
118
|
cacheAdapter.set = (key, value, opts) => cacheSet(key.replaceAll('fqc:', ''), value, opts);
|
|
119
119
|
const { cacheKeyGenerator, invalidateCacheKeyGenerator, logger } = this;
|
|
120
|
+
const serverPlugins = [
|
|
121
|
+
ApolloServerPluginCacheControl(),
|
|
122
|
+
invalidateCachePlugin({ cache: this.redisClient, invalidateCacheKeyGenerator }),
|
|
123
|
+
responseCachePlugin({ logger, cacheKeyGenerator }),
|
|
124
|
+
...(this.plugins ?? []),
|
|
125
|
+
];
|
|
126
|
+
// For classic express, add drain plugin to gracefully close the HTTP server.
|
|
127
|
+
// ultimate-express (uWebSockets.js) handles connection draining natively.
|
|
128
|
+
if (!isUltimateEngine && this.wsServerHost) {
|
|
129
|
+
try {
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
131
|
+
const { ApolloServerPluginDrainHttpServer } = require('@apollo/server/plugin/drainHttpServer');
|
|
132
|
+
serverPlugins.push(ApolloServerPluginDrainHttpServer({ httpServer: this.wsServerHost }));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Plugin not available — skip
|
|
136
|
+
}
|
|
137
|
+
}
|
|
120
138
|
const serverConfig = {
|
|
121
139
|
schema: this.moduleService.schema,
|
|
122
140
|
allowBatchedHttpRequests: true,
|
|
123
141
|
cache: cacheAdapter,
|
|
124
|
-
plugins:
|
|
125
|
-
ApolloServerPluginDrainHttpServer({ httpServer: this.httpServer }),
|
|
126
|
-
ApolloServerPluginCacheControl(),
|
|
127
|
-
invalidateCachePlugin({ cache: this.redisClient, invalidateCacheKeyGenerator }),
|
|
128
|
-
responseCachePlugin({ logger, cacheKeyGenerator }),
|
|
129
|
-
...(this.plugins ?? []),
|
|
130
|
-
],
|
|
142
|
+
plugins: serverPlugins,
|
|
131
143
|
};
|
|
132
144
|
if (this.enableSubscription) {
|
|
133
145
|
serverConfig.plugins.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlServer.mjs","sources":["../../src/servers/GraphqlServer.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GraphqlServer.mjs","sources":["../../src/servers/GraphqlServer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
this.logger = this.moduleService.logger;
|
|
12
12
|
}
|
|
13
13
|
create() {
|
|
14
|
+
// Drop a stalled WS connection if the client never sends
|
|
15
|
+
// `connection_init` within this window. Transport-level ping/pong is
|
|
16
|
+
// handled by the graphql-ws `ws` / `uWS` adapter via the third
|
|
17
|
+
// positional `keepAlive` arg (default 12s; we raise it to evict only
|
|
18
|
+
// truly dead clients). Tunable via env so ops can adjust without a
|
|
19
|
+
// rebuild.
|
|
20
|
+
const ackTimeoutMs = Number(process.env.GRAPHQL_WS_ACK_TIMEOUT_MS) || 30_000;
|
|
21
|
+
const keepAliveMs = Number(process.env.GRAPHQL_WS_KEEPALIVE_MS) || 30_000;
|
|
14
22
|
this.subscriptionServer = ws.useServer({
|
|
15
23
|
schema: this.moduleService.schema,
|
|
16
24
|
// Adding a context property lets you add data to your GraphQL operation context
|
|
17
25
|
// Using shared context creation function to maintain consistency
|
|
18
26
|
context: async (ctx) => websocketContext.createWebSocketContext(ctx, this.moduleService, this.cache),
|
|
27
|
+
connectionInitWaitTimeout: ackTimeoutMs,
|
|
19
28
|
// onConnect: async (ctx) => {
|
|
20
29
|
// // do anything when connected
|
|
21
30
|
// },
|
|
@@ -45,7 +54,7 @@
|
|
|
45
54
|
// }
|
|
46
55
|
// return { ...connection }; // TODO: we didn't add `context`
|
|
47
56
|
// },
|
|
48
|
-
}, this.wsServer);
|
|
57
|
+
}, this.wsServer, keepAliveMs);
|
|
49
58
|
return this.subscriptionServer;
|
|
50
59
|
}
|
|
51
60
|
disconnect() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlWs.cjs","sources":["../../src/servers/GraphqlWs.ts"],"sourcesContent":[null],"names":["useServer","createWebSocketContext"],"mappings":"sIAmDa,SAAS,CAAA;AAMN,IAAA,QAAA,CAAA;AACA,IAAA,aAAA,CAAA;AACE,IAAA,KAAA,CAAA;AAPN,IAAA,kBAAkB,CAAa;AAE/B,IAAA,MAAM,CAAU;AAExB,IAAA,WAAA,CACY,
|
|
1
|
+
{"version":3,"file":"GraphqlWs.cjs","sources":["../../src/servers/GraphqlWs.ts"],"sourcesContent":[null],"names":["useServer","createWebSocketContext"],"mappings":"sIAmDa,SAAS,CAAA;AAMN,IAAA,QAAA,CAAA;AACA,IAAA,aAAA,CAAA;AACE,IAAA,KAAA,CAAA;AAPN,IAAA,kBAAkB,CAAa;AAE/B,IAAA,MAAM,CAAU;AAExB,IAAA,WAAA,CACY,QAA8C,EAC9C,aAA6B,EAC3B,KAAsC,EAAA;QAFxC,IAAQ,CAAA,QAAA,GAAR,QAAQ,CAAsC;QAC9C,IAAa,CAAA,aAAA,GAAb,aAAa,CAAgB;QAC3B,IAAK,CAAA,KAAA,GAAL,KAAK,CAAiC;QAEhD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;KAC3C;IAEM,MAAM,GAAA;;;;;;;AAOT,QAAA,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,MAAM,CAAC;AAC7E,QAAA,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,MAAM,CAAC;AAE1E,QAAA,IAAI,CAAC,kBAAkB,GAAGA,YAAS,CAC/B;AACI,YAAA,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM;;;AAGjC,YAAA,OAAO,EAAE,OAAO,GAAG,KAAKC,uCAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC;AACnF,YAAA,yBAAyB,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC1C,SAAA,EACD,IAAI,CAAC,QAAQ,EACb,WAAW,CACd,CAAC;QACF,OAAO,IAAI,CAAC,kBAAkB,CAAC;KAClC;IAEM,UAAU,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;AACzB,YAAA,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;SACrC;KACJ;AACJ"}
|
|
@@ -11,11 +11,20 @@ import {useServer}from'graphql-ws/lib/use/ws';import'graphql';import {createWebS
|
|
|
11
11
|
this.logger = this.moduleService.logger;
|
|
12
12
|
}
|
|
13
13
|
create() {
|
|
14
|
+
// Drop a stalled WS connection if the client never sends
|
|
15
|
+
// `connection_init` within this window. Transport-level ping/pong is
|
|
16
|
+
// handled by the graphql-ws `ws` / `uWS` adapter via the third
|
|
17
|
+
// positional `keepAlive` arg (default 12s; we raise it to evict only
|
|
18
|
+
// truly dead clients). Tunable via env so ops can adjust without a
|
|
19
|
+
// rebuild.
|
|
20
|
+
const ackTimeoutMs = Number(process.env.GRAPHQL_WS_ACK_TIMEOUT_MS) || 30_000;
|
|
21
|
+
const keepAliveMs = Number(process.env.GRAPHQL_WS_KEEPALIVE_MS) || 30_000;
|
|
14
22
|
this.subscriptionServer = useServer({
|
|
15
23
|
schema: this.moduleService.schema,
|
|
16
24
|
// Adding a context property lets you add data to your GraphQL operation context
|
|
17
25
|
// Using shared context creation function to maintain consistency
|
|
18
26
|
context: async (ctx) => createWebSocketContext(ctx, this.moduleService, this.cache),
|
|
27
|
+
connectionInitWaitTimeout: ackTimeoutMs,
|
|
19
28
|
// onConnect: async (ctx) => {
|
|
20
29
|
// // do anything when connected
|
|
21
30
|
// },
|
|
@@ -45,7 +54,7 @@ import {useServer}from'graphql-ws/lib/use/ws';import'graphql';import {createWebS
|
|
|
45
54
|
// }
|
|
46
55
|
// return { ...connection }; // TODO: we didn't add `context`
|
|
47
56
|
// },
|
|
48
|
-
}, this.wsServer);
|
|
57
|
+
}, this.wsServer, keepAliveMs);
|
|
49
58
|
return this.subscriptionServer;
|
|
50
59
|
}
|
|
51
60
|
disconnect() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlWs.mjs","sources":["../../src/servers/GraphqlWs.ts"],"sourcesContent":[null],"names":[],"mappings":"iIAmDa,SAAS,CAAA;AAMN,IAAA,QAAA,CAAA;AACA,IAAA,aAAA,CAAA;AACE,IAAA,KAAA,CAAA;AAPN,IAAA,kBAAkB,CAAa;AAE/B,IAAA,MAAM,CAAU;AAExB,IAAA,WAAA,CACY,
|
|
1
|
+
{"version":3,"file":"GraphqlWs.mjs","sources":["../../src/servers/GraphqlWs.ts"],"sourcesContent":[null],"names":[],"mappings":"iIAmDa,SAAS,CAAA;AAMN,IAAA,QAAA,CAAA;AACA,IAAA,aAAA,CAAA;AACE,IAAA,KAAA,CAAA;AAPN,IAAA,kBAAkB,CAAa;AAE/B,IAAA,MAAM,CAAU;AAExB,IAAA,WAAA,CACY,QAA8C,EAC9C,aAA6B,EAC3B,KAAsC,EAAA;QAFxC,IAAQ,CAAA,QAAA,GAAR,QAAQ,CAAsC;QAC9C,IAAa,CAAA,aAAA,GAAb,aAAa,CAAgB;QAC3B,IAAK,CAAA,KAAA,GAAL,KAAK,CAAiC;QAEhD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;KAC3C;IAEM,MAAM,GAAA;;;;;;;AAOT,QAAA,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,MAAM,CAAC;AAC7E,QAAA,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,MAAM,CAAC;AAE1E,QAAA,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAC/B;AACI,YAAA,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM;;;AAGjC,YAAA,OAAO,EAAE,OAAO,GAAG,KAAK,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC;AACnF,YAAA,yBAAyB,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC1C,SAAA,EACD,IAAI,CAAC,QAAQ,EACb,WAAW,CACd,CAAC;QACF,OAAO,IAAI,CAAC,kBAAkB,CAAC;KAClC;IAEM,UAAU,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;AACzB,YAAA,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;SACrC;KACJ;AACJ"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var expressAdapter=require('../express-adapter.cjs'),ws=require('graphql-ws/lib/use/ws'),websocketContext=require('./websocket-context.cjs'),envConfig=require('../config/env-config.cjs');class WebsocketMultiPathServer {
|
|
2
2
|
moduleService;
|
|
3
3
|
cache;
|
|
4
|
+
serverHost;
|
|
4
5
|
webSockets = {};
|
|
5
6
|
// private graphqlSubscriptionServer: GraphqlSubscriptionServer;
|
|
6
7
|
_graphqlWs;
|
|
@@ -8,27 +9,58 @@
|
|
|
8
9
|
maxConnections;
|
|
9
10
|
/** Whether connection limiting is enabled */
|
|
10
11
|
limitEnabled;
|
|
11
|
-
constructor(moduleService, cache,
|
|
12
|
+
constructor(moduleService, cache, serverHost, // ultimate-express app or http.Server for WebSocket binding
|
|
13
|
+
multiplePathConfig, limitConfig) {
|
|
12
14
|
this.moduleService = moduleService;
|
|
13
15
|
this.cache = cache;
|
|
16
|
+
this.serverHost = serverHost;
|
|
14
17
|
// Read from validated config (Kubernetes configmap) or use defaults
|
|
15
18
|
this.maxConnections = limitConfig?.maxConnections ?? envConfig.config.WEBSOCKET_MAX_CONNECTIONS;
|
|
16
19
|
this.limitEnabled = limitConfig?.limitEnabled ?? envConfig.config.WEBSOCKET_LIMIT_ENABLED;
|
|
17
|
-
|
|
20
|
+
// With the adapter, WebSocketServer works with both ultimate-ws and ws.
|
|
21
|
+
// - ultimate-ws: binds to the ultimate-express app via { server: app, path }
|
|
22
|
+
// - ws: binds to the http.Server via { server: httpServer, path }
|
|
23
|
+
this._graphqlWs = new expressAdapter.WebSocketServer({
|
|
24
|
+
server: this.serverHost,
|
|
25
|
+
path: __GRAPHQL_ENDPOINT__,
|
|
26
|
+
verifyClient: (info, cb) => {
|
|
27
|
+
if (this.limitEnabled && this.isConnectionLimitReached()) {
|
|
28
|
+
this.moduleService.logger?.warn?.(`WebSocket connection limit reached (${this.maxConnections}). Rejecting new connection.`);
|
|
29
|
+
cb(false, 503, 'Service Unavailable');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
cb(true);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
18
35
|
this.webSockets[__GRAPHQL_ENDPOINT__] = this._graphqlWs;
|
|
19
36
|
// Initialize useServer ONCE for the GraphQL WebSocket server
|
|
20
|
-
// This prevents memory leaks from creating new listeners on each connection
|
|
21
|
-
|
|
37
|
+
// This prevents memory leaks from creating new listeners on each connection.
|
|
38
|
+
// The 3rd positional `keepAlive` arg drives transport-level ping/pong so
|
|
39
|
+
// dead clients (mobile sleep, NAT timeout) are evicted. Default 30s,
|
|
40
|
+
// tunable via `GRAPHQL_WS_KEEPALIVE_MS`.
|
|
41
|
+
const keepAliveMs = Number(process.env.GRAPHQL_WS_KEEPALIVE_MS) || 30_000;
|
|
42
|
+
ws.useServer({
|
|
22
43
|
schema: moduleService.schema,
|
|
23
44
|
// Using shared context creation function to maintain consistency with GraphqlWs
|
|
24
45
|
context: async (ctx) => websocketContext.createWebSocketContext(ctx, moduleService, cache),
|
|
25
|
-
}, this._graphqlWs);
|
|
46
|
+
}, this._graphqlWs, keepAliveMs);
|
|
26
47
|
for (let key in multiplePathConfig) {
|
|
27
48
|
if (!multiplePathConfig.hasOwnProperty(key)) {
|
|
28
49
|
continue;
|
|
29
50
|
}
|
|
30
51
|
if (!this.webSockets[key]) {
|
|
31
|
-
this.webSockets[key] = new
|
|
52
|
+
this.webSockets[key] = new expressAdapter.WebSocketServer({
|
|
53
|
+
server: this.serverHost,
|
|
54
|
+
path: key,
|
|
55
|
+
verifyClient: (info, cb) => {
|
|
56
|
+
if (this.limitEnabled && this.isConnectionLimitReached()) {
|
|
57
|
+
this.moduleService.logger?.warn?.(`WebSocket connection limit reached (${this.maxConnections}). Rejecting new connection.`);
|
|
58
|
+
cb(false, 503, 'Service Unavailable');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
cb(true);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
32
64
|
this.webSockets[key].on('connection', (ws, request) => {
|
|
33
65
|
Promise.all([
|
|
34
66
|
moduleService.createContext(request, null),
|
|
@@ -38,37 +70,6 @@
|
|
|
38
70
|
}
|
|
39
71
|
}
|
|
40
72
|
}
|
|
41
|
-
httpServerUpgrade(httpServer) {
|
|
42
|
-
httpServer.on('upgrade', (request, socket, head) => {
|
|
43
|
-
const pathname = url__namespace.parse(request.url).pathname;
|
|
44
|
-
// Check connection limit before accepting new connections
|
|
45
|
-
if (this.limitEnabled && this.isConnectionLimitReached()) {
|
|
46
|
-
this.moduleService.logger?.warn?.(`WebSocket connection limit reached (${this.maxConnections}). Rejecting new connection.`);
|
|
47
|
-
socket.write('HTTP/1.1 503 Service Unavailable\r\n');
|
|
48
|
-
socket.write('Retry-After: 60\r\n');
|
|
49
|
-
socket.write('\r\n');
|
|
50
|
-
socket.destroy();
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (!this.webSockets[pathname]) {
|
|
54
|
-
// in development
|
|
55
|
-
if (pathname !== '/sockjs-node') {
|
|
56
|
-
// need to destroy
|
|
57
|
-
socket.destroy();
|
|
58
|
-
}
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
// code to run when a new connection is made
|
|
62
|
-
this.webSockets[pathname].handleUpgrade(request, socket, head, (ws) => {
|
|
63
|
-
this.webSockets[pathname].emit('connection', ws, request);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
// (new GraphqlWs(this.graphqlWs, this.moduleService, this.cache)).create();
|
|
67
|
-
// useServer({
|
|
68
|
-
// schema: this.moduleService.schema,
|
|
69
|
-
// }, this.graphqlWs);
|
|
70
|
-
return httpServer;
|
|
71
|
-
}
|
|
72
73
|
/**
|
|
73
74
|
* Get total number of active WebSocket connections across all paths
|
|
74
75
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebsocketMultipathUpdate.cjs","sources":["../../src/servers/WebsocketMultipathUpdate.ts"],"sourcesContent":[null],"names":["config","WebSocketServer","useServer","createWebSocketContext"
|
|
1
|
+
{"version":3,"file":"WebsocketMultipathUpdate.cjs","sources":["../../src/servers/WebsocketMultipathUpdate.ts"],"sourcesContent":[null],"names":["config","WebSocketServer","useServer","createWebSocketContext"],"mappings":"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"}
|