Skip to content

Commit 60ad6e7

Browse files
committed
feat: add a rest example which makes use of graphql-modules
1 parent 4070f90 commit 60ad6e7

File tree

9 files changed

+245
-32
lines changed

9 files changed

+245
-32
lines changed

.changeset/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"@examples/magic-link-server-typescript",
2525
"@examples/react-graphql-typescript",
2626
"@examples/react-rest-typescript",
27-
"@examples/rest-express-typescript"
27+
"@examples/rest-express-typescript",
28+
"@examples/rest-express-typescript-without-modules"
2829
],
2930
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
3031
"onlyUpdatePeerDependentsWhenOutOfRange": true
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# rest-express-typescript
2+
3+
This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts).
4+
5+
You must have a mongodb server running before starting the server.
6+
7+
## Setup example
8+
9+
In order to be able to run this example on your machine you first need to do the following steps:
10+
11+
- Clone the repository `git clone [email protected]:accounts-js/accounts.git`
12+
- Install project dependencies: `yarn install`
13+
- Compile the packages `yarn run compile`
14+
- Go to the example folder `cd examples/rest-express-typescript`
15+
16+
## Getting Started
17+
18+
Start the app.
19+
20+
```
21+
yarn run start
22+
```
23+
24+
Open a browser and navigate to [http://localhost:4000](http://localhost:4000).
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": 2,
3+
"name": "rest-express-typescript",
4+
"builds": [
5+
{
6+
"src": "lib/index.js",
7+
"use": "@now/node-server"
8+
}
9+
],
10+
"routes": [
11+
{
12+
"src": ".*",
13+
"dest": "/lib/index.js"
14+
}
15+
],
16+
"env": {
17+
"MONGO_URL": "@accounts-js-rest-express"
18+
}
19+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@examples/rest-express-typescript-without-modules",
3+
"private": true,
4+
"version": "0.32.0",
5+
"main": "lib/index.js",
6+
"license": "MIT",
7+
"scripts": {
8+
"start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts",
9+
"build": "yarn run -T tsc",
10+
"test": "yarn run build"
11+
},
12+
"dependencies": {
13+
"@accounts/mongo": "^0.34.1",
14+
"@accounts/password": "^0.32.2",
15+
"@accounts/rest-express": "^0.33.1",
16+
"@accounts/server": "^0.33.1",
17+
"body-parser": "1.20.2",
18+
"cors": "2.8.5",
19+
"express": "4.18.2",
20+
"mongoose": "8.0.1",
21+
"tslib": "2.6.2"
22+
}
23+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import 'reflect-metadata';
2+
import express from 'express';
3+
import bodyParser from 'body-parser';
4+
import cors from 'cors';
5+
import mongoose from 'mongoose';
6+
import { AccountsServer, ServerHooks } from '@accounts/server';
7+
import { AccountsPassword } from '@accounts/password';
8+
import accountsExpress, { userLoader } from '@accounts/rest-express';
9+
import { Mongo } from '@accounts/mongo';
10+
11+
mongoose.connect(process.env.MONGO_URL || 'mongodb://localhost:27017/accounts-js-rest-example');
12+
const db = mongoose.connection;
13+
14+
const app = express();
15+
16+
app.use(bodyParser.json());
17+
app.use(bodyParser.urlencoded({ extended: true }));
18+
app.use(cors());
19+
20+
interface UserDoc extends mongoose.Document {
21+
firstName: string;
22+
lastName: string;
23+
}
24+
25+
const User = mongoose.model<UserDoc>(
26+
'User',
27+
new mongoose.Schema({ firstName: String, lastName: String })
28+
);
29+
30+
const accountsPassword = new AccountsPassword({
31+
// This option is called when a new user create an account
32+
// Inside we can apply our logic to validate the user fields
33+
validateNewUser: (user) => {
34+
// For example we can allow only some kind of emails
35+
if (user.email.endsWith('.xyz')) {
36+
throw new Error('Invalid email');
37+
}
38+
return user;
39+
},
40+
});
41+
42+
const accountsServer = new AccountsServer(
43+
{
44+
tokenSecret: 'secret',
45+
},
46+
{
47+
password: accountsPassword,
48+
},
49+
new Mongo(db)
50+
);
51+
52+
accountsServer.on(ServerHooks.ValidateLogin, ({ user }) => {
53+
// This hook is called every time a user try to login.
54+
// You can use it to only allow users with verified email to login.
55+
// If you throw an error here it will be returned to the client.
56+
console.log('Logged in', user);
57+
});
58+
59+
/**
60+
* Load and expose the accounts-js middleware
61+
*/
62+
app.use(accountsExpress(accountsServer));
63+
64+
/**
65+
* Return the current logged in user
66+
*/
67+
app.get('/user', userLoader(accountsServer), (req, res) => {
68+
res.json({ user: (req as any).user });
69+
});
70+
71+
/**
72+
* Expose a public route to edit user informations
73+
* - route is protected
74+
* - update the current logged in user in the db
75+
*/
76+
app.put('/user', userLoader(accountsServer), async (req, res) => {
77+
const userId = (req as any).userId;
78+
if (!userId) {
79+
res.status(401);
80+
res.json({ message: 'Unauthorized' });
81+
return;
82+
}
83+
const user = await User.findById(userId).exec();
84+
user.firstName = req.body.firstName;
85+
user.lastName = req.body.lastName;
86+
await user.save();
87+
res.json(true);
88+
});
89+
90+
app.listen(process.env.PORT || 4000, () => {
91+
console.log('Server listening on port 4000');
92+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"outDir": "./lib",
4+
"target": "es5",
5+
"lib": ["es2015", "esnext.asynciterable"],
6+
"sourceMap": true,
7+
"importHelpers": true,
8+
"skipLibCheck": true,
9+
"isolatedModules": true,
10+
"esModuleInterop": true
11+
},
12+
"include": ["./src/**/*"]
13+
}

examples/rest-express-typescript/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
"test": "yarn run build"
1111
},
1212
"dependencies": {
13+
"@accounts/module-core": "^0.34.0",
14+
"@accounts/module-mongo": "^0.34.0",
15+
"@accounts/module-password": "^0.34.0",
1316
"@accounts/mongo": "^0.34.1",
1417
"@accounts/password": "^0.32.2",
1518
"@accounts/rest-express": "^0.33.1",

examples/rest-express-typescript/src/index.ts

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,54 @@ import express from 'express';
33
import bodyParser from 'body-parser';
44
import cors from 'cors';
55
import mongoose from 'mongoose';
6-
import { AccountsServer, ServerHooks } from '@accounts/server';
6+
import { AccountsServer, AuthenticationServicesToken, ServerHooks } from '@accounts/server';
77
import { AccountsPassword } from '@accounts/password';
88
import accountsExpress, { userLoader } from '@accounts/rest-express';
9-
import { Mongo } from '@accounts/mongo';
9+
import { createApplication } from 'graphql-modules';
10+
import { createAccountsCoreModule } from '@accounts/module-core';
11+
import { createAccountsPasswordModule } from '@accounts/module-password';
12+
import { createAccountsMongoModule } from '@accounts/module-mongo';
1013

1114
mongoose.connect(process.env.MONGO_URL || 'mongodb://localhost:27017/accounts-js-rest-example');
12-
const db = mongoose.connection;
15+
const dbConn = mongoose.connection;
1316

14-
const app = express();
17+
const app = createApplication({
18+
modules: [
19+
createAccountsCoreModule({ tokenSecret: 'secret' }),
20+
createAccountsPasswordModule({
21+
// This option is called when a new user create an account
22+
// Inside we can apply our logic to validate the user fields
23+
validateNewUser: (user) => {
24+
if (!user.firstName) {
25+
throw new Error('First name required');
26+
}
27+
if (!user.lastName) {
28+
throw new Error('Last name required');
29+
}
1530

16-
app.use(bodyParser.json());
17-
app.use(bodyParser.urlencoded({ extended: true }));
18-
app.use(cors());
31+
// For example we can allow only some kind of emails
32+
if (user.email.endsWith('.xyz')) {
33+
throw new Error('Invalid email');
34+
}
35+
return user;
36+
},
37+
}),
38+
createAccountsMongoModule({ dbConn }),
39+
],
40+
providers: [
41+
{
42+
provide: AuthenticationServicesToken,
43+
useValue: { password: AccountsPassword },
44+
global: true,
45+
},
46+
],
47+
});
48+
49+
const expressApp = express();
50+
51+
expressApp.use(bodyParser.json());
52+
expressApp.use(bodyParser.urlencoded({ extended: true }));
53+
expressApp.use(cors());
1954

2055
interface UserDoc extends mongoose.Document {
2156
firstName: string;
@@ -27,27 +62,11 @@ const User = mongoose.model<UserDoc>(
2762
new mongoose.Schema({ firstName: String, lastName: String })
2863
);
2964

30-
const accountsPassword = new AccountsPassword({
31-
// This option is called when a new user create an account
32-
// Inside we can apply our logic to validate the user fields
33-
validateNewUser: (user) => {
34-
// For example we can allow only some kind of emails
35-
if (user.email.endsWith('.xyz')) {
36-
throw new Error('Invalid email');
37-
}
38-
return user;
39-
},
65+
const controller = app.createOperationController({
66+
context: {},
4067
});
41-
42-
const accountsServer = new AccountsServer(
43-
{
44-
tokenSecret: 'secret',
45-
},
46-
{
47-
password: accountsPassword,
48-
},
49-
new Mongo(db)
50-
);
68+
const accountsServer = controller.injector.get(AccountsServer);
69+
expressApp.use(accountsExpress(accountsServer));
5170

5271
accountsServer.on(ServerHooks.ValidateLogin, ({ user }) => {
5372
// This hook is called every time a user try to login.
@@ -59,12 +78,12 @@ accountsServer.on(ServerHooks.ValidateLogin, ({ user }) => {
5978
/**
6079
* Load and expose the accounts-js middleware
6180
*/
62-
app.use(accountsExpress(accountsServer));
81+
expressApp.use(accountsExpress(accountsServer));
6382

6483
/**
6584
* Return the current logged in user
6685
*/
67-
app.get('/user', userLoader(accountsServer), (req, res) => {
86+
expressApp.get('/user', userLoader(accountsServer), (req, res) => {
6887
res.json({ user: (req as any).user });
6988
});
7089

@@ -73,7 +92,7 @@ app.get('/user', userLoader(accountsServer), (req, res) => {
7392
* - route is protected
7493
* - update the current logged in user in the db
7594
*/
76-
app.put('/user', userLoader(accountsServer), async (req, res) => {
95+
expressApp.put('/user', userLoader(accountsServer), async (req, res) => {
7796
const userId = (req as any).userId;
7897
if (!userId) {
7998
res.status(401);
@@ -87,6 +106,6 @@ app.put('/user', userLoader(accountsServer), async (req, res) => {
87106
res.json(true);
88107
});
89108

90-
app.listen(process.env.PORT || 4000, () => {
109+
expressApp.listen(process.env.PORT || 4000, () => {
91110
console.log('Server listening on port 4000');
92111
});

yarn.lock

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4046,10 +4046,29 @@ __metadata:
40464046
languageName: unknown
40474047
linkType: soft
40484048

4049+
"@examples/rest-express-typescript-without-modules@workspace:examples/rest-express-typescript-without-modules":
4050+
version: 0.0.0-use.local
4051+
resolution: "@examples/rest-express-typescript-without-modules@workspace:examples/rest-express-typescript-without-modules"
4052+
dependencies:
4053+
"@accounts/mongo": "npm:^0.34.1"
4054+
"@accounts/password": "npm:^0.32.2"
4055+
"@accounts/rest-express": "npm:^0.33.1"
4056+
"@accounts/server": "npm:^0.33.1"
4057+
body-parser: "npm:1.20.2"
4058+
cors: "npm:2.8.5"
4059+
express: "npm:4.18.2"
4060+
mongoose: "npm:8.0.1"
4061+
tslib: "npm:2.6.2"
4062+
languageName: unknown
4063+
linkType: soft
4064+
40494065
"@examples/rest-express-typescript@workspace:examples/rest-express-typescript":
40504066
version: 0.0.0-use.local
40514067
resolution: "@examples/rest-express-typescript@workspace:examples/rest-express-typescript"
40524068
dependencies:
4069+
"@accounts/module-core": "npm:^0.34.0"
4070+
"@accounts/module-mongo": "npm:^0.34.0"
4071+
"@accounts/module-password": "npm:^0.34.0"
40534072
"@accounts/mongo": "npm:^0.34.1"
40544073
"@accounts/password": "npm:^0.32.2"
40554074
"@accounts/rest-express": "npm:^0.33.1"

0 commit comments

Comments
 (0)