@naturalcycles/backend-lib 9.42.3 → 9.43.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/dist/express/createDefaultApp.js +8 -0
- package/dist/server/server.model.d.ts +9 -0
- package/package.json +2 -3
- package/src/express/createDefaultApp.ts +13 -1
- package/src/server/server.model.ts +9 -0
- package/dist/cloudrun/cloudRun.d.ts +0 -114
- package/dist/cloudrun/cloudRun.js +0 -37
- package/src/cloudrun/cloudRun.ts +0 -171
|
@@ -33,6 +33,10 @@ export async function createDefaultApp(cfg) {
|
|
|
33
33
|
// accepts application/json
|
|
34
34
|
app.use(express.json({
|
|
35
35
|
limit: '1mb',
|
|
36
|
+
verify(req, _res, buf) {
|
|
37
|
+
// Store the raw Buffer body
|
|
38
|
+
req.rawBody = buf;
|
|
39
|
+
},
|
|
36
40
|
...cfg.bodyParserJsonOptions,
|
|
37
41
|
}));
|
|
38
42
|
app.use(express.urlencoded({
|
|
@@ -44,6 +48,10 @@ export async function createDefaultApp(cfg) {
|
|
|
44
48
|
app.use(express.raw({
|
|
45
49
|
// inflate: true, // default is `true`
|
|
46
50
|
limit: '1mb',
|
|
51
|
+
verify(req, _res, buf) {
|
|
52
|
+
// Store the raw Buffer body
|
|
53
|
+
req.rawBody = buf;
|
|
54
|
+
},
|
|
47
55
|
...cfg.bodyParserRawOptions,
|
|
48
56
|
}));
|
|
49
57
|
app.use(cookieParser());
|
|
@@ -18,6 +18,15 @@ export interface BackendRequest extends Request {
|
|
|
18
18
|
* Only used for request logging purposes.
|
|
19
19
|
*/
|
|
20
20
|
userId?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Raw Buffer of the `req.body`, before it's stringified and json-parsed.
|
|
23
|
+
* Useful for when something mutates `req.body` json (e.g j validation), and you
|
|
24
|
+
* want access to the original input.
|
|
25
|
+
*
|
|
26
|
+
* For `req.rawBody` to exist - you need to use `createDefaultApp`, or use the
|
|
27
|
+
* `verify` option of the json parser (copy-paste it from `createDefaultApp`).
|
|
28
|
+
*/
|
|
29
|
+
rawBody?: Buffer;
|
|
21
30
|
/**
|
|
22
31
|
* Set by requestTimeoutMiddleware.
|
|
23
32
|
* Can be used to cancel/override the timeout.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.43.0",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@sentry/node": "^10"
|
|
7
7
|
},
|
|
@@ -29,13 +29,12 @@
|
|
|
29
29
|
"@sentry/node": "^10",
|
|
30
30
|
"@types/ejs": "^3",
|
|
31
31
|
"fastify": "^5",
|
|
32
|
-
"@naturalcycles/dev-lib": "
|
|
32
|
+
"@naturalcycles/dev-lib": "18.4.2"
|
|
33
33
|
},
|
|
34
34
|
"exports": {
|
|
35
35
|
".": "./dist/index.js",
|
|
36
36
|
"./admin": "./dist/admin/index.js",
|
|
37
37
|
"./admin/*.js": "./dist/admin/*.js",
|
|
38
|
-
"./cloudrun": "./dist/cloudrun/cloudRun.js",
|
|
39
38
|
"./db": "./dist/db/index.js",
|
|
40
39
|
"./deploy": "./dist/deploy/index.js",
|
|
41
40
|
"./deploy/*.js": "./dist/deploy/*.js",
|
|
@@ -10,7 +10,11 @@ import { logMiddleware } from '../server/logMiddleware.js'
|
|
|
10
10
|
import { methodOverrideMiddleware } from '../server/methodOverrideMiddleware.js'
|
|
11
11
|
import { notFoundMiddleware } from '../server/notFoundMiddleware.js'
|
|
12
12
|
import { requestTimeoutMiddleware } from '../server/requestTimeoutMiddleware.js'
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
BackendApplication,
|
|
15
|
+
BackendRequest,
|
|
16
|
+
BackendRequestHandler,
|
|
17
|
+
} from '../server/server.model.js'
|
|
14
18
|
import { simpleRequestLoggerMiddleware } from '../server/simpleRequestLoggerMiddleware.js'
|
|
15
19
|
|
|
16
20
|
const isTest = process.env['APP_ENV'] === 'test'
|
|
@@ -53,6 +57,10 @@ export async function createDefaultApp(cfg: DefaultAppCfg): Promise<BackendAppli
|
|
|
53
57
|
app.use(
|
|
54
58
|
express.json({
|
|
55
59
|
limit: '1mb',
|
|
60
|
+
verify(req: BackendRequest, _res, buf) {
|
|
61
|
+
// Store the raw Buffer body
|
|
62
|
+
req.rawBody = buf
|
|
63
|
+
},
|
|
56
64
|
...cfg.bodyParserJsonOptions,
|
|
57
65
|
}),
|
|
58
66
|
)
|
|
@@ -70,6 +78,10 @@ export async function createDefaultApp(cfg: DefaultAppCfg): Promise<BackendAppli
|
|
|
70
78
|
express.raw({
|
|
71
79
|
// inflate: true, // default is `true`
|
|
72
80
|
limit: '1mb',
|
|
81
|
+
verify(req: BackendRequest, _res, buf) {
|
|
82
|
+
// Store the raw Buffer body
|
|
83
|
+
req.rawBody = buf
|
|
84
|
+
},
|
|
73
85
|
...cfg.bodyParserRawOptions,
|
|
74
86
|
}),
|
|
75
87
|
)
|
|
@@ -20,6 +20,15 @@ export interface BackendRequest extends Request {
|
|
|
20
20
|
* Only used for request logging purposes.
|
|
21
21
|
*/
|
|
22
22
|
userId?: string
|
|
23
|
+
/**
|
|
24
|
+
* Raw Buffer of the `req.body`, before it's stringified and json-parsed.
|
|
25
|
+
* Useful for when something mutates `req.body` json (e.g j validation), and you
|
|
26
|
+
* want access to the original input.
|
|
27
|
+
*
|
|
28
|
+
* For `req.rawBody` to exist - you need to use `createDefaultApp`, or use the
|
|
29
|
+
* `verify` option of the json parser (copy-paste it from `createDefaultApp`).
|
|
30
|
+
*/
|
|
31
|
+
rawBody?: Buffer
|
|
23
32
|
|
|
24
33
|
/**
|
|
25
34
|
* Set by requestTimeoutMiddleware.
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import type { AnyObject, NonNegativeInteger, NumberOfMilliseconds, NumberOfSeconds, PositiveInteger, UnixTimestamp } from '@naturalcycles/js-lib/types';
|
|
2
|
-
export interface CloudRunConfig {
|
|
3
|
-
gcpProject: string;
|
|
4
|
-
/**
|
|
5
|
-
* Name of the Cloud Run service.
|
|
6
|
-
*/
|
|
7
|
-
cloudRunService: string;
|
|
8
|
-
cloudRunServiceBase?: string;
|
|
9
|
-
runtimeServiceAccount: string;
|
|
10
|
-
/**
|
|
11
|
-
* GCP region where the Cloud Run service is deployed. Example: 'europe-west1'
|
|
12
|
-
*/
|
|
13
|
-
cloudRunRegion: string;
|
|
14
|
-
sqlInstance?: string;
|
|
15
|
-
vpcConnector?: string;
|
|
16
|
-
serviceUrl?: string;
|
|
17
|
-
/**
|
|
18
|
-
* Service URL that is used to access the service externally (through load balancer)
|
|
19
|
-
* todo: overlaps with env.K_EXTERNAL_URL
|
|
20
|
-
*/
|
|
21
|
-
externalUrl?: string;
|
|
22
|
-
buildVersion: string;
|
|
23
|
-
/**
|
|
24
|
-
* Unix timestamp of the build/deployment time.
|
|
25
|
-
*/
|
|
26
|
-
tsUnix: UnixTimestamp;
|
|
27
|
-
targetDockerImageId: string;
|
|
28
|
-
dockerImageTag: string;
|
|
29
|
-
/**
|
|
30
|
-
* Short SHA of the commit used for this deployment.
|
|
31
|
-
*/
|
|
32
|
-
gitRev: string;
|
|
33
|
-
gitBranch: string;
|
|
34
|
-
/**
|
|
35
|
-
* Example: 'APP_ENV=prod,BUILD_VERSION=abcd,a=b'
|
|
36
|
-
*/
|
|
37
|
-
envString: string;
|
|
38
|
-
/**
|
|
39
|
-
* Example: httpGet.path='/',httpGet.port=8080,initialDelaySeconds=3,failureThreshold=50,timeoutSeconds=1,periodSeconds=2
|
|
40
|
-
*/
|
|
41
|
-
startupProbeConfigString: string;
|
|
42
|
-
livenessProbeConfigString?: string;
|
|
43
|
-
minInstances: NonNegativeInteger;
|
|
44
|
-
maxInstances: PositiveInteger;
|
|
45
|
-
/**
|
|
46
|
-
* CloudRun concurrency setting.
|
|
47
|
-
* Example: 80
|
|
48
|
-
*/
|
|
49
|
-
concurrency: PositiveInteger;
|
|
50
|
-
/**
|
|
51
|
-
* Example: '512Mi'
|
|
52
|
-
*/
|
|
53
|
-
memoryPerInstance: string;
|
|
54
|
-
}
|
|
55
|
-
export interface CloudRunProbeConfig {
|
|
56
|
-
/**
|
|
57
|
-
* Example: '/'
|
|
58
|
-
*/
|
|
59
|
-
'httpGet.path': string;
|
|
60
|
-
'httpGet.port': PositiveInteger;
|
|
61
|
-
initialDelaySeconds: NumberOfSeconds;
|
|
62
|
-
failureThreshold: PositiveInteger;
|
|
63
|
-
timeoutSeconds: NumberOfSeconds;
|
|
64
|
-
periodSeconds: NumberOfSeconds;
|
|
65
|
-
}
|
|
66
|
-
export interface CloudRunEnv {
|
|
67
|
-
APP_ENV: string;
|
|
68
|
-
/**
|
|
69
|
-
* Example: '--max-old-space-size=864'
|
|
70
|
-
*/
|
|
71
|
-
NODE_OPTIONS?: string;
|
|
72
|
-
/**
|
|
73
|
-
* Example: '2025-09-01T15:23:20.769Z'
|
|
74
|
-
* The result of running `new Date().toISOString()`
|
|
75
|
-
*/
|
|
76
|
-
DEPLOY_BUILD_TIME: string;
|
|
77
|
-
/**
|
|
78
|
-
* Example: 'abcd'
|
|
79
|
-
* Should match the name of the GCP project.
|
|
80
|
-
*/
|
|
81
|
-
GOOGLE_CLOUD_PROJECT: string;
|
|
82
|
-
/**
|
|
83
|
-
* Anything (a string) that would identify the build.
|
|
84
|
-
*/
|
|
85
|
-
BUILD_VERSION: string;
|
|
86
|
-
/**
|
|
87
|
-
* External url of the deployed service.
|
|
88
|
-
*/
|
|
89
|
-
K_EXTERNAL_URL?: string;
|
|
90
|
-
OTEL_SERVICE_NAME?: string;
|
|
91
|
-
OTEL_METRICS_EXPORTER?: 'console' | 'otlp' | string;
|
|
92
|
-
OTEL_METRIC_EXPORT_INTERVAL?: NumberOfMilliseconds;
|
|
93
|
-
OTEL_METRIC_EXPORT_TIMEOUT?: NumberOfMilliseconds;
|
|
94
|
-
OTEL_EXPORTER_OTLP_PROTOCOL?: 'http/protobuf' | string;
|
|
95
|
-
/**
|
|
96
|
-
* Example: 'http://localhost:4317'
|
|
97
|
-
*/
|
|
98
|
-
OTEL_EXPORTER_OTLP_ENDPOINT?: string;
|
|
99
|
-
OTEL_LOG_LEVEL?: 'INFO' | 'DEBUG';
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* @experimental
|
|
103
|
-
*/
|
|
104
|
-
declare class CloudRunUtil {
|
|
105
|
-
/**
|
|
106
|
-
* Turns an object into a string representation where each
|
|
107
|
-
* key-value pair is represented as `key1=value1,key2=value2,...`.
|
|
108
|
-
*/
|
|
109
|
-
stringifyObject(obj: AnyObject): string;
|
|
110
|
-
readonly defaultStartupProbeConfig: CloudRunProbeConfig;
|
|
111
|
-
readonly defaultLivenessProbeConfig: CloudRunProbeConfig;
|
|
112
|
-
}
|
|
113
|
-
export declare const cloudRunUtil: CloudRunUtil;
|
|
114
|
-
export {};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { _filterUndefinedValues } from '@naturalcycles/js-lib/object';
|
|
2
|
-
/**
|
|
3
|
-
* @experimental
|
|
4
|
-
*/
|
|
5
|
-
class CloudRunUtil {
|
|
6
|
-
/**
|
|
7
|
-
* Turns an object into a string representation where each
|
|
8
|
-
* key-value pair is represented as `key1=value1,key2=value2,...`.
|
|
9
|
-
*/
|
|
10
|
-
stringifyObject(obj) {
|
|
11
|
-
const filteredObj = _filterUndefinedValues(obj);
|
|
12
|
-
return Object.entries(filteredObj)
|
|
13
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
14
|
-
.join(',');
|
|
15
|
-
}
|
|
16
|
-
defaultStartupProbeConfig = {
|
|
17
|
-
'httpGet.path': '/',
|
|
18
|
-
'httpGet.port': 8080,
|
|
19
|
-
initialDelaySeconds: 3,
|
|
20
|
-
failureThreshold: 50,
|
|
21
|
-
timeoutSeconds: 1,
|
|
22
|
-
periodSeconds: 2,
|
|
23
|
-
};
|
|
24
|
-
defaultLivenessProbeConfig = {
|
|
25
|
-
'httpGet.path': '/',
|
|
26
|
-
'httpGet.port': 8080,
|
|
27
|
-
// how long to wait before doing the first check, AFTER the startup probe has succeeded
|
|
28
|
-
initialDelaySeconds: 60,
|
|
29
|
-
// after how many failure it should kill/restart the container
|
|
30
|
-
failureThreshold: 5,
|
|
31
|
-
// how long to wait until liveness probe considers the endpoint unhealthy
|
|
32
|
-
timeoutSeconds: 30,
|
|
33
|
-
// check every periodSeconds
|
|
34
|
-
periodSeconds: 60,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
export const cloudRunUtil = new CloudRunUtil();
|
package/src/cloudrun/cloudRun.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { _filterUndefinedValues } from '@naturalcycles/js-lib/object'
|
|
2
|
-
import type {
|
|
3
|
-
AnyObject,
|
|
4
|
-
NonNegativeInteger,
|
|
5
|
-
NumberOfMilliseconds,
|
|
6
|
-
NumberOfSeconds,
|
|
7
|
-
PositiveInteger,
|
|
8
|
-
UnixTimestamp,
|
|
9
|
-
} from '@naturalcycles/js-lib/types'
|
|
10
|
-
|
|
11
|
-
export interface CloudRunConfig {
|
|
12
|
-
//
|
|
13
|
-
// GCP settings
|
|
14
|
-
//
|
|
15
|
-
gcpProject: string
|
|
16
|
-
/**
|
|
17
|
-
* Name of the Cloud Run service.
|
|
18
|
-
*/
|
|
19
|
-
cloudRunService: string
|
|
20
|
-
cloudRunServiceBase?: string // todo: review
|
|
21
|
-
runtimeServiceAccount: string
|
|
22
|
-
/**
|
|
23
|
-
* GCP region where the Cloud Run service is deployed. Example: 'europe-west1'
|
|
24
|
-
*/
|
|
25
|
-
cloudRunRegion: string
|
|
26
|
-
sqlInstance?: string
|
|
27
|
-
vpcConnector?: string
|
|
28
|
-
//
|
|
29
|
-
// Urls
|
|
30
|
-
//
|
|
31
|
-
serviceUrl?: string
|
|
32
|
-
/**
|
|
33
|
-
* Service URL that is used to access the service externally (through load balancer)
|
|
34
|
-
* todo: overlaps with env.K_EXTERNAL_URL
|
|
35
|
-
*/
|
|
36
|
-
externalUrl?: string
|
|
37
|
-
//
|
|
38
|
-
// Versioning
|
|
39
|
-
//
|
|
40
|
-
buildVersion: string // todo: overlaps with env.BUILD_VERSION
|
|
41
|
-
/**
|
|
42
|
-
* Unix timestamp of the build/deployment time.
|
|
43
|
-
*/
|
|
44
|
-
tsUnix: UnixTimestamp
|
|
45
|
-
//
|
|
46
|
-
// Docker
|
|
47
|
-
//
|
|
48
|
-
targetDockerImageId: string
|
|
49
|
-
dockerImageTag: string
|
|
50
|
-
//
|
|
51
|
-
// Git
|
|
52
|
-
//
|
|
53
|
-
/**
|
|
54
|
-
* Short SHA of the commit used for this deployment.
|
|
55
|
-
*/
|
|
56
|
-
gitRev: string
|
|
57
|
-
gitBranch: string
|
|
58
|
-
//
|
|
59
|
-
// Cloud Run environment settings
|
|
60
|
-
//
|
|
61
|
-
/**
|
|
62
|
-
* Example: 'APP_ENV=prod,BUILD_VERSION=abcd,a=b'
|
|
63
|
-
*/
|
|
64
|
-
envString: string
|
|
65
|
-
/**
|
|
66
|
-
* Example: httpGet.path='/',httpGet.port=8080,initialDelaySeconds=3,failureThreshold=50,timeoutSeconds=1,periodSeconds=2
|
|
67
|
-
*/
|
|
68
|
-
startupProbeConfigString: string
|
|
69
|
-
livenessProbeConfigString?: string
|
|
70
|
-
minInstances: NonNegativeInteger
|
|
71
|
-
maxInstances: PositiveInteger
|
|
72
|
-
/**
|
|
73
|
-
* CloudRun concurrency setting.
|
|
74
|
-
* Example: 80
|
|
75
|
-
*/
|
|
76
|
-
concurrency: PositiveInteger
|
|
77
|
-
/**
|
|
78
|
-
* Example: '512Mi'
|
|
79
|
-
*/
|
|
80
|
-
memoryPerInstance: string
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface CloudRunProbeConfig {
|
|
84
|
-
/**
|
|
85
|
-
* Example: '/'
|
|
86
|
-
*/
|
|
87
|
-
'httpGet.path': string
|
|
88
|
-
'httpGet.port': PositiveInteger
|
|
89
|
-
initialDelaySeconds: NumberOfSeconds
|
|
90
|
-
failureThreshold: PositiveInteger
|
|
91
|
-
timeoutSeconds: NumberOfSeconds
|
|
92
|
-
periodSeconds: NumberOfSeconds
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface CloudRunEnv {
|
|
96
|
-
APP_ENV: string
|
|
97
|
-
/**
|
|
98
|
-
* Example: '--max-old-space-size=864'
|
|
99
|
-
*/
|
|
100
|
-
NODE_OPTIONS?: string
|
|
101
|
-
/**
|
|
102
|
-
* Example: '2025-09-01T15:23:20.769Z'
|
|
103
|
-
* The result of running `new Date().toISOString()`
|
|
104
|
-
*/
|
|
105
|
-
DEPLOY_BUILD_TIME: string
|
|
106
|
-
/**
|
|
107
|
-
* Example: 'abcd'
|
|
108
|
-
* Should match the name of the GCP project.
|
|
109
|
-
*/
|
|
110
|
-
GOOGLE_CLOUD_PROJECT: string
|
|
111
|
-
/**
|
|
112
|
-
* Anything (a string) that would identify the build.
|
|
113
|
-
*/
|
|
114
|
-
BUILD_VERSION: string
|
|
115
|
-
/**
|
|
116
|
-
* External url of the deployed service.
|
|
117
|
-
*/
|
|
118
|
-
K_EXTERNAL_URL?: string
|
|
119
|
-
// UV_THREADPOOL_SIZE?: number
|
|
120
|
-
|
|
121
|
-
OTEL_SERVICE_NAME?: string
|
|
122
|
-
OTEL_METRICS_EXPORTER?: 'console' | 'otlp' | string
|
|
123
|
-
OTEL_METRIC_EXPORT_INTERVAL?: NumberOfMilliseconds
|
|
124
|
-
OTEL_METRIC_EXPORT_TIMEOUT?: NumberOfMilliseconds
|
|
125
|
-
OTEL_EXPORTER_OTLP_PROTOCOL?: 'http/protobuf' | string
|
|
126
|
-
/**
|
|
127
|
-
* Example: 'http://localhost:4317'
|
|
128
|
-
*/
|
|
129
|
-
OTEL_EXPORTER_OTLP_ENDPOINT?: string
|
|
130
|
-
OTEL_LOG_LEVEL?: 'INFO' | 'DEBUG'
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @experimental
|
|
135
|
-
*/
|
|
136
|
-
class CloudRunUtil {
|
|
137
|
-
/**
|
|
138
|
-
* Turns an object into a string representation where each
|
|
139
|
-
* key-value pair is represented as `key1=value1,key2=value2,...`.
|
|
140
|
-
*/
|
|
141
|
-
stringifyObject(obj: AnyObject): string {
|
|
142
|
-
const filteredObj = _filterUndefinedValues(obj)
|
|
143
|
-
return Object.entries(filteredObj)
|
|
144
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
145
|
-
.join(',')
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
readonly defaultStartupProbeConfig: CloudRunProbeConfig = {
|
|
149
|
-
'httpGet.path': '/',
|
|
150
|
-
'httpGet.port': 8080,
|
|
151
|
-
initialDelaySeconds: 3,
|
|
152
|
-
failureThreshold: 50,
|
|
153
|
-
timeoutSeconds: 1,
|
|
154
|
-
periodSeconds: 2,
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
readonly defaultLivenessProbeConfig: CloudRunProbeConfig = {
|
|
158
|
-
'httpGet.path': '/',
|
|
159
|
-
'httpGet.port': 8080,
|
|
160
|
-
// how long to wait before doing the first check, AFTER the startup probe has succeeded
|
|
161
|
-
initialDelaySeconds: 60,
|
|
162
|
-
// after how many failure it should kill/restart the container
|
|
163
|
-
failureThreshold: 5,
|
|
164
|
-
// how long to wait until liveness probe considers the endpoint unhealthy
|
|
165
|
-
timeoutSeconds: 30,
|
|
166
|
-
// check every periodSeconds
|
|
167
|
-
periodSeconds: 60,
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export const cloudRunUtil = new CloudRunUtil()
|