serverest 2.27.5 → 2.29.0-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverest",
3
- "version": "2.27.5",
3
+ "version": "2.29.0-beta.1",
4
4
  "description": "Servidor REST local de forma rápida e simples para estudo de testes de API",
5
5
  "author": "Paulo Gonçalves <author@serverest.dev> (https://www.linkedin.com/in/paulo-goncalves/)",
6
6
  "license": "GPL-3.0",
@@ -53,6 +53,7 @@
53
53
  "dd-trace": "^4.14.0",
54
54
  "debug": "^4.3.4",
55
55
  "dotenv": "^16.3.1",
56
+ "escape-string-regexp": "^4.0.0",
56
57
  "express": "^4.17.1",
57
58
  "express-async-errors": "^3.1.1",
58
59
  "express-query-int": "^3.0.0",
package/src/app.js CHANGED
@@ -9,7 +9,6 @@ const queryParser = require('express-query-int')
9
9
  const timeout = require('connect-timeout')
10
10
  const { join } = require('path')
11
11
  const swaggerUi = require('swagger-ui-express')
12
- const ddTrace = require('dd-trace')
13
12
 
14
13
  const {
15
14
  aplicacaoExecutandoLocalmente,
@@ -27,7 +26,8 @@ const packageJson = require('../package.json')
27
26
  const app = express()
28
27
 
29
28
  /* istanbul ignore next */
30
- if (formaDeExecucao() !== 'npm') {
29
+ if (!aplicacaoExecutandoLocalmente()) {
30
+ const ddTrace = require('dd-trace')
31
31
  ddTrace.init()
32
32
  ddTrace.use('express')
33
33
  }
@@ -44,6 +44,8 @@ app.disable('etag')
44
44
  /* istanbul ignore else */
45
45
  if (!conf.semHeaderDeSeguranca) {
46
46
  app.disable('x-powered-by')
47
+ app.disable('Server')
48
+ app.disable('X-Cloud-Trace-Context')
47
49
  app.use((req, res, next) => {
48
50
  res.set('x-dns-prefetch-control', 'off')
49
51
  res.set('x-frame-options', 'SAMEORIGIN')
@@ -62,25 +64,18 @@ if (aplicacaoExecutandoLocalmente() && !ehAmbienteDeTestes) {
62
64
 
63
65
  localMonitor(app)
64
66
 
65
- /* istanbul ignore next */
66
- switch (formaDeExecucao()) {
67
- case 'serverest.dev':
68
- swaggerDocument.host = 'serverest.dev'
69
- break
70
- case 'staging.serverest.dev':
71
- swaggerDocument.host = 'staging.serverest.dev'
72
- break
73
- case 'agilizei':
74
- swaggerDocument.host = 'agilizei.serverest.dev'
75
- break
76
- case 'compassuol':
77
- swaggerDocument.host = 'compassuol.serverest.dev'
78
- break
79
- case 'cesarschool':
80
- swaggerDocument.host = 'cesarschool.serverest.dev'
81
- break
67
+ const hostMapping = {
68
+ 'serverest.dev': 'serverest.dev',
69
+ 'staging.serverest.dev': 'staging.serverest.dev',
70
+ agilizei: 'agilizei.serverest.dev',
71
+ compassuol: 'compassuol.serverest.dev',
72
+ cesarschool: 'cesarschool.serverest.dev'
82
73
  }
83
74
 
75
+ const environment = formaDeExecucao()
76
+
77
+ swaggerDocument.host = hostMapping?.[environment] ?? swaggerDocument.host
78
+
84
79
  swaggerDocument.info.version = packageJson.version
85
80
 
86
81
  const uiOptions = {
@@ -6,11 +6,13 @@ const { conf } = require('../utils/conf')
6
6
  const usuariosService = require('../services/usuarios-service')
7
7
 
8
8
  exports.post = async (req, res) => {
9
- if (await usuariosService.existeUsuario(req.body)) {
10
- const token = authService.createToken(req.body)
11
- /* istanbul ignore next */
12
- const authorization = conf.semBearer ? token : `Bearer ${token}`
13
- return res.status(200).send({ message: constant.LOGIN_SUCCESS, authorization })
9
+ const userExists = await usuariosService.existeUsuario(req.body)
10
+ if (!userExists) {
11
+ return res.status(401).send({ message: constant.LOGIN_FAIL })
14
12
  }
15
- res.status(401).send({ message: constant.LOGIN_FAIL })
13
+
14
+ const token = authService.createToken(req.body)
15
+ /* istanbul ignore next */
16
+ const authorization = conf.semBearer ? token : `Bearer ${token}`
17
+ return res.status(200).send({ message: constant.LOGIN_SUCCESS, authorization })
16
18
  }
@@ -19,18 +19,25 @@ exports.getOne = async (req, res) => {
19
19
  }
20
20
 
21
21
  exports.post = async (req, res) => {
22
- if (await service.existeProduto({ nome: req.body.nome.trim() })) {
22
+ const { nome } = req.body
23
+ const trimmedName = nome.trim()
24
+
25
+ const productExists = await service.existeProduto({ nome: trimmedName })
26
+
27
+ if (productExists) {
23
28
  return res.status(400).send({ message: constant.NAME_ALREADY_USED })
24
29
  }
25
- const dadosCadastrados = await service.criarProduto(req.body)
26
- res.status(201).send({ message: constant.POST_SUCCESS, _id: dadosCadastrados._id })
30
+
31
+ const { _id } = await service.criarProduto(req.body)
32
+
33
+ res.status(201).send({ message: constant.POST_SUCCESS, _id })
27
34
  }
28
35
 
29
36
  exports.delete = async (req, res) => {
30
37
  const carrinhoDoUsuario = await carrinhosService.getAll({ produtos: { $elemMatch: { idProduto: req.params.id } } })
31
- const usuarioTemCarrinho = typeof carrinhoDoUsuario[0] !== 'undefined'
38
+ const usuarioTemCarrinho = carrinhoDoUsuario.length > 0
32
39
  if (usuarioTemCarrinho) {
33
- const idCarrinhos = carrinhoDoUsuario.map((carrinhos) => { return carrinhos._id })
40
+ const idCarrinhos = carrinhoDoUsuario.map(carrinhos => carrinhos._id)
34
41
  return res.status(400).send({ message: constant.DELETE_PRODUCT_WITH_CART, idCarrinhos })
35
42
  }
36
43
  const quantidadeRegistrosExcluidos = await service.deleteById(req.params.id)
@@ -39,11 +46,20 @@ exports.delete = async (req, res) => {
39
46
  }
40
47
 
41
48
  exports.put = async (req, res) => {
42
- const idInexistenteENomeRepetido = await service.existeProduto({ nome: req.body.nome.trim(), $not: { _id: req.params.id } })
43
- if (idInexistenteENomeRepetido) {
44
- return res.status(400).send({ message: constant.NAME_ALREADY_USED })
49
+ const { id } = req.params
50
+ const { nome } = req.body
51
+ const product = { nome: nome.trim(), $not: { _id: id } }
52
+
53
+ const productExists = await service.existeProduto(product)
54
+
55
+ if (productExists) {
56
+ return res.status(400).json({ message: constant.NAME_ALREADY_USED })
45
57
  }
46
- const registroCriado = await service.createOrUpdateById(req.params.id, req.body)
47
- if (registroCriado._id !== req.params.id) { return res.status(201).send({ message: constant.POST_SUCCESS, _id: registroCriado._id }) }
48
- res.status(200).send({ message: constant.PUT_SUCCESS })
58
+
59
+ const updatedProduct = await service.createOrUpdateById(id, req.body)
60
+ if (updatedProduct._id !== id) {
61
+ return res.status(201).json({ message: constant.POST_SUCCESS, _id: updatedProduct._id })
62
+ }
63
+
64
+ return res.status(200).json({ message: constant.PUT_SUCCESS })
49
65
  }
@@ -1,9 +1,17 @@
1
+ const escapeStringRegexp = require('escape-string-regexp')
2
+
3
+ const { log } = require('./logger')
4
+
1
5
  module.exports = queryString => {
2
6
  Object.keys(queryString).forEach(key => {
3
7
  if (['nome', 'password', 'descricao'].includes(key)) {
4
8
  try {
5
- queryString[key] = new RegExp(queryString[key])
6
- } catch (error) {}
9
+ // Add 'i' flag for case-insensitive matching
10
+ queryString[key] = new RegExp(escapeStringRegexp(queryString[key]), 'i')
11
+ } catch (error) /* istanbul ignore next */ {
12
+ log({ level: 'error', message: `Failed to convert ${key} to RegExp: ${error.message}` })
13
+ throw error
14
+ }
7
15
  }
8
16
  })
9
17
  return queryString
@@ -2,40 +2,39 @@
2
2
 
3
3
  const { conf } = require('./conf')
4
4
 
5
+ const environments = new Set([
6
+ 'docker',
7
+ 'serverest.dev',
8
+ 'staging.serverest.dev',
9
+ 'agilizei',
10
+ 'cesarschool',
11
+ 'compassuol'
12
+ ])
13
+
5
14
  function formaDeExecucao () {
6
- if (process.env.ENVIRONMENT === 'docker' ||
7
- process.env.ENVIRONMENT === 'serverest.dev' ||
8
- process.env.ENVIRONMENT === 'staging.serverest.dev' ||
9
- process.env.ENVIRONMENT === 'agilizei' ||
10
- process.env.ENVIRONMENT === 'cesarschool' ||
11
- process.env.ENVIRONMENT === 'compassuol') {
12
- return process.env.ENVIRONMENT
13
- }
14
- return 'npm'
15
+ const env = process.env.ENVIRONMENT
16
+ return environments.has(env) ? env : 'npm'
15
17
  }
16
18
 
17
19
  const ehAmbienteDeTestes = process.env.NODE_ENV === 'serverest-test'
18
20
  const ehAmbienteDeDesenvolvimento = process.env.NODE_ENV === 'serverest-development'
19
21
 
20
22
  const aplicacaoExecutandoLocalmente = () => {
21
- return (formaDeExecucao() === 'npm' || formaDeExecucao() === 'docker')
23
+ const environment = formaDeExecucao()
24
+ return environment === 'npm' || environment === 'docker'
25
+ }
26
+
27
+ const urlMapping = {
28
+ 'serverest.dev': 'https://serverest.dev',
29
+ 'staging.serverest.dev': 'https://staging.serverest.dev',
30
+ agilizei: 'https://agilizei.serverest.dev',
31
+ compassuol: 'https://compassuol.serverest.dev',
32
+ cesarschool: 'https://cesarschool.serverest.dev'
22
33
  }
23
34
 
24
35
  function urlDocumentacao () {
25
- switch (formaDeExecucao()) {
26
- case 'serverest.dev':
27
- return 'https://serverest.dev'
28
- case 'staging.serverest.dev':
29
- return 'https://staging.serverest.dev'
30
- case 'agilizei':
31
- return 'https://agilizei.serverest.dev'
32
- case 'compassuol':
33
- return 'https://compassuol.serverest.dev'
34
- case 'cesarschool':
35
- return 'https://cesarschool.serverest.dev'
36
- default:
37
- return `http://localhost:${conf.porta}`
38
- }
36
+ const environment = formaDeExecucao()
37
+ return urlMapping[environment] || `http://localhost:${conf.porta}`
39
38
  }
40
39
 
41
40
  module.exports = {
@@ -2,23 +2,29 @@
2
2
 
3
3
  const axios = require('axios')
4
4
 
5
+ const { log } = require('../utils/logger')
6
+
5
7
  module.exports = async () => {
6
- const { data } = await axios.get('https://opencollective.com/serverest/members/all.json')
7
- const userArray = removeAdminAndHostUser(data)
8
- let arrayNameUsers = getOnlyNameFromAllUsers(userArray)
9
- arrayNameUsers = removeDuplicatedValuesFromArray(arrayNameUsers)
10
- const randomFinancialContributor = arrayNameUsers[Math.floor(Math.random() * arrayNameUsers.length)]
11
- return randomFinancialContributor
8
+ try {
9
+ const { data: users } = await axios.get('https://opencollective.com/serverest/members/all.json')
10
+ const filteredUsers = removeAdminAndHostUser(users)
11
+ const uniqueUserNames = getUniqueUserNames(filteredUsers)
12
+ const randomFinancialContributor = getRandomElement(uniqueUserNames)
13
+ return randomFinancialContributor
14
+ } catch (error) {
15
+ log({ level: 'error', message: 'Failed to get financial contributor.' })
16
+ }
12
17
  }
13
18
 
14
19
  const removeAdminAndHostUser = userArray => {
15
20
  return userArray.filter((user) => user.role !== 'ADMIN' && user.role !== 'HOST' && user.name !== 'Paulo Gonçalves')
16
21
  }
17
22
 
18
- const getOnlyNameFromAllUsers = userArray => {
19
- return Object.keys(userArray).map((key) => userArray[key].name)
23
+ const getUniqueUserNames = userArray => {
24
+ const names = userArray.map(user => user.name)
25
+ return [...new Set(names)]
20
26
  }
21
27
 
22
- const removeDuplicatedValuesFromArray = array => {
23
- return [...new Set(array)]
28
+ const getRandomElement = array => {
29
+ return array[Math.floor(Math.random() * array.length)]
24
30
  }
@@ -22,23 +22,24 @@ module.exports = async app => {
22
22
  return
23
23
  }
24
24
  const { porta, timeout, nodoc, nobearer, nosec } = require('../server').argv
25
+ const urlsToSkip = [
26
+ '/__messages__',
27
+ '/favicon.ico',
28
+ '/socket.io',
29
+ '/swagger-ui.css',
30
+ '/swagger-ui.css.map',
31
+ '/swagger-ui-init.js',
32
+ '/swagger-ui-standalone-preset.js',
33
+ '/swagger-ui-standalone-preset.js.map',
34
+ '/swagger-ui-bundle.js',
35
+ '/swagger-ui-bundle.js.map'
36
+ ]
25
37
  const moesifMiddleware = moesif({
26
38
  applicationId: process.env.MOESIF_APPLICATION_ID,
27
39
  identifyUser: (req, res) => { return formaDeExecucao() },
28
40
  identifyCompany: (req, res) => { return version },
29
41
  skip: (req, res) => {
30
- if (req.originalUrl === '/__messages__' ||
31
- req.originalUrl === '/favicon.ico' ||
32
- req.originalUrl === '/socket.io' ||
33
- req.originalUrl === '/swagger-ui.css' ||
34
- req.originalUrl === '/swagger-ui.css.map' ||
35
- req.originalUrl === '/swagger-ui-init.js' ||
36
- req.originalUrl === '/swagger-ui-standalone-preset.js' ||
37
- req.originalUrl === '/swagger-ui-standalone-preset.js.map' ||
38
- req.originalUrl === '/swagger-ui-bundle.js' ||
39
- req.originalUrl === '/swagger-ui-bundle.js.map') {
40
- return true
41
- }
42
+ return urlsToSkip.includes(req.originalUrl)
42
43
  },
43
44
  getMetadata: (req, res) => {
44
45
  return {
@@ -1,15 +1,20 @@
1
- const tracer = require('dd-trace')
2
- const formats = require('dd-trace/ext/formats')
1
+ const { aplicacaoExecutandoLocalmente } = require('./ambiente')
2
+ /* istanbul ignore next */
3
+ const tracer = aplicacaoExecutandoLocalmente() ? null : require('dd-trace')
4
+ /* istanbul ignore next */
5
+ const formats = tracer ? require('dd-trace/ext/formats') : null
3
6
 
4
7
  function log ({ level = 'alert', message }) {
5
- const span = tracer.scope().active()
6
8
  const time = new Date().toISOString()
7
9
  const record = { time, level, message }
10
+ console.log(record)
8
11
  /* istanbul ignore next */
9
- if (span) {
10
- tracer.inject(span.context(), formats.LOG, record)
12
+ if (tracer) {
13
+ const span = tracer.scope().active()
14
+ if (span) {
15
+ tracer.inject(span.context(), formats.LOG, record)
16
+ }
11
17
  }
12
- console.log(record)
13
18
  }
14
19
 
15
20
  module.exports = { log }