create-sip 0.9.0 → 0.10.0

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,65 @@
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
+ ## APP KEY generation
14
+
15
+ Run the genkey tools:
16
+
17
+ ```cmd
18
+ node tools/genkey.js
19
+ ```
20
+
21
+ ## Database settings
22
+
23
+ The database settings can be found at the following location:
24
+
25
+ * config/default.json
26
+
27
+ ### Database dialect
28
+
29
+ The default database is an in-memory database. Its contents are cleared after the server is restarted.
30
+
31
+ One of:
32
+
33
+ * sqlite
34
+ * mariadb
35
+
36
+ After installing the appropriate dependencies, it can be used:
37
+
38
+ * mysql
39
+ * postgres
40
+ * mssql
41
+ * db2
42
+ * snowflake
43
+ * oracle
44
+
45
+ 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.
46
+
47
+ ## Starting
48
+
49
+ For development:
50
+
51
+ ```cmd
52
+ npm run dev
53
+ ```
54
+
55
+ Run productum:
56
+
57
+ ```cmd
58
+ npm start
59
+ ```
60
+
61
+ ## Licence
62
+
63
+ May be freely distributed under the MIT license.
64
+
65
+ 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,53 @@
1
+ # User documentation
2
+
3
+ ## Install dependencies
4
+
5
+ ```cmd
6
+ pnpm install
7
+ ```
8
+
9
+ ## App key generation
10
+
11
+ ```cmd
12
+ node tools/genkey.js
13
+ ```
14
+
15
+ ## Database setup
16
+
17
+ Edit the config/default.json file.
18
+
19
+ ## Endpoints
20
+
21
+ All endpoint have a /api prefix.
22
+
23
+ | Endpoint | Method | Auth | Description |
24
+ |-|-|-|-|
25
+ | /register | POST | no | create user |
26
+ | /login | POST | no | login |
27
+ | /users | GET | yes | read users |
28
+
29
+ ## The register endpoint
30
+
31
+ ```json
32
+ {
33
+ "name": "joe",
34
+ "email": "joe@green.lan",
35
+ "password": "secret",
36
+ "password_confirmation": "secret"
37
+ }
38
+ ```
39
+
40
+ ## The login endpoint
41
+
42
+ ```json
43
+ {
44
+ "name": "joe",
45
+ "password": "secret"
46
+ }
47
+ ```
48
+
49
+ You receive the bearear token with accessToken key.
50
+
51
+ ## The users endpoint
52
+
53
+ 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.0",
4
4
  "main": "index.js",
5
5
  "bin": {
6
6
  "create-sip": "create-sip.js"