UNPKG

5.42 kBMarkdownView Raw
1# @accounts/graphql-api
2
3_Schema, Resolvers and Utils for GraphQL server with JSAccounts_
4
5[![npm](https://img.shields.io/npm/v/@accounts/graphql-api.svg?maxAge=2592000)](https://www.npmjs.com/package/@accounts/graphql-api)
6![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)
7
8> This package does not requires any network interface / express in order to combine with your GraphQL - it's just a collection of GraphQL schema, resolvers and utils!
9
10## How to use this package?
11
12This package exports GraphQL schema and GraphQL resolvers, which you can extend with your existing GraphQL schema server.
13
14Start by installing it from NPM / Yarn:
15
16```bash
17// Npm
18npm install --save @accounts/server @accounts/graphql-api @graphql-modules/core
19
20// Yarn
21yarn add @accounts/server @accounts/graphql-api @graphql-modules/core
22```
23
24> This package does not create a transport or anything else, only schema and string and resolvers as object.
25
26Start by configuring your `AccountsServer` as you wish. For example, using MongoDB:
27
28```js
29import mongoose from 'mongoose'
30import AccountsServer from '@accounts/server'
31import AccountsPassword from '@accounts/password'
32import MongoDBInterface from '@accounts/mongo'
33
34const db = mongoose.connection
35
36const password = new AccountsPassword()
37
38const accountsServer = new AccountsServer({
39 {
40 db: new MongoDBInterface(db),
41 tokenSecret: 'SECRET',
42 },
43 {
44 password,
45 }
46});
47```
48
49Next, import `AccountsModule` from this package, and run it with your `AccountsServer`:
50
51```js
52import { AccountsModule } from '@accounts/graphql-api';
53
54const accountsGraphQL = AccountsModule.forRoot({
55 accountsServer,
56});
57```
58
59Now, add `accountsGraphQL.typeDefs` to your schema definition (just before using it with `makeExecutableSchema`), and merge your resolvers object with `accountsGraphQL.resolvers` by using `@graphql-tools/epoxy`, for example:
60
61```js
62import { makeExecutableSchema } from 'graphql-tools';
63import { mergeGraphQLSchemas, mergeResolvers } from '@graphql-tools/epoxy';
64
65const typeDefs = [
66 `
67 type Query {
68 myQuery: String
69 }
70
71 type Mutation {
72 myMutation: String
73 }
74
75 schema {
76 query: Query,
77 mutation: Mutation
78 }
79 `,
80 accountsGraphQL.typeDefs,
81];
82
83let myResolvers = {
84 Query: {
85 myQuery: () => 'Hello',
86 },
87 Mutation: {
88 myMutation: () => 'Hello',
89 },
90};
91
92const schema = makeExecutableSchema({
93 resolvers: mergeResolvers([accountsGraphQL.resolvers, myResolvers]),
94 typeDefs: mergeGraphQLSchemas([typeDefs]),
95});
96```
97
98The last step is to extend your `graphqlExpress` with a context middleware, that extracts the authentication token from the HTTP request, so AccountsServer will automatically validate it:
99
100```js
101app.use(
102 GRAPHQL_ROUTE,
103 bodyParser.json(),
104 graphqlExpress((request) => {
105 return {
106 context: {
107 ...accountsGraphQL(request),
108 // your context
109 },
110 schema,
111 };
112 })
113);
114```
115
116## Authenticating Resolvers
117
118You can authenticate your own resolvers with `JSAccounts` authentication flow, by using `authenticated` method from this package.
119
120This method composer also extends `context` with the current authenticated user!
121
122This is an example for a protected mutation:
123
124```js
125import AccountsServer from '@accounts/server';
126import { authenticated } from '@accounts/graphql-api';
127
128export const resolver = {
129 Mutation: {
130 updateUserProfile: authenticated(AccountsServer, (rootValue, args, context) => {
131 // Write your resolver here
132 // context.user - the current authenticated user!
133 }),
134 },
135};
136```
137
138## Customization
139
140This package allow you to customize the GraphQL schema and it's resolvers.
141
142For example, some application main query called `MyQuery` or `RootQuery` instead of query, so you can customize the name, without modifying you application's schema.
143
144These are the available customizations:
145
146- `rootQueryName` (string) - The name of the root query, default: `Query`.
147- `rootMutationName` (string) - The name of the root mutation, default: `Mutation`.
148- `extend` (boolean) - whether to add `extend` before the root type declaration, default: `true`.
149- `withSchemaDefinition` (boolean): whether to add `schema { ... }` declaration to the generation schema, default: `false`.
150
151Pass a second object to `createAccountsGraphQL`, for example:
152
153Another possible customization is to modify the name of the authentication header, use it with `accountsContext` (the default is `Authorization`):
154
155```js
156const myCustomGraphQLAccounts = AccountsModule.forRoot({
157 accountsServer,
158 rootQueryName: 'RootQuery',
159 rootMutationName: 'RootMutation',
160 headerName: 'MyCustomHeader',
161});
162```
163
164## Extending `User`
165
166To extend `User` object with custom fields and logic, add your own GraphQL type definition of `User` with the prefix of `extend`, and add your fields:
167
168```graphql
169extend type User {
170 firstName: String
171 lastName: String
172}
173```
174
175And also implement a regular resolver, for the fields you added:
176
177```js
178const UserResolver = {
179 firstName: () => 'Dotan',
180 lastName: () => 'Simha',
181};
182```
183
184## Extending `User` during password creation
185
186To extend the user object during the user creation you need to extend the `CreateUserInput` type and add your fields:
187
188```graphql
189extend input CreateUserInput {
190 profile: CreateUserProfileInput!
191}
192
193input CreateUserProfileInput {
194 firstName: String!
195 lastName: String!
196}
197```
198
199The user will be saved in the db with the profile key set.