@naturalcycles/backend-lib 2.73.3 → 3.0.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.
Files changed (95) hide show
  1. package/dist/admin/admin.mw.d.ts +4 -4
  2. package/dist/admin/base.admin.service.d.ts +11 -12
  3. package/dist/db/httpDBRequestHandler.d.ts +2 -2
  4. package/dist/index.d.ts +25 -24
  5. package/dist/index.js +28 -50
  6. package/dist/sentry/sentry.shared.service.d.ts +3 -3
  7. package/dist/server/appEngineLogMiddleware.d.ts +13 -0
  8. package/dist/server/{handlers/createGaeLogMiddleware.js → appEngineLogMiddleware.js} +4 -4
  9. package/dist/server/{handlers/asyncLocalStorage.mw.d.ts → asyncLocalStorageMiddleware.d.ts} +4 -4
  10. package/dist/server/{handlers/asyncLocalStorage.mw.js → asyncLocalStorageMiddleware.js} +5 -5
  11. package/dist/server/{handlers/bodyParserTimeout.mw.d.ts → bodyParserTimeoutMiddleware.d.ts} +4 -4
  12. package/dist/server/{handlers/bodyParserTimeout.mw.js → bodyParserTimeoutMiddleware.js} +10 -7
  13. package/dist/server/catchWrapper.d.ts +2 -2
  14. package/dist/server/createDefaultApp.d.ts +2 -2
  15. package/dist/server/createDefaultApp.js +13 -13
  16. package/dist/server/createDefaultApp.model.d.ts +8 -8
  17. package/dist/server/deployInfo.util.d.ts +1 -1
  18. package/dist/server/genericErrorMiddleware.d.ts +12 -0
  19. package/dist/server/{handlers/genericErrorHandler.mw.js → genericErrorMiddleware.js} +14 -7
  20. package/dist/server/getDefaultRouter.d.ts +2 -2
  21. package/dist/server/methodOverrideMiddleware.d.ts +8 -0
  22. package/dist/server/{handlers/methodOverride.mw.js → methodOverrideMiddleware.js} +3 -3
  23. package/dist/server/notFoundMiddleware.d.ts +2 -0
  24. package/dist/server/notFoundMiddleware.js +10 -0
  25. package/dist/server/okMiddleware.d.ts +2 -0
  26. package/dist/server/{handlers/okHandler.mw.js → okMiddleware.js} +3 -3
  27. package/dist/server/{handlers/reqValidation.mw.d.ts → reqValidationMiddleware.d.ts} +2 -2
  28. package/dist/server/{handlers/reqValidation.mw.js → reqValidationMiddleware.js} +0 -0
  29. package/dist/server/request.log.util.d.ts +2 -2
  30. package/dist/server/request.util.d.ts +10 -2
  31. package/dist/server/request.util.js +8 -0
  32. package/dist/server/requestTimeoutMiddleware.d.ts +31 -0
  33. package/dist/server/requestTimeoutMiddleware.js +68 -0
  34. package/dist/server/{handlers/safeJsonMiddleware.d.ts → safeJsonMiddleware.d.ts} +2 -2
  35. package/dist/server/{handlers/safeJsonMiddleware.js → safeJsonMiddleware.js} +0 -0
  36. package/dist/server/server.model.d.ts +37 -0
  37. package/dist/server/server.model.js +2 -0
  38. package/dist/server/serverStatsMiddleware.d.ts +13 -0
  39. package/dist/server/{handlers/serverStatsMiddleware.js → serverStatsMiddleware.js} +2 -2
  40. package/dist/server/serverStatusMiddleware.d.ts +3 -0
  41. package/dist/server/{handlers/statusHandler.js → serverStatusMiddleware.js} +7 -7
  42. package/dist/server/simpleRequestLoggerMiddleware.d.ts +12 -0
  43. package/dist/server/{handlers/simpleRequestLogger.mw.js → simpleRequestLoggerMiddleware.js} +5 -5
  44. package/dist/server/startServer.model.d.ts +2 -2
  45. package/dist/server/{handlers/validate.mw.d.ts → validateMiddleware.d.ts} +5 -5
  46. package/dist/server/{handlers/validate.mw.js → validateMiddleware.js} +0 -0
  47. package/dist/testing/express.test.service.d.ts +5 -5
  48. package/package.json +1 -1
  49. package/src/admin/admin.mw.ts +7 -4
  50. package/src/admin/base.admin.service.ts +11 -12
  51. package/src/admin/secureHeader.mw.ts +2 -2
  52. package/src/db/httpDBRequestHandler.ts +2 -3
  53. package/src/index.ts +54 -68
  54. package/src/sentry/sentry.shared.service.ts +3 -4
  55. package/src/server/{handlers/createGaeLogMiddleware.ts → appEngineLogMiddleware.ts} +4 -25
  56. package/src/server/{handlers/asyncLocalStorage.mw.ts → asyncLocalStorageMiddleware.ts} +5 -5
  57. package/src/server/{handlers/bodyParserTimeout.mw.ts → bodyParserTimeoutMiddleware.ts} +14 -13
  58. package/src/server/catchWrapper.ts +2 -2
  59. package/src/server/createDefaultApp.model.ts +8 -8
  60. package/src/server/createDefaultApp.ts +22 -19
  61. package/src/server/deployInfo.util.ts +1 -1
  62. package/src/server/{handlers/genericErrorHandler.mw.ts → genericErrorMiddleware.ts} +19 -13
  63. package/src/server/getDefaultRouter.ts +2 -2
  64. package/src/server/{handlers/methodOverride.mw.ts → methodOverrideMiddleware.ts} +5 -3
  65. package/src/server/notFoundMiddleware.ts +8 -0
  66. package/src/server/okMiddleware.ts +7 -0
  67. package/src/server/{handlers/reqValidation.mw.ts → reqValidationMiddleware.ts} +2 -2
  68. package/src/server/request.log.util.ts +2 -2
  69. package/src/server/request.util.ts +10 -2
  70. package/src/server/requestTimeoutMiddleware.ts +117 -0
  71. package/src/server/{handlers/safeJsonMiddleware.ts → safeJsonMiddleware.ts} +3 -3
  72. package/src/server/server.model.ts +56 -0
  73. package/src/server/{handlers/serverStatsMiddleware.ts → serverStatsMiddleware.ts} +4 -5
  74. package/src/server/{handlers/statusHandler.ts → serverStatusMiddleware.ts} +5 -5
  75. package/src/server/{handlers/simpleRequestLogger.mw.ts → simpleRequestLoggerMiddleware.ts} +8 -7
  76. package/src/server/startServer.model.ts +2 -2
  77. package/src/server/{handlers/validate.mw.ts → validateMiddleware.ts} +6 -6
  78. package/src/testing/express.test.service.ts +6 -7
  79. package/dist/server/handlers/createGaeLogMiddleware.d.ts +0 -30
  80. package/dist/server/handlers/genericErrorHandler.mw.d.ts +0 -13
  81. package/dist/server/handlers/methodOverride.mw.d.ts +0 -8
  82. package/dist/server/handlers/notFoundHandler.mw.d.ts +0 -2
  83. package/dist/server/handlers/notFoundHandler.mw.js +0 -9
  84. package/dist/server/handlers/okHandler.mw.d.ts +0 -2
  85. package/dist/server/handlers/requestTimeout.mw.d.ts +0 -16
  86. package/dist/server/handlers/requestTimeout.mw.js +0 -34
  87. package/dist/server/handlers/sentryErrorHandler.mw.d.ts +0 -10
  88. package/dist/server/handlers/sentryErrorHandler.mw.js +0 -26
  89. package/dist/server/handlers/serverStatsMiddleware.d.ts +0 -13
  90. package/dist/server/handlers/simpleRequestLogger.mw.d.ts +0 -12
  91. package/dist/server/handlers/statusHandler.d.ts +0 -3
  92. package/src/server/handlers/notFoundHandler.mw.ts +0 -7
  93. package/src/server/handlers/okHandler.mw.ts +0 -7
  94. package/src/server/handlers/requestTimeout.mw.ts +0 -62
  95. package/src/server/handlers/sentryErrorHandler.mw.ts +0 -34
package/src/index.ts CHANGED
@@ -10,57 +10,60 @@ import { FirebaseSharedService } from './admin/firebase.shared.service'
10
10
  import { createSecureHeaderMiddleware, SecureHeaderMiddlewareCfg } from './admin/secureHeader.mw'
11
11
  import { BaseEnv } from './env/env.model'
12
12
  import { EnvSharedService, EnvSharedServiceCfg } from './env/env.shared.service'
13
- import { isGAE } from './gae/appEngine.util'
13
+ export * from './gae/appEngine.util'
14
14
  import { SentrySharedService, SentrySharedServiceCfg } from './sentry/sentry.shared.service'
15
- import { catchWrapper } from './server/catchWrapper'
16
- import { createDefaultApp } from './server/createDefaultApp'
15
+ export * from './server/catchWrapper'
16
+ export * from './server/createDefaultApp'
17
17
  import {
18
18
  DefaultAppCfg,
19
- RequestHandlerCfg,
20
- RequestHandlerWithPath,
19
+ BackendRequestHandlerCfg,
20
+ BackendRequestHandlerWithPath,
21
21
  } from './server/createDefaultApp.model'
22
- import { getDeployInfo } from './server/deployInfo.util'
23
- import { getDefaultRouter } from './server/getDefaultRouter'
22
+ export * from './server/deployInfo.util'
23
+ export * from './server/getDefaultRouter'
24
24
  import {
25
- bodyParserTimeout,
26
- BodyParserTimeoutCfg,
25
+ bodyParserTimeoutMiddleware,
26
+ BodyParserTimeoutMiddlewareCfg,
27
27
  clearBodyParserTimeout,
28
- } from './server/handlers/bodyParserTimeout.mw'
29
- import { genericErrorHandler, respondWithError } from './server/handlers/genericErrorHandler.mw'
28
+ } from './server/bodyParserTimeoutMiddleware'
29
+ export * from './server/genericErrorMiddleware'
30
+ export * from './server/serverStatsMiddleware'
30
31
  import {
31
- serverStatsHTMLHandler,
32
- serverStatsMiddleware,
33
- } from './server/handlers/serverStatsMiddleware'
34
- import { methodOverride, MethodOverrideCfg } from './server/handlers/methodOverride.mw'
35
- import { notFoundHandler } from './server/handlers/notFoundHandler.mw'
36
- import { okHandler } from './server/handlers/okHandler.mw'
37
- import { requestTimeout, RequestTimeoutCfg } from './server/handlers/requestTimeout.mw'
38
- import { reqValidation, ReqValidationOptions } from './server/handlers/reqValidation.mw'
32
+ methodOverrideMiddleware,
33
+ MethodOverrideMiddlewareCfg,
34
+ } from './server/methodOverrideMiddleware'
35
+ export * from './server/notFoundMiddleware'
36
+ export * from './server/okMiddleware'
37
+ import { RequestTimeoutMiddlewareCfg } from './server/requestTimeoutMiddleware'
38
+ export * from './server/requestTimeoutMiddleware'
39
+ import { reqValidation, ReqValidationOptions } from './server/reqValidationMiddleware'
39
40
  import {
40
- simpleRequestLogger,
41
- SimpleRequestLoggerCfg,
42
- } from './server/handlers/simpleRequestLogger.mw'
43
- import { statusHandler, statusHandlerData } from './server/handlers/statusHandler'
44
- import { validateBody, validateParams, validateQuery } from './server/handlers/validate.mw'
45
- import { coloredHttpCode, logRequest } from './server/request.log.util'
41
+ simpleRequestLoggerMiddleware,
42
+ SimpleRequestLoggerMiddlewareCfg,
43
+ } from './server/simpleRequestLoggerMiddleware'
44
+ import { serverStatusMiddleware, getServerStatusData } from './server/serverStatusMiddleware'
45
+ export * from './server/validateMiddleware'
46
+ export * from './server/request.log.util'
46
47
  import { BackendServer, startServer } from './server/startServer'
47
48
  import { StartServerCfg, StartServerData } from './server/startServer.model'
48
- import {
49
- createAsyncLocalStorage,
50
- getRequest,
51
- getRequestLogger,
52
- requestLogger,
53
- } from './server/handlers/asyncLocalStorage.mw'
54
- import type { RequestWithLog } from './server/handlers/createGaeLogMiddleware'
55
- export * from './server/handlers/createGaeLogMiddleware'
56
- import { safeJsonMiddleware } from './server/handlers/safeJsonMiddleware'
49
+ export * from './server/asyncLocalStorageMiddleware'
50
+ import type {
51
+ BackendRequest,
52
+ BackendRequestHandler,
53
+ BackendResponse,
54
+ BackendErrorRequestHandler,
55
+ BackendRouter,
56
+ BackendApplication,
57
+ } from './server/server.model'
58
+ export * from './server/appEngineLogMiddleware'
59
+ export * from './server/safeJsonMiddleware'
57
60
  export * from './server/request.util'
58
61
 
59
62
  export type {
60
- MethodOverrideCfg,
63
+ MethodOverrideMiddlewareCfg,
61
64
  SentrySharedServiceCfg,
62
- RequestHandlerWithPath,
63
- RequestHandlerCfg,
65
+ BackendRequestHandlerWithPath,
66
+ BackendRequestHandlerCfg,
64
67
  DefaultAppCfg,
65
68
  StartServerCfg,
66
69
  StartServerData,
@@ -71,11 +74,16 @@ export type {
71
74
  AdminInfo,
72
75
  RequireAdminCfg,
73
76
  SecureHeaderMiddlewareCfg,
74
- BodyParserTimeoutCfg,
75
- RequestTimeoutCfg,
76
- SimpleRequestLoggerCfg,
77
+ BodyParserTimeoutMiddlewareCfg,
78
+ RequestTimeoutMiddlewareCfg,
79
+ SimpleRequestLoggerMiddlewareCfg,
77
80
  ReqValidationOptions,
78
- RequestWithLog,
81
+ BackendRequest,
82
+ BackendRequestHandler,
83
+ BackendResponse,
84
+ BackendErrorRequestHandler,
85
+ BackendRouter,
86
+ BackendApplication,
79
87
  }
80
88
 
81
89
  export {
@@ -83,39 +91,17 @@ export {
83
91
  SentrySharedService,
84
92
  EnvSharedService,
85
93
  reqValidation,
86
- notFoundHandler,
87
- genericErrorHandler,
88
- methodOverride,
89
- createDefaultApp,
94
+ methodOverrideMiddleware,
90
95
  startServer,
91
- catchWrapper,
92
- getDefaultRouter,
93
- isGAE,
94
- statusHandler,
95
- statusHandlerData,
96
- okHandler,
97
- getDeployInfo,
96
+ serverStatusMiddleware,
97
+ getServerStatusData,
98
98
  onFinished,
99
- respondWithError,
100
- logRequest,
101
99
  FirebaseSharedService,
102
100
  createAdminMiddleware,
103
101
  BaseAdminService,
104
102
  loginHtml,
105
103
  createSecureHeaderMiddleware,
106
- bodyParserTimeout,
104
+ bodyParserTimeoutMiddleware,
107
105
  clearBodyParserTimeout,
108
- requestTimeout,
109
- simpleRequestLogger,
110
- coloredHttpCode,
111
- validateBody,
112
- validateParams,
113
- validateQuery,
114
- createAsyncLocalStorage,
115
- getRequest,
116
- getRequestLogger,
117
- requestLogger,
118
- serverStatsHTMLHandler,
119
- serverStatsMiddleware,
120
- safeJsonMiddleware,
106
+ simpleRequestLoggerMiddleware,
121
107
  }
@@ -3,8 +3,7 @@ import { inspectAny, inspectAnyStringifyFn } from '@naturalcycles/nodejs-lib'
3
3
  import { Severity } from '@sentry/node'
4
4
  import type { Breadcrumb, NodeOptions } from '@sentry/node'
5
5
  import type * as SentryLib from '@sentry/node'
6
- import { ErrorRequestHandler, RequestHandler } from 'express'
7
- import { getRequestLogger } from '../index'
6
+ import { BackendErrorRequestHandler, BackendRequestHandler, getRequestLogger } from '../index'
8
7
 
9
8
  export interface SentrySharedServiceCfg extends NodeOptions {}
10
9
 
@@ -51,7 +50,7 @@ export class SentrySharedService {
51
50
  *
52
51
  * UPD: to be tested. Without it - request is not enriched and the error is less useful.
53
52
  */
54
- getRequestHandler(): RequestHandler {
53
+ getRequestHandler(): BackendRequestHandler {
55
54
  return this.sentry().Handlers.requestHandler()
56
55
  }
57
56
 
@@ -60,7 +59,7 @@ export class SentrySharedService {
60
59
  *
61
60
  * @deprecated
62
61
  */
63
- getErrorHandler(): ErrorRequestHandler {
62
+ getErrorHandler(): BackendErrorRequestHandler {
64
63
  return this.sentry().Handlers.errorHandler()
65
64
  }
66
65
 
@@ -1,29 +1,8 @@
1
1
  import { inspect } from 'util'
2
2
  import { dimGrey } from '@naturalcycles/nodejs-lib/dist/colors'
3
3
  import { inspectAny } from '@naturalcycles/nodejs-lib'
4
- import { AnyObject, CommonLogFunction, CommonLogger } from '@naturalcycles/js-lib'
5
- import { Request, RequestHandler } from 'express'
6
-
7
- /**
8
- * Use this interface instead of express.Request in cases when TypeScript gives an error, because it haven't "included" this very file
9
- */
10
- export interface RequestWithLog extends Request {
11
- log: CommonLogFunction
12
- warn: CommonLogFunction
13
- error: CommonLogFunction
14
-
15
- requestId?: string
16
- }
17
-
18
- declare module 'http' {
19
- interface IncomingMessage {
20
- log: CommonLogFunction
21
- warn: CommonLogFunction
22
- error: CommonLogFunction
23
-
24
- requestId?: string
25
- }
26
- }
4
+ import { AnyObject, CommonLogger } from '@naturalcycles/js-lib'
5
+ import { BackendRequestHandler } from './server.model'
27
6
 
28
7
  const { GOOGLE_CLOUD_PROJECT, GAE_INSTANCE } = process.env
29
8
  const isGAE = !!GAE_INSTANCE
@@ -71,7 +50,7 @@ function logToDev(requestId: string | null, args: any[]): void {
71
50
  )
72
51
  }
73
52
 
74
- export function createGAELogMiddleware(): RequestHandler {
53
+ export function appEngineLogMiddleware(): BackendRequestHandler {
75
54
  if (!isGAE || !GOOGLE_CLOUD_PROJECT) {
76
55
  // Local machine, return "simple" logToDev middleware with request numbering
77
56
  return function gaeLogMiddlewareDev(req, res, next) {
@@ -84,7 +63,7 @@ export function createGAELogMiddleware(): RequestHandler {
84
63
 
85
64
  // Otherwise, we're in AppEngine
86
65
 
87
- return function gaeLogMiddleware(req, res, next) {
66
+ return function appEngineLogHandler(req, res, next) {
88
67
  const traceHeader = req.header('x-cloud-trace-context')
89
68
  if (traceHeader) {
90
69
  const [trace] = traceHeader.split('/')
@@ -1,20 +1,20 @@
1
1
  import { AsyncLocalStorage } from 'async_hooks'
2
2
  import { _lazyValue, CommonLogger } from '@naturalcycles/js-lib'
3
- import { Request, RequestHandler } from 'express'
4
- import { gaeLogger, devLogger } from './createGaeLogMiddleware'
3
+ import { BackendRequest, BackendRequestHandler } from './server.model'
4
+ import { gaeLogger, devLogger } from './appEngineLogMiddleware'
5
5
 
6
6
  const { GAE_INSTANCE } = process.env
7
7
  const isGAE = !!GAE_INSTANCE
8
8
 
9
9
  export interface RequestLocalStorage {
10
- req: Request
10
+ req: BackendRequest
11
11
  }
12
12
 
13
13
  // Singleton, for simplicity
14
14
  // Create it lazily (on demand)
15
15
  const storage = _lazyValue(() => new AsyncLocalStorage<RequestLocalStorage>())
16
16
 
17
- export function createAsyncLocalStorage(): RequestHandler {
17
+ export function asyncLocalStorageMiddleware(): BackendRequestHandler {
18
18
  return (req, res, next) => {
19
19
  const store: RequestLocalStorage = {
20
20
  req,
@@ -24,7 +24,7 @@ export function createAsyncLocalStorage(): RequestHandler {
24
24
  }
25
25
  }
26
26
 
27
- export function getRequest(): Request | undefined {
27
+ export function getRequest(): BackendRequest | undefined {
28
28
  return storage().getStore()?.req
29
29
  }
30
30
 
@@ -1,8 +1,7 @@
1
1
  import { HttpError } from '@naturalcycles/js-lib'
2
- import { RequestHandler, Request } from 'express'
3
- import { respondWithError } from '../../index'
2
+ import { BackendRequestHandler, respondWithError } from '../index'
4
3
 
5
- export interface BodyParserTimeoutCfg {
4
+ export interface BodyParserTimeoutMiddlewareCfg {
6
5
  /**
7
6
  * @default 10
8
7
  */
@@ -19,16 +18,14 @@ export interface BodyParserTimeoutCfg {
19
18
  httpStatus?: string
20
19
  }
21
20
 
22
- interface RequestWithTimeout extends Request {
23
- _bodyParserTimeout?: NodeJS.Timeout
24
- }
25
-
26
21
  const code = 'BODY_PARSER_TIMEOUT'
27
22
 
28
23
  /**
29
24
  * Should be called BEFORE bodyParser
30
25
  */
31
- export function bodyParserTimeout(cfg: BodyParserTimeoutCfg = {}): RequestHandler {
26
+ export function bodyParserTimeoutMiddleware(
27
+ cfg: BodyParserTimeoutMiddlewareCfg = {},
28
+ ): BackendRequestHandler {
32
29
  const { timeoutSeconds, httpStatusCode, httpStatus } = {
33
30
  timeoutSeconds: 10,
34
31
  httpStatusCode: 400,
@@ -38,8 +35,12 @@ export function bodyParserTimeout(cfg: BodyParserTimeoutCfg = {}): RequestHandle
38
35
 
39
36
  const timeout = timeoutSeconds * 1000
40
37
 
41
- return (req: RequestWithTimeout, res, next) => {
42
- req._bodyParserTimeout = setTimeout(() => {
38
+ return (req, res, next) => {
39
+ // If requestTimeout was previously set - cancel it first
40
+ // Then set the new requestTimeout and handler
41
+ if (req.bodyParserTimeout) clearTimeout(req.bodyParserTimeout)
42
+
43
+ req.bodyParserTimeout = setTimeout(() => {
43
44
  respondWithError(
44
45
  req,
45
46
  res,
@@ -58,9 +59,9 @@ export function bodyParserTimeout(cfg: BodyParserTimeoutCfg = {}): RequestHandle
58
59
  /**
59
60
  * Should be called AFTER bodyParser
60
61
  */
61
- export function clearBodyParserTimeout(): RequestHandler {
62
- return (req: RequestWithTimeout, res, next) => {
63
- if (req._bodyParserTimeout) clearTimeout(req._bodyParserTimeout)
62
+ export function clearBodyParserTimeout(): BackendRequestHandler {
63
+ return (req, res, next) => {
64
+ clearTimeout(req.bodyParserTimeout!)
64
65
  next()
65
66
  }
66
67
  }
@@ -1,9 +1,9 @@
1
- import { RequestHandler } from 'express'
1
+ import { BackendRequestHandler } from './server.model'
2
2
 
3
3
  // https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/
4
4
  // https://stackoverflow.com/a/43564267/4919972
5
5
  export const catchWrapper =
6
- (fn: RequestHandler): RequestHandler =>
6
+ (fn: BackendRequestHandler): BackendRequestHandler =>
7
7
  async (req, res, next) => {
8
8
  try {
9
9
  // eslint-disable-next-line @typescript-eslint/await-thenable
@@ -1,15 +1,15 @@
1
- import { RequestHandler } from 'express'
2
1
  import { SentrySharedService } from '../sentry/sentry.shared.service'
2
+ import { BackendRequestHandler } from './server.model'
3
3
 
4
4
  /**
5
5
  * Plain RequestHandler can be provided - then it's mounted to /
6
6
  * Otherwise `path` can be provided to specify mounting point.
7
7
  */
8
- export type RequestHandlerCfg = RequestHandler | RequestHandlerWithPath
8
+ export type BackendRequestHandlerCfg = BackendRequestHandler | BackendRequestHandlerWithPath
9
9
 
10
- export interface RequestHandlerWithPath {
10
+ export interface BackendRequestHandlerWithPath {
11
11
  path: string
12
- handler: RequestHandler
12
+ handler: BackendRequestHandler
13
13
  }
14
14
 
15
15
  /**
@@ -21,9 +21,9 @@ export interface RequestHandlerWithPath {
21
21
  * 4. postHandlers
22
22
  */
23
23
  export interface DefaultAppCfg {
24
- preHandlers?: RequestHandlerCfg[]
25
- handlers?: RequestHandlerCfg[]
26
- resources?: RequestHandlerCfg[]
27
- postHandlers?: RequestHandlerCfg[]
24
+ preHandlers?: BackendRequestHandlerCfg[]
25
+ handlers?: BackendRequestHandlerCfg[]
26
+ resources?: BackendRequestHandlerCfg[]
27
+ postHandlers?: BackendRequestHandlerCfg[]
28
28
  sentryService?: SentrySharedService
29
29
  }
@@ -1,19 +1,22 @@
1
1
  import cookieParser = require('cookie-parser')
2
2
  import cors = require('cors')
3
- import type { Application } from 'express'
4
3
  import express = require('express')
5
- import { isGAE, methodOverride } from '..'
6
- import { DefaultAppCfg, RequestHandlerCfg, RequestHandlerWithPath } from './createDefaultApp.model'
7
- import { createAsyncLocalStorage } from './handlers/asyncLocalStorage.mw'
8
- import { createGAELogMiddleware } from './handlers/createGaeLogMiddleware'
9
- import { genericErrorHandler } from './handlers/genericErrorHandler.mw'
10
- import { notFoundHandler } from './handlers/notFoundHandler.mw'
11
- import { requestTimeout } from './handlers/requestTimeout.mw'
12
- import { simpleRequestLogger } from './handlers/simpleRequestLogger.mw'
4
+ import { BackendApplication, isGAE, methodOverrideMiddleware } from '..'
5
+ import {
6
+ DefaultAppCfg,
7
+ BackendRequestHandlerCfg,
8
+ BackendRequestHandlerWithPath,
9
+ } from './createDefaultApp.model'
10
+ import { asyncLocalStorageMiddleware } from './asyncLocalStorageMiddleware'
11
+ import { appEngineLogMiddleware } from './appEngineLogMiddleware'
12
+ import { genericErrorMiddleware } from './genericErrorMiddleware'
13
+ import { notFoundMiddleware } from './notFoundMiddleware'
14
+ import { requestTimeoutMiddleware } from './requestTimeoutMiddleware'
15
+ import { simpleRequestLoggerMiddleware } from './simpleRequestLoggerMiddleware'
13
16
 
14
17
  const isTest = process.env['APP_ENV'] === 'test'
15
18
 
16
- export function createDefaultApp(cfg: DefaultAppCfg): Application {
19
+ export function createDefaultApp(cfg: DefaultAppCfg): BackendApplication {
17
20
  const { sentryService } = cfg
18
21
 
19
22
  const app = express()
@@ -25,10 +28,10 @@ export function createDefaultApp(cfg: DefaultAppCfg): Application {
25
28
  // preHandlers
26
29
  useHandlers(app, cfg.preHandlers)
27
30
 
28
- app.use(createGAELogMiddleware())
31
+ app.use(appEngineLogMiddleware())
29
32
 
30
33
  if (!isTest) {
31
- app.use(createAsyncLocalStorage())
34
+ app.use(asyncLocalStorageMiddleware())
32
35
  }
33
36
 
34
37
  // The request handler must be the first middleware on the app
@@ -38,13 +41,13 @@ export function createDefaultApp(cfg: DefaultAppCfg): Application {
38
41
  app.use(sentryService.getRequestHandler())
39
42
  }
40
43
 
41
- app.use(methodOverride())
42
- app.use(requestTimeout())
44
+ app.use(methodOverrideMiddleware())
45
+ app.use(requestTimeoutMiddleware())
43
46
  // app.use(serverStatsMiddleware()) // disabled by default
44
47
  // app.use(bodyParserTimeout()) // removed by default
45
48
 
46
49
  if (!isGAE() && !isTest) {
47
- app.use(simpleRequestLogger())
50
+ app.use(simpleRequestLoggerMiddleware())
48
51
  }
49
52
 
50
53
  // app.use(safeJsonMiddleware()) // optional
@@ -86,19 +89,19 @@ export function createDefaultApp(cfg: DefaultAppCfg): Application {
86
89
  useHandlers(app, cfg.postHandlers)
87
90
 
88
91
  // Generic 404 handler
89
- app.use(notFoundHandler())
92
+ app.use(notFoundMiddleware())
90
93
 
91
94
  // Generic error handler
92
95
  // It handles errors, returns proper status, does sentry.captureException(),
93
96
  // assigns err.data.errorId from sentry
94
- app.use(genericErrorHandler({ sentryService }))
97
+ app.use(genericErrorMiddleware({ sentryService }))
95
98
 
96
99
  return app
97
100
  }
98
101
 
99
- function useHandlers(app: Application, handlers: RequestHandlerCfg[] = []): void {
102
+ function useHandlers(app: BackendApplication, handlers: BackendRequestHandlerCfg[] = []): void {
100
103
  handlers
101
- .map<RequestHandlerWithPath>(cfg => {
104
+ .map<BackendRequestHandlerWithPath>(cfg => {
102
105
  if (typeof cfg === 'function') {
103
106
  return {
104
107
  path: '/',
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs'
2
2
  import { _memoFn } from '@naturalcycles/js-lib'
3
- import type { DeployInfo } from '../deploy/deploy.model'
3
+ import type { DeployInfo } from '../deploy'
4
4
 
5
5
  export const getDeployInfo = _memoFn((projectDir: string): DeployInfo => {
6
6
  const deployInfoPath = `${projectDir}/deployInfo.json`
@@ -7,11 +7,10 @@ import {
7
7
  HttpErrorResponse,
8
8
  } from '@naturalcycles/js-lib'
9
9
  import { inspectAnyStringifyFn } from '@naturalcycles/nodejs-lib'
10
- import { ErrorRequestHandler, Response } from 'express'
11
- import { SentrySharedService } from '../../sentry/sentry.shared.service'
12
- import { RequestWithLog } from './createGaeLogMiddleware'
10
+ import { SentrySharedService } from '../sentry/sentry.shared.service'
11
+ import { BackendErrorRequestHandler, BackendRequest, BackendResponse } from './server.model'
13
12
 
14
- export interface GenericErrorHandlerCfg {
13
+ export interface GenericErrorMiddlewareCfg {
15
14
  sentryService?: SentrySharedService
16
15
  }
17
16
 
@@ -26,10 +25,12 @@ let sentryService: SentrySharedService | undefined
26
25
  * Returns HTTP code based on err.data.httpStatusCode (default to 500).
27
26
  * Sends json payload as ErrorResponse, transformed via errorSharedUtil.
28
27
  */
29
- export function genericErrorHandler(cfg: GenericErrorHandlerCfg = {}): ErrorRequestHandler {
28
+ export function genericErrorMiddleware(
29
+ cfg: GenericErrorMiddlewareCfg = {},
30
+ ): BackendErrorRequestHandler {
30
31
  sentryService ||= cfg.sentryService
31
32
 
32
- return (err, req: RequestWithLog, res, _next) => {
33
+ return (err, req, res, _next) => {
33
34
  // if (res.headersSent) {
34
35
  // Here we don't even log this error
35
36
  // It's known that it comes from sentry.requestHandler()
@@ -49,7 +50,7 @@ export function genericErrorHandler(cfg: GenericErrorHandlerCfg = {}): ErrorRequ
49
50
  // export interface ResponseWithError extends Response {
50
51
  // __err?: any
51
52
  // }
52
- export function respondWithError(req: RequestWithLog, res: Response, err: any): void {
53
+ export function respondWithError(req: BackendRequest, res: BackendResponse, err: any): void {
53
54
  const { headersSent } = res
54
55
 
55
56
  req.error(`genericErrorHandler${headersSent ? ' after headersSent' : ''}:\n`, err)
@@ -80,10 +81,15 @@ export function respondWithError(req: RequestWithLog, res: Response, err: any):
80
81
  }
81
82
 
82
83
  function shouldReportToSentry(err: Error): boolean {
83
- // Only report 5xx
84
- return (
85
- (err as HttpError)?.data?.report ||
86
- !(err as HttpError)?.data ||
87
- (err as HttpError).data.httpStatusCode >= 500
88
- )
84
+ const e = err as HttpError
85
+
86
+ // By default - report
87
+ if (!e?.data) return true
88
+
89
+ // If `report` is set - do as it says
90
+ if (e.data.report === true) return true
91
+ if (e.data.report === false) return false
92
+
93
+ // Report if http 5xx, otherwise not
94
+ return !e.data.httpStatusCode || e.data.httpStatusCode >= 500
89
95
  }
@@ -1,10 +1,10 @@
1
- import { RequestHandler, Router } from 'express'
2
1
  import PromiseRouter from 'express-promise-router'
2
+ import { BackendRequestHandler, BackendRouter } from './server.model'
3
3
 
4
4
  /**
5
5
  * Convenience method.
6
6
  */
7
- export function getDefaultRouter(defaultHandlers: RequestHandler[] = []): Router {
7
+ export function getDefaultRouter(defaultHandlers: BackendRequestHandler[] = []): BackendRouter {
8
8
  const router = PromiseRouter()
9
9
 
10
10
  // Use default handlers
@@ -1,13 +1,15 @@
1
- import { RequestHandler } from 'express'
1
+ import { BackendRequestHandler } from './server.model'
2
2
 
3
- export interface MethodOverrideCfg {
3
+ export interface MethodOverrideMiddlewareCfg {
4
4
  /**
5
5
  * @default _method
6
6
  */
7
7
  methodKey?: string
8
8
  }
9
9
 
10
- export function methodOverride(cfg: MethodOverrideCfg = {}): RequestHandler {
10
+ export function methodOverrideMiddleware(
11
+ cfg: MethodOverrideMiddlewareCfg = {},
12
+ ): BackendRequestHandler {
11
13
  const { methodKey } = {
12
14
  methodKey: '_method',
13
15
  ...cfg,
@@ -0,0 +1,8 @@
1
+ import { getRequestEndpoint } from './request.util'
2
+ import { BackendRequestHandler } from './server.model'
3
+
4
+ export function notFoundMiddleware(): BackendRequestHandler {
5
+ return (req, res) => {
6
+ res.status(404).send(`404 Not Found: ${getRequestEndpoint(req)}`)
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ import { BackendRequestHandler } from './server.model'
2
+
3
+ export function okMiddleware(): BackendRequestHandler {
4
+ return (req, res) => {
5
+ res.json({ ok: 1 })
6
+ }
7
+ }
@@ -1,6 +1,6 @@
1
1
  import { HttpError, _get } from '@naturalcycles/js-lib'
2
2
  import { AnySchema, getValidationResult, JoiValidationError } from '@naturalcycles/nodejs-lib'
3
- import { RequestHandler } from 'express'
3
+ import { BackendRequestHandler } from './server.model'
4
4
 
5
5
  const REDACTED = 'REDACTED'
6
6
 
@@ -22,7 +22,7 @@ export function reqValidation(
22
22
  reqProperty: 'body' | 'params' | 'query',
23
23
  schema: AnySchema,
24
24
  opt: ReqValidationOptions<JoiValidationError> = {},
25
- ): RequestHandler {
25
+ ): BackendRequestHandler {
26
26
  const reportPredicate = typeof opt.report === 'function' ? opt.report : () => !!opt.report
27
27
 
28
28
  return (req, res, next) => {
@@ -1,8 +1,8 @@
1
1
  import { CommonLogLevel } from '@naturalcycles/js-lib'
2
2
  import { boldGrey, green, red, yellow } from '@naturalcycles/nodejs-lib/dist/colors'
3
- import { Request } from 'express'
3
+ import { BackendRequest } from './server.model'
4
4
 
5
- export function logRequest(req: Request, statusCode: number, ...tokens: any[]): void {
5
+ export function logRequest(req: BackendRequest, statusCode: number, ...tokens: any[]): void {
6
6
  req[logLevel(statusCode)](
7
7
  [coloredHttpCode(statusCode), req.method, boldGrey(req.url), ...tokens].join(' '),
8
8
  )
@@ -1,6 +1,14 @@
1
- import { Request } from 'express'
1
+ import { BackendRequest } from './server.model'
2
2
 
3
- export function getRequestEndpoint(req: Request): string {
3
+ /**
4
+ * Returns e.g:
5
+ *
6
+ * GET /some/endpoint
7
+ *
8
+ * Gets the correct full path when used from sub-router-resources.
9
+ * Strips away the queryString.
10
+ */
11
+ export function getRequestEndpoint(req: BackendRequest): string {
4
12
  let path = (req.baseUrl + (req.route?.path || req.path)).toLowerCase()
5
13
  if (path.length > 1 && path.endsWith('/')) {
6
14
  path = path.slice(0, path.length - 1)