create-sip 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/create-sip.js CHANGED
@@ -7,7 +7,8 @@ const {
7
7
  genNodejs,
8
8
  genWebEsbuildJs,
9
9
  genWebEsbuildTs,
10
- genMockApi
10
+ genMockApi,
11
+ genExpressApi
11
12
  } = require('./manager');
12
13
  const prompts = require('prompts');
13
14
 
@@ -57,6 +58,15 @@ const questions = [
57
58
  title: 'MockAPI',
58
59
  description: 'API server with hai-server 0.0.4',
59
60
  value: 'mockapi'
61
+ },
62
+ {
63
+ title: 'Express API',
64
+ description: 'Express API with simple Sequelize',
65
+ value: 'expressapi'
66
+ },
67
+ {
68
+ title: 'Cancel',
69
+ value: 'cancel'
60
70
  }
61
71
  ],
62
72
  initial: 0
@@ -100,5 +110,10 @@ const questions = [
100
110
  genMockApi(res.name);
101
111
  return;
102
112
  }
113
+ if(res.type === 'expressapi') {
114
+ console.log('Create a new Express API...');
115
+ genExpressApi(res.name);
116
+ return;
117
+ }
103
118
 
104
119
  })();
@@ -0,0 +1,69 @@
1
+ # exapi
2
+
3
+ Exapi framework
4
+
5
+ Express based REST API sablon
6
+
7
+ ## Install
8
+
9
+ ```cmd
10
+ npm install
11
+ ```
12
+
13
+ ## Copy config file
14
+
15
+ Copy **config/default.json.example** to **config/default.json** file.
16
+
17
+ ## APP KEY generation
18
+
19
+ Run the genkey tools:
20
+
21
+ ```cmd
22
+ node tools/genkey.js
23
+ ```
24
+
25
+ ## Database settings
26
+
27
+ The database settings can be found at the following location:
28
+
29
+ * config/default.json
30
+
31
+ ### Database dialect
32
+
33
+ The default database is an in-memory database. Its contents are cleared after the server is restarted.
34
+
35
+ One of:
36
+
37
+ * sqlite
38
+ * mariadb
39
+
40
+ After installing the appropriate dependencies, it can be used:
41
+
42
+ * mysql
43
+ * postgres
44
+ * mssql
45
+ * db2
46
+ * snowflake
47
+ * oracle
48
+
49
+ With the `sqlite` option, the database is stored in the `database.sqlite` file, or you can add :memory:, then the database is stored in memory.
50
+
51
+ ## Starting
52
+
53
+ For development:
54
+
55
+ ```cmd
56
+ npm run dev
57
+ ```
58
+
59
+ Run productum:
60
+
61
+ ```cmd
62
+ npm start
63
+ ```
64
+
65
+ ## Licence
66
+
67
+ May be freely distributed under the MIT license.
68
+
69
+ Copyright (c) 2023 Sallai András
@@ -0,0 +1,103 @@
1
+ const bcrypt = require('bcryptjs')
2
+ const jwt = require('jsonwebtoken')
3
+ const User = require('../models/user')
4
+ const config = require('../../config/default.json')
5
+
6
+ const AuthController = {
7
+ async register(req, res) {
8
+ var clientError = false;
9
+ try {
10
+ if(!req.body.name ||
11
+ !req.body.email ||
12
+ !req.body.password ||
13
+ !req.body.password_confirmation) {
14
+ clientError = true
15
+ throw new Error('Error! Bad request data!')
16
+ }
17
+ if(req.body.password != req.body.password_confirmation) {
18
+ clientError = true
19
+ throw new Error('Error! The two password is not same!')
20
+ }
21
+ const user = await User.findOne({
22
+ where: { name: req.body.name }
23
+ })
24
+ if(user) {
25
+ clientError = true
26
+ throw new Error('Error! User already exists: ' + user.name)
27
+ }
28
+ AuthController.tryRegister(req, res)
29
+ } catch (error) {
30
+ if (clientError) {
31
+ res.status(400)
32
+ }else {
33
+ res.status(500)
34
+ }
35
+ await res.json({
36
+ success: false,
37
+ message: 'Error! User creation failed!',
38
+ error: error.message
39
+ })
40
+ }
41
+ },
42
+ async tryRegister(req, res) {
43
+ const user = {
44
+ name: req.body.name,
45
+ email: req.body.email,
46
+ password: bcrypt.hashSync(req.body.password)
47
+ }
48
+ await User.create(user)
49
+ .then( result => {
50
+ res.status(201)
51
+ res.json({
52
+ succes: true,
53
+ data: result
54
+ })
55
+ })
56
+ },
57
+ async login(req, res) {
58
+
59
+ try {
60
+ if(!req.body.name || !req.body.password) {
61
+ res.status(400)
62
+ throw new Error('Error! Bad name or password!')
63
+ }
64
+ const user = await User.findOne({
65
+ where: { name: req.body.name }
66
+ })
67
+
68
+ if(!user) {
69
+ res.status(404)
70
+ throw new Error('Error! User not found!')
71
+ }
72
+ var passwordIsValid = await bcrypt.compare(
73
+ req.body.password,
74
+ user.dataValues.password
75
+ );
76
+ if(!passwordIsValid) {
77
+ res.status(401)
78
+ throw new Error('Error! Password is not valid!')
79
+ }
80
+ AuthController.tryLogin(req, res, user)
81
+
82
+ } catch (error) {
83
+ res.json({
84
+ success: false,
85
+ message: 'Error! The login is failed!',
86
+ error: error.message
87
+ })
88
+ }
89
+ },
90
+ async tryLogin(req, res, user) {
91
+ var token = jwt.sign({ id: user.id }, config.app.key, {
92
+ expiresIn: 86400 //24 óra
93
+ })
94
+ res.status(200).json({
95
+ id: user.id,
96
+ name: user.name,
97
+ email: user.email,
98
+ accessToken: token
99
+ })
100
+ }
101
+ }
102
+
103
+ module.exports = AuthController
@@ -0,0 +1,27 @@
1
+ const User = require('../models/user')
2
+
3
+
4
+
5
+ const UserController = {
6
+ async index(req, res) {
7
+ try {
8
+ UserController.tryIndex(req, res)
9
+ }catch(error) {
10
+ res.status(500)
11
+ res.json({
12
+ success: false,
13
+ message: 'Error! The query is failed!'
14
+ })
15
+ }
16
+ },
17
+ async tryIndex(req, res) {
18
+ const users = await User.findAll()
19
+ res.status(200)
20
+ res.json({
21
+ success: true,
22
+ data: users
23
+ })
24
+ }
25
+ }
26
+
27
+ module.exports = UserController
@@ -0,0 +1,22 @@
1
+ const Sequelize = require('sequelize')
2
+ const config = require('../../config/default.json')
3
+
4
+ if(config.app.log != false) {
5
+ var log = console.log
6
+ }
7
+
8
+ console.log(typeof console.log)
9
+ const sequelize = new Sequelize(
10
+ config.db.name,
11
+ config.db.user,
12
+ config.db.pass,
13
+ {
14
+ logging: log,
15
+ dialect: config.db.dialect,
16
+ storage: config.db.path,
17
+ host: config.db.host,
18
+ dialectOptions: {}
19
+ }
20
+ )
21
+
22
+ module.exports = sequelize
@@ -0,0 +1,19 @@
1
+ const express = require('express')
2
+ const morgan = require('morgan')
3
+ const app = express()
4
+ const fs = require('fs')
5
+ const router = require('./routes/api')
6
+ const config = require('../config/default.json')
7
+
8
+ const PORT = config.app.port || 8000
9
+
10
+ const logfile = 'access.log'
11
+ var accessLogStream = fs.createWriteStream(logfile, { flags: 'a' })
12
+ app.use(morgan('dev', { stream: accessLogStream }))
13
+
14
+ app.use(express.json())
15
+ app.use('/api', router);
16
+
17
+ app.listen(PORT, () => {
18
+ console.log(`Listening on port: ${PORT}`)
19
+ })
@@ -0,0 +1,22 @@
1
+ const jwt = require("jsonwebtoken");
2
+ const config = require('../../config/default.json')
3
+
4
+ exports.verifyToken = (req, res, next) => {
5
+ let authData = req.headers.authorization;
6
+ if(!authData) {
7
+ return res.status(403).send({
8
+ message: 'No token provided!'
9
+ })
10
+ }
11
+ let token = authData.split(' ')[1];
12
+
13
+ jwt.verify(token, config.app.key, (err, decoded) => {
14
+ if(err) {
15
+ return res.status(401).send({
16
+ message: "Unauthorized!"
17
+ })
18
+ }
19
+ req.userId = decoded.id;
20
+ next()
21
+ })
22
+ };
@@ -0,0 +1,19 @@
1
+ const { DataTypes } = require('sequelize')
2
+ const sequelize = require('../database/database')
3
+
4
+ const User = sequelize.define('User', {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true
9
+ },
10
+ name: { type: DataTypes.STRING, allowNull: false },
11
+ email: { type: DataTypes.STRING, allowNull: true },
12
+ password: { type: DataTypes.STRING , allowNull: false }
13
+ })
14
+
15
+
16
+ sequelize.sync({
17
+ force: false
18
+ })
19
+ module.exports = User
@@ -0,0 +1,12 @@
1
+ const Router = require('express')
2
+ const router = Router()
3
+
4
+ const AuthController = require('../controllers/authcontroller')
5
+ const UserController = require('../controllers/usercontroller')
6
+ const { verifyToken } = require('../middleware/authjwt')
7
+
8
+ router.post('/register', AuthController.register)
9
+ router.post('/login', AuthController.login)
10
+ router.get('/users', [verifyToken], UserController.index)
11
+
12
+ module.exports = router
@@ -0,0 +1,15 @@
1
+ {
2
+ "app": {
3
+ "port": 8000,
4
+ "key": "",
5
+ "log": "console.log"
6
+ },
7
+ "db": {
8
+ "dialect": "sqlite",
9
+ "host": "127.0.0.1",
10
+ "name": "",
11
+ "user": "",
12
+ "pass": "",
13
+ "path": ":memory:"
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ # expressapi
2
+
3
+ ## API KEY
4
+
5
+ The app key generated with generate-api-key package.
6
+
7
+ ## Testing
8
+
9
+ Set in config/default.json file, the db.dialect to sqlite. Set db.path to :memory:
10
+
11
+ Start the application:
12
+
13
+ ```cmd
14
+ npm run dev
15
+ ```
@@ -0,0 +1,57 @@
1
+ # User documentation
2
+
3
+ ## Install dependencies
4
+
5
+ ```cmd
6
+ pnpm install
7
+ ```
8
+
9
+ ## Copy config file
10
+
11
+ Copy **config/default.json.example** to **config/default.json** file.
12
+
13
+ ## App key generation
14
+
15
+ ```cmd
16
+ node tools/genkey.js
17
+ ```
18
+
19
+ ## Database setup
20
+
21
+ Edit the config/default.json file.
22
+
23
+ ## Endpoints
24
+
25
+ All endpoint have a /api prefix.
26
+
27
+ | Endpoint | Method | Auth | Description |
28
+ |-|-|-|-|
29
+ | /register | POST | no | create user |
30
+ | /login | POST | no | login |
31
+ | /users | GET | yes | read users |
32
+
33
+ ## The register endpoint
34
+
35
+ ```json
36
+ {
37
+ "name": "joe",
38
+ "email": "joe@green.lan",
39
+ "password": "secret",
40
+ "password_confirmation": "secret"
41
+ }
42
+ ```
43
+
44
+ ## The login endpoint
45
+
46
+ ```json
47
+ {
48
+ "name": "joe",
49
+ "password": "secret"
50
+ }
51
+ ```
52
+
53
+ You receive the bearear token with accessToken key.
54
+
55
+ ## The users endpoint
56
+
57
+ Send the bearer token.
@@ -0,0 +1,4 @@
1
+ {
2
+ "watch": ["app/index.js", "app"],
3
+ "ext": "js"
4
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "expressapi",
3
+ "version": "1.0.1",
4
+ "description": "Express API with simple Sequelize",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "mocha",
8
+ "dev": "nodemon app",
9
+ "start": "node app"
10
+ },
11
+ "keywords": [
12
+ "express",
13
+ "api"
14
+ ],
15
+ "author": "Sallai András",
16
+ "license": "ISC",
17
+ "dependencies": {
18
+ "bcryptjs": "^2.4.3",
19
+ "express": "^4.18.2",
20
+ "generate-api-key": "^1.0.2",
21
+ "jsonwebtoken": "^9.0.0",
22
+ "mariadb": "^3.1.2",
23
+ "morgan": "^1.10.0",
24
+ "replace": "^1.2.2",
25
+ "sequelize": "^6.32.0",
26
+ "sqlite3": "^5.1.6"
27
+ },
28
+ "devDependencies": {
29
+ "nodemon": "^2.0.22",
30
+ "supertest": "^6.3.3"
31
+ }
32
+ }
@@ -0,0 +1,43 @@
1
+ const supertest = require('supertest')
2
+
3
+ describe('GET /api/users', () => {
4
+
5
+ const host = 'http://localhost:8000/api'
6
+ const restype= 'application/json; charset=utf-8'
7
+ var token = null
8
+
9
+ it('post /register ', function(done) {
10
+ supertest(host)
11
+ .post('/register')
12
+ .set('Accept', 'application/json')
13
+ .send({
14
+ name: 'mari',
15
+ email: 'mari@zold.lan',
16
+ password: 'titok',
17
+ password_confirmation: 'titok'
18
+ })
19
+ .expect('Content-Type', restype)
20
+ .expect(201, done)
21
+ })
22
+ it('post /login ', (done) => {
23
+ supertest(host)
24
+ .post('/login')
25
+ .set('Accept', 'application/json')
26
+ .send({
27
+ name: 'mari',
28
+ password: 'titok'
29
+ })
30
+ .expect('Content-Type', restype)
31
+ .expect(200, done)
32
+ .expect(res => {
33
+ token = res.body.accessToken
34
+ })
35
+ })
36
+ it('get /users ', function(done) {
37
+ supertest(host)
38
+ .get('/users')
39
+ .set('Accept', 'application/json')
40
+ .set('Authorization', 'Bearer ' + token)
41
+ .expect(200, done)
42
+ })
43
+ })
@@ -0,0 +1,19 @@
1
+ const fs = require('fs').promises
2
+ const path = require('path')
3
+ const fileName = '../config/default.json'
4
+ const { generateApiKey } = require('generate-api-key')
5
+
6
+ function generateKey(size = 32, format = 'base64') {
7
+ const buffer = crypto.randomBytes(size);
8
+ return buffer.toString(format);
9
+ }
10
+
11
+ fs.readFile(path.join(__dirname, fileName))
12
+ .then(body => JSON.parse(body))
13
+ .then(json => {
14
+ json.app.key = generateApiKey({method: 'bytes', length: 32})
15
+ return json
16
+ })
17
+ .then(json => JSON.stringify(json, null, 4))
18
+ .then(body => fs.writeFile(path.join(__dirname, fileName), body, 'utf8'))
19
+ .catch(error => console.log(error))
package/manager.js CHANGED
@@ -57,6 +57,13 @@ const genMockApi = (target) => {
57
57
  console.log('npm start');
58
58
  }
59
59
 
60
+ const genExpressApi = (target) => {
61
+ copyDir(`${dir}/expressapi`, target);
62
+ updatePackageName(`${target}/package.json`, target);
63
+ console.log('ExpressJS REST API sablon created');
64
+ console.log('Read docs/user_doc.md');
65
+ }
66
+
60
67
  const updatePackageName = (filePath, newName) => {
61
68
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
62
69
  if (content.name) {
@@ -87,5 +94,6 @@ module.exports = {
87
94
  genNodejs,
88
95
  genWebEsbuildJs,
89
96
  genWebEsbuildTs,
90
- genMockApi
97
+ genMockApi,
98
+ genExpressApi
91
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sip",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
4
4
  "main": "index.js",
5
5
  "bin": {
6
6
  "create-sip": "create-sip.js"