@ttoss/graphql-api-server 0.5.1 → 0.5.2
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/README.md +60 -2
- package/dist/esm/index.js +14 -16
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -16
- package/package.json +1 -5
- package/src/index.ts +34 -28
- package/src/typings.d.ts +0 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ This package provides a Koa server to run your [`@ttoss/graphql-api` API](https:
|
|
|
8
8
|
pnpm add @ttoss/graphql-api-server @ttoss/graphql-api graphql
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Getting Started
|
|
12
12
|
|
|
13
13
|
You can use the `createServer` method to create your server.
|
|
14
14
|
|
|
@@ -60,7 +60,7 @@ server.listen(3000, () => {
|
|
|
60
60
|
});
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
## Middlewares
|
|
64
64
|
|
|
65
65
|
You can add middlewares compatible with [`graphql-middleware`](https://github.com/dimatill/graphql-middleware) to the server using the `middlewares` option.
|
|
66
66
|
|
|
@@ -97,3 +97,61 @@ const server = createServer({
|
|
|
97
97
|
middlewares: [permissions],
|
|
98
98
|
});
|
|
99
99
|
```
|
|
100
|
+
|
|
101
|
+
## Handling Other Routes
|
|
102
|
+
|
|
103
|
+
If you want to handle other routes than `/graphql`, you can use the `Router` class from `koa` and add it to the server.
|
|
104
|
+
|
|
105
|
+
### Serving a SPA
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { createServer } from '@ttoss/graphql-api-server';
|
|
109
|
+
import { schemaComposer } from './schemaComposer';
|
|
110
|
+
import mount from 'koa-mount';
|
|
111
|
+
import * as path from 'path';
|
|
112
|
+
|
|
113
|
+
const server = createServer({
|
|
114
|
+
schemaComposer,
|
|
115
|
+
graphiql: true,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const APP_DIR = path.resolve(__dirname, '../../app/dist');
|
|
119
|
+
|
|
120
|
+
server.use(mount('/', serve(APP_DIR)));
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Serve a SPA—redirect all requests to index.html
|
|
124
|
+
* https://dejanvasic.wordpress.com/2020/08/22/serving-react-spa-in-koa/
|
|
125
|
+
*/
|
|
126
|
+
server.use(async (ctx, next) => {
|
|
127
|
+
return await serve(APP_DIR)(Object.assign(ctx, { path: 'index.html' }), next);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
server.listen(3000, () => {
|
|
131
|
+
console.log('Server listening on port 3000');
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Serving Another Endpoint
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { Router, createServer } from '@ttoss/graphql-api-server';
|
|
139
|
+
import { schemaComposer } from './schemaComposer';
|
|
140
|
+
|
|
141
|
+
const server = createServer({
|
|
142
|
+
schemaComposer,
|
|
143
|
+
graphiql: true,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const router = new Router();
|
|
147
|
+
|
|
148
|
+
router.get('/health', (ctx: any) => {
|
|
149
|
+
ctx.body = 'OK';
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
server.use(router.routes()).use(router.allowedMethods());
|
|
153
|
+
|
|
154
|
+
server.listen(3000, () => {
|
|
155
|
+
console.log('Server listening on port 3000');
|
|
156
|
+
});
|
|
157
|
+
```
|
package/dist/esm/index.js
CHANGED
|
@@ -9,9 +9,16 @@ import Router from "@koa/router";
|
|
|
9
9
|
var createServer = ({
|
|
10
10
|
authenticationType,
|
|
11
11
|
userPoolConfig,
|
|
12
|
+
graphiql,
|
|
12
13
|
...buildSchemaInput
|
|
13
14
|
}) => {
|
|
14
15
|
const app = new Koa();
|
|
16
|
+
const yoga = createYoga({
|
|
17
|
+
schema: buildSchema(buildSchemaInput),
|
|
18
|
+
graphiql,
|
|
19
|
+
landingPage: false,
|
|
20
|
+
logging: false
|
|
21
|
+
});
|
|
15
22
|
const jwtVerifier = (() => {
|
|
16
23
|
if (authenticationType === "AMAZON_COGNITO_USER_POOLS") {
|
|
17
24
|
if (!userPoolConfig) {
|
|
@@ -24,17 +31,15 @@ var createServer = ({
|
|
|
24
31
|
}
|
|
25
32
|
return null;
|
|
26
33
|
})();
|
|
27
|
-
app.use(async ctx => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
if (request.method !== "GET" && request.headers.referer !== "http://localhost:4000/graphql") {
|
|
34
|
+
app.use(async (ctx, next) => {
|
|
35
|
+
if (ctx.path !== "/graphql") {
|
|
36
|
+
return next();
|
|
37
|
+
}
|
|
38
|
+
const isGraphiqlRequest = ctx.headers.accept?.includes("text/html") && graphiql;
|
|
39
|
+
if (!isGraphiqlRequest) {
|
|
35
40
|
try {
|
|
36
41
|
if (authenticationType === "AMAZON_COGNITO_USER_POOLS" && jwtVerifier) {
|
|
37
|
-
const token =
|
|
42
|
+
const token = ctx.headers.authorization?.replace("Bearer ", "");
|
|
38
43
|
const identity = await jwtVerifier.verify(token || "");
|
|
39
44
|
ctx.identity = identity;
|
|
40
45
|
}
|
|
@@ -44,13 +49,6 @@ var createServer = ({
|
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
|
-
const operationName = request.body;
|
|
48
|
-
const query = request.headers;
|
|
49
|
-
const variables = request.method;
|
|
50
|
-
const yoga = createYoga({
|
|
51
|
-
schema: buildSchema(buildSchemaInput),
|
|
52
|
-
logging: false
|
|
53
|
-
});
|
|
54
52
|
const response = await yoga.handleNodeRequest(ctx.req, ctx);
|
|
55
53
|
ctx.status = response.status;
|
|
56
54
|
for (const [key, value] of response.headers.entries()) {
|
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,6 @@ type CreateServerInput = {
|
|
|
12
12
|
clientId: string;
|
|
13
13
|
};
|
|
14
14
|
} & BuildSchemaInput;
|
|
15
|
-
declare const createServer: ({ authenticationType, userPoolConfig, ...buildSchemaInput }: CreateServerInput) => Koa;
|
|
15
|
+
declare const createServer: ({ authenticationType, userPoolConfig, graphiql, ...buildSchemaInput }: CreateServerInput) => Koa;
|
|
16
16
|
|
|
17
17
|
export { type AuthenticationType, type CreateServerInput, createServer };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ type CreateServerInput = {
|
|
|
12
12
|
clientId: string;
|
|
13
13
|
};
|
|
14
14
|
} & BuildSchemaInput;
|
|
15
|
-
declare const createServer: ({ authenticationType, userPoolConfig, ...buildSchemaInput }: CreateServerInput) => Koa;
|
|
15
|
+
declare const createServer: ({ authenticationType, userPoolConfig, graphiql, ...buildSchemaInput }: CreateServerInput) => Koa;
|
|
16
16
|
|
|
17
17
|
export { type AuthenticationType, type CreateServerInput, createServer };
|
package/dist/index.js
CHANGED
|
@@ -50,9 +50,16 @@ var import_router = __toESM(require("@koa/router"));
|
|
|
50
50
|
var createServer = ({
|
|
51
51
|
authenticationType,
|
|
52
52
|
userPoolConfig,
|
|
53
|
+
graphiql,
|
|
53
54
|
...buildSchemaInput
|
|
54
55
|
}) => {
|
|
55
56
|
const app = new import_koa.default();
|
|
57
|
+
const yoga = (0, import_graphql_yoga.createYoga)({
|
|
58
|
+
schema: (0, import_graphql_api.buildSchema)(buildSchemaInput),
|
|
59
|
+
graphiql,
|
|
60
|
+
landingPage: false,
|
|
61
|
+
logging: false
|
|
62
|
+
});
|
|
56
63
|
const jwtVerifier = (() => {
|
|
57
64
|
if (authenticationType === "AMAZON_COGNITO_USER_POOLS") {
|
|
58
65
|
if (!userPoolConfig) {
|
|
@@ -65,17 +72,15 @@ var createServer = ({
|
|
|
65
72
|
}
|
|
66
73
|
return null;
|
|
67
74
|
})();
|
|
68
|
-
app.use(async ctx => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
75
|
-
if (request.method !== "GET" && request.headers.referer !== "http://localhost:4000/graphql") {
|
|
75
|
+
app.use(async (ctx, next) => {
|
|
76
|
+
if (ctx.path !== "/graphql") {
|
|
77
|
+
return next();
|
|
78
|
+
}
|
|
79
|
+
const isGraphiqlRequest = ctx.headers.accept?.includes("text/html") && graphiql;
|
|
80
|
+
if (!isGraphiqlRequest) {
|
|
76
81
|
try {
|
|
77
82
|
if (authenticationType === "AMAZON_COGNITO_USER_POOLS" && jwtVerifier) {
|
|
78
|
-
const token =
|
|
83
|
+
const token = ctx.headers.authorization?.replace("Bearer ", "");
|
|
79
84
|
const identity = await jwtVerifier.verify(token || "");
|
|
80
85
|
ctx.identity = identity;
|
|
81
86
|
}
|
|
@@ -85,13 +90,6 @@ var createServer = ({
|
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
|
-
const operationName = request.body;
|
|
89
|
-
const query = request.headers;
|
|
90
|
-
const variables = request.method;
|
|
91
|
-
const yoga = (0, import_graphql_yoga.createYoga)({
|
|
92
|
-
schema: (0, import_graphql_api.buildSchema)(buildSchemaInput),
|
|
93
|
-
logging: false
|
|
94
|
-
});
|
|
95
93
|
const response = await yoga.handleNodeRequest(ctx.req, ctx);
|
|
96
94
|
ctx.status = response.status;
|
|
97
95
|
for (const [key, value] of response.headers.entries()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/graphql-api-server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "GraphQL API Server",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -20,11 +20,9 @@
|
|
|
20
20
|
"sideEffects": false,
|
|
21
21
|
"typings": "dist/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@koa/cors": "^5.0.0",
|
|
24
23
|
"@koa/router": "^12.0.1",
|
|
25
24
|
"graphql-yoga": "^5.1.1",
|
|
26
25
|
"koa": "^2.15.0",
|
|
27
|
-
"koa-bodyparser": "^4.4.1",
|
|
28
26
|
"@ttoss/auth-core": "^0.0.2"
|
|
29
27
|
},
|
|
30
28
|
"peerDependencies": {
|
|
@@ -33,9 +31,7 @@
|
|
|
33
31
|
},
|
|
34
32
|
"devDependencies": {
|
|
35
33
|
"@types/koa": "^2.14.0",
|
|
36
|
-
"@types/koa__cors": "^5.0.0",
|
|
37
34
|
"@types/koa__router": "^12.0.4",
|
|
38
|
-
"@types/koa-bodyparser": "^4.3.12",
|
|
39
35
|
"@types/supertest": "^6.0.2",
|
|
40
36
|
"graphql": "^16.8.1",
|
|
41
37
|
"jest": "^29.7.0",
|
package/src/index.ts
CHANGED
|
@@ -21,10 +21,21 @@ export type CreateServerInput = {
|
|
|
21
21
|
export const createServer = ({
|
|
22
22
|
authenticationType,
|
|
23
23
|
userPoolConfig,
|
|
24
|
+
graphiql,
|
|
24
25
|
...buildSchemaInput
|
|
25
26
|
}: CreateServerInput): Koa => {
|
|
26
27
|
const app = new Koa();
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* https://the-guild.dev/graphql/yoga-server/docs/integrations/integration-with-koa
|
|
31
|
+
*/
|
|
32
|
+
const yoga = createYoga<Koa.ParameterizedContext>({
|
|
33
|
+
schema: buildSchema(buildSchemaInput),
|
|
34
|
+
graphiql,
|
|
35
|
+
landingPage: false,
|
|
36
|
+
logging: false,
|
|
37
|
+
});
|
|
38
|
+
|
|
28
39
|
const jwtVerifier = (() => {
|
|
29
40
|
if (authenticationType === 'AMAZON_COGNITO_USER_POOLS') {
|
|
30
41
|
if (!userPoolConfig) {
|
|
@@ -41,23 +52,27 @@ export const createServer = ({
|
|
|
41
52
|
return null;
|
|
42
53
|
})();
|
|
43
54
|
|
|
44
|
-
app.use(async (ctx) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
app.use(async (ctx, next) => {
|
|
56
|
+
/**
|
|
57
|
+
* Check if the request is for the GraphQL endpoint.
|
|
58
|
+
* If not, pass it to the next middleware.
|
|
59
|
+
*/
|
|
60
|
+
if (ctx.path !== '/graphql') {
|
|
61
|
+
return next();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const isGraphiqlRequest =
|
|
65
|
+
ctx.headers.accept?.includes('text/html') && graphiql;
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
/**
|
|
68
|
+
* If the request is not a GraphiQL request, verify the JWT token, else
|
|
69
|
+
* set Unauthorized status code and return.
|
|
70
|
+
*/
|
|
71
|
+
if (!isGraphiqlRequest) {
|
|
56
72
|
try {
|
|
57
73
|
if (authenticationType === 'AMAZON_COGNITO_USER_POOLS' && jwtVerifier) {
|
|
58
|
-
const token =
|
|
74
|
+
const token = ctx.headers.authorization?.replace('Bearer ', '');
|
|
59
75
|
const identity = await jwtVerifier.verify(token || '');
|
|
60
|
-
|
|
61
76
|
ctx.identity = identity;
|
|
62
77
|
}
|
|
63
78
|
} catch {
|
|
@@ -67,25 +82,16 @@ export const createServer = ({
|
|
|
67
82
|
}
|
|
68
83
|
}
|
|
69
84
|
|
|
70
|
-
//console.log(ctx.identity);
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
72
|
-
const operationName = request.body;
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
74
|
-
const query = request.headers;
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
76
|
-
const variables = request.method;
|
|
77
|
-
|
|
78
|
-
const yoga = createYoga<Koa.ParameterizedContext>({
|
|
79
|
-
schema: buildSchema(buildSchemaInput),
|
|
80
|
-
logging: false,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
85
|
const response = await yoga.handleNodeRequest(ctx.req, ctx);
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Set status code
|
|
89
|
+
*/
|
|
86
90
|
ctx.status = response.status;
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Set headers
|
|
94
|
+
*/
|
|
89
95
|
for (const [key, value] of response.headers.entries()) {
|
|
90
96
|
if (ctx.status != 401) {
|
|
91
97
|
ctx.append(key, value);
|
package/src/typings.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
declare module 'graphql-helix';
|