@common-stack/generate-plugin 5.0.4-alpha.9 → 5.0.5-alpha.0

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 (89) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +42 -0
  3. package/generators.json +5 -0
  4. package/lib/generators/add-backend/files/CHANGELOG.md +196 -0
  5. package/lib/generators/add-backend/files/Dockerfile +30 -0
  6. package/lib/generators/add-backend/files/LICENSE +661 -0
  7. package/lib/generators/add-backend/files/README.md +133 -0
  8. package/lib/generators/add-backend/files/__tests__/test.ts.template +95 -0
  9. package/lib/generators/add-backend/files/babel.config.js +45 -0
  10. package/lib/generators/add-backend/files/build.config.js +14 -0
  11. package/lib/generators/add-backend/files/build.config.mjs +27 -0
  12. package/lib/generators/add-backend/files/generated-schema.graphql +235 -0
  13. package/lib/generators/add-backend/files/jest.config.js +27 -0
  14. package/lib/generators/add-backend/files/knexfile.js +63 -0
  15. package/lib/generators/add-backend/files/package.json +162 -0
  16. package/lib/generators/add-backend/files/src/api/remote-config.ts.template +11 -0
  17. package/lib/generators/add-backend/files/src/api/resolver.ts.template +15 -0
  18. package/lib/generators/add-backend/files/src/api/root-schema.graphqls +96 -0
  19. package/lib/generators/add-backend/files/src/api/scalar.ts.template +16 -0
  20. package/lib/generators/add-backend/files/src/api/schema-builder.ts.template +189 -0
  21. package/lib/generators/add-backend/files/src/api/utils.ts.template +44 -0
  22. package/lib/generators/add-backend/files/src/config/env-config.ts.template +34 -0
  23. package/lib/generators/add-backend/files/src/config/index.ts.template +1 -0
  24. package/lib/generators/add-backend/files/src/config/moleculer.config.ts.template +228 -0
  25. package/lib/generators/add-backend/files/src/connectors/connection-broker.ts.template +80 -0
  26. package/lib/generators/add-backend/files/src/connectors/graphql-pubsub-connector.ts.template +43 -0
  27. package/lib/generators/add-backend/files/src/connectors/mongo-connector.ts.template +78 -0
  28. package/lib/generators/add-backend/files/src/connectors/nats-connector.ts.template +82 -0
  29. package/lib/generators/add-backend/files/src/connectors/redis-connector.ts.template +73 -0
  30. package/lib/generators/add-backend/files/src/env.ts.template +5 -0
  31. package/lib/generators/add-backend/files/src/express-app.ts.template +67 -0
  32. package/lib/generators/add-backend/files/src/index.ts.template +56 -0
  33. package/lib/generators/add-backend/files/src/interfaces/index.ts.template +1 -0
  34. package/lib/generators/add-backend/files/src/interfaces/module-interface.ts.template +16 -0
  35. package/lib/generators/add-backend/files/src/main.spec.ts.template +129 -0
  36. package/lib/generators/add-backend/files/src/middleware/__tests__/cors.test.ts.template +12 -0
  37. package/lib/generators/add-backend/files/src/middleware/cors.ts.template +31 -0
  38. package/lib/generators/add-backend/files/src/middleware/error.ts.template +63 -0
  39. package/lib/generators/add-backend/files/src/middleware/moleculer-inter-namespace.ts.template +60 -0
  40. package/lib/generators/add-backend/files/src/middleware/persistedQuery.ts.template +40 -0
  41. package/lib/generators/add-backend/files/src/middleware/sentry.ts.template +9 -0
  42. package/lib/generators/add-backend/files/src/middleware/services.ts.template +16 -0
  43. package/lib/generators/add-backend/files/src/middleware/tracer.ts.template +24 -0
  44. package/lib/generators/add-backend/files/src/modules/auth/schema/auth-schema.graphql +25 -0
  45. package/lib/generators/add-backend/files/src/modules/index.ts.template +17 -0
  46. package/lib/generators/add-backend/files/src/modules/module.ts.template +78 -0
  47. package/lib/generators/add-backend/files/src/server-setup/graphql-server.ts.template +185 -0
  48. package/lib/generators/add-backend/files/src/server-setup/graphql-subscription-server.ts.template +113 -0
  49. package/lib/generators/add-backend/files/src/server-setup/graphql-ws.ts.template +158 -0
  50. package/lib/generators/add-backend/files/src/server-setup/mongodb-migration-update.ts.template +47 -0
  51. package/lib/generators/add-backend/files/src/server-setup/utils.ts.template +43 -0
  52. package/lib/generators/add-backend/files/src/server-setup/websocket-multipath-update.ts.template +88 -0
  53. package/lib/generators/add-backend/files/src/service.ts.template +36 -0
  54. package/lib/generators/add-backend/files/src/stack-server.ts.template +277 -0
  55. package/lib/generators/add-backend/files/src/utils/migrations.ts.template +32 -0
  56. package/lib/generators/add-backend/files/tsconfig.base.json +30 -0
  57. package/lib/generators/add-backend/files/tsconfig.json +19 -0
  58. package/lib/generators/add-backend/files/uploads/3986781.ppt +0 -0
  59. package/lib/generators/add-backend/files/webpack.config.js +186 -0
  60. package/lib/generators/add-backend/files/webpack.config.mjs +209 -0
  61. package/lib/generators/add-backend/generator.cjs +20 -0
  62. package/lib/generators/add-backend/generator.cjs.map +1 -0
  63. package/lib/generators/add-backend/generator.d.ts +4 -0
  64. package/lib/generators/add-backend/generator.mjs +20 -0
  65. package/lib/generators/add-backend/generator.mjs.map +1 -0
  66. package/lib/generators/add-backend/generator.spec.d.ts +1 -0
  67. package/lib/generators/add-backend/schema.json +17 -0
  68. package/lib/generators/add-frontend/generator.cjs +3 -12
  69. package/lib/generators/add-frontend/generator.cjs.map +1 -1
  70. package/lib/generators/add-frontend/generator.mjs +2 -11
  71. package/lib/generators/add-frontend/generator.mjs.map +1 -1
  72. package/lib/generators/add-frontend/templates/package.json +23 -24
  73. package/lib/index.cjs +1 -1
  74. package/lib/index.d.ts +1 -0
  75. package/lib/index.mjs +1 -1
  76. package/lib/utils/index.cjs +8 -0
  77. package/lib/utils/index.cjs.map +1 -0
  78. package/lib/utils/index.d.ts +1 -0
  79. package/lib/utils/index.mjs +8 -0
  80. package/lib/utils/index.mjs.map +1 -0
  81. package/package.json +2 -2
  82. package/rollup.config.mjs +6 -4
  83. package/src/generators/add-backend/generator.spec.ts +20 -0
  84. package/src/generators/add-backend/generator.ts +30 -0
  85. package/src/generators/add-backend/schema.d.ts +4 -0
  86. package/src/generators/add-backend/schema.json +17 -0
  87. package/src/generators/add-frontend/generator.ts +2 -12
  88. package/src/index.ts +1 -1
  89. package/src/utils/index.ts +10 -0
@@ -0,0 +1,162 @@
1
+ {
2
+ "name": "adminide-stack-backend-server",
3
+ "version": "3.1.1-alpha.5",
4
+ "private": true,
5
+ "description": "Starter kit for apollo server using webpack and typescript",
6
+ "keywords": [
7
+ "apollo",
8
+ "apollo-server",
9
+ "backend",
10
+ "express",
11
+ "graphiql",
12
+ "graphql",
13
+ "typescript",
14
+ "webpack"
15
+ ],
16
+ "homepage": "https://github.com/cdmbase/fullstack-pro#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/cdmbase/fullstack-pro/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/cdmbase/fullstack-pro.git"
23
+ },
24
+ "license": "MIT",
25
+ "author": "CDMBase LLC",
26
+ "main": "dist/index.js",
27
+ "typings": "dist/main.d.ts",
28
+ "scripts": {
29
+ "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
30
+ "build:clean": "rimraf dist .awcache",
31
+ "build:dev": "cross-env NODE_ENV=development ENV_FILE=../../config/development/dev.env webpack --config webpack.config.js",
32
+ "db:migrate": "knex -- migrate:latest --cwd . --knexfile ./knexfile.js",
33
+ "db:migrate:rollback": "knex -- migrate:rollback --cwd . --knexfile ./knexfile.js",
34
+ "db:seed": "yarn db:migrate && knex -- seed:run --cwd . --knexfile ./knexfile.js",
35
+ "docker:build": "yarn build && docker build . -t $npm_package_name:$npm_package_version",
36
+ "docker:build:debug": "yarn build:debug && docker build . -t $npm_package_name:$npm_package_version",
37
+ "docker:run": "docker run --env-file ../../config/staging/docker-staging.env -p 8080:8080 -it $npm_package_name:$npm_package_version",
38
+ "docker:run:debug": "cross-env NODE_ENV=development docker run --env-file ../../config/staging/docker-staging.env -p 8080:8080 -it $npm_package_name:$npm_package_version",
39
+ "proddb:migrate": "NODE_ENV=production yarn db:migrate",
40
+ "proddb:migrate:rollback": "NODE_ENV=production yarn db:migrate:rollback",
41
+ "proddb:seed": "NODE_ENV=production yarn db:seed",
42
+ "prepublish": "yarn build:clean",
43
+ "stagedb:migrate": "cross-env ENV_FILE=../../config/test/test.env NODE_ENV=test yarn db:migrate",
44
+ "stagedb:migrate:rollback": "cross-env ENV_FILE=../../config/test/test.env NODE_ENV=test yarn db:migrate:rollback",
45
+ "stagedb:seed": "cross-env ENV_FILE=../../config/test/test.env NODE_ENV=test yarn db:seed",
46
+ "start": "cross-env NODE_ENV=production tsx dist/index.js",
47
+ "start:dev": "cross-env NODE_ENV=development ENV_FILE=../../config/development/dev.env tsx watch dist/index.js",
48
+ "start:staging": "cross-env NODE_ENV=staging ENV_FILE=../../config/staging/staging.env tsx dist/index.js",
49
+ "start:test": "cross-env NODE_ENV=test ENV_FILE=../../config/test/test.env tsx dist/index.js",
50
+ "test": "jest",
51
+ "test:notify": "yarn test:watch -- --notify",
52
+ "test:watch": "npm test -- --watch",
53
+ "preupver": "npm test",
54
+ "upver": "standard-version",
55
+ "watch": "cross-env NODE_ENV=development ENV_FILE=../../config/development/dev.env yarn build:dev && yarn start:dev",
56
+ "watch:staging": "cross-env NODE_ENV=test ENV_FILE=../../config/staging/staging.env yarn build && yarn start:stage",
57
+ "watch:test": "cross-env NODE_ENV=test ENV_FILE=../../config/test/test.env yarn build:test && yarn start:test",
58
+ "zen:watch": "zen watch -x"
59
+ },
60
+ "resolutions": {
61
+ "apollo-upload-client": "^16.0.0",
62
+ "extract-files": "^10.0.0",
63
+ "html-to-text": "^8.0.0"
64
+ },
65
+ "dependencies": {
66
+ "@adminide-stack/account-api-server": "7.2.6-alpha.13",
67
+ "@adminide-stack/billing-api-server": "7.2.6-alpha.13",
68
+ "@adminide-stack/core": "7.2.6-alpha.13",
69
+ "@adminide-stack/extension-module-server": "7.2.6-alpha.13",
70
+ "@adminide-stack/git-api-server": "7.2.6-alpha.13",
71
+ "@adminide-stack/integration-api-server": "7.2.6-alpha.13",
72
+ "@adminide-stack/marketplace-module-server": "7.2.6-alpha.13",
73
+ "@adminide-stack/platform-server": "7.2.6-alpha.13",
74
+ "@adminide-stack/project-mgmt-server": "7.2.6-alpha.13",
75
+ "@adminide-stack/registry-api-server": "7.2.6-alpha.13",
76
+ "@adminide-stack/user-auth0-server": "7.2.6-alpha.13",
77
+ "@apollo/client": "^3.9.0",
78
+ "@apollo/utils.keyvadapter": "3.1.0",
79
+ "@babel/runtime": "^7.20.1",
80
+ "@casl/ability": "^4.1.5",
81
+ "@cdm-logger/client": "9.0.3",
82
+ "@cdm-logger/server": "^9.0.3",
83
+ "@cdmbase/graphql-type-uri": "^3.0.0",
84
+ "@common-stack/cache-api-server": "0.0.1",
85
+ "@common-stack/client-core": "0.0.1",
86
+ "@common-stack/core": "0.0.1",
87
+ "@common-stack/server-core": "0.0.1",
88
+ "@common-stack/store-mongo": "0.0.1",
89
+ "@container-stack/core": "5.1.2",
90
+ "@container-stack/mailing-api": "5.1.2",
91
+ "@container-stack/notification-api-core": "5.1.2",
92
+ "@container-stack/notification-api-server": "5.1.2",
93
+ "@container-stack/territory": "5.1.2",
94
+ "@graphql-tools/links": "^8.3.21",
95
+ "@graphql-tools/schema": "^8.3.14",
96
+ "@graphql-tools/stitch": "^8.7.29",
97
+ "@graphql-tools/utils": "^8.0.0",
98
+ "@graphql-tools/wrap": "^8.4.20",
99
+ "@keyv/redis": "2.8.4",
100
+ "@remix-run/node": "^2.8.1",
101
+ "@sentry/node": "~7.24.2",
102
+ "apollo-datasource": "^3.3.1",
103
+ "apollo-datasource-rest": "^3.3.1",
104
+ "apollo-errors": "^1.9.0",
105
+ "apollo-server-cache-memcached": "^3.3.1",
106
+ "apollo-server-cache-redis": "^3.3.1",
107
+ "apollo-server-caching": "^3.3.0",
108
+ "apollo-server-core": "^3.11.1",
109
+ "apollo-server-errors": "^3.3.1",
110
+ "apollo-server-express": "^3.11.1",
111
+ "apollo-server-plugin-response-cache": "^3.8.1",
112
+ "app-root-path": "^3.0.0",
113
+ "body-parser": "^1.19.0",
114
+ "cors": "^2.8.5",
115
+ "dataloader": "^2.0.0",
116
+ "dotenv": "^8.2.0",
117
+ "dotenv-esm": "^16.0.3-4",
118
+ "envalid": "~7.2.2",
119
+ "esm": "^3.2.25",
120
+ "express": "^4.17.1",
121
+ "graphql": "^15.0.0",
122
+ "graphql-bigint": "^1.0.0",
123
+ "graphql-iso-date": "^3.6.1",
124
+ "graphql-middleware": "^6.1.33",
125
+ "graphql-nats-subscriptions": "^1.5.0",
126
+ "graphql-playground-middleware-express": "^1.7.3",
127
+ "graphql-shield": "^7.3.5",
128
+ "graphql-subscriptions": "^2.0.0",
129
+ "graphql-tools": "^8.0.0",
130
+ "graphql-type-json": "^0.3.1",
131
+ "graphql-ws": "^5.11.2",
132
+ "inversify": "^6.0.2",
133
+ "ioredis": "^5.4.1",
134
+ "isomorphic-fetch": "^2.2.1",
135
+ "lodash": "^4.17.15",
136
+ "moleculer": "^0.14.2",
137
+ "moleculer-zipkin": "0.2.2",
138
+ "mongoose": "^6.3.3",
139
+ "mongoose-execution-time": "^1.1.0",
140
+ "morgan": "^1.9.1",
141
+ "nats": "^1.3.2",
142
+ "react": "18.2.0",
143
+ "reflect-metadata": "^0.1.13",
144
+ "rxjs": "^6.5.3",
145
+ "rxjs-compat": "^6.5.3",
146
+ "subscriptions-transport-ws": "^0.11.0",
147
+ "universal-cookie-express": "^4.0.1",
148
+ "ws": "^8.11.0"
149
+ },
150
+ "devDependencies": {
151
+ "cross-env": "^7.0.3",
152
+ "pm2": "^5.2.2",
153
+ "rimraf": "^3.0.2",
154
+ "tsx": "^4.7.0"
155
+ },
156
+ "engines": {
157
+ "vscode": "^1.52.1"
158
+ },
159
+ "typescript": {
160
+ "definition": "dist/main.d.ts"
161
+ }
162
+ }
@@ -0,0 +1,11 @@
1
+ interface ISchemaConfig {
2
+ uri: string;
3
+ wsUri: string;
4
+ }
5
+
6
+ export const remoteSchemaDetails: ISchemaConfig[] = [
7
+ // {
8
+ // uri: 'http://localhost:8085/graphql',
9
+ // wsUri: 'ws://localhost:8085/graphql',
10
+ // },
11
+ ];
@@ -0,0 +1,15 @@
1
+ import GraphQLJSON, { GraphQLJSONObject } from 'graphql-type-json';
2
+ import { GraphQLDate, GraphQLTime, GraphQLDateTime } from 'graphql-iso-date';
3
+ import { GraphQLAnyObject } from './scalar';
4
+ import GraphQLURI from '@cdmbase/graphql-type-uri';
5
+
6
+ export const resolvers = {
7
+ AnyObject: GraphQLAnyObject,
8
+ Date: GraphQLDate,
9
+ Time: GraphQLTime,
10
+ URI: GraphQLURI('URI'),
11
+ URIInput: GraphQLURI('URIInput'),
12
+ DateTime: GraphQLDateTime,
13
+ JSON: GraphQLJSON,
14
+ JSONObject: GraphQLJSONObject,
15
+ };
@@ -0,0 +1,96 @@
1
+ scalar AnyObject
2
+ scalar Date
3
+ scalar Time
4
+ scalar DateTime
5
+ scalar URI
6
+ scalar URIInput
7
+ scalar Observable
8
+
9
+ scalar JSON
10
+ scalar JSONObject
11
+
12
+ directive @cacheControl(maxAge: Int, scope: CacheControlScope) on FIELD_DEFINITION | OBJECT | INTERFACE
13
+ enum CacheControlScope {
14
+ PUBLIC
15
+ PRIVATE
16
+ }
17
+
18
+ """
19
+ An object with an ID.
20
+ """
21
+ interface Node {
22
+ """
23
+ The ID of the node.
24
+ """
25
+ id: ID!
26
+ }
27
+
28
+ # Pagination information. See https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo.
29
+ type PageInfo {
30
+ # Whether there is a next page of nodes in the connection.
31
+ hasNextPage: Boolean!
32
+ }
33
+
34
+ """
35
+ Represents a null return value.
36
+ """
37
+ type EmptyResponse {
38
+ # A dummy null value.
39
+ alwaysNil: String
40
+ }
41
+
42
+ type FieldError {
43
+ field: String!
44
+ message: String!
45
+ }
46
+
47
+ input Sort{
48
+ key: String!,
49
+ value: SortEnum!,
50
+ }
51
+
52
+ enum SortEnum{
53
+ ASC,
54
+ DESC
55
+ }
56
+
57
+ type Query {
58
+ """
59
+ Looks up a node by ID.
60
+ """
61
+ node(id: ID!): Node
62
+ }
63
+
64
+ type Mutation {
65
+ dummy: Int
66
+ }
67
+
68
+ type Subscription {
69
+ dummy: Int
70
+ }
71
+
72
+ type AdminIdeSettings {
73
+ dummy: Int
74
+ }
75
+
76
+ """ All Moleculer Topic names are extended from this."""
77
+ enum MoleculerServiceName {
78
+ dummy
79
+ }
80
+
81
+ interface IResourceUtilizationSettings {
82
+ subTopic: String
83
+ adminApiNamespace: String
84
+ }
85
+
86
+
87
+ type GeoLocation {
88
+ coordinates: [Float]
89
+ }
90
+
91
+ schema {
92
+ query: Query
93
+ mutation: Mutation
94
+ subscription: Subscription
95
+ }
96
+
@@ -0,0 +1,16 @@
1
+ // add any scalar types
2
+ import { GraphQLError, GraphQLScalarType, Kind } from 'graphql';
3
+
4
+ // https://stackoverflow.com/questions/41557536/custom-map-keys-in-graphql-response
5
+ export const GraphQLAnyObject = new GraphQLScalarType({
6
+ name: 'AnyObject',
7
+ description: 'Any JSON object. This type bypasses type checking.',
8
+ serialize: (value) => value,
9
+ parseValue: (value) => value,
10
+ parseLiteral: (ast) => {
11
+ if (ast.kind !== Kind.OBJECT) {
12
+ throw new GraphQLError(`Query error: Can only parse object but got a: ${ast.kind}`, [ast]);
13
+ }
14
+ return ast.fields;
15
+ },
16
+ });
@@ -0,0 +1,189 @@
1
+ /* eslint-disable class-methods-use-this */
2
+ /* eslint-disable no-useless-constructor */
3
+ /* eslint-disable import/no-extraneous-dependencies */
4
+ import * as fs from 'fs';
5
+ import { GraphQLSchema, OperationDefinitionNode } from 'graphql';
6
+ import { stitchSchemas } from '@graphql-tools/stitch';
7
+ import { makeExecutableSchema } from '@graphql-tools/schema';
8
+ import { linkToExecutor } from '@graphql-tools/links';
9
+ import { introspectSchema, wrapSchema } from '@graphql-tools/wrap';
10
+ // import { transformSchema } from '@graphql-tools/delegate';
11
+ import * as ws from 'ws';
12
+ import { getMainDefinition } from '@apollo/client/utilities';
13
+ import { WebSocketLink } from '@apollo/client/link/ws';
14
+ import { split } from '@apollo/client/index.js';
15
+ import { IGraphqlShieldRules, logger } from '@common-stack/server-core';
16
+ import { HttpLink } from '@apollo/client/link/http';
17
+ import * as fetch from 'isomorphic-fetch';
18
+ import { CdmLogger } from '@cdm-logger/core';
19
+ import { shield } from 'graphql-shield';
20
+ import { applyMiddleware } from 'graphql-middleware';
21
+ import { remoteSchemaDetails } from './remote-config';
22
+ import rootSchemaDef from './root-schema.graphqls';
23
+ import { resolvers as rootResolver } from './resolver';
24
+ import { attachDirectiveResolvers } from './utils';
25
+
26
+ interface IGraphqlOptions {
27
+ schema: string | string[];
28
+ resolvers: any;
29
+ directives: any[];
30
+ directiveResolvers: { [key: string]: any };
31
+ middlewares: any[];
32
+ rules?: IGraphqlShieldRules;
33
+ logger: CdmLogger.ILogger;
34
+ }
35
+ export class GatewaySchemaBuilder {
36
+ constructor(private options: IGraphqlOptions) {}
37
+
38
+ public async build(): Promise<GraphQLSchema> {
39
+ let gatewaySchema;
40
+ let ownSchema;
41
+ try {
42
+ ownSchema = this.createOwnSchema();
43
+ const remoteSchema = await this.load();
44
+ // techSchema = this.patchSchema(techSchema, 'TechService');
45
+
46
+ gatewaySchema = stitchSchemas({
47
+ subschemas: [ownSchema],
48
+ });
49
+
50
+ // Apply middleware to the schema
51
+ if (this.options.middlewares && this.options.middlewares.length > 0) {
52
+ gatewaySchema = applyMiddleware(
53
+ gatewaySchema,
54
+ ...this.options.middlewares,
55
+ shield(this.options.rules || {}, {
56
+ allowExternalErrors: true,
57
+ }),
58
+ );
59
+ }
60
+ // TODO after updating graphql-tools to v8
61
+ // addErrorLoggingToSchema(schema, { log: (e) => logger.error(e as Error) });
62
+ } catch (err) {
63
+ logger.error('[Graphql Schema Errors] when building schema:', err.message);
64
+ gatewaySchema = ownSchema;
65
+ }
66
+
67
+ return gatewaySchema;
68
+ }
69
+
70
+ private async load() {
71
+ const schemas = [];
72
+ // eslint-disable-next-line no-plusplus
73
+ for (let i = 0; i < remoteSchemaDetails.length; i++) {
74
+ // eslint-disable-next-line no-await-in-loop
75
+ const schema = await this.loadRemoteSchema(remoteSchemaDetails[i]);
76
+ schemas.push(schema);
77
+ }
78
+ return schemas;
79
+ }
80
+
81
+ private async createRemoteSchema(service: string, iteration?: number): Promise<GraphQLSchema> {
82
+ logger.info('Fetch service [%s] iteration [%s]', service, iteration);
83
+ const services = remoteSchemaDetails;
84
+ if (!services.length) {
85
+ console.warn(`Service ${services} is undefined`);
86
+ if (iteration && iteration > 2) {
87
+ return Promise.reject(`tried upto ${iteration} attempts, now failing...`);
88
+ }
89
+ return new Promise<GraphQLSchema>((resolve, reject) => {
90
+ const timeout = iteration ? 1000 * iteration : 1000;
91
+ logger.info('Wait for service startup %s', timeout);
92
+ setTimeout(() => {
93
+ this.createRemoteSchema(service, iteration ? iteration + 1 : 1)
94
+ .then(resolve)
95
+ .catch(reject);
96
+ }, timeout);
97
+ });
98
+ }
99
+ // instead need to loop it
100
+ // https://github.com/j-colter/graphql-gateway/blob/9c64d90a74727d2002d10b06f47e1f4a316070fc/src/schema.js#L50
101
+ const url = services[0].uri;
102
+ logger.info('fetch service [%s]', url);
103
+ // 1. Create apollo Link that's connected to the underlying GraphQL API
104
+ const link = new HttpLink({ uri: url, fetch });
105
+ const executor: any = linkToExecutor(link);
106
+ // 2. Retrieve schema definition of the underlying GraphQL API
107
+ const remoteSchema = await introspectSchema(link as any);
108
+
109
+ // 3. Create the executable schema based on schema definition and Apollo Link
110
+ return wrapSchema({
111
+ schema: remoteSchema,
112
+ executor,
113
+ });
114
+ }
115
+
116
+ private async loadRemoteSchema({ uri, wsUri }) {
117
+ try {
118
+ const httpLink = new HttpLink({ uri, fetch });
119
+ let link = null;
120
+
121
+ if (wsUri) {
122
+ const wsLink = new WebSocketLink({
123
+ uri: wsUri,
124
+ options: {
125
+ reconnect: true,
126
+ },
127
+ webSocketImpl: ws,
128
+ });
129
+ link = split(
130
+ // split based on operatino type
131
+ ({ query }) => {
132
+ const { kind, operation } = getMainDefinition(query) as OperationDefinitionNode;
133
+ return kind === 'OperationDefinition' && operation === 'subscription';
134
+ },
135
+ wsLink,
136
+ httpLink,
137
+ );
138
+ } else {
139
+ link = httpLink;
140
+ }
141
+ const executor: any = linkToExecutor(link);
142
+ const remoteSchema = await introspectSchema(link);
143
+ const executableSchema = wrapSchema({
144
+ schema: remoteSchema,
145
+ executor,
146
+ });
147
+ return executableSchema;
148
+ } catch (err) {
149
+ this.options.logger.error('fetching schema error: ', err);
150
+ return {};
151
+ }
152
+ }
153
+
154
+ // disabled after updating to apollo-client to v3 and graphql-tools to v8
155
+ // private patchSchema(schema: GraphQLSchema, systemName: string) {
156
+ // return transformSchema(schema, [
157
+ // new RenameTypes((name: string) => (name === 'StatusInfo' ? `${systemName}StatusInfo` : undefined)),
158
+ // new RenameRootFields((_operation: string, name: string) =>
159
+ // name === 'status'
160
+ // ? `${systemName.substring(0, 1).toLowerCase()}${systemName.substring(1)}Status`
161
+ // : name,
162
+ // ),
163
+ // ]);
164
+ // }
165
+
166
+ private createOwnSchema(): GraphQLSchema {
167
+ const typeDefs = [rootSchemaDef, this.options.schema].join('\n');
168
+ if (__DEV__) {
169
+ import('../modules/module').then(({ ExternalModules }) => {
170
+ const externalSchema = ExternalModules?.schemas || ``;
171
+ const writeData = `${externalSchema}`;
172
+ fs.writeFileSync('./generated-schema.graphql', writeData);
173
+ });
174
+ }
175
+ let mergedSchema = makeExecutableSchema({
176
+ resolvers: [rootResolver, this.options.resolvers],
177
+ typeDefs,
178
+ resolverValidationOptions: {
179
+ requireResolversForResolveType: 'warn',
180
+ },
181
+ });
182
+ // mergedSchema = this.options.directives.reduce((curSchema,transform) => transform(curSchema), mergedSchema);
183
+ if (this.options.directiveResolvers && Object.keys(this.options.directiveResolvers).length !== 0) {
184
+ this.options.logger.warn('directiveResolvers deprecated replaced with directives');
185
+ mergedSchema = attachDirectiveResolvers(mergedSchema, this.options.directiveResolvers);
186
+ }
187
+ return mergedSchema;
188
+ }
189
+ }
@@ -0,0 +1,44 @@
1
+ import { defaultFieldResolver, GraphQLSchema } from 'graphql';
2
+ import { mapSchema, MapperKind, getDirectives } from '@graphql-tools/utils';
3
+
4
+ export function attachDirectiveResolvers(
5
+ schema: GraphQLSchema,
6
+ directiveResolvers: {[key: string]: Function},
7
+ ): GraphQLSchema {
8
+ // ... argument validation ...
9
+
10
+ return mapSchema(schema, {
11
+ [MapperKind.OBJECT_FIELD]: (fieldConfig) => {
12
+ const newFieldConfig = { ...fieldConfig };
13
+
14
+ const directives = getDirectives(schema, fieldConfig);
15
+ for (const directive of directives) {
16
+ const directiveName = directive.name;
17
+ if (directiveResolvers[directiveName]) {
18
+ const resolver = directiveResolvers[directiveName];
19
+ const originalResolver =
20
+ newFieldConfig.resolve != null ? newFieldConfig.resolve : defaultFieldResolver;
21
+ const directiveArgs = directive.args;
22
+ newFieldConfig.resolve = (source, originalArgs, context, info) => {
23
+ return resolver(
24
+ () =>
25
+ new Promise((resolve, reject) => {
26
+ const result = originalResolver(source, originalArgs, context, info);
27
+ if (result instanceof Error) {
28
+ reject(result);
29
+ }
30
+ resolve(result);
31
+ }),
32
+ source,
33
+ directiveArgs,
34
+ context,
35
+ info,
36
+ );
37
+ };
38
+ }
39
+ }
40
+
41
+ return newFieldConfig;
42
+ },
43
+ });
44
+ }
@@ -0,0 +1,34 @@
1
+ /// <reference path='../../../../typings/index.d.ts' />
2
+ import { str, bool, num, json, cleanEnv } from 'envalid';
3
+
4
+ export const config = cleanEnv(process.env, {
5
+ NODE_ENV: str({ default: 'production', choices: ['production', 'staging', 'development', 'test'] }),
6
+ NATS_URL: str({ devDefault: 'nats://localhost:4222/' }),
7
+ NATS_USER: str({ devDefault: 'test' }),
8
+ NATS_PW: str({ devDefault: 'test' }),
9
+ MONGO_URL: str({ devDefault: 'mongodb://localhost:27017/sample-stack' }),
10
+ MONGO_OPTIONS: str({ default: '{}' }),
11
+ LOG_LEVEL: str({ default: 'info', devDefault: 'trace', choices: ['info', 'debug', 'trace'] }),
12
+ REDIS_CLUSTER_URL: json({
13
+ devDefault: '[{"port":6379,"host":"localhost"}]',
14
+ example: '[{"port":6379,"host":"localhost"}]',
15
+ }),
16
+ REDIS_URL: str({ devDefault: 'localhost' }),
17
+ REDIS_CLUSTER_ENABLED: bool({ devDefault: false }),
18
+ REDIS_SENTINEL_ENABLED: bool({ devDefault: true }),
19
+ HEMERA_LOG_LEVEL: str({
20
+ default: 'info',
21
+ devDefault: 'info',
22
+ choices: ['fatal', 'error', 'warn', 'info', 'debug', 'trace'],
23
+ }),
24
+ BACKEND_URL: str({ devDefault: __BACKEND_URL__ }),
25
+ GRAPHQL_URL: str({ devDefault: __GRAPHQL_URL__ }),
26
+ CLIENT_URL: str({ devDefault: __BACKEND_URL__ }),
27
+ CONNECTION_ID: str({ devDefault: 'CONNECTION_ID' }),
28
+ MAILGUN_KEY: str(),
29
+ MAILGUN_DOMAIN: str(),
30
+ NAMESPACE: str({ default: 'default' }),
31
+ ACTIVITY_NAMESPACE: str({ devDefault: 'default' }),
32
+ API_NAMESPACE: str({ devDefault: 'default' }),
33
+ ADMIN_API_NAMESPACE: str({ devDefault: 'default' }),
34
+ });
@@ -0,0 +1 @@
1
+ export * from './env-config';