@naturalcycles/backend-lib 2.73.2 → 3.2.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 (96) 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 +26 -24
  5. package/dist/index.js +29 -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} +6 -7
  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} +20 -8
  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} +4 -16
  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 +6 -6
  48. package/dist/testing/express.test.service.js +8 -5
  49. package/package.json +1 -2
  50. package/src/admin/admin.mw.ts +7 -4
  51. package/src/admin/base.admin.service.ts +11 -12
  52. package/src/admin/secureHeader.mw.ts +2 -2
  53. package/src/db/httpDBRequestHandler.ts +2 -3
  54. package/src/index.ts +55 -68
  55. package/src/sentry/sentry.shared.service.ts +3 -4
  56. package/src/server/{handlers/createGaeLogMiddleware.ts → appEngineLogMiddleware.ts} +6 -29
  57. package/src/server/{handlers/asyncLocalStorage.mw.ts → asyncLocalStorageMiddleware.ts} +5 -5
  58. package/src/server/{handlers/bodyParserTimeout.mw.ts → bodyParserTimeoutMiddleware.ts} +14 -13
  59. package/src/server/catchWrapper.ts +2 -2
  60. package/src/server/createDefaultApp.model.ts +8 -8
  61. package/src/server/createDefaultApp.ts +22 -19
  62. package/src/server/deployInfo.util.ts +1 -1
  63. package/src/server/{handlers/genericErrorHandler.mw.ts → genericErrorMiddleware.ts} +24 -14
  64. package/src/server/getDefaultRouter.ts +2 -2
  65. package/src/server/{handlers/methodOverride.mw.ts → methodOverrideMiddleware.ts} +5 -3
  66. package/src/server/notFoundMiddleware.ts +8 -0
  67. package/src/server/okMiddleware.ts +7 -0
  68. package/src/server/{handlers/reqValidation.mw.ts → reqValidationMiddleware.ts} +2 -2
  69. package/src/server/request.log.util.ts +2 -2
  70. package/src/server/request.util.ts +10 -2
  71. package/src/server/requestTimeoutMiddleware.ts +117 -0
  72. package/src/server/{handlers/safeJsonMiddleware.ts → safeJsonMiddleware.ts} +3 -3
  73. package/src/server/server.model.ts +56 -0
  74. package/src/server/{handlers/serverStatsMiddleware.ts → serverStatsMiddleware.ts} +10 -22
  75. package/src/server/{handlers/statusHandler.ts → serverStatusMiddleware.ts} +5 -5
  76. package/src/server/{handlers/simpleRequestLogger.mw.ts → simpleRequestLoggerMiddleware.ts} +8 -7
  77. package/src/server/startServer.model.ts +2 -2
  78. package/src/server/{handlers/validate.mw.ts → validateMiddleware.ts} +6 -6
  79. package/src/testing/express.test.service.ts +12 -8
  80. package/dist/server/handlers/createGaeLogMiddleware.d.ts +0 -30
  81. package/dist/server/handlers/genericErrorHandler.mw.d.ts +0 -13
  82. package/dist/server/handlers/methodOverride.mw.d.ts +0 -8
  83. package/dist/server/handlers/notFoundHandler.mw.d.ts +0 -2
  84. package/dist/server/handlers/notFoundHandler.mw.js +0 -9
  85. package/dist/server/handlers/okHandler.mw.d.ts +0 -2
  86. package/dist/server/handlers/requestTimeout.mw.d.ts +0 -16
  87. package/dist/server/handlers/requestTimeout.mw.js +0 -34
  88. package/dist/server/handlers/sentryErrorHandler.mw.d.ts +0 -10
  89. package/dist/server/handlers/sentryErrorHandler.mw.js +0 -26
  90. package/dist/server/handlers/serverStatsMiddleware.d.ts +0 -13
  91. package/dist/server/handlers/simpleRequestLogger.mw.d.ts +0 -12
  92. package/dist/server/handlers/statusHandler.d.ts +0 -3
  93. package/src/server/handlers/notFoundHandler.mw.ts +0 -7
  94. package/src/server/handlers/okHandler.mw.ts +0 -7
  95. package/src/server/handlers/requestTimeout.mw.ts +0 -62
  96. package/src/server/handlers/sentryErrorHandler.mw.ts +0 -34
@@ -1,8 +1,7 @@
1
1
  import { _assert, Admin401ErrorData, Admin403ErrorData, HttpError } from '@naturalcycles/js-lib'
2
2
  import { dimGrey, green, red } from '@naturalcycles/nodejs-lib/dist/colors'
3
- import { Request, RequestHandler } from 'express'
4
3
  import type * as FirebaseAdmin from 'firebase-admin'
5
- import { RequestWithLog } from '../server/handlers/createGaeLogMiddleware'
4
+ import { BackendRequest, BackendRequestHandler } from '../server/server.model'
6
5
 
7
6
  export interface AdminServiceCfg {
8
7
  /**
@@ -70,7 +69,7 @@ export class BaseAdminService {
70
69
  * To be extended.
71
70
  */
72
71
  protected async onPermissionCheck(
73
- req: RequestWithLog,
72
+ req: BackendRequest,
74
73
  email: string,
75
74
  reqPermissions: string[],
76
75
  required: boolean,
@@ -85,7 +84,7 @@ export class BaseAdminService {
85
84
  )
86
85
  }
87
86
 
88
- async getEmailByToken(req: RequestWithLog, adminToken?: string): Promise<string | undefined> {
87
+ async getEmailByToken(req: BackendRequest, adminToken?: string): Promise<string | undefined> {
89
88
  if (!adminToken) return
90
89
 
91
90
  try {
@@ -112,7 +111,7 @@ export class BaseAdminService {
112
111
  * Current implementation is based on req=Request (from Express).
113
112
  * Override if needed.
114
113
  */
115
- async getAdminToken(req: Request): Promise<string | undefined> {
114
+ async getAdminToken(req: BackendRequest): Promise<string | undefined> {
116
115
  return (
117
116
  (req.cookies || {})[this.cfg.adminTokenKey] ||
118
117
  req.header(this.cfg.adminTokenKey) ||
@@ -120,13 +119,13 @@ export class BaseAdminService {
120
119
  )
121
120
  }
122
121
 
123
- async isAdmin(req: Request): Promise<boolean> {
122
+ async isAdmin(req: BackendRequest): Promise<boolean> {
124
123
  const adminToken = await this.getAdminToken(req)
125
124
  const email = await this.getEmailByToken(req, adminToken)
126
125
  return !!this.getEmailPermissions(email)
127
126
  }
128
127
 
129
- async getAdminInfo(req: Request): Promise<AdminInfo | undefined> {
128
+ async getAdminInfo(req: BackendRequest): Promise<AdminInfo | undefined> {
130
129
  return await this.hasPermissions(req)
131
130
  }
132
131
 
@@ -140,7 +139,7 @@ export class BaseAdminService {
140
139
  * Otherwise returns undefined
141
140
  */
142
141
  async hasPermissions(
143
- req: Request,
142
+ req: BackendRequest,
144
143
  reqPermissions: string[] = [],
145
144
  meta: Record<string, any> = {},
146
145
  ): Promise<AdminInfo | undefined> {
@@ -164,7 +163,7 @@ export class BaseAdminService {
164
163
  }
165
164
 
166
165
  async requirePermissions(
167
- req: Request,
166
+ req: BackendRequest,
168
167
  reqPermissions: string[] = [],
169
168
  meta: Record<string, any> = {},
170
169
  andComparison: boolean = true,
@@ -221,7 +220,7 @@ export class BaseAdminService {
221
220
 
222
221
  // convenience method
223
222
  async hasPermission(
224
- req: Request,
223
+ req: BackendRequest,
225
224
  reqPermission: string,
226
225
  meta?: Record<string, any>,
227
226
  ): Promise<boolean> {
@@ -229,7 +228,7 @@ export class BaseAdminService {
229
228
  }
230
229
 
231
230
  async requirePermission(
232
- req: Request,
231
+ req: BackendRequest,
233
232
  reqPermission: string,
234
233
  meta?: Record<string, any>,
235
234
  ): Promise<AdminInfo> {
@@ -245,7 +244,7 @@ export class BaseAdminService {
245
244
  *
246
245
  * Same endpoint is used to logout, but the `Authentication` header should contain `logout` magic string.
247
246
  */
248
- getFirebaseAuthLoginHandler(): RequestHandler {
247
+ getFirebaseAuthLoginHandler(): BackendRequestHandler {
249
248
  return async (req, res) => {
250
249
  const token = req.header('authentication')
251
250
  _assert(token, `401 Unauthenticated`, {
@@ -1,5 +1,5 @@
1
1
  import { Admin401ErrorData, HttpError } from '@naturalcycles/js-lib'
2
- import { RequestHandler } from 'express'
2
+ import { BackendRequestHandler } from '../server/server.model'
3
3
  import { AdminMiddleware, RequireAdminCfg, requireAdminPermissions } from './admin.mw'
4
4
  import { BaseAdminService } from './base.admin.service'
5
5
 
@@ -19,7 +19,7 @@ export function createSecureHeaderMiddleware(cfg: SecureHeaderMiddlewareCfg): Ad
19
19
  function requireSecureHeaderOrAdmin(
20
20
  cfg: SecureHeaderMiddlewareCfg,
21
21
  reqPermissions?: string[],
22
- ): RequestHandler {
22
+ ): BackendRequestHandler {
23
23
  const requireAdmin = requireAdminPermissions(cfg.adminService, reqPermissions, cfg)
24
24
 
25
25
  return async (req, res, next) => {
@@ -12,8 +12,7 @@ import {
12
12
  } from '@naturalcycles/db-lib/dist/validation'
13
13
  import { ObjectWithId } from '@naturalcycles/js-lib'
14
14
  import { anyObjectSchema, arraySchema, objectSchema, stringSchema } from '@naturalcycles/nodejs-lib'
15
- import { Router } from 'express'
16
- import { getDefaultRouter, reqValidation } from '..'
15
+ import { BackendRouter, getDefaultRouter, reqValidation } from '..'
17
16
 
18
17
  export interface GetByIdsInput {
19
18
  table: string
@@ -52,7 +51,7 @@ const saveBatchInputSchema = objectSchema<SaveBatchInput>({
52
51
  /**
53
52
  * Exposes CommonDB interface from provided CommonDB as HTTP endpoint (Express RequestHandler).
54
53
  */
55
- export function httpDBRequestHandler(db: CommonDB): Router {
54
+ export function httpDBRequestHandler(db: CommonDB): BackendRouter {
56
55
  const router = getDefaultRouter()
57
56
 
58
57
  // resetCache, only applicable to InMemoryDB
package/src/index.ts CHANGED
@@ -10,56 +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'
60
+ export * from './server/request.util'
57
61
 
58
62
  export type {
59
- MethodOverrideCfg,
63
+ MethodOverrideMiddlewareCfg,
60
64
  SentrySharedServiceCfg,
61
- RequestHandlerWithPath,
62
- RequestHandlerCfg,
65
+ BackendRequestHandlerWithPath,
66
+ BackendRequestHandlerCfg,
63
67
  DefaultAppCfg,
64
68
  StartServerCfg,
65
69
  StartServerData,
@@ -70,11 +74,16 @@ export type {
70
74
  AdminInfo,
71
75
  RequireAdminCfg,
72
76
  SecureHeaderMiddlewareCfg,
73
- BodyParserTimeoutCfg,
74
- RequestTimeoutCfg,
75
- SimpleRequestLoggerCfg,
77
+ BodyParserTimeoutMiddlewareCfg,
78
+ RequestTimeoutMiddlewareCfg,
79
+ SimpleRequestLoggerMiddlewareCfg,
76
80
  ReqValidationOptions,
77
- RequestWithLog,
81
+ BackendRequest,
82
+ BackendRequestHandler,
83
+ BackendResponse,
84
+ BackendErrorRequestHandler,
85
+ BackendRouter,
86
+ BackendApplication,
78
87
  }
79
88
 
80
89
  export {
@@ -82,39 +91,17 @@ export {
82
91
  SentrySharedService,
83
92
  EnvSharedService,
84
93
  reqValidation,
85
- notFoundHandler,
86
- genericErrorHandler,
87
- methodOverride,
88
- createDefaultApp,
94
+ methodOverrideMiddleware,
89
95
  startServer,
90
- catchWrapper,
91
- getDefaultRouter,
92
- isGAE,
93
- statusHandler,
94
- statusHandlerData,
95
- okHandler,
96
- getDeployInfo,
96
+ serverStatusMiddleware,
97
+ getServerStatusData,
97
98
  onFinished,
98
- respondWithError,
99
- logRequest,
100
99
  FirebaseSharedService,
101
100
  createAdminMiddleware,
102
101
  BaseAdminService,
103
102
  loginHtml,
104
103
  createSecureHeaderMiddleware,
105
- bodyParserTimeout,
104
+ bodyParserTimeoutMiddleware,
106
105
  clearBodyParserTimeout,
107
- requestTimeout,
108
- simpleRequestLogger,
109
- coloredHttpCode,
110
- validateBody,
111
- validateParams,
112
- validateQuery,
113
- createAsyncLocalStorage,
114
- getRequest,
115
- getRequestLogger,
116
- requestLogger,
117
- serverStatsHTMLHandler,
118
- serverStatsMiddleware,
119
- safeJsonMiddleware,
106
+ simpleRequestLoggerMiddleware,
120
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,16 +63,14 @@ export function createGAELogMiddleware(): RequestHandler {
84
63
 
85
64
  // Otherwise, we're in AppEngine
86
65
 
87
- return function gaeLogMiddleware(req, res, next) {
88
- const meta: AnyObject = {}
89
-
66
+ return function appEngineLogHandler(req, res, next) {
90
67
  const traceHeader = req.header('x-cloud-trace-context')
91
68
  if (traceHeader) {
92
69
  const [trace] = traceHeader.split('/')
93
- Object.assign(meta, {
70
+ const meta = {
94
71
  'logging.googleapis.com/trace': `projects/${GOOGLE_CLOUD_PROJECT}/traces/${trace}`,
95
72
  'appengine.googleapis.com/request_id': req.header('x-appengine-request-log-id'),
96
- })
73
+ }
97
74
  Object.assign(req, {
98
75
  log: (...args: any[]) => logToAppEngine({ ...meta, severity: 'INFO' }, args),
99
76
  warn: (...args: any[]) => logToAppEngine({ ...meta, severity: 'WARNING' }, args),
@@ -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`