https://github.com/akornatskyy/graphql-ext-js
GraphQL extensions and toolkit for JS.
https://github.com/akornatskyy/graphql-ext-js
api expressjs graphql http middleware validation
Last synced: 10 months ago
JSON representation
GraphQL extensions and toolkit for JS.
- Host: GitHub
- URL: https://github.com/akornatskyy/graphql-ext-js
- Owner: akornatskyy
- License: mit
- Created: 2022-10-03T09:29:04.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-08-04T12:03:38.000Z (11 months ago)
- Last Synced: 2025-08-30T13:49:22.875Z (10 months ago)
- Topics: api, expressjs, graphql, http, middleware, validation
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/graphql-ext
- Size: 1.33 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# graphql-ext-js
[](https://github.com/akornatskyy/graphql-ext-js/actions/workflows/tests.yml)
[](https://www.npmjs.com/package/graphql-ext)
GraphQL extensions and toolkit for JS.
## Install
```sh
npm i graphql-ext
```
## Examples
See [examples](./examples).
### express
```js
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
```graphql
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!
}
```
```js
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
```graphql
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!
}
```
```js
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:
```js
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](https://github.com/ndjson/ndjson-spec) stream.
```graphql
type Subscription {
countdown(initial: Int! = 2): Int
}
```
```js
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;
},
},
},
};
```