graphql-ext
v1.5.6
Published
GraphQL extensions and toolkit for JS.
Downloads
74
Maintainers
Readme
graphql-ext-js
GraphQL extensions and toolkit for JS.
Install
npm i graphql-ext
Examples
See examples.
express
const express = require('express');
const {specifiedRules: rules} = require('graphql');
const {graphql} = require('graphql-ext/http');
const {schema, rootValue} = require('./schema');
function main() {
const app = express();
app.use(express.json());
app.post(
'/graphql',
graphql({
schema,
rootValue,
rules,
parseParams: async (req) => req.body,
context: (req) => req.headers['x-user'],
}),
);
app.listen(4000, () =>
console.info('Running a GraphQL API at http://localhost:4000/graphql'),
);
}
main();
validation
directive @length(
min: Int
max: Int
message: String
) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
type Query {
hello(name: String! @length(min: 2, max: 10)): String!
}
const {specifiedRules} = require('graphql');
const {inputValidationDirectiveRule} = require('graphql-ext/validation');
const {length} = require('graphql-ext/validation/rules');
app.post(
'/graphql',
graphql({
// ...
rules: [
...specifiedRules,
inputValidationDirectiveRule({
entries: [['length', length]],
}),
],
}),
);
relay
directive @range(
min: Int
max: Int
message: String
) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
type Query {
numbers(
first: Int @range(min: 1, max: 15)
after: String
last: Int @range(min: 1, max: 15)
before: String
): NumberConnection!
}
type NumberConnection {
edges: [NumberEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type NumberEdge {
cursor: String!
node: Int!
}
type PageInfo {
endCursor: String!
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String!
}
const {CursorConnection} = require('graphql-ext/relay');
const {addResolvers} = require('graphql-ext/misc');
// ...
const items = Array.from({length: 20}).map((_, i) => i);
const cc = new CursorConnection('numbers:');
const resolvers = {
Query: {
numbers: (parent, args) => cc.fromArray(items, args),
},
};
addResolvers(schema, resolvers);
offset paging:
const service = {
countNumbers: async () => items.length,
listNumbers: async ({offset, limit}) => items.slice(offset, offset + limit),
};
const resolvers = {
Query: {
numbers: async (parent, args) => {
const totalCount = await service.countNumbers();
const [offset, limit] = cc.toOffsetPaging(args, totalCount);
const items = await service.listNumbers({offset, limit});
return cc.fromSlice(items, offset, totalCount);
},
},
};
subscription
Subscription returns ndjson stream.
type Subscription {
countdown(initial: Int! = 2): Int
}
const resolvers = {
Subscription: {
countdown: {
async *subscribe(_, {initial}) {
for (let i = initial; i >= 0; i--) {
await new Promise((resolve) => setTimeout(resolve, 500));
yield i;
}
},
resolve(value) {
return value;
},
},
},
};