-
-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add basic graphql-http example
- Loading branch information
Showing
11 changed files
with
310 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# graphql-server-typescript | ||
|
||
This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts). | ||
|
||
## Setup example | ||
|
||
In order to be able to run this example on your machine you first need to do the following steps: | ||
|
||
- Clone the repository `git clone [email protected]:accounts-js/accounts.git` | ||
- Install project dependencies: `yarn install` | ||
- Compile the packages `yarn run compile` | ||
- Go to the example folder `cd examples/graphql-server-typescript` | ||
|
||
## Prerequisites | ||
|
||
You will need a MongoDB server to run this server. If you don't have a MongoDB server running already, and you have Docker & Docker Compose, you can do | ||
|
||
```bash | ||
docker-compose up -d | ||
``` | ||
|
||
to start a new one. | ||
|
||
## Getting Started | ||
|
||
Start the app. | ||
|
||
Visit http://localhost:4000/ | ||
|
||
```bash | ||
yarn run start | ||
``` | ||
|
||
-> [Start the client side](../react-graphql-typescript). | ||
|
||
```graphql | ||
mutation CreateUser { | ||
createUser( | ||
user: { email: "[email protected]", password: "1234567", firstName: "John", lastName: "Doe" } | ||
) | ||
} | ||
|
||
mutation Auth { | ||
authenticate( | ||
serviceName: "password" | ||
params: { password: "1234567", user: { email: "[email protected]" } } | ||
) { | ||
tokens { | ||
accessToken | ||
} | ||
} | ||
} | ||
|
||
query Test { | ||
privateField | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
version: '3.6' | ||
services: | ||
db-mongo-accounts: | ||
image: mongo:3.6.5-jessie | ||
ports: | ||
- '27017:27017' | ||
restart: always |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "@examples/graphql-server-typescript-basic", | ||
"private": true, | ||
"version": "0.32.0", | ||
"main": "lib/index.js", | ||
"license": "MIT", | ||
"scripts": { | ||
"start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", | ||
"build": "yarn run -T tsc", | ||
"test": "yarn run build" | ||
}, | ||
"dependencies": { | ||
"@accounts/module-core": "^0.34.0", | ||
"@accounts/module-mongo": "^0.34.0", | ||
"@accounts/module-password": "^0.34.0", | ||
"@accounts/password": "^0.32.2", | ||
"@accounts/server": "^0.33.1", | ||
"@graphql-tools/merge": "9.0.0", | ||
"@graphql-tools/schema": "10.0.0", | ||
"graphql": "16.8.1", | ||
"graphql-http": "1.22.0", | ||
"graphql-modules": "3.0.0-alpha-20231010152921-a1eddea3", | ||
"graphql-tag": "2.12.6", | ||
"mongoose": "7.6.1", | ||
"tslib": "2.6.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import 'reflect-metadata'; | ||
import { | ||
authenticated, | ||
buildSchema, | ||
context, | ||
createAccountsCoreModule, | ||
} from '@accounts/module-core'; | ||
import { createAccountsPasswordModule } from '@accounts/module-password'; | ||
import { AccountsPassword } from '@accounts/password'; | ||
import { AccountsServer, AuthenticationServicesToken, ServerHooks } from '@accounts/server'; | ||
import gql from 'graphql-tag'; | ||
import mongoose from 'mongoose'; | ||
import { createApplication } from 'graphql-modules'; | ||
import { createAccountsMongoModule } from '@accounts/module-mongo'; | ||
import { createHandler } from 'graphql-http/lib/use/http'; | ||
import http from 'http'; | ||
import { IContext } from '@accounts/types'; | ||
|
||
void (async () => { | ||
// Create database connection | ||
await mongoose.connect('mongodb://localhost:27017/accounts-js-graphql-example'); | ||
const dbConn = mongoose.connection; | ||
|
||
const typeDefs = gql` | ||
type PrivateType @auth { | ||
field: String | ||
} | ||
# Our custom fields to add to the user | ||
extend input CreateUserInput { | ||
firstName: String! | ||
lastName: String! | ||
} | ||
extend type User { | ||
firstName: String! | ||
lastName: String! | ||
} | ||
extend type Query { | ||
# Example of how to get the userId from the context and return the current logged in user or null | ||
me: User | ||
publicField: String | ||
# You can only query this if you are logged in | ||
privateField: String @auth | ||
privateType: PrivateType | ||
privateFieldWithAuthResolver: String | ||
} | ||
extend type Mutation { | ||
privateMutation: String @auth | ||
publicMutation: String | ||
} | ||
`; | ||
|
||
// TODO: use resolvers typings from codegen | ||
const resolvers = { | ||
Query: { | ||
me: (_, __, ctx) => { | ||
// ctx.userId will be set if user is logged in | ||
if (ctx.userId) { | ||
// We could have simply returned ctx.user instead | ||
return ctx.injector.get(AccountsServer).findUserById(ctx.userId); | ||
} | ||
return null; | ||
}, | ||
publicField: () => 'public', | ||
privateField: () => 'private', | ||
privateFieldWithAuthResolver: authenticated(() => { | ||
return 'private'; | ||
}), | ||
privateType: () => ({ | ||
field: () => 'private', | ||
}), | ||
}, | ||
Mutation: { | ||
privateMutation: () => 'private', | ||
publicMutation: () => 'public', | ||
}, | ||
}; | ||
|
||
const app = createApplication({ | ||
modules: [ | ||
createAccountsCoreModule({ tokenSecret: 'secret' }), | ||
createAccountsPasswordModule({ | ||
// This option is called when a new user create an account | ||
// Inside we can apply our logic to validate the user fields | ||
validateNewUser: (user) => { | ||
if (!user.firstName) { | ||
throw new Error('First name required'); | ||
} | ||
if (!user.lastName) { | ||
throw new Error('Last name required'); | ||
} | ||
|
||
// For example we can allow only some kind of emails | ||
if (user.email.endsWith('.xyz')) { | ||
throw new Error('Invalid email'); | ||
} | ||
return user; | ||
}, | ||
}), | ||
createAccountsMongoModule({ dbConn }), | ||
], | ||
providers: [ | ||
{ | ||
provide: AuthenticationServicesToken, | ||
useValue: { password: AccountsPassword }, | ||
global: true, | ||
}, | ||
], | ||
schemaBuilder: buildSchema({ typeDefs, resolvers }), | ||
}); | ||
const { injector, createOperationController } = app; | ||
|
||
// Create the GraphQL over HTTP Node request handler | ||
const handler = createHandler<Pick<IContext, keyof IContext>>({ | ||
schema: app.schema, | ||
execute: app.createExecution(), | ||
context: (request) => context({ request }, { createOperationController }), | ||
}); | ||
|
||
injector.get(AccountsServer).on(ServerHooks.ValidateLogin, ({ user }) => { | ||
// This hook is called every time a user try to login. | ||
// You can use it to only allow users with verified email to login. | ||
// If you throw an error here it will be returned to the client. | ||
console.log(`${user.firstName} ${user.lastName} logged in`); | ||
}); | ||
|
||
// Create a HTTP server using the listener on `/graphql` | ||
const server = http.createServer((req, res) => { | ||
// Set CORS headers | ||
res.setHeader('Access-Control-Allow-Origin', '*'); | ||
res.setHeader('Access-Control-Request-Method', '*'); | ||
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET'); | ||
res.setHeader('Access-Control-Allow-Headers', '*'); | ||
if (req.method === 'OPTIONS') { | ||
res.writeHead(200); | ||
res.end(); | ||
return; | ||
} | ||
if (req.url?.startsWith('/graphql')) { | ||
handler(req, res); | ||
} else { | ||
res.writeHead(404).end(); | ||
} | ||
}); | ||
|
||
server.listen(4000); | ||
console.log(`🚀 Server ready at http://localhost:4000/graphql`); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"compilerOptions": { | ||
"outDir": "./lib", | ||
"target": "es5", | ||
"lib": ["es2015", "esnext.asynciterable"], | ||
"sourceMap": true, | ||
"importHelpers": true, | ||
"esModuleInterop": true, | ||
"skipLibCheck": true | ||
}, | ||
"include": ["./src/**/*"], | ||
"exclude": ["node_modules", "lib"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.