@ttoss/graphql-api 0.2.0 → 0.3.1
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 +56 -0
- package/dist/esm/index.js +22 -1
- package/dist/esm/shield.js +4 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +23 -0
- package/dist/shield.d.ts +2 -0
- package/dist/shield.js +29 -0
- package/package.json +24 -2
- package/src/buildSchema.ts +45 -0
- package/src/index.ts +1 -0
- package/src/shield.ts +14 -0
package/README.md
CHANGED
|
@@ -163,6 +163,52 @@ composeWithConnection(AuthorTC, {
|
|
|
163
163
|
});
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
### Middlewares
|
|
167
|
+
|
|
168
|
+
This package provides a way to add middlewares to your final schema. You can add middlewares compatible with [`graphql-middleware`](https://github.com/dimatill/graphql-middleware) by passing them to the `middlewares` option on `buildSchema` method. For example, you can use [GraphQL Shield](https://the-guild.dev/graphql/shield) to add authorization to your API:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { buildSchema } from '@ttoss/graphql-api';
|
|
172
|
+
import { allow, deny, shield } from '@ttoss/graphql-api/shield';
|
|
173
|
+
import { schemaComposer } from './schemaComposer';
|
|
174
|
+
|
|
175
|
+
const NotAuthorizedError = new Error('Not authorized!');
|
|
176
|
+
/**
|
|
177
|
+
* The error name is the same value `errorType` on GraphQL errors response.
|
|
178
|
+
*/
|
|
179
|
+
NotAuthorizedError.name = 'NotAuthorizedError';
|
|
180
|
+
|
|
181
|
+
const permissions = shield(
|
|
182
|
+
{
|
|
183
|
+
Query: {
|
|
184
|
+
'*': deny,
|
|
185
|
+
author: allow,
|
|
186
|
+
},
|
|
187
|
+
Author: {
|
|
188
|
+
id: allow,
|
|
189
|
+
name: allow,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
fallbackRule: deny,
|
|
194
|
+
fallbackError: NotAuthorizedError,
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const schema = buildSchema({
|
|
199
|
+
schemaComposer,
|
|
200
|
+
middlewares; [permissions],
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Shield
|
|
205
|
+
|
|
206
|
+
This package re-exports the all methods from [GraphQL Shield](https://the-guild.dev/graphql/shield).
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { allow, deny, shield } from '@ttoss/graphql-api/shield';
|
|
210
|
+
```
|
|
211
|
+
|
|
166
212
|
## Building Schema
|
|
167
213
|
|
|
168
214
|
As Relay needs an introspection query to work, this package provides a way to build the GraphQL schema by running `ttoss-graphl-api build-schema`.
|
|
@@ -171,6 +217,16 @@ As Relay needs an introspection query to work, this package provides a way to bu
|
|
|
171
217
|
ttoss-graphl-api build-schema
|
|
172
218
|
```
|
|
173
219
|
|
|
220
|
+
You can add the `schema` script to your `package.json`:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"scripts": {
|
|
225
|
+
"schema": "ttoss-graphl-api build-schema"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
174
230
|
## How to Create Tests
|
|
175
231
|
|
|
176
232
|
We recommend testing the whole GraphQL API using the `graphql` object and the schema composer to provide the schema. For example:
|
package/dist/esm/index.js
CHANGED
|
@@ -153,4 +153,25 @@ composeWithRelay(schemaComposer.Query);
|
|
|
153
153
|
// src/index.ts
|
|
154
154
|
import { default as default2 } from "graphql-compose-connection";
|
|
155
155
|
export * from "graphql-compose";
|
|
156
|
-
|
|
156
|
+
|
|
157
|
+
// src/buildSchema.ts
|
|
158
|
+
import { applyMiddleware } from "graphql-middleware";
|
|
159
|
+
var buildSchema = ({
|
|
160
|
+
schemaComposer: schemaComposer2,
|
|
161
|
+
middlewares
|
|
162
|
+
}) => {
|
|
163
|
+
if (!schemaComposer2) {
|
|
164
|
+
throw new Error("No schemaComposer provided");
|
|
165
|
+
}
|
|
166
|
+
const schema = schemaComposer2.buildSchema();
|
|
167
|
+
if (middlewares) {
|
|
168
|
+
return applyMiddleware(schema, ...middlewares.map(middleware => {
|
|
169
|
+
if (middleware.generate) {
|
|
170
|
+
return middleware.generate(schema);
|
|
171
|
+
}
|
|
172
|
+
return middleware;
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
return schema;
|
|
176
|
+
};
|
|
177
|
+
export { buildSchema, default2 as composeWithConnection, composeWithRelay, fromGlobalId, toGlobalId };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { ObjectTypeComposer } from 'graphql-compose';
|
|
1
|
+
import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose';
|
|
2
2
|
export * from 'graphql-compose';
|
|
3
3
|
export { default as composeWithConnection } from 'graphql-compose-connection';
|
|
4
|
+
import { GraphQLSchema } from 'graphql';
|
|
5
|
+
import { IMiddleware, IMiddlewareGenerator } from 'graphql-middleware';
|
|
4
6
|
|
|
5
7
|
declare const composeWithRelay: <TContext>(tc: ObjectTypeComposer<any, TContext>) => ObjectTypeComposer<any, TContext>;
|
|
6
8
|
|
|
@@ -19,4 +21,10 @@ declare const toGlobalId: (type: string, recordId: string | number) => string;
|
|
|
19
21
|
*/
|
|
20
22
|
declare const fromGlobalId: (globalId: string) => ResolvedGlobalId;
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
type BuildSchemaInput<TContext = any> = {
|
|
25
|
+
schemaComposer: SchemaComposer<TContext>;
|
|
26
|
+
middlewares?: (IMiddleware | IMiddlewareGenerator<any, TContext, any>)[];
|
|
27
|
+
};
|
|
28
|
+
declare const buildSchema: ({ schemaComposer, middlewares, }: BuildSchemaInput) => GraphQLSchema;
|
|
29
|
+
|
|
30
|
+
export { BuildSchemaInput, buildSchema, composeWithRelay, fromGlobalId, toGlobalId };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
39
39
|
// src/index.ts
|
|
40
40
|
var src_exports = {};
|
|
41
41
|
__export(src_exports, {
|
|
42
|
+
buildSchema: () => buildSchema,
|
|
42
43
|
composeWithConnection: () => import_graphql_compose_connection.default,
|
|
43
44
|
composeWithRelay: () => composeWithRelay,
|
|
44
45
|
fromGlobalId: () => fromGlobalId,
|
|
@@ -198,8 +199,30 @@ composeWithRelay(import_graphql_compose4.schemaComposer.Query);
|
|
|
198
199
|
// src/index.ts
|
|
199
200
|
var import_graphql_compose_connection = __toESM(require("graphql-compose-connection"));
|
|
200
201
|
__reExport(src_exports, require("graphql-compose"), module.exports);
|
|
202
|
+
|
|
203
|
+
// src/buildSchema.ts
|
|
204
|
+
var import_graphql_middleware = require("graphql-middleware");
|
|
205
|
+
var buildSchema = ({
|
|
206
|
+
schemaComposer: schemaComposer2,
|
|
207
|
+
middlewares
|
|
208
|
+
}) => {
|
|
209
|
+
if (!schemaComposer2) {
|
|
210
|
+
throw new Error("No schemaComposer provided");
|
|
211
|
+
}
|
|
212
|
+
const schema = schemaComposer2.buildSchema();
|
|
213
|
+
if (middlewares) {
|
|
214
|
+
return (0, import_graphql_middleware.applyMiddleware)(schema, ...middlewares.map(middleware => {
|
|
215
|
+
if (middleware.generate) {
|
|
216
|
+
return middleware.generate(schema);
|
|
217
|
+
}
|
|
218
|
+
return middleware;
|
|
219
|
+
}));
|
|
220
|
+
}
|
|
221
|
+
return schema;
|
|
222
|
+
};
|
|
201
223
|
// Annotate the CommonJS export names for ESM import in node:
|
|
202
224
|
0 && (module.exports = {
|
|
225
|
+
buildSchema,
|
|
203
226
|
composeWithConnection,
|
|
204
227
|
composeWithRelay,
|
|
205
228
|
fromGlobalId,
|
package/dist/shield.d.ts
ADDED
package/dist/shield.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
11
|
+
get: () => from[key],
|
|
12
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
|
+
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
19
|
+
value: true
|
|
20
|
+
}), mod);
|
|
21
|
+
|
|
22
|
+
// src/shield.ts
|
|
23
|
+
var shield_exports = {};
|
|
24
|
+
module.exports = __toCommonJS(shield_exports);
|
|
25
|
+
__reExport(shield_exports, require("graphql-shield"), module.exports);
|
|
26
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
27
|
+
0 && (module.exports = {
|
|
28
|
+
...require("graphql-shield")
|
|
29
|
+
});
|
package/package.json
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/graphql-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A library for building GraphQL APIs.",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"
|
|
8
8
|
],
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/esm/index.js",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./shield": {
|
|
15
|
+
"import": "./dist/esm/shield.js",
|
|
16
|
+
"require": "./dist/shield.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
9
19
|
"main": "dist/index.js",
|
|
10
20
|
"module": "dist/esm/index.js",
|
|
11
21
|
"bin": {
|
|
@@ -20,6 +30,8 @@
|
|
|
20
30
|
"dependencies": {
|
|
21
31
|
"graphql-compose": "^9.0.10",
|
|
22
32
|
"graphql-compose-connection": "^8.2.1",
|
|
33
|
+
"graphql-middleware": "^6.1.34",
|
|
34
|
+
"graphql-shield": "^7.6.5",
|
|
23
35
|
"npmlog": "^7.0.1",
|
|
24
36
|
"ts-node": "^10.9.1",
|
|
25
37
|
"yargs": "^17.7.2"
|
|
@@ -32,7 +44,7 @@
|
|
|
32
44
|
"graphql": "^16.6.0",
|
|
33
45
|
"jest": "^29.5.0",
|
|
34
46
|
"tsup": "^6.7.0",
|
|
35
|
-
"@ttoss/config": "^1.30.
|
|
47
|
+
"@ttoss/config": "^1.30.1"
|
|
36
48
|
},
|
|
37
49
|
"keywords": [
|
|
38
50
|
"api",
|
|
@@ -41,6 +53,16 @@
|
|
|
41
53
|
"publishConfig": {
|
|
42
54
|
"access": "public"
|
|
43
55
|
},
|
|
56
|
+
"typesVersions": {
|
|
57
|
+
"*": {
|
|
58
|
+
".": [
|
|
59
|
+
"./dist/index.d.ts"
|
|
60
|
+
],
|
|
61
|
+
"shield": [
|
|
62
|
+
"./dist/shield.d.ts"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
44
66
|
"scripts": {
|
|
45
67
|
"build": "tsup",
|
|
46
68
|
"test": "jest"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type GraphQLSchema } from 'graphql';
|
|
2
|
+
import {
|
|
3
|
+
type IMiddleware,
|
|
4
|
+
type IMiddlewareGenerator,
|
|
5
|
+
applyMiddleware,
|
|
6
|
+
} from 'graphql-middleware';
|
|
7
|
+
import { type SchemaComposer } from 'graphql-compose';
|
|
8
|
+
|
|
9
|
+
export type { IMiddleware, IMiddlewareGenerator };
|
|
10
|
+
|
|
11
|
+
export type BuildSchemaInput<TContext = any> = {
|
|
12
|
+
schemaComposer: SchemaComposer<TContext>;
|
|
13
|
+
middlewares?: (IMiddleware | IMiddlewareGenerator<any, TContext, any>)[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const buildSchema = ({
|
|
17
|
+
schemaComposer,
|
|
18
|
+
middlewares,
|
|
19
|
+
}: BuildSchemaInput): GraphQLSchema => {
|
|
20
|
+
if (!schemaComposer) {
|
|
21
|
+
throw new Error('No schemaComposer provided');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const schema = schemaComposer.buildSchema();
|
|
25
|
+
|
|
26
|
+
if (middlewares) {
|
|
27
|
+
return applyMiddleware(
|
|
28
|
+
schema,
|
|
29
|
+
...middlewares.map((middleware) => {
|
|
30
|
+
/**
|
|
31
|
+
* https://github.com/dimatill/graphql-middleware/issues/433#issuecomment-1170187160
|
|
32
|
+
*/
|
|
33
|
+
if ((middleware as IMiddlewareGenerator<any, any, any>).generate) {
|
|
34
|
+
return (middleware as IMiddlewareGenerator<any, any, any>).generate(
|
|
35
|
+
schema
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return middleware;
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return schema;
|
|
45
|
+
};
|
package/src/index.ts
CHANGED
package/src/shield.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from 'graphql-shield';
|
|
2
|
+
/**
|
|
3
|
+
* Export types from graphql-middleware to avoid "The inferred type of 'x'
|
|
4
|
+
* cannot be named without a reference to '.../graphql-middleware/index.d.ts(1,1)'.
|
|
5
|
+
* This is likely not portable. A type annotation is necessary."
|
|
6
|
+
*/
|
|
7
|
+
export type {
|
|
8
|
+
IMiddlewareGenerator,
|
|
9
|
+
IMiddleware,
|
|
10
|
+
IMiddlewareFieldMap,
|
|
11
|
+
IMiddlewareFunction,
|
|
12
|
+
IMiddlewareGeneratorConstructor,
|
|
13
|
+
IMiddlewareTypeMap,
|
|
14
|
+
} from 'graphql-middleware';
|