@teambit/graphql 0.0.555 → 0.0.556
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/package.json +16 -10
- package/create-link.ts +0 -20
- package/create-remote-schemas/create-remote-schemas.ts +0 -58
- package/create-remote-schemas/index.ts +0 -1
- package/graphql-error.ts +0 -13
- package/graphql-provider/graphql-provider.tsx +0 -12
- package/graphql-provider/index.ts +0 -1
- package/graphql-server.ts +0 -5
- package/graphql.aspect.ts +0 -9
- package/graphql.main.runtime.ts +0 -282
- package/graphql.preview.runtime.tsx +0 -7
- package/graphql.ui.runtime.tsx +0 -103
- package/index.ts +0 -8
- package/logging.ts +0 -26
- package/package-tar/teambit-graphql-0.0.555.tgz +0 -0
- package/render-lifecycle.tsx +0 -91
- package/schema.ts +0 -9
- package/tsconfig.json +0 -34
- package/types/asset.d.ts +0 -29
- package/types/style.d.ts +0 -42
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teambit/graphql",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.556",
|
|
4
4
|
"homepage": "https://bit.dev/teambit/harmony/graphql",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "teambit.harmony",
|
|
8
8
|
"name": "graphql",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.556"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@teambit/harmony": "0.2.11",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"bufferutil": "4.0.3",
|
|
33
33
|
"@babel/runtime": "7.12.18",
|
|
34
34
|
"core-js": "^3.0.0",
|
|
35
|
-
"@teambit/cli": "0.0.
|
|
36
|
-
"@teambit/logger": "0.0.
|
|
37
|
-
"@teambit/toolbox.network.get-port": "0.0.
|
|
38
|
-
"@teambit/preview": "0.0.
|
|
39
|
-
"@teambit/ui": "0.0.
|
|
40
|
-
"@teambit/ui-foundation.ui.is-browser": "0.0.
|
|
35
|
+
"@teambit/cli": "0.0.387",
|
|
36
|
+
"@teambit/logger": "0.0.472",
|
|
37
|
+
"@teambit/toolbox.network.get-port": "0.0.91",
|
|
38
|
+
"@teambit/preview": "0.0.556",
|
|
39
|
+
"@teambit/ui": "0.0.556",
|
|
40
|
+
"@teambit/ui-foundation.ui.is-browser": "0.0.464"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/cors": "2.8.10",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@apollo/client": "^3.0.0",
|
|
56
56
|
"graphql": "14.7.0",
|
|
57
|
-
"@teambit/legacy": "1.0.
|
|
57
|
+
"@teambit/legacy": "1.0.173",
|
|
58
58
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
59
59
|
"react": "^16.8.0 || ^17.0.0"
|
|
60
60
|
},
|
|
@@ -84,12 +84,18 @@
|
|
|
84
84
|
"react": "-"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
|
-
"@teambit/legacy": "1.0.
|
|
87
|
+
"@teambit/legacy": "1.0.173",
|
|
88
88
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
89
89
|
"react": "^16.8.0 || ^17.0.0"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
|
+
"files": [
|
|
94
|
+
"dist",
|
|
95
|
+
"!dist/tsconfig.tsbuildinfo",
|
|
96
|
+
"README.md",
|
|
97
|
+
"README.mdx"
|
|
98
|
+
],
|
|
93
99
|
"private": false,
|
|
94
100
|
"engines": {
|
|
95
101
|
"node": ">=12.22.0"
|
package/create-link.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { HttpLink, split } from '@apollo/client';
|
|
2
|
-
import { getMainDefinition } from '@apollo/client/utilities';
|
|
3
|
-
import type { WebSocketLink } from '@apollo/client/link/ws';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* create a link which splits routes data depending on type of operation.
|
|
7
|
-
* @param httpLink http link for apollo graphql
|
|
8
|
-
* @param wsLink web socket link for apollo graphql
|
|
9
|
-
*/
|
|
10
|
-
export function createSplitLink(httpLink: HttpLink, wsLink: WebSocketLink) {
|
|
11
|
-
return split(
|
|
12
|
-
// split based on operation type
|
|
13
|
-
({ query }) => {
|
|
14
|
-
const definition = getMainDefinition(query);
|
|
15
|
-
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
|
|
16
|
-
},
|
|
17
|
-
wsLink,
|
|
18
|
-
httpLink
|
|
19
|
-
);
|
|
20
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import fetch from 'node-fetch';
|
|
2
|
-
import { setContext } from 'apollo-link-context';
|
|
3
|
-
import { HttpLink } from 'apollo-link-http';
|
|
4
|
-
import { makeRemoteExecutableSchema, introspectSchema } from 'apollo-server';
|
|
5
|
-
import { WebSocketLink } from 'apollo-link-ws';
|
|
6
|
-
import { split } from 'apollo-link';
|
|
7
|
-
import { getMainDefinition } from 'apollo-utilities';
|
|
8
|
-
import { SubscriptionClient } from 'subscriptions-transport-ws';
|
|
9
|
-
import ws from 'ws';
|
|
10
|
-
import { GraphQLServer } from '../graphql-server';
|
|
11
|
-
|
|
12
|
-
async function getRemoteSchema({ uri, subscriptionsUri }) {
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
const http = new HttpLink({ uri, fetch });
|
|
15
|
-
const httpLink = setContext((request, previousContext) => {
|
|
16
|
-
return {
|
|
17
|
-
headers: previousContext?.graphqlContext?.headers,
|
|
18
|
-
};
|
|
19
|
-
}).concat(http);
|
|
20
|
-
|
|
21
|
-
if (!subscriptionsUri) {
|
|
22
|
-
return makeRemoteExecutableSchema({
|
|
23
|
-
schema: await introspectSchema(httpLink),
|
|
24
|
-
link: httpLink,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Create WebSocket link with custom client
|
|
29
|
-
const client = new SubscriptionClient(subscriptionsUri, { reconnect: true }, ws);
|
|
30
|
-
const wsLink = new WebSocketLink(client);
|
|
31
|
-
|
|
32
|
-
// Using the ability to split links, we can send data to each link
|
|
33
|
-
// depending on what kind of operation is being sent
|
|
34
|
-
const link = split(
|
|
35
|
-
(operation) => {
|
|
36
|
-
const definition = getMainDefinition(operation.query);
|
|
37
|
-
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
|
|
38
|
-
},
|
|
39
|
-
wsLink,
|
|
40
|
-
httpLink
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
return makeRemoteExecutableSchema({
|
|
44
|
-
schema: await introspectSchema(httpLink),
|
|
45
|
-
link,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function createRemoteSchemas(servers: GraphQLServer[]) {
|
|
50
|
-
const schemasP = servers.map(async (server) => {
|
|
51
|
-
return getRemoteSchema({
|
|
52
|
-
uri: server.uri,
|
|
53
|
-
subscriptionsUri: server.subscriptionsUri,
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return Promise.all(schemasP);
|
|
58
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { createRemoteSchemas } from './create-remote-schemas';
|
package/graphql-error.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
import { ApolloProvider } from '@apollo/client';
|
|
3
|
-
import type { GraphQLClient } from '../graphql.ui.runtime';
|
|
4
|
-
|
|
5
|
-
export type GraphQLProviderProps = {
|
|
6
|
-
client: GraphQLClient<any>;
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export function GraphQLProvider({ client, children }: GraphQLProviderProps) {
|
|
11
|
-
return <ApolloProvider client={client}>{children}</ApolloProvider>;
|
|
12
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { GraphQLProvider } from './graphql-provider';
|
package/graphql-server.ts
DELETED
package/graphql.aspect.ts
DELETED
package/graphql.main.runtime.ts
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { mergeSchemas } from 'graphql-tools';
|
|
2
|
-
import { GraphQLModule } from '@graphql-modules/core';
|
|
3
|
-
import { MainRuntime } from '@teambit/cli';
|
|
4
|
-
import { Harmony, Slot, SlotRegistry } from '@teambit/harmony';
|
|
5
|
-
import { Logger, LoggerAspect, LoggerMain } from '@teambit/logger';
|
|
6
|
-
import express, { Express } from 'express';
|
|
7
|
-
import { graphqlHTTP } from 'express-graphql';
|
|
8
|
-
import { Port } from '@teambit/toolbox.network.get-port';
|
|
9
|
-
import { execute, subscribe } from 'graphql';
|
|
10
|
-
import { PubSub } from 'graphql-subscriptions';
|
|
11
|
-
import { createServer, Server } from 'http';
|
|
12
|
-
import httpProxy from 'http-proxy';
|
|
13
|
-
import { SubscriptionServer } from 'subscriptions-transport-ws';
|
|
14
|
-
import cors from 'cors';
|
|
15
|
-
import { GraphQLServer } from './graphql-server';
|
|
16
|
-
import { createRemoteSchemas } from './create-remote-schemas';
|
|
17
|
-
import { GraphqlAspect } from './graphql.aspect';
|
|
18
|
-
import { Schema } from './schema';
|
|
19
|
-
|
|
20
|
-
export enum Verb {
|
|
21
|
-
WRITE = 'write',
|
|
22
|
-
READ = 'read',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type GraphQLConfig = {
|
|
26
|
-
port: number;
|
|
27
|
-
subscriptionsPortRange: number[];
|
|
28
|
-
subscriptionsPath: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type GraphQLServerSlot = SlotRegistry<GraphQLServer>;
|
|
32
|
-
|
|
33
|
-
export type SchemaSlot = SlotRegistry<Schema>;
|
|
34
|
-
|
|
35
|
-
export type GraphQLServerOptions = {
|
|
36
|
-
schemaSlot?: SchemaSlot;
|
|
37
|
-
app?: Express;
|
|
38
|
-
graphiql?: boolean;
|
|
39
|
-
remoteSchemas?: GraphQLServer[];
|
|
40
|
-
subscriptionsPortRange?: number[];
|
|
41
|
-
onWsConnect?: Function;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export class GraphqlMain {
|
|
45
|
-
constructor(
|
|
46
|
-
/**
|
|
47
|
-
* extension config
|
|
48
|
-
*/
|
|
49
|
-
readonly config: GraphQLConfig,
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* slot for registering graphql modules
|
|
53
|
-
*/
|
|
54
|
-
private moduleSlot: SchemaSlot,
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* harmony context.
|
|
58
|
-
*/
|
|
59
|
-
private context: Harmony,
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* graphql pubsub. allows to emit events to clients.
|
|
63
|
-
*/
|
|
64
|
-
readonly pubsub: PubSub,
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* logger extension.
|
|
68
|
-
*/
|
|
69
|
-
readonly logger: Logger,
|
|
70
|
-
|
|
71
|
-
private graphQLServerSlot: GraphQLServerSlot
|
|
72
|
-
) {}
|
|
73
|
-
|
|
74
|
-
private modules = new Map<string, GraphQLModule>();
|
|
75
|
-
|
|
76
|
-
async createServer(options: GraphQLServerOptions) {
|
|
77
|
-
const { graphiql = true } = options;
|
|
78
|
-
const localSchema = this.createRootModule(options.schemaSlot);
|
|
79
|
-
const remoteSchemas = await createRemoteSchemas(options.remoteSchemas || this.graphQLServerSlot.values());
|
|
80
|
-
const schemas = [localSchema.schema].concat(remoteSchemas).filter((x) => x);
|
|
81
|
-
const schema = mergeSchemas({
|
|
82
|
-
schemas,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// TODO: @guy please consider to refactor to express extension.
|
|
86
|
-
const app = options.app || express();
|
|
87
|
-
app.use(
|
|
88
|
-
// @ts-ignore todo: it's not clear what's the issue.
|
|
89
|
-
cors({
|
|
90
|
-
origin(origin, callback) {
|
|
91
|
-
callback(null, true);
|
|
92
|
-
},
|
|
93
|
-
credentials: true,
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
app.use(
|
|
98
|
-
'/graphql',
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
100
|
-
graphqlHTTP((request, res, params) => ({
|
|
101
|
-
customFormatErrorFn: (err) => {
|
|
102
|
-
this.logger.error('graphql got an error during running the following query:', params);
|
|
103
|
-
this.logger.error('graphql error ', err);
|
|
104
|
-
return Object.assign(err, {
|
|
105
|
-
// @ts-ignore
|
|
106
|
-
ERR_CODE: err?.originalError?.errors?.[0].ERR_CODE || err.originalError?.constructor?.name,
|
|
107
|
-
// @ts-ignore
|
|
108
|
-
HTTP_CODE: err?.originalError?.errors?.[0].HTTP_CODE || err.originalError?.code,
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
schema,
|
|
112
|
-
rootValue: request,
|
|
113
|
-
graphiql,
|
|
114
|
-
}))
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const server = createServer(app);
|
|
118
|
-
const subscriptionsPort = options.subscriptionsPortRange || this.config.subscriptionsPortRange;
|
|
119
|
-
const subscriptionServerPort = await this.getPort(subscriptionsPort);
|
|
120
|
-
const { port } = await this.createSubscription(options, subscriptionServerPort);
|
|
121
|
-
this.proxySubscription(server, port);
|
|
122
|
-
|
|
123
|
-
return server;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* register a new graphql server.
|
|
128
|
-
*/
|
|
129
|
-
registerServer(server: GraphQLServer) {
|
|
130
|
-
this.graphQLServerSlot.register(server);
|
|
131
|
-
return this;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* start a graphql server.
|
|
136
|
-
*/
|
|
137
|
-
async listen(port?: number, server?: Server, app?: Express) {
|
|
138
|
-
const serverPort = port || this.config.port;
|
|
139
|
-
const subServer = server || (await this.createServer({ app }));
|
|
140
|
-
|
|
141
|
-
subServer.listen(serverPort, () => {
|
|
142
|
-
this.logger.info(`API Server over HTTP is now running on http://localhost:${serverPort}`);
|
|
143
|
-
this.logger.info(
|
|
144
|
-
`API Server over web socket with subscriptions is now running on ws://localhost:${serverPort}/${this.config.subscriptionsPath}`
|
|
145
|
-
);
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* register a new graphql module.
|
|
151
|
-
*/
|
|
152
|
-
register(schema: Schema) {
|
|
153
|
-
// const module = new GraphQLModule(schema);
|
|
154
|
-
this.moduleSlot.register(schema);
|
|
155
|
-
return this;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
private async getPort(range: number[]) {
|
|
159
|
-
const [from, to] = range;
|
|
160
|
-
return Port.getPort(from, to);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** create Subscription server with different port */
|
|
164
|
-
|
|
165
|
-
private async createSubscription(options: GraphQLServerOptions, port: number) {
|
|
166
|
-
// Create WebSocket listener server
|
|
167
|
-
const websocketServer = createServer((request, response) => {
|
|
168
|
-
response.writeHead(404);
|
|
169
|
-
response.end();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Bind it to port and start listening
|
|
173
|
-
websocketServer.listen(port, () =>
|
|
174
|
-
this.logger.debug(`Websocket Server is now running on http://localhost:${port}`)
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
const localSchema = this.createRootModule(options.schemaSlot);
|
|
178
|
-
const remoteSchemas = await createRemoteSchemas(options.remoteSchemas || this.graphQLServerSlot.values());
|
|
179
|
-
const schemas = [localSchema.schema].concat(remoteSchemas).filter((x) => x);
|
|
180
|
-
const schema = mergeSchemas({
|
|
181
|
-
schemas,
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
185
|
-
const subServer = new SubscriptionServer(
|
|
186
|
-
{
|
|
187
|
-
execute,
|
|
188
|
-
subscribe,
|
|
189
|
-
schema,
|
|
190
|
-
onConnect: options.onWsConnect,
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
server: websocketServer,
|
|
194
|
-
path: this.config.subscriptionsPath,
|
|
195
|
-
}
|
|
196
|
-
);
|
|
197
|
-
return { subServer, port };
|
|
198
|
-
}
|
|
199
|
-
/** proxy ws Subscription server to avoid conflict with different websocket connections */
|
|
200
|
-
|
|
201
|
-
private proxySubscription(server: Server, port: number) {
|
|
202
|
-
const proxServer = httpProxy.createProxyServer();
|
|
203
|
-
const subscriptionsPath = this.config.subscriptionsPath;
|
|
204
|
-
const logger = this.logger;
|
|
205
|
-
server.on('upgrade', function (req, socket, head) {
|
|
206
|
-
if (req.url === subscriptionsPath) {
|
|
207
|
-
logger.debug(`proxy from ${req.url} to ${port}`);
|
|
208
|
-
proxServer.ws(req, socket, head, { target: { host: 'localhost', port } });
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
private createRootModule(schemaSlot?: SchemaSlot) {
|
|
214
|
-
const modules = this.buildModules(schemaSlot);
|
|
215
|
-
|
|
216
|
-
return new GraphQLModule({
|
|
217
|
-
imports: modules,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private buildModules(schemaSlot?: SchemaSlot) {
|
|
222
|
-
const schemaSlots = schemaSlot ? schemaSlot.toArray() : this.moduleSlot.toArray();
|
|
223
|
-
return schemaSlots.map(([extensionId, schema]) => {
|
|
224
|
-
const moduleDeps = this.getModuleDependencies(extensionId);
|
|
225
|
-
|
|
226
|
-
const module = new GraphQLModule({
|
|
227
|
-
typeDefs: schema.typeDefs,
|
|
228
|
-
resolvers: schema.resolvers,
|
|
229
|
-
imports: moduleDeps,
|
|
230
|
-
context: (session) => {
|
|
231
|
-
return {
|
|
232
|
-
...session,
|
|
233
|
-
verb: session?.headers?.['x-verb'] || Verb.READ,
|
|
234
|
-
};
|
|
235
|
-
},
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
this.modules.set(extensionId, module);
|
|
239
|
-
|
|
240
|
-
return module;
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
private getModuleDependencies(extensionId: string): GraphQLModule[] {
|
|
245
|
-
const extension = this.context.extensions.get(extensionId);
|
|
246
|
-
if (!extension) throw new Error(`aspect ${extensionId} was not found`);
|
|
247
|
-
const deps = this.context.getDependencies(extension);
|
|
248
|
-
const ids = deps.map((dep) => dep.id);
|
|
249
|
-
|
|
250
|
-
// @ts-ignore check :TODO why types are breaking here.
|
|
251
|
-
return Array.from(this.modules.entries())
|
|
252
|
-
.map(([depId, module]) => {
|
|
253
|
-
const dep = ids.includes(depId);
|
|
254
|
-
if (!dep) return undefined;
|
|
255
|
-
return module;
|
|
256
|
-
})
|
|
257
|
-
.filter((module) => !!module);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
static slots = [Slot.withType<Schema>(), Slot.withType<GraphQLServer>()];
|
|
261
|
-
|
|
262
|
-
static defaultConfig = {
|
|
263
|
-
port: 4000,
|
|
264
|
-
subscriptionsPortRange: [2000, 2100],
|
|
265
|
-
subscriptionsPath: '/subscriptions',
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
static runtime = MainRuntime;
|
|
269
|
-
static dependencies = [LoggerAspect];
|
|
270
|
-
|
|
271
|
-
static async provider(
|
|
272
|
-
[loggerFactory]: [LoggerMain],
|
|
273
|
-
config: GraphQLConfig,
|
|
274
|
-
[moduleSlot, graphQLServerSlot]: [SchemaSlot, GraphQLServerSlot],
|
|
275
|
-
context: Harmony
|
|
276
|
-
) {
|
|
277
|
-
const logger = loggerFactory.createLogger(GraphqlAspect.id);
|
|
278
|
-
return new GraphqlMain(config, moduleSlot, context, new PubSub(), logger, graphQLServerSlot);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
GraphqlAspect.addRuntime(GraphqlMain);
|
package/graphql.ui.runtime.tsx
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
import { UIRuntime } from '@teambit/ui';
|
|
3
|
-
|
|
4
|
-
import { InMemoryCache, ApolloClient, ApolloLink, HttpLink, createHttpLink } from '@apollo/client';
|
|
5
|
-
import type { NormalizedCacheObject } from '@apollo/client';
|
|
6
|
-
import { WebSocketLink } from '@apollo/client/link/ws';
|
|
7
|
-
import { onError } from '@apollo/client/link/error';
|
|
8
|
-
|
|
9
|
-
import crossFetch from 'cross-fetch';
|
|
10
|
-
|
|
11
|
-
import { createSplitLink } from './create-link';
|
|
12
|
-
import { GraphQLProvider } from './graphql-provider';
|
|
13
|
-
import { GraphqlAspect } from './graphql.aspect';
|
|
14
|
-
import { GraphqlRenderLifecycle } from './render-lifecycle';
|
|
15
|
-
import { logError } from './logging';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Type of gql client.
|
|
19
|
-
* Used to abstract Apollo client, so consumers could import the type from graphql.ui, and not have to depend on @apollo/client directly
|
|
20
|
-
* */
|
|
21
|
-
export type GraphQLClient<T> = ApolloClient<T>;
|
|
22
|
-
|
|
23
|
-
type ClientOptions = {
|
|
24
|
-
/** Preset in-memory cache with state (e.g. continue state from SSR) */
|
|
25
|
-
state?: NormalizedCacheObject;
|
|
26
|
-
/** endpoint for websocket connections */
|
|
27
|
-
subscriptionUri?: string;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export class GraphqlUI {
|
|
31
|
-
createClient(uri: string, { state, subscriptionUri }: ClientOptions = {}) {
|
|
32
|
-
const client = new ApolloClient({
|
|
33
|
-
link: this.createLink(uri, { subscriptionUri }),
|
|
34
|
-
cache: this.createCache({ state }),
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
return client;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
createSsrClient({ serverUrl, headers }: { serverUrl: string; headers: any }) {
|
|
41
|
-
const link = ApolloLink.from([
|
|
42
|
-
onError(logError),
|
|
43
|
-
createHttpLink({
|
|
44
|
-
credentials: 'include',
|
|
45
|
-
uri: serverUrl,
|
|
46
|
-
headers,
|
|
47
|
-
fetch: crossFetch,
|
|
48
|
-
}),
|
|
49
|
-
]);
|
|
50
|
-
|
|
51
|
-
const client = new ApolloClient({
|
|
52
|
-
ssrMode: true,
|
|
53
|
-
link,
|
|
54
|
-
cache: this.createCache(),
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return client;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private createCache({ state }: { state?: NormalizedCacheObject } = {}) {
|
|
61
|
-
const cache = new InMemoryCache();
|
|
62
|
-
|
|
63
|
-
if (state) cache.restore(state);
|
|
64
|
-
|
|
65
|
-
return cache;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private createLink(uri: string, { subscriptionUri }: { subscriptionUri?: string } = {}) {
|
|
69
|
-
const httpLink = new HttpLink({ credentials: 'include', uri });
|
|
70
|
-
const subsLink = subscriptionUri
|
|
71
|
-
? new WebSocketLink({
|
|
72
|
-
uri: subscriptionUri,
|
|
73
|
-
options: { reconnect: true },
|
|
74
|
-
})
|
|
75
|
-
: undefined;
|
|
76
|
-
|
|
77
|
-
const hybridLink = subsLink ? createSplitLink(httpLink, subsLink) : httpLink;
|
|
78
|
-
const errorLogger = onError(logError);
|
|
79
|
-
|
|
80
|
-
return ApolloLink.from([errorLogger, hybridLink]);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* get the graphQL provider
|
|
85
|
-
*/
|
|
86
|
-
getProvider = ({ client, children }: { client: GraphQLClient<any>; children: ReactNode }) => {
|
|
87
|
-
return <GraphQLProvider client={client}>{children}</GraphQLProvider>;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
renderHooks = new GraphqlRenderLifecycle(this);
|
|
91
|
-
|
|
92
|
-
static runtime = UIRuntime;
|
|
93
|
-
static dependencies = [];
|
|
94
|
-
static slots = [];
|
|
95
|
-
|
|
96
|
-
static async provider() {
|
|
97
|
-
const graphqlUI = new GraphqlUI();
|
|
98
|
-
|
|
99
|
-
return graphqlUI;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
GraphqlAspect.addRuntime(GraphqlUI);
|
package/index.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { GraphqlAspect, GraphqlAspect as default } from './graphql.aspect';
|
|
2
|
-
|
|
3
|
-
export type { Schema } from './schema';
|
|
4
|
-
export type { GraphqlMain, SchemaSlot } from './graphql.main.runtime';
|
|
5
|
-
export type { GraphqlUI, GraphQLClient } from './graphql.ui.runtime';
|
|
6
|
-
export type { GraphQLServer } from './graphql-server';
|
|
7
|
-
export { GraphQLProvider } from './graphql-provider';
|
|
8
|
-
export { GraphQlError } from './graphql-error';
|
package/logging.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ErrorResponse } from '@apollo/client/link/error';
|
|
2
|
-
|
|
3
|
-
export function logError({ graphQLErrors, networkError, operation }: ErrorResponse) {
|
|
4
|
-
if (graphQLErrors)
|
|
5
|
-
graphQLErrors.forEach(({ message, locations, path }) =>
|
|
6
|
-
// eslint-disable-next-line no-console
|
|
7
|
-
console.error(`[gql] error on "${operation.operationName}" - "${message}"`, locations, path)
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line no-console
|
|
11
|
-
if (networkError) console.error('[gql] network error', `"${operation.operationName}"`, networkError);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// // // a fetch monkey patch with logs. useful to debug gql
|
|
15
|
-
// function loggingCrossFetch(...p: Parameters<typeof fetch>) {
|
|
16
|
-
// const [url, init] = p;
|
|
17
|
-
// const headers = init?.headers;
|
|
18
|
-
// const body = init?.body;
|
|
19
|
-
|
|
20
|
-
// console.debug('[gql]', 'fetching', url, body, { headers });
|
|
21
|
-
// const promise = crossFetch(...p);
|
|
22
|
-
// promise
|
|
23
|
-
// .then((result) => console.debug('[gql]', 'finished', result))
|
|
24
|
-
// .catch((err) => console.debug('[gql]', 'error', err));
|
|
25
|
-
// return promise;
|
|
26
|
-
// }
|
|
Binary file
|
package/render-lifecycle.tsx
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
import { getDataFromTree } from '@apollo/client/react/ssr';
|
|
3
|
-
import type { NormalizedCacheObject } from '@apollo/client';
|
|
4
|
-
import pick from 'lodash.pick';
|
|
5
|
-
|
|
6
|
-
import { isBrowser } from '@teambit/ui-foundation.ui.is-browser';
|
|
7
|
-
import type { BrowserData, RenderLifecycle } from '@teambit/ui';
|
|
8
|
-
|
|
9
|
-
import type { GraphqlUI, GraphQLClient } from './graphql.ui.runtime';
|
|
10
|
-
import { GraphQLProvider } from './graphql-provider';
|
|
11
|
-
|
|
12
|
-
type RenderContext = {
|
|
13
|
-
client: GraphQLClient<any>;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const ALLOWED_HEADERS = ['cookie'];
|
|
17
|
-
|
|
18
|
-
export class GraphqlRenderLifecycle implements RenderLifecycle<RenderContext, { state?: NormalizedCacheObject }> {
|
|
19
|
-
constructor(private graphqlUI: GraphqlUI) {}
|
|
20
|
-
|
|
21
|
-
serverInit = ({ browser, server }: { browser?: BrowserData; server?: { port: number } } = {}) => {
|
|
22
|
-
if (!browser) return undefined;
|
|
23
|
-
|
|
24
|
-
const port = server?.port || 3000;
|
|
25
|
-
const serverUrl = `http://localhost:${port}/graphql`;
|
|
26
|
-
|
|
27
|
-
const client = this.graphqlUI.createSsrClient({
|
|
28
|
-
serverUrl,
|
|
29
|
-
headers: pick(browser.connection.headers, ALLOWED_HEADERS),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const ctx: RenderContext = { client };
|
|
33
|
-
return ctx;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Eagerly and recursively execute all gql queries in the app.
|
|
38
|
-
* Data will be available in gqlClient.extract()
|
|
39
|
-
*/
|
|
40
|
-
onBeforeRender = async (ctx: RenderContext, app: ReactNode) => {
|
|
41
|
-
await getDataFromTree(app);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
serialize = (ctx?: RenderContext) => {
|
|
45
|
-
const client = ctx?.client;
|
|
46
|
-
if (!client) return undefined;
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
json: JSON.stringify(client.extract()),
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
deserialize = (raw?: string) => {
|
|
54
|
-
if (!raw) return { state: undefined };
|
|
55
|
-
let state: NormalizedCacheObject | undefined;
|
|
56
|
-
try {
|
|
57
|
-
state = JSON.parse(raw);
|
|
58
|
-
} catch (e) {
|
|
59
|
-
// eslint-disable-next-line no-console
|
|
60
|
-
console.error('[GraphQL] failed deserializing state from DOM', e);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return { state };
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
browserInit = ({ state }: { state?: NormalizedCacheObject } = {}) => {
|
|
67
|
-
const { location } = window;
|
|
68
|
-
const isInsecure = location.protocol === 'http:';
|
|
69
|
-
const wsUrl = `${isInsecure ? 'ws:' : 'wss:'}//${location.host}/subscriptions`;
|
|
70
|
-
|
|
71
|
-
const client = this.graphqlUI.createClient('/graphql', { state, subscriptionUri: wsUrl });
|
|
72
|
-
|
|
73
|
-
return { client };
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
private BrowserGqlProvider = ({ renderCtx, children }: { renderCtx?: RenderContext; children: ReactNode }) => {
|
|
77
|
-
if (!renderCtx?.client) throw new TypeError('GQL client is not initialized, make sure `.browserInit()` executes');
|
|
78
|
-
|
|
79
|
-
return <this.graphqlUI.getProvider client={renderCtx?.client}>{children}</this.graphqlUI.getProvider>;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
reactContext = isBrowser ? this.BrowserGqlProvider : ServerGqlProvider;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function ServerGqlProvider({ renderCtx, children }: { renderCtx?: RenderContext; children: ReactNode }) {
|
|
86
|
-
if (!renderCtx?.client)
|
|
87
|
-
throw new TypeError('GQL client has not been initialized during SSR, make sure `.serverInit()` executes');
|
|
88
|
-
|
|
89
|
-
const { client } = renderCtx;
|
|
90
|
-
return <GraphQLProvider client={client}>{children}</GraphQLProvider>;
|
|
91
|
-
}
|
package/schema.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"lib": [
|
|
4
|
-
"es2019",
|
|
5
|
-
"DOM",
|
|
6
|
-
"ES6",
|
|
7
|
-
"DOM.Iterable",
|
|
8
|
-
"ScriptHost"
|
|
9
|
-
],
|
|
10
|
-
"target": "es2015",
|
|
11
|
-
"module": "commonjs",
|
|
12
|
-
"jsx": "react",
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"sourceMap": true,
|
|
15
|
-
"skipLibCheck": true,
|
|
16
|
-
"moduleResolution": "node",
|
|
17
|
-
"esModuleInterop": true,
|
|
18
|
-
"outDir": "dist",
|
|
19
|
-
"composite": true,
|
|
20
|
-
"emitDeclarationOnly": true,
|
|
21
|
-
"experimentalDecorators": true,
|
|
22
|
-
"emitDecoratorMetadata": true,
|
|
23
|
-
"allowSyntheticDefaultImports": true,
|
|
24
|
-
"strictPropertyInitialization": false,
|
|
25
|
-
"strict": true,
|
|
26
|
-
"noImplicitAny": false,
|
|
27
|
-
"rootDir": ".",
|
|
28
|
-
"preserveConstEnums": true,
|
|
29
|
-
"resolveJsonModule": true
|
|
30
|
-
},
|
|
31
|
-
"exclude": [
|
|
32
|
-
"dist"
|
|
33
|
-
]
|
|
34
|
-
}
|
package/types/asset.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
declare module '*.png' {
|
|
2
|
-
const value: any;
|
|
3
|
-
export = value;
|
|
4
|
-
}
|
|
5
|
-
declare module '*.svg' {
|
|
6
|
-
import type { FunctionComponent, SVGProps } from 'react';
|
|
7
|
-
|
|
8
|
-
export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
|
|
9
|
-
const src: string;
|
|
10
|
-
export default src;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// @TODO Gilad
|
|
14
|
-
declare module '*.jpg' {
|
|
15
|
-
const value: any;
|
|
16
|
-
export = value;
|
|
17
|
-
}
|
|
18
|
-
declare module '*.jpeg' {
|
|
19
|
-
const value: any;
|
|
20
|
-
export = value;
|
|
21
|
-
}
|
|
22
|
-
declare module '*.gif' {
|
|
23
|
-
const value: any;
|
|
24
|
-
export = value;
|
|
25
|
-
}
|
|
26
|
-
declare module '*.bmp' {
|
|
27
|
-
const value: any;
|
|
28
|
-
export = value;
|
|
29
|
-
}
|
package/types/style.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
declare module '*.module.css' {
|
|
2
|
-
const classes: { readonly [key: string]: string };
|
|
3
|
-
export default classes;
|
|
4
|
-
}
|
|
5
|
-
declare module '*.module.scss' {
|
|
6
|
-
const classes: { readonly [key: string]: string };
|
|
7
|
-
export default classes;
|
|
8
|
-
}
|
|
9
|
-
declare module '*.module.sass' {
|
|
10
|
-
const classes: { readonly [key: string]: string };
|
|
11
|
-
export default classes;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
declare module '*.module.less' {
|
|
15
|
-
const classes: { readonly [key: string]: string };
|
|
16
|
-
export default classes;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
declare module '*.less' {
|
|
20
|
-
const classes: { readonly [key: string]: string };
|
|
21
|
-
export default classes;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
declare module '*.css' {
|
|
25
|
-
const classes: { readonly [key: string]: string };
|
|
26
|
-
export default classes;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
declare module '*.sass' {
|
|
30
|
-
const classes: { readonly [key: string]: string };
|
|
31
|
-
export default classes;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
declare module '*.scss' {
|
|
35
|
-
const classes: { readonly [key: string]: string };
|
|
36
|
-
export default classes;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
declare module '*.mdx' {
|
|
40
|
-
const component: any;
|
|
41
|
-
export default component;
|
|
42
|
-
}
|