Skip to content

Commit d156f40

Browse files
author
Dan McGhan
committed
Added part 5 on manual pagination, sorting, and filtering
1 parent 22bdd38 commit d156f40

File tree

409 files changed

+87179
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

409 files changed

+87179
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module.exports = {
2+
hrPool: {
3+
user: process.env.HR_USER,
4+
password: process.env.HR_PASSWORD,
5+
connectString: process.env.HR_CONNECTIONSTRING,
6+
poolMin: 10,
7+
poolMax: 10,
8+
poolIncrement: 0
9+
}
10+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
port: process.env.HTTP_PORT || 3000
3+
};
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
const employees = require('../db_apis/employees.js');
2+
3+
async function get(req, res, next) {
4+
try {
5+
const context = {};
6+
7+
context.id = parseInt(req.params.id, 10);
8+
context.skip = parseInt(req.query.skip, 10);
9+
context.limit = parseInt(req.query.limit, 10);
10+
context.sort = req.query.sort;
11+
context.department_id = parseInt(req.query.department_id, 10);
12+
context.manager_id = parseInt(req.query.manager_id, 10);
13+
14+
const rows = await employees.find(context);
15+
16+
if (req.params.id) {
17+
if (rows.length === 1) {
18+
res.status(200).json(rows[0]);
19+
} else {
20+
res.status(404).end();
21+
}
22+
} else {
23+
res.status(200).json(rows);
24+
}
25+
} catch (err) {
26+
next(err);
27+
}
28+
}
29+
30+
module.exports.get = get;
31+
32+
function getEmployeeFromRec(req) {
33+
const employee = {
34+
first_name: req.body.first_name,
35+
last_name: req.body.last_name,
36+
email: req.body.email,
37+
phone_number: req.body.phone_number,
38+
hire_date: req.body.hire_date,
39+
job_id: req.body.job_id,
40+
salary: req.body.salary,
41+
commission_pct: req.body.commission_pct,
42+
manager_id: req.body.manager_id,
43+
department_id: req.body.department_id
44+
};
45+
46+
return employee;
47+
}
48+
49+
async function post(req, res, next) {
50+
try {
51+
let employee = getEmployeeFromRec(req);
52+
53+
employee = await employees.create(employee);
54+
55+
res.status(201).json(employee);
56+
} catch (err) {
57+
next(err);
58+
}
59+
}
60+
61+
module.exports.post = post;
62+
63+
async function put(req, res, next) {
64+
try {
65+
let employee = getEmployeeFromRec(req);
66+
67+
employee.employee_id = parseInt(req.params.id, 10);
68+
69+
employee = await employees.update(employee);
70+
71+
if (employee !== null) {
72+
res.status(200).json(employee);
73+
} else {
74+
res.status(404).end();
75+
}
76+
} catch (err) {
77+
next(err);
78+
}
79+
}
80+
81+
module.exports.put = put;
82+
83+
async function del(req, res, next) {
84+
try {
85+
const id = parseInt(req.params.id, 10);
86+
87+
const success = await employees.delete(id);
88+
89+
if (success) {
90+
res.status(204).end();
91+
} else {
92+
res.status(404).end();
93+
}
94+
} catch (err) {
95+
next(err);
96+
}
97+
}
98+
99+
module.exports.delete = del;
100+
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
const oracledb = require('oracledb');
2+
const database = require('../services/database.js');
3+
4+
const baseQuery =
5+
`select employee_id "id",
6+
first_name "first_name",
7+
last_name "last_name",
8+
email "email",
9+
phone_number "phone_number",
10+
hire_date "hire_date",
11+
job_id "job_id",
12+
salary "salary",
13+
commission_pct "commission_pct",
14+
manager_id "manager_id",
15+
department_id "department_id"
16+
from employees
17+
where 1 = 1`;
18+
19+
const sortableColumns = ['id', 'last_name', 'email', 'hire_date', 'salary'];
20+
21+
async function find(context) {
22+
let query = baseQuery;
23+
const binds = {};
24+
25+
if (context.id) {
26+
binds.employee_id = context.id;
27+
28+
query += '\nand employee_id = :employee_id';
29+
}
30+
31+
if (context.department_id) {
32+
binds.department_id = context.department_id;
33+
34+
query += '\nand department_id = :department_id';
35+
}
36+
37+
if (context.manager_id) {
38+
binds.manager_id = context.manager_id;
39+
40+
query += '\nand manager_id = :manager_id';
41+
}
42+
43+
if (context.sort === undefined) {
44+
query += '\norder by last_name asc';
45+
} else {
46+
let [column, order] = context.sort.split(':');
47+
48+
if (!sortableColumns.includes(column)) {
49+
throw new Error('Invalid "sort" column');
50+
}
51+
52+
if (order === undefined) {
53+
order = 'asc';
54+
}
55+
56+
if (order !== 'asc' && order !== 'desc') {
57+
throw new Error('Invalid "sort" order');
58+
}
59+
60+
query += `\norder by "${column}" ${order}`;
61+
}
62+
63+
if (context.skip) {
64+
binds.row_offset = context.skip;
65+
66+
query += '\noffset :row_offset rows';
67+
}
68+
69+
const limit = (context.limit > 0) ? context.limit : 30;
70+
71+
binds.row_limit = limit;
72+
73+
query += '\nfetch next :row_limit rows only';
74+
75+
const result = await database.simpleExecute(query, binds);
76+
77+
return result.rows;
78+
}
79+
80+
module.exports.find = find;
81+
82+
const createSql =
83+
`insert into employees (
84+
first_name,
85+
last_name,
86+
email,
87+
phone_number,
88+
hire_date,
89+
job_id,
90+
salary,
91+
commission_pct,
92+
manager_id,
93+
department_id
94+
) values (
95+
:first_name,
96+
:last_name,
97+
:email,
98+
:phone_number,
99+
:hire_date,
100+
:job_id,
101+
:salary,
102+
:commission_pct,
103+
:manager_id,
104+
:department_id
105+
) returning employee_id
106+
into :employee_id`;
107+
108+
async function create(emp) {
109+
const employee = Object.assign({}, emp);
110+
111+
employee.employee_id = {
112+
dir: oracledb.BIND_OUT,
113+
type: oracledb.NUMBER
114+
}
115+
116+
const result = await database.simpleExecute(createSql, employee);
117+
118+
employee.employee_id = result.outBinds.employee_id[0];
119+
120+
return employee;
121+
}
122+
123+
module.exports.create = create;
124+
125+
const updateSql =
126+
`update employees
127+
set first_name = :first_name,
128+
last_name = :last_name,
129+
email = :email,
130+
phone_number = :phone_number,
131+
hire_date = :hire_date,
132+
job_id = :job_id,
133+
salary = :salary,
134+
commission_pct = :commission_pct,
135+
manager_id = :manager_id,
136+
department_id = :department_id
137+
where employee_id = :employee_id`;
138+
139+
async function update(emp) {
140+
const employee = Object.assign({}, emp);
141+
const result = await database.simpleExecute(updateSql, employee);
142+
143+
if (result.rowsAffected && result.rowsAffected === 1) {
144+
return employee;
145+
} else {
146+
return null;
147+
}
148+
}
149+
150+
module.exports.update = update;
151+
152+
const deleteSql =
153+
`begin
154+
155+
delete from job_history
156+
where employee_id = :employee_id;
157+
158+
delete from employees
159+
where employee_id = :employee_id;
160+
161+
:rowcount := sql%rowcount;
162+
163+
end;`
164+
165+
async function del(id) {
166+
const binds = {
167+
employee_id: id,
168+
rowcount: {
169+
dir: oracledb.BIND_OUT,
170+
type: oracledb.NUMBER
171+
}
172+
}
173+
const result = await database.simpleExecute(deleteSql, binds);
174+
175+
return result.outBinds.rowcount === 1;
176+
}
177+
178+
module.exports.delete = del;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
const webServer = require('./services/web-server.js');
2+
const database = require('./services/database.js');
3+
const dbConfig = require('./config/database.js');
4+
const defaultThreadPoolSize = 4;
5+
6+
// Increase thread pool size by poolMax
7+
process.env.UV_THREADPOOL_SIZE = dbConfig.hrPool.poolMax + defaultThreadPoolSize;
8+
9+
async function startup() {
10+
console.log('Starting application');
11+
12+
try {
13+
console.log('Initializing database module');
14+
15+
await database.initialize();
16+
} catch (err) {
17+
console.error(err);
18+
19+
process.exit(1); // Non-zero failure code
20+
}
21+
22+
try {
23+
console.log('Initializing web server module');
24+
25+
await webServer.initialize();
26+
} catch (err) {
27+
console.error(err);
28+
29+
process.exit(1); // Non-zero failure code
30+
}
31+
}
32+
33+
startup();
34+
35+
async function shutdown(e) {
36+
let err = e;
37+
38+
console.log('Shutting down application');
39+
40+
try {
41+
console.log('Closing web server module');
42+
43+
await webServer.close();
44+
} catch (e) {
45+
console.error(e);
46+
47+
err = err || e;
48+
}
49+
50+
try {
51+
console.log('Closing database module');
52+
53+
await database.close();
54+
} catch (e) {
55+
console.error(e);
56+
57+
err = err || e;
58+
}
59+
60+
console.log('Exiting process');
61+
62+
if (err) {
63+
process.exit(1); // Non-zero failure code
64+
} else {
65+
process.exit(0);
66+
}
67+
}
68+
69+
process.on('SIGTERM', () => {
70+
console.log('Received SIGTERM');
71+
72+
shutdown();
73+
});
74+
75+
process.on('SIGINT', () => {
76+
console.log('Received SIGINT');
77+
78+
shutdown();
79+
});
80+
81+
process.on('uncaughtException', err => {
82+
console.log('Uncaught exception');
83+
console.error(err);
84+
85+
shutdown(err);
86+
});

0 commit comments

Comments
 (0)