Skip to content

Commit 99ae826

Browse files
committed
Initial additions
1 parent 98a8467 commit 99ae826

File tree

11 files changed

+1753
-0
lines changed

11 files changed

+1753
-0
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "src/client"]
2+
path = src/client
3+
url = https://github.com/mariadb-developers/todo-app-client.git

README.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# TODO
2+
3+
**TODO** is a web application that introduces you to the power, performance, and simplicity of [MariaDB](https://mariadb.com/products/).
4+
5+
This project uses the MariaDB Node.js connector in combination with the [Sequelize object-relational mapping module](https://sequelize.org/) to connect to and communicate to a MariaDB database instance.
6+
7+
<p align="center" spacing="10">
8+
<kbd>
9+
<img src="media/demo.gif" />
10+
</kbd>
11+
</p>
12+
13+
This README will walk you through the steps for getting the TODO web application up and running using MariaDB.
14+
15+
# Table of Contents
16+
1. [Requirements](#requirements)
17+
2. [Getting started with MariaDB](#mariadb)
18+
3. [Get the code](#code)
19+
4. [Create the database and table](#schema)
20+
5. [Configure, build and run the app](#app)
21+
1. [Configure](#configure-app)
22+
2. [Build and run](#build-run)
23+
6. [Support and contribution](#support-contribution)
24+
7. [License](#license)
25+
26+
## Requirements <a name="requirements"></a>
27+
28+
This sample application requires the following to be installed/enabled on your machine:
29+
30+
* [Node.js (v. 12+)](https://nodejs.org/docs/latest-v12.x/api/index.html)
31+
* [NPM (v. 6+)](https://docs.npmjs.com/)
32+
* [MariaDB command-line client](https://mariadb.com/products/skysql/docs/clients/mariadb-clients/mariadb-client/) (optional), used to connect to MariaDB database instances.
33+
34+
## 1.) Getting Started with MariaDB <a name="mariadb"></a>
35+
36+
[MariaDB](https://mariadb.com) is a community-developed, commercially supported relational database management system, and the database you'll be using for this application.
37+
38+
If you don't have a MariaDB database up and running you can find more information on how to download, install and start using a MariaDB database in the [MariaDB Quickstart Guide](https://github.com/mariadb-developers/mariadb-getting-started).
39+
40+
## 2.) Get the code <a name="code"></a>
41+
42+
First, use [git](git-scm.org) (through CLI or a client) to retrieve the code using `git clone`:
43+
44+
```
45+
$ git clone https://github.com/mariadb-developers/todo_app_nodejs.git
46+
```
47+
48+
Next, because this repo uses a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules), you will need to pull the [client application](https://github.com/mariadb-developers/todo_app_client) using:
49+
50+
```bash
51+
$ git submodule update --init --recursive
52+
```
53+
54+
## 3.) Create the database and table <a name="schema"></a>
55+
56+
[Connect to your MariaDB database](https://mariadb.com/products/skysql/docs/clients/) (from [Step #2](#mariadb)) and execute the following SQL scripts using the following options:
57+
58+
a.) Use the [MariaDB command-line client](https://mariadb.com/products/skysql/docs/clients/mariadb-clients/mariadb-client/) to execute the SQL contained within [schema.sql](schema.sql).
59+
60+
_Example command:_
61+
```bash
62+
$ mariadb --host HOST_ADDRESS --port PORT_NO --user USER --password PASSWORD < schema.sql
63+
```
64+
65+
**OR**
66+
67+
b.) Copy, paste and execute the raw SQL commands contained in [schema.sql](schema.sql) using a [client of your choice](https://mariadb.com/products/skysql/docs/clients/).
68+
69+
```sql
70+
CREATE DATABASE todo;
71+
72+
CREATE TABLE todo.tasks (
73+
id INT(11) unsigned NOT NULL AUTO_INCREMENT,
74+
description VARCHAR(500) NOT NULL,
75+
completed BOOLEAN NOT NULL DEFAULT 0,
76+
PRIMARY KEY (id)
77+
);
78+
```
79+
80+
## 4.) Configure, Build and Run the App <a name="app"></a>
81+
82+
This application is made of two parts:
83+
84+
* Client
85+
- communicates with the API.
86+
- is a React.js project located in the [client](src/client) folder.
87+
* API
88+
- uses the [MariaDB Node.js Connector](https://github.com/mariadb-corporation/mariadb-connector-nodejs) to connect to MariaDB.
89+
- is a Node.js project located int the [api](src/api) folder.
90+
91+
### a.) Configure the app <a name="configure-app"></a>
92+
93+
Configure the MariaDB connection by [adding an .env file to the Node.js project](https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/master/documentation/promise-api.md#security-consideration). Add the .env file [here](src/api) (the `api` folder).
94+
95+
Example implementation:
96+
97+
```
98+
DB_HOST=<host_address>
99+
DB_PORT=<port_number>
100+
DB_USER=<username>
101+
DB_PASS=<password>
102+
DB_NAME=todo
103+
```
104+
105+
**Configuring db.js**
106+
107+
The environmental variables from `.env` are used within the [db.js](src/api/db.js) for the MariaDB Node.js Connector configuration Sequelize settings:
108+
109+
```javascript
110+
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
111+
host: process.env.DB_HOST,
112+
port: process.env.DB_PORT,
113+
dialect: 'mariadb',
114+
define: {
115+
timestamps: false
116+
}
117+
});
118+
```
119+
120+
**Configuring db.js for the MariaDB cloud database service [SkySQL](https://mariadb.com/products/skysql/)**
121+
122+
MariaDB SkySQL requires SSL additions to `dialectOptions` within the Sequelize settings. It's as easy as 1-2-3 (steps below).
123+
124+
```javascript
125+
// 1.) Access the Node File System package
126+
const fs = require("fs");
127+
128+
// 2.) Retrieve the Certificate Authority chain file (wherever you placed it - notice it's just in the Node project root here)
129+
const serverCert = [fs.readFileSync("skysql_chain.pem", "utf8")];
130+
131+
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
132+
host: process.env.DB_HOST,
133+
port: process.env.DB_PORT,
134+
dialect: 'mariadb',
135+
// 3.) Add an "ssl" property to the dialectOptions configuration, using the serverCert const defined above
136+
dialectOptions: {
137+
ssl: {
138+
ca: serverCert
139+
}
140+
},
141+
define: {
142+
timestamps: false
143+
}
144+
});
145+
```
146+
147+
### b.) Build and run the app <a name="build-run-app"></a>
148+
149+
Within separate terminal windows perform the following steps:
150+
151+
1. Install the Node.js packages (dependendies) for the [client](src/client) and [api](src/api) apps using the `npm install` command.
152+
153+
_For example:_
154+
```bash
155+
$ npm install ./src/client
156+
$ npm install ./src/api
157+
```
158+
159+
2. Run the [client](src/client) and [api](src/api) apps using the `npm start` command.
160+
161+
_For example:_
162+
```bash
163+
$ npm start --prefix ./src/api
164+
$ npm start --prefix ./src/client
165+
```
166+
167+
**Note:** You will need to use seperate terminals for the `client` and `api` apps.
168+
169+
## Support and Contribution <a name="support-contribution"></a>
170+
171+
Please feel free to submit PR's, issues or requests to this project project directly.
172+
173+
If you have any other questions, comments, or looking for more information on MariaDB please check out:
174+
175+
* [MariaDB Developer Hub](https://mariadb.com/developers)
176+
* [MariaDB Community Slack](https://r.mariadb.com/join-community-slack)
177+
178+
Or reach out to us diretly via:
179+
180+
181+
* [MariaDB Twitter](https://twitter.com/mariadb)
182+
183+
## License <a name="license"></a>
184+
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=plastic)](https://opensource.org/licenses/MIT)

src/api/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# dependency directory
2+
node_modules
3+
4+
# dotenv environment variables file
5+
.env
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
const db = require("../db.js");
2+
const Task = db.tasks;
3+
4+
// Create and Save a new Task
5+
exports.create = (req, res) => {
6+
// Validate request
7+
if (!req.body.description) {
8+
res.status(400).send({
9+
message: "Content can not be empty!"
10+
});
11+
return;
12+
}
13+
14+
// Create a Task
15+
const task = {
16+
description: req.body.description,
17+
completed: req.body.completed ? req.body.completed : false
18+
};
19+
20+
// Save Task in the database
21+
Task.create(task)
22+
.then(data => {
23+
res.send(data);
24+
})
25+
.catch(err => {
26+
res.status(500).send({
27+
message:
28+
err.message || "Some error occurred while creating the Task."
29+
});
30+
});
31+
};
32+
33+
// Retrieve all Tasks from the database
34+
exports.findAll = (req, res) => {
35+
Task.findAll()
36+
.then(data => {
37+
res.send(data);
38+
})
39+
.catch(err => {
40+
res.status(500).send({
41+
message:
42+
err.message || "Some error occurred while retrieving tasks."
43+
});
44+
});
45+
};
46+
47+
// Update a Task by the id in the request
48+
exports.update = (req, res) => {
49+
const id = req.body.id;
50+
51+
Task.update(req.body, {
52+
where: { id: id }
53+
})
54+
.then(num => {
55+
if (num == 1) {
56+
res.send({
57+
message: "Task was updated successfully."
58+
});
59+
} else {
60+
res.send({
61+
message: `Cannot update Task with id=${id}. Maybe Task was not found or req.body is empty!`
62+
});
63+
}
64+
})
65+
.catch(err => {
66+
res.status(500).send({
67+
message: "Error updating Task with id=" + id
68+
});
69+
});
70+
};
71+
72+
// Delete a Task with the specified id in the request
73+
exports.delete = (req, res) => {
74+
const id = req.query.id;
75+
76+
Task.destroy({
77+
where: { id: id }
78+
})
79+
.then(num => {
80+
if (num == 1) {
81+
res.send({
82+
message: "Task was deleted successfully!"
83+
});
84+
} else {
85+
res.send({
86+
message: `Cannot delete Task with id=${id}. Maybe Task was not found!`
87+
});
88+
}
89+
})
90+
.catch(err => {
91+
res.status(500).send({
92+
message: "Could not delete Task with id=" + id
93+
});
94+
});
95+
};
96+

src/api/db.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require('dotenv').config();
2+
3+
// 1.) Access the Node File System package
4+
//const fs = require("fs");
5+
6+
// 2.) Retrieve the Certificate Authority chain file (wherever you placed it - notice it's just in the Node project root here)
7+
//const cert = [fs.readFileSync("skysql_chain.pem", "utf8")];
8+
9+
const Sequelize = require("sequelize");
10+
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
11+
host: process.env.DB_HOST,
12+
port: process.env.DB_PORT,
13+
dialect: 'mariadb',
14+
// 3.) Add an "ssl" property to the dialectOptions configuration, using the serverCert const defined above
15+
/*dialectOptions: {
16+
ssl: {
17+
ca: cert
18+
}
19+
},*/
20+
define: {
21+
timestamps: false
22+
}
23+
});
24+
25+
const db = {};
26+
27+
db.Sequelize = Sequelize;
28+
db.sequelize = sequelize;
29+
30+
db.tasks = require("./models/task.model.js")(sequelize, Sequelize);
31+
32+
module.exports = db;

src/api/models/task.model.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = (sequelize, Sequelize) => {
2+
const Task = sequelize.define("task", {
3+
id: {
4+
type: Sequelize.INTEGER,
5+
primaryKey: true
6+
},
7+
description: {
8+
type: Sequelize.STRING
9+
},
10+
completed: {
11+
type: Sequelize.BOOLEAN
12+
}
13+
});
14+
return Task;
15+
};

0 commit comments

Comments
 (0)