@common-stack/generate-plugin 5.0.6-alpha.3 → 5.0.6-alpha.4

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.
Files changed (141) hide show
  1. package/.eslintrc.json +1 -1
  2. package/CHANGELOG.md +4 -0
  3. package/executors.json +14 -0
  4. package/generators.json +15 -0
  5. package/lib/executors/sort-package-json/executor.cjs +46 -0
  6. package/lib/executors/sort-package-json/executor.cjs.map +1 -0
  7. package/lib/executors/sort-package-json/executor.d.ts +4 -0
  8. package/lib/executors/sort-package-json/executor.mjs +46 -0
  9. package/lib/executors/sort-package-json/executor.mjs.map +1 -0
  10. package/lib/executors/sort-package-json/executor.spec.d.ts +1 -0
  11. package/lib/executors/sort-package-json/schema.json +9 -0
  12. package/lib/executors/update-deploy-version/executor.cjs +22 -0
  13. package/lib/executors/update-deploy-version/executor.cjs.map +1 -0
  14. package/lib/executors/update-deploy-version/executor.d.ts +4 -0
  15. package/lib/executors/update-deploy-version/executor.mjs +22 -0
  16. package/lib/executors/update-deploy-version/executor.mjs.map +1 -0
  17. package/lib/executors/update-deploy-version/executor.spec.d.ts +1 -0
  18. package/lib/executors/update-deploy-version/schema.json +14 -0
  19. package/lib/generators/add-backend/files/package.json +5 -5
  20. package/lib/generators/add-backend/files/tsconfig.json +1 -1
  21. package/lib/generators/add-backend/files/webpack.config.js +6 -10
  22. package/lib/generators/add-browser-package/files/package.json +1 -1
  23. package/lib/generators/add-client-package/files/CHANGELOG.md +807 -0
  24. package/lib/generators/add-client-package/files/LICENSE +674 -0
  25. package/lib/generators/add-client-package/files/jest.config.js +13 -0
  26. package/lib/generators/add-client-package/files/package.json +31 -0
  27. package/lib/generators/add-client-package/files/rollup.config.mjs +29 -0
  28. package/lib/generators/add-client-package/files/src/components/index.tsx.template +1 -0
  29. package/lib/generators/add-client-package/files/src/index.ts.template +1 -0
  30. package/lib/generators/add-client-package/files/tsconfig.json +27 -0
  31. package/lib/generators/add-client-package/files/webpack.config.js +72 -0
  32. package/lib/generators/add-client-package/generator.cjs +19 -0
  33. package/lib/generators/add-client-package/generator.cjs.map +1 -0
  34. package/lib/generators/add-client-package/generator.d.ts +4 -0
  35. package/lib/generators/add-client-package/generator.mjs +19 -0
  36. package/lib/generators/add-client-package/generator.mjs.map +1 -0
  37. package/lib/generators/add-client-package/generator.spec.d.ts +1 -0
  38. package/lib/generators/add-client-package/schema.json +19 -0
  39. package/lib/generators/add-core-package/files/CHANGELOG.md +1076 -0
  40. package/lib/generators/add-core-package/files/LICENSE +39 -0
  41. package/lib/generators/add-core-package/files/jest.config.js +3 -0
  42. package/lib/generators/add-core-package/files/package.json +31 -0
  43. package/lib/generators/add-core-package/files/rollup.config.mjs +65 -0
  44. package/lib/generators/add-core-package/files/src/constants/index.ts.template +1 -0
  45. package/lib/generators/add-core-package/files/src/constants/types.ts.template +3 -0
  46. package/lib/generators/add-core-package/files/src/index.ts.template +2 -0
  47. package/lib/generators/add-core-package/files/src/types/index.ts.template +1 -0
  48. package/lib/generators/add-core-package/files/src/types/types.ts.template +17 -0
  49. package/lib/generators/add-core-package/files/tsconfig.json +22 -0
  50. package/lib/generators/add-core-package/files/webpack.config.js +53 -0
  51. package/lib/generators/add-core-package/generator.cjs +19 -0
  52. package/lib/generators/add-core-package/generator.cjs.map +1 -0
  53. package/lib/generators/add-core-package/generator.d.ts +4 -0
  54. package/lib/generators/add-core-package/generator.mjs +19 -0
  55. package/lib/generators/add-core-package/generator.mjs.map +1 -0
  56. package/lib/generators/add-core-package/generator.spec.d.ts +1 -0
  57. package/lib/generators/add-core-package/schema.json +19 -0
  58. package/lib/generators/add-frontend/templates/package.json +8 -8
  59. package/lib/generators/add-fullstack/files/package.json +1 -1
  60. package/lib/generators/add-moleculer/files/package.json +5 -5
  61. package/lib/generators/add-server-package/files/CHANGELOG.md +2599 -0
  62. package/lib/generators/add-server-package/files/LICENSE +674 -0
  63. package/lib/generators/add-server-package/files/jest.config.js +32 -0
  64. package/lib/generators/add-server-package/files/package.json +78 -0
  65. package/lib/generators/add-server-package/files/rollup.config.mjs +30 -0
  66. package/lib/generators/add-server-package/files/src/constants/constants.ts.template +62 -0
  67. package/lib/generators/add-server-package/files/src/constants/index.ts.template +1 -0
  68. package/lib/generators/add-server-package/files/src/constants/types.ts.template +21 -0
  69. package/lib/generators/add-server-package/files/src/index.ts.template +6 -0
  70. package/lib/generators/add-server-package/files/src/module.ts.template +6 -0
  71. package/lib/generators/add-server-package/files/tsconfig.json +27 -0
  72. package/lib/generators/add-server-package/generator.cjs +19 -0
  73. package/lib/generators/add-server-package/generator.cjs.map +1 -0
  74. package/lib/generators/add-server-package/generator.d.ts +4 -0
  75. package/lib/generators/add-server-package/generator.mjs +19 -0
  76. package/lib/generators/add-server-package/generator.mjs.map +1 -0
  77. package/lib/generators/add-server-package/generator.spec.d.ts +1 -0
  78. package/lib/generators/add-server-package/schema.json +19 -0
  79. package/lib/index.cjs +1 -1
  80. package/lib/index.d.ts +5 -0
  81. package/lib/index.mjs +1 -1
  82. package/package.json +3 -2
  83. package/project.json +12 -1
  84. package/rollup.config.mjs +8 -0
  85. package/src/executors/sort-package-json/executor.spec.ts +18 -0
  86. package/src/executors/sort-package-json/executor.ts +53 -0
  87. package/src/executors/sort-package-json/schema.d.ts +1 -0
  88. package/src/executors/sort-package-json/schema.json +9 -0
  89. package/src/executors/update-deploy-version/executor.spec.ts +18 -0
  90. package/src/executors/update-deploy-version/executor.ts +36 -0
  91. package/src/executors/update-deploy-version/schema.d.ts +3 -0
  92. package/src/executors/update-deploy-version/schema.json +14 -0
  93. package/src/generators/add-client-package/generator.spec.ts +20 -0
  94. package/src/generators/add-client-package/generator.ts +23 -0
  95. package/src/generators/add-client-package/schema.d.ts +4 -0
  96. package/src/generators/add-client-package/schema.json +19 -0
  97. package/src/generators/add-core-package/generator.spec.ts +20 -0
  98. package/src/generators/add-core-package/generator.ts +23 -0
  99. package/src/generators/add-core-package/schema.d.ts +4 -0
  100. package/src/generators/add-core-package/schema.json +19 -0
  101. package/src/generators/add-fullstack/files/package.json +1 -1
  102. package/src/generators/add-moleculer/files/package.json +5 -5
  103. package/src/generators/add-server-package/generator.spec.ts +20 -0
  104. package/src/generators/add-server-package/generator.ts +23 -0
  105. package/src/generators/add-server-package/schema.d.ts +4 -0
  106. package/src/generators/add-server-package/schema.json +19 -0
  107. package/src/index.ts +5 -0
  108. package/lib/generators/add-backend/files/knexfile.js +0 -63
  109. package/lib/generators/add-backend/files/src/api/remote-config.ts.template +0 -11
  110. package/lib/generators/add-backend/files/src/api/resolver.ts.template +0 -15
  111. package/lib/generators/add-backend/files/src/api/scalar.ts.template +0 -16
  112. package/lib/generators/add-backend/files/src/api/schema-builder.ts.template +0 -189
  113. package/lib/generators/add-backend/files/src/api/utils.ts.template +0 -44
  114. package/lib/generators/add-backend/files/src/config/moleculer.config.ts.template +0 -228
  115. package/lib/generators/add-backend/files/src/connectors/connection-broker.ts.template +0 -80
  116. package/lib/generators/add-backend/files/src/connectors/graphql-pubsub-connector.ts.template +0 -43
  117. package/lib/generators/add-backend/files/src/connectors/mongo-connector.ts.template +0 -78
  118. package/lib/generators/add-backend/files/src/connectors/nats-connector.ts.template +0 -82
  119. package/lib/generators/add-backend/files/src/connectors/redis-connector.ts.template +0 -73
  120. package/lib/generators/add-backend/files/src/express-app.ts.template +0 -67
  121. package/lib/generators/add-backend/files/src/interfaces/index.ts.template +0 -1
  122. package/lib/generators/add-backend/files/src/interfaces/module-interface.ts.template +0 -16
  123. package/lib/generators/add-backend/files/src/main.spec.ts.template +0 -129
  124. package/lib/generators/add-backend/files/src/middleware/__tests__/cors.test.ts.template +0 -12
  125. package/lib/generators/add-backend/files/src/middleware/cors.ts.template +0 -31
  126. package/lib/generators/add-backend/files/src/middleware/error.ts.template +0 -63
  127. package/lib/generators/add-backend/files/src/middleware/moleculer-inter-namespace.ts.template +0 -60
  128. package/lib/generators/add-backend/files/src/middleware/persistedQuery.ts.template +0 -40
  129. package/lib/generators/add-backend/files/src/middleware/sentry.ts.template +0 -9
  130. package/lib/generators/add-backend/files/src/middleware/services.ts.template +0 -16
  131. package/lib/generators/add-backend/files/src/middleware/tracer.ts.template +0 -24
  132. package/lib/generators/add-backend/files/src/modules/auth/schema/auth-schema.graphql +0 -25
  133. package/lib/generators/add-backend/files/src/server-setup/graphql-server.ts.template +0 -185
  134. package/lib/generators/add-backend/files/src/server-setup/graphql-subscription-server.ts.template +0 -113
  135. package/lib/generators/add-backend/files/src/server-setup/graphql-ws.ts.template +0 -158
  136. package/lib/generators/add-backend/files/src/server-setup/mongodb-migration-update.ts.template +0 -47
  137. package/lib/generators/add-backend/files/src/server-setup/utils.ts.template +0 -43
  138. package/lib/generators/add-backend/files/src/server-setup/websocket-multipath-update.ts.template +0 -88
  139. package/lib/generators/add-backend/files/src/stack-server.ts.template +0 -277
  140. package/lib/generators/add-backend/files/src/utils/migrations.ts.template +0 -32
  141. package/lib/generators/add-backend/files/uploads/3986781.ppt +0 -0
@@ -1,129 +0,0 @@
1
- // import {GRAPHQL_ROUTE, GRAPHIQL_ROUTE, main} from './main';
2
- // import {get as httpGet, Server} from 'http';
3
- // import 'jest';
4
-
5
- // const ERRNO_KEY = 'errno';
6
- // const PORT: number = 8080;
7
-
8
- // function getFromServer(uri) {
9
- // return new Promise((resolve, reject) => {
10
- // httpGet(`http://localhost:${PORT}${uri}`, (res) => {
11
- // resolve(res);
12
- // }).on('error', (err: Error) => {
13
- // reject(err);
14
- // });
15
- // });
16
- // }
17
-
18
- // describe('main', () => {
19
- // it('should be able to Initialize a server (production)', () => {
20
- // return main({
21
- // enableCors: false,
22
- // enableGraphiql: false,
23
- // env: 'production',
24
- // port: PORT,
25
- // })
26
- // .then(([server]) => {
27
- // return (<Server>server).close();
28
- // });
29
- // });
30
-
31
- // it('should be able to Initialize a server (development)', () => {
32
- // return main({
33
- // enableCors: true,
34
- // enableGraphiql: true,
35
- // env: 'dev',
36
- // port: PORT,
37
- // })
38
- // .then(([server]) => {
39
- // return (<Server>server).close();
40
- // });
41
- // });
42
-
43
- // it('should have a working GET graphql (developemnt)', () => {
44
- // return main({
45
- // enableCors: true,
46
- // enableGraphiql: true,
47
- // env: 'dev',
48
- // port: PORT,
49
- // })
50
- // .then(([server]) => {
51
- // return getFromServer(GRAPHQL_ROUTE).then((res: any) => {
52
- // (<Server>server).close();
53
- // // GET without query returns 400
54
- // expect(res.statusCode).toBe(400);
55
- // });
56
- // });
57
- // });
58
-
59
- // it('should have a working GET graphql (production)', () => {
60
- // return main({
61
- // enableCors: false,
62
- // enableGraphiql: false,
63
- // env: 'production',
64
- // port: PORT,
65
- // })
66
- // .then(([server]) => {
67
- // return getFromServer(GRAPHQL_ROUTE).then((res: any) => {
68
- // (<Server>server).close();
69
- // // GET without query returns 400
70
- // expect(res.statusCode).toBe(400);
71
- // });
72
- // });
73
- // });
74
-
75
- // it('should have a working graphiql (developemnt)', () => {
76
- // return main({
77
- // enableCors: true,
78
- // enableGraphiql: true,
79
- // env: 'dev',
80
- // port: PORT,
81
- // })
82
- // .then(([server]) => {
83
- // return getFromServer(GRAPHIQL_ROUTE).then((res: any) => {
84
- // (<Server>server).close();
85
- // expect(res.statusCode).toBe(200);
86
- // });
87
- // });
88
- // });
89
-
90
- // it('should have block graphiql (production)', () => {
91
- // return main({
92
- // enableCors: false,
93
- // enableGraphiql: false,
94
- // env: 'production',
95
- // port: PORT,
96
- // })
97
- // .then(([server]) => {
98
- // return getFromServer(GRAPHIQL_ROUTE).then((res: any) => {
99
- // (<Server>server).close();
100
- // expect(res.statusCode).toBe(404);
101
- // });
102
- // });
103
- // });
104
-
105
- // it('should reject twice on same port', () => {
106
- // return main({
107
- // enableCors: false,
108
- // enableGraphiql: false,
109
- // env: 'production',
110
- // port: PORT,
111
- // })
112
- // .then(([server]) => {
113
- // return main({
114
- // enableCors: false,
115
- // enableGraphiql: false,
116
- // env: 'production',
117
- // port: PORT,
118
- // })
119
- // .then(([secondServer]) => {
120
- // (<Server>server).close();
121
- // (<Server>secondServer).close();
122
- // throw new Error('Was able to listen twice!');
123
- // }, (err: Error) => {
124
- // (<Server>server).close();
125
- // expect(err[ERRNO_KEY]).toBe('EADDRINUSE');
126
- // });
127
- // });
128
- // });
129
- // });
@@ -1,12 +0,0 @@
1
- import Url from 'url';
2
- import * as express from 'express';
3
- import * as nock from 'nock';
4
- import * as request from 'supertest';
5
-
6
-
7
- describe('test', () => {
8
- const app = express();
9
- test('test', () => {
10
- app.get('/graphql')
11
- });
12
- });
@@ -1,31 +0,0 @@
1
- /* eslint-disable jest/require-hook */
2
- import * as cors from 'cors';
3
- import { logger } from '@cdm-logger/server';
4
- import { config } from '../config';
5
-
6
- const CLIENT_URL = config.CLIENT_URL;
7
- const BACKEND_URL = config.BACKEND_URL;
8
-
9
- const corsWhitelist = [
10
- BACKEND_URL,
11
- CLIENT_URL,
12
- config.GRAPHQL_URL,
13
- // 'http://localhost:3000',
14
- ];
15
- logger.info('Cors whitelist: %j', corsWhitelist);
16
- const corsOptions = {
17
- origin: (origin, callback) => {
18
- if (corsWhitelist.indexOf(origin) !== -1) {
19
- callback(null, true);
20
- } else {
21
- // TODO: only throw when in debug mode
22
- logger.error('url (%s) is not in the whitelist', origin);
23
- // callback(new Error('Not allowed by CORS'))
24
- logger.warn('allowing all origins temporarily, you need to disable it.');
25
- callback(null, true);
26
- }
27
- },
28
- credentials: true,
29
- };
30
-
31
- export const corsMiddleware = cors(corsOptions);
@@ -1,63 +0,0 @@
1
- /// <reference path='../../../../typings/index.d.ts' />
2
-
3
- import * as path from 'path';
4
- import * as fs from 'fs';
5
- import * as url from 'url';
6
- import { logger } from '@cdm-logger/server';
7
-
8
-
9
- let assetMap;
10
-
11
- const stripCircular = (from, seen?: any) => {
12
- const to = Array.isArray(from) ? [] : {};
13
- seen = seen || [];
14
- seen.push(from);
15
- Object.getOwnPropertyNames(from).forEach(key => {
16
- if (!from[key] || (typeof from[key] !== 'object' && !Array.isArray(from[key]))) {
17
- to[key] = from[key];
18
- } else if (seen.indexOf(from[key]) < 0) {
19
- to[key] = stripCircular(from[key], seen.slice(0));
20
- } else { to[key] = '[Circular]'; }
21
- });
22
- return to;
23
- };
24
-
25
- const { pathname } = url.parse(__BACKEND_URL__);
26
-
27
- /**
28
- * Middleware function that takes 4 arguments is classified as "error handling middleware"
29
- * and will only get called if an error occurs.
30
- * @param e
31
- * @param req
32
- * @param res
33
- * @param next
34
- */
35
- export const errorMiddleware =
36
- (e, req, res, next) => {
37
- if (req.path === pathname) {
38
- const stack = e.stack.toString().replace(/[\n]/g, '\\n');
39
- res.status(200).send(`[{"data": {}, "errors":[{"message": "${stack}"}]}]`);
40
- } else {
41
- logger.error(e);
42
-
43
- if (__DEV__ || !assetMap) {
44
- assetMap = JSON.parse(fs.readFileSync(path.join(__FRONTEND_BUILD_DIR__, 'assets.json')).toString());
45
- }
46
-
47
- const serverErrorScript = `<script charset="UTF-8">window.__SERVER_ERROR__=${JSON.stringify(
48
- stripCircular(e),
49
- )};</script>`;
50
- const vendorScript = assetMap['vendor.js']
51
- ? `<script src="/${assetMap['vendor.js']}" charSet="utf-8"></script>`
52
- : '';
53
-
54
- res.status(200).send(
55
- `<html>${serverErrorScript}<body><div id="content"></div>
56
- ${vendorScript}
57
- <script src="/${assetMap['index.js']}" charSet="utf-8"></script>
58
- </body></html>`,
59
- );
60
- }
61
- };
62
-
63
-
@@ -1,60 +0,0 @@
1
- /* eslint-disable no-param-reassign */
2
- import { ServiceBroker, Middleware } from 'moleculer';
3
- import { isString, defaultsDeep } from 'lodash-es';
4
-
5
- export const InterNamespaceMiddleware = function (options): Middleware {
6
- if (!Array.isArray(options)) {
7
- throw new Error('Must be an Array');
8
- }
9
-
10
- let thisBroker: ServiceBroker;
11
- const brokers: { [key: string]: ServiceBroker } = {};
12
-
13
- return {
14
- created(broker: ServiceBroker) {
15
- thisBroker = broker;
16
- options.forEach((nsOpts) => {
17
- if (isString(nsOpts)) {
18
- nsOpts = {
19
- namespace: nsOpts,
20
- };
21
- }
22
- const ns = nsOpts.namespace;
23
-
24
- const brokerOpts = defaultsDeep(
25
- {},
26
- nsOpts,
27
- { nodeID: null, middlewares: null, created: null, started: null },
28
- broker.options,
29
- );
30
- brokers[ns] = new ServiceBroker(brokerOpts);
31
- });
32
- },
33
-
34
- started() {
35
- return Promise.all(Object.values(brokers).map((b) => b.start()));
36
- },
37
-
38
- stopped() {
39
- return Promise.all(Object.values(brokers).map((b) => b.stop()));
40
- },
41
-
42
- call(next) {
43
- return function (actionName, params, opts = {}) {
44
- if (isString(actionName) && actionName.includes('@')) {
45
- const [action, namespace] = actionName.split('@');
46
-
47
- if (brokers[namespace]) {
48
- return brokers[namespace].call(action, params, opts);
49
- }
50
- if (namespace === thisBroker.namespace) {
51
- return next(action, params, opts);
52
- }
53
- throw new Error(`Unknown namespace: ${namespace}`);
54
- }
55
-
56
- return next(actionName, params, opts);
57
- };
58
- },
59
- };
60
- };
@@ -1,40 +0,0 @@
1
- import { invert, isArray } from 'lodash-es';
2
- import { GRAPHIQL_ROUTE } from '../ENDPOINTS';
3
- import { logger } from '@cdm-logger/server';
4
-
5
- let reqlib: any = require('app-root-path');
6
-
7
- let persistCache = true;
8
- let queryMap;
9
- try {
10
- queryMap = reqlib.require('@adminide-stack/graphql-gql/extracted_queries.json');
11
-
12
- } catch (err) {
13
- logger.warn('extracted_queries.json file is unavailable, disabling persist queries');
14
- }
15
- export const persistedQueryMiddleware = (req, res, next) => {
16
-
17
- if (queryMap) {
18
- const invertedMap = invert(queryMap);
19
-
20
- if (isArray(req.body)) {
21
- req.body = req.body.map(body => {
22
- const id = body['id'];
23
- return {
24
- query: invertedMap[id],
25
- ...body,
26
- };
27
- });
28
- next();
29
- } else {
30
- if (!__DEV__ || (req.get('Referer') || '').indexOf(GRAPHIQL_ROUTE) < 0) {
31
- res.status(500).send('Unknown GraphQL query has been received, rejecting...');
32
- } else {
33
- next();
34
- }
35
- }
36
- } else {
37
- next();
38
- }
39
- };
40
-
@@ -1,9 +0,0 @@
1
- const Sentry = require('@sentry/node');
2
-
3
- Sentry.init({ dsn: process.env.SENTRY_DSN_BACKEND });
4
-
5
-
6
- export const sentryMiddleware = Sentry.Handlers.requestHandler();
7
-
8
-
9
- export const sentryErrorHandlerMiddleware = Sentry.Handlers.errorHandler();
@@ -1,16 +0,0 @@
1
- import 'isomorphic-fetch';
2
-
3
-
4
- export const contextServicesMiddleware = (createContext, serviceContext) => (req, res, next) => {
5
- Promise.all([
6
- createContext(req, res),
7
- serviceContext(req, res),
8
- ])
9
- .then(([ context, services ]) => {
10
- req.context = context;
11
- req.services = services;
12
-
13
- next();
14
- })
15
- .catch((err) => next());
16
- };
@@ -1,24 +0,0 @@
1
- const ZipkinOpentracing = require('zipkin-javascript-opentracing');
2
- import { config } from '../config';
3
-
4
- const ZIPKIN_HOST_PORT = `${config.ZIPKIN_URL}`;
5
-
6
-
7
- export const server = new ZipkinOpentracing({
8
- serviceName: 'graphql',
9
- endpoint: ZIPKIN_HOST_PORT,
10
- kind: 'server',
11
- });
12
-
13
-
14
- export const client = new ZipkinOpentracing({
15
- serviceName: 'graphql',
16
- endpoint: ZIPKIN_HOST_PORT,
17
- kind: 'client',
18
- });
19
-
20
- export const local = new ZipkinOpentracing({
21
- serviceName: 'graphql',
22
- endpoint: ZIPKIN_HOST_PORT,
23
- kind: 'local',
24
- });
@@ -1,25 +0,0 @@
1
- type LoggedInUserPayload {
2
- # if `id` is `null`, it means there is not logged in user
3
- id: ID
4
- }
5
-
6
- extend type Query {
7
- loggedInUser: LoggedInUserPayload!
8
- }
9
-
10
- type AuthenticateUserPayload {
11
- token: String!
12
- }
13
-
14
- extend type Mutation {
15
- authenticateUser(email: String!, password: String!): AuthenticateUserPayload
16
- }
17
-
18
- type SignupUserPayload {
19
- id: ID!
20
- token: String!
21
- }
22
-
23
- extend type Mutation {
24
- signupUser(email: String!, password: String!): SignupUserPayload
25
- }
@@ -1,185 +0,0 @@
1
- import { ApolloServer, ApolloServerExpressConfig } from 'apollo-server-express';
2
- import {
3
- ApolloServerPluginCacheControl,
4
- ApolloServerPluginDrainHttpServer,
5
- GraphQLRequestContext
6
- } from 'apollo-server-core';
7
- import responseCachePlugin from 'apollo-server-plugin-response-cache';
8
- import 'isomorphic-fetch';
9
- import { Express } from 'express';
10
- import * as http from 'http';
11
- import Keyv from 'keyv';
12
- import KeyvRedis from '@keyv/redis';
13
- import { KeyvAdapter } from '@apollo/utils.keyvadapter';
14
- import { RedisCache, RedisClusterCache } from 'apollo-server-cache-redis';
15
- import { CdmLogger } from '@cdm-logger/core';
16
- import { WebSocketServer } from 'ws';
17
- import { IModuleService } from '../interfaces';
18
- import { GraphqlWs } from './graphql-ws';
19
- import { invalidateCachePlugin } from '@adminide-stack/platform-server';
20
- import { config } from '../config';
21
-
22
- type ILogger = CdmLogger.ILogger;
23
-
24
- let debug = false;
25
- if ((process.env.LOG_LEVEL && process.env.LOG_LEVEL === 'trace') || process.env.LOG_LEVEL === 'debug') {
26
- debug = true;
27
- }
28
-
29
- // @workaround as the `dataSources` not available in Subscription (websocket) Context.
30
- // https://github.com/apollographql/apollo-server/issues/1526 need to revisit in Apollo-Server v3.
31
- const constructDataSourcesForSubscriptions = (context, cache, dataSources) => {
32
- const intializeDataSource = (instance) => {
33
- instance.initialize({ context, cache });
34
- };
35
- // tslint:disable-next-line:forin
36
- // eslint-disable-next-line guard-for-in
37
- for (const prop in dataSources) {
38
- intializeDataSource(dataSources[prop]);
39
- }
40
- return dataSources;
41
- };
42
-
43
- let wsServerCleanup: any;
44
-
45
-
46
-
47
- export class GraphqlServer {
48
- private logger: ILogger;
49
-
50
- constructor(
51
- private app: Express,
52
- private httpServer: http.Server,
53
- private cache: RedisCache | RedisClusterCache,
54
- private moduleService: IModuleService,
55
- private enableSubscription = true,
56
- ) {
57
- this.logger = this.moduleService.logger.child({ className: 'GraphqlServer' });
58
- if (enableSubscription) {
59
- const wsServer = new WebSocketServer({
60
- server: this.httpServer,
61
- path: __GRAPHQL_ENDPOINT__,
62
- });
63
- const graphqlWs = new GraphqlWs(wsServer, this.moduleService, this.cache);
64
- wsServerCleanup = graphqlWs.create();
65
- }
66
- }
67
-
68
- public async initialize() {
69
- this.logger.info('GraphqlServer initializing...');
70
- const apolloServer = this.configureApolloServer();
71
- await apolloServer.start();
72
- const corsOptions = {
73
- origin: [config.CLIENT_URL],
74
- credentials: true,
75
- };
76
- apolloServer.applyMiddleware({
77
- app: this.app,
78
- cors: corsOptions,
79
- path: __GRAPHQL_ENDPOINT__,
80
- });
81
- this.logger.info('GraphqlServer initialized - ', config.CLIENT_URL);
82
- }
83
-
84
- getUserIpAddress(req) {
85
- let ip = (req?.headers['x-forwarded-for'] || '').split(',')[0] || req?.connection?.remoteAddress;
86
- if (ip.substr(0, 7) === '::ffff:') {
87
- ip = ip.substr(7);
88
- }
89
- if (ip === '::1') {
90
- ip = '127.0.0.1';
91
- }
92
- return ip;
93
- }
94
-
95
- private configureApolloServer(): ApolloServer {
96
- this.logger.info('-- Configuring Apollo Server --');
97
- const cache = new KeyvAdapter(new Keyv({ store: new KeyvRedis(this.cache.client) }), {
98
- disableBatchReads: true,
99
- });
100
-
101
- const serverConfig: ApolloServerExpressConfig = {
102
- debug,
103
- cache,
104
- schema: this.moduleService.schema,
105
- dataSources: () => this.moduleService.dataSource,
106
- context: async ({
107
- req,
108
- res,
109
- connection,
110
- }: {
111
- req: Express.Request;
112
- res: Express.Response;
113
- connection: any;
114
- }) => {
115
- let context;
116
- let addons = {};
117
- try {
118
- if (connection) {
119
- context = connection.context;
120
- if (!context.dataSources) {
121
- addons = {
122
- // @workaround for apollo server issue #1526
123
- dataSources: constructDataSourcesForSubscriptions(
124
- connection.context,
125
- this.cache,
126
- this.moduleService.dataSource,
127
- ),
128
- };
129
- } else {
130
- addons = {
131
- // @workaround for apollo server issue #1526
132
- dataSources: context.dataSources,
133
- };
134
- }
135
- } else {
136
- const pureContext = await this.moduleService.createContext(req, res);
137
- const contextServices = await this.moduleService.serviceContext(req, res);
138
- context = {
139
- ...pureContext,
140
- ...contextServices,
141
- preferences: this.moduleService.defaultPreferences,
142
- // update: updateContainers,
143
- };
144
- }
145
- context.userIp = this.getUserIpAddress(req);
146
- } catch (err) {
147
- this.logger.error('Adding context to GraphQL failed', { error: err });
148
- throw err;
149
- }
150
- return {
151
- req,
152
- res,
153
- ...context,
154
- ...addons,
155
- };
156
- },
157
- plugins: [
158
- ApolloServerPluginDrainHttpServer({ httpServer: this.httpServer }),
159
- ApolloServerPluginCacheControl(),
160
- responseCachePlugin({
161
- sessionId: ({ context }) => context?.userContext?.accountId ?? null,
162
- generateCacheKey({
163
- queryHash,
164
- operationName
165
- }: GraphQLRequestContext<Record<string, any>>, keyData): string {
166
- return `${operationName}:${queryHash}`;
167
- },
168
- }),
169
- invalidateCachePlugin({ cache: this.cache }),
170
- ],
171
- };
172
- if (this.enableSubscription) {
173
- serverConfig.plugins.push({
174
- async serverWillStart() {
175
- return {
176
- drainServer: async () => {
177
- await wsServerCleanup.dispose();
178
- },
179
- };
180
- },
181
- });
182
- }
183
- return new ApolloServer(serverConfig);
184
- }
185
- }