[[toc]]
Create package.json
npm initinstall express
npm install express --saveindex.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 5000;
app.listen(PORT,()=>console.log(`Server running on port ${PORT}`));run server
node .add run script to package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start" : "node ."
}run server
npm startindex.js
const express = require('express');
const app = express();
app.get('/', (req,res) => {
res.send('<h1>Hello World!</h1>')
});
const PORT = process.env.PORT || 5000;
app.listen(PORT,()=>console.log(`Server running on port ${PORT}`));installing nodemon as dev dependacy
npm install -D nodemonadding run script to package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node .",
"dev": "nodemon"
}Run server with nodemon
npm run devAdd dumy data - index.js
const users = [
{
"id": "1",
"name": "Byron",
"role": "user",
"email": "byron@mail.com",
"password": "P@ssword"
},
{
"id": "2",
"name": "brett",
"role": "service provider",
"email": "brett@mail.com",
"password": "P@ssword1"
},
{
"id": "3",
"name": "Riaz",
"role": "user",
"email": "riaz@mail.com",
"password": "P@ssword2"
},
]Get users route - index.js
app.get('/api/users', (req,res) => {
res.json(users);
});Install fs
npm install fsAdd dumy data - ./data/data.json
{
"users":[
{
"id":"1",
"name":"Byron",
"surname":"de Villiers",
"cellPhone":"0829123465",
"email":"byron@mail.com",
"password":"P@ssword",
"role":"provider"
}
]
}Update users route - index.js
var fs = require("fs");
router.get("/api/users", (req, res) => {
//res.send('<h1>Hello World!</h1>');
fs.readFile("./src/data/data.json", function(err, data) {
if (err) throw err;
var parseData = JSON.parse(data);
res.json(parseData.users);
});
});index.js
//Middleware function:
const logger = (req,res,next) => {
console.log(`${req.protocol}://${req.get('host')}${req.originalUrl}`);
next();
}
//Middleware execue:
app.use(logger)index.js
//Middleware function:
const logger = (req,res,next) => {
console.log(`${req.protocol}://${req.get('host')}${req.originalUrl}`);
next();
}
//Middleware execue:
app.use(logger)index.js
app.get("api/users/:id", (req, res) => {
fs.readFile("./src/data/data.json", function(err, data) {
if (err) throw err;
var parseData = JSON.parse(data);
res.json(users.filter(user => user.id === req.params.id));
});
});index.js
app.get("api/users/:id", (req, res) => {
fs.readFile("./src/data/data.json", function(err, data) {
if (err) throw err;
var parseData = JSON.parse(data);
const found = parseData.users.some(user => user.id === req.params.id);
if (found) {
res.json(users.filter(user => user.id === req.params.id));
} else {
res.status(400).json({ msg: "User not found" });
}
});
});./src/api/user-routes.js
const express = require("express");
const router = express.Router();
var fs = require("fs");
router.get("/", (req, res) => {
//res.send('<h1>Hello World!</h1>');
fs.readFile("./src/data/data.json", function(err, data) {
if (err) throw err;
var parseData = JSON.parse(data);
res.json(parseData.users);
});
});
router.get("/:id", (req, res) => {
fs.readFile("./src/data/data.json", function(err, data) {
if (err) throw err;
var parseData = JSON.parse(data);
const found = parseData.users.some(user => user.id === req.params.id);
if (found) {
res.json(parseData.users.filter(user => user.id === req.params.id));
} else {
res.status(400).json({ msg: "User not found" });
}
});
});
module.exports = router;Updating express router - index.js
//Routes:
app.use("/api/users", require("./src/api/users-routes"));index.js
//Body Parser Middlware:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));user-routes.js
router.post("/", (req, res) => {
const user = req.body;
fs.readFile("./src/data/data.json", function(err, data) {
var error = false;
var errMsg = "";
if (err) {
error = true;
throw err;
} else {
var count = 0;
if (data.length > 0) {
var parseData = JSON.parse(data);
parseData.users.forEach(existingUser => {
if (existingUser.email === user.email) {
throw new Error("This email address already been used");
}
count++;
});
} else {
parseData = {
users: []
};
}
const newUser = {
id: (count + 1).toString(),
name: user.name,
surname: user.surname,
cellPhone: user.cellPhone,
email: user.email,
password: user.password,
role: user.role
};
parseData.users.push(newUser);
fs.writeFile("./src/data/data.json", JSON.stringify(parseData), function(
err
) {
if (err) {
error = true;
throw err;
}
res.json(newUser);
});
}
if (error) {
res.status(400).json({ msg: errMsg });
} else {
res.json(user);
}
});
});user-routes.js
router.post("/update", (req, res) => {
const user = req.body;
fs.readFile("./src/data/data.json", function(err, data) {
var error = false;
if (err) {
error = true;
throw err;
} else {
if (data.length > 0) {
var parseData = JSON.parse(data);
} else {
throw Error("No Users");
}
parseData.users = parseData.users.filter(existingUser => {
return existingUser.email !== user.email;
});
const updateUser = {
id: user.id,
name: user.name,
surname: user.surname,
cellPhone: user.cellPhone,
email: user.email,
password: user.password,
role: user.role
};
parseData.users.push(updateUser);
fs.writeFile("./src/data/data.json", JSON.stringify(parseData), function(
err
) {
if (err) {
error = true;
throw err;
}
res.json(updateUser);
});
}
if (error) {
res.status(400).json({ msg: err.msg });
} else {
res.json(user);
}
});
});user-route.js
router.get("/delete/:id", (req, res) => {
fs.readFile("./src/data/data.json", function(err, data) {
var error = false;
if (err) {
error = true;
throw err;
}
var parseData = JSON.parse(data);
parseData.users = parseData.users.filter(user => user.id === req.params.id);
fs.writeFile("./src/data/data.json", JSON.stringify(parseData), function(
err
) {
if (err) {
error = true;
throw err;
}
res.json({ status: "User deleted" });
});
if (error) {
res.status(400).json({ msg: err.message });
} else {
res.json({ status: "User deleted" });
}
});
});Install LoopBack
npm i -g @loopback/cliGenerate new loopback project
lb4 app fs-bnb-apiOpen project in VS Code and run
cd fs-bnb-api
code .
npm startMake slides to go with a breif over view of files and what that do
Generate user model
lb4 model
? Model class name: user
? Please select the model base class: Entity
? Allow additional (free-form) properties? No
Let's add a property to user
Enter an empty property name when done
? Enter the property name: id
? Property type: number
? Is id the ID property? Yes
? Is it required?: No
? Default value [leave blank for none]:
Let's add another property to user
Enter an empty property name when done
? Enter the property name: name
? Property type: string
? Is it required?: Yes
? Default value [leave blank for none]:
Let's add another property to user
Enter an empty property name when done
? Enter the property name: lastName
? Property type: string
? Is it required?: No
? Default value [leave blank for none]:
Let's add another property to user
Enter an empty property name when done
? Enter the property name: email
? Property type: string
? Is it required?: Yes
? Default value [leave blank for none]:
Let's add a property to user
Enter an empty property name when done
? Enter the property name: cellPhone
? Property type: number
? Is id the ID property? Yes
? Is it required?: No
? Default value [leave blank for none]:
Let's add another property to user
Enter an empty property name when done
? Enter the property name:
create src/models/user.model.ts
update src/models/index.ts
Model user was created in src/models/user.model.ts
import {Entity, model, property} from '@loopback/repository';
@model({settings: {}})
export class User extends Entity {
@property({
type: 'number',
id: true,
})
id?: number;
@property({
type: 'string',
required: true,
})
name: string;
@property({
type: 'string',
})
lastName?: string;
@property({
type: 'string',
required: true,
})
email: string;
@property({
type: 'string',
})
cellPhone?: string;
constructor(data?: Partial<User>) {
super(data);
}
}notice it was added to src/models/index.ts
export * from './user.model';Generate Datasource files
lb4 datasource
? Datasource name: db
? Select the connector for db: In-memory db (supported by StrongLoop)
? window.localStorage key to use for persistence (browser only):
? Full path to file for persistence (server only): ./data/db.json
create src/datasources/db.datasource.json
create src/datasources/db.datasource.ts
update src/datasources/index.ts
Datasource db was created in src/datasources/db.datasource.ts
import {inject} from '@loopback/core';
import {juggler} from '@loopback/repository';
import * as config from './db.datasource.json';
export class DbDataSource extends juggler.DataSource {
static dataSourceName = 'db';
constructor(
@inject('datasources.config.db', {optional: true})
dsConfig: object = config,
) {
super(dsConfig);
}
}db.datasource.json
{
"name": "db",
"connector": "memory",
"localStorage": "",
"file": "./data/db.json"
}notice it was added to src/datasources/index.ts
export * from './db.datasource';./data/db.json
{
"ids": {
"User": 6
},
"models": {
"User": {
"1": "{\"name\":\"Joe\",\"lastName\":\"Soap\",\"email\":\"joe@mail.com\",\"cellPhone\":\"0821234567\",\"id\":1}",
"2": "{\"name\":\"John\",\"lastName\":\"Doe\",\"email\":\"john@mail.com\",\"cellPhone\":\"0831234567\",\"id\":2}",
"3": "{\"name\":\"Jane\",\"lastName\":\"Smith\",\"email\":\"jane@mail.com\",\"cellPhone\":\"0741234567\",\"id\":3}",
"4": "{\"name\":\"Sam\",\"lastName\":\"Hill\",\"email\":\"sam@mail.com\",\"cellPhone\":\"0829876543\",\"id\":4}",
"5": "{\"name\":\"Byron\",\"lastName\":\"de Villiers\",\"email\":\"byron@mail.com\",\"cellPhone\":\"0741234567\",\"id\":5}"
}
}
}generate user repository
lb4 repository
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository User
? Please select the repository base class DefaultCrudRepository (Legacy juggler bridge)
create src\repositories\user.repository.ts
update src\repositories\index.ts
Repository UserRepository was created in src\repositories/user.repository.ts
import {DefaultCrudRepository} from '@loopback/repository';
import {User} from '../models';
import {DbDataSource} from '../datasources';
import {inject} from '@loopback/core';
export class UserRepository extends DefaultCrudRepository<
User,
typeof User.prototype.id
> {
constructor(
@inject('datasources.db') dataSource: DbDataSource,
) {
super(User, dataSource);
}
}notice it was added to /src/repositories/index.ts
export * from './user.repository';Generate user controller
lb4 controller
? Controller class name: user
? What kind of controller would you like to generate? REST Controller with CRUD functions
? What is the name of the model to use with this CRUD repository? User
? What is the name of your CRUD repository? UserRepository
? What is the type of your ID? number
? What is the base HTTP path name of the CRUD operations? /users
create src\controllers\user.controller.ts
update src\controllers\index.ts
Controller user was created in src\controllers/user.controller.ts
import {
Count,
CountSchema,
Filter,
repository,
Where,
} from '@loopback/repository';
import {
post,
param,
get,
getFilterSchemaFor,
getWhereSchemaFor,
patch,
put,
del,
requestBody,
} from '@loopback/rest';
import {User} from '../models';
import {UserRepository} from '../repositories';
export class UserController {
constructor(
@repository(UserRepository)
public userRepository : UserRepository,
) {}
@post('/users', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async create(@requestBody() user: User): Promise<User> {
return await this.userRepository.create(user);
}
@get('/users/count', {
responses: {
'200': {
description: 'User model count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async count(
@param.query.object('where', getWhereSchemaFor(User)) where?: Where,
): Promise<Count> {
return await this.userRepository.count(where);
}
@get('/users', {
responses: {
'200': {
description: 'Array of User model instances',
content: {
'application/json': {
schema: {type: 'array', items: {'x-ts-type': User}},
},
},
},
},
})
async find(
@param.query.object('filter', getFilterSchemaFor(User)) filter?: Filter,
): Promise<User[]> {
return await this.userRepository.find(filter);
}
@patch('/users', {
responses: {
'200': {
description: 'User PATCH success count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async updateAll(
@requestBody() user: User,
@param.query.object('where', getWhereSchemaFor(User)) where?: Where,
): Promise<Count> {
return await this.userRepository.updateAll(user, where);
}
@get('/users/{id}', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async findById(@param.path.number('id') id: number): Promise<User> {
return await this.userRepository.findById(id);
}
@patch('/users/{id}', {
responses: {
'204': {
description: 'User PATCH success',
},
},
})
async updateById(
@param.path.number('id') id: number,
@requestBody() user: User,
): Promise<void> {
await this.userRepository.updateById(id, user);
}
@put('/users/{id}', {
responses: {
'204': {
description: 'User PUT success',
},
},
})
async replaceById(
@param.path.number('id') id: number,
@requestBody() user: User,
): Promise<void> {
await this.userRepository.replaceById(id, user);
}
@del('/users/{id}', {
responses: {
'204': {
description: 'User DELETE success',
},
},
})
async deleteById(@param.path.number('id') id: number): Promise<void> {
await this.userRepository.deleteById(id);
}
}notice it was added to /src/controllers/index.ts
export * from './ping.controller';
export * from './user.controller';