node-server-engine 1.13.0 → 2.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.
- package/README.md +1 -0
- package/dist/entities/ElasticSearch/ElasticSearch.js +2 -1
- package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
- package/dist/entities/PubSub/PubSub.js +13 -6
- package/dist/entities/PubSub/PubSub.js.map +1 -1
- package/dist/entities/Sequelize/Sequelize.js +21 -1
- package/dist/entities/Sequelize/Sequelize.js.map +1 -1
- package/dist/entities/Server/Server.d.ts +2 -0
- package/dist/entities/Server/Server.js +15 -1
- package/dist/entities/Server/Server.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/authJwt/authJwt.js +3 -5
- package/dist/middleware/authJwt/authJwt.js.map +1 -1
- package/dist/middleware/authStatic/authStatic.js +12 -8
- package/dist/middleware/authStatic/authStatic.js.map +1 -1
- package/dist/middleware/authTls/authTls.js +2 -1
- package/dist/middleware/authTls/authTls.js.map +1 -1
- package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js +50 -3
- package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js.map +1 -1
- package/dist/utils/dbMigration/dbMigration.js +2 -1
- package/dist/utils/dbMigration/dbMigration.js.map +1 -1
- package/dist/utils/geminiFileUpload/geminiFileUpload.d.ts +10 -1
- package/dist/utils/geminiFileUpload/geminiFileUpload.js +58 -46
- package/dist/utils/geminiFileUpload/geminiFileUpload.js.map +1 -1
- package/dist/utils/jwt/jwt.js +0 -3
- package/dist/utils/jwt/jwt.js.map +1 -1
- package/dist/utils/report/output.d.ts +2 -0
- package/dist/utils/report/output.js +27 -0
- package/dist/utils/report/output.js.map +1 -1
- package/dist/utils/sendEmail/sendEmail.js +5 -4
- package/dist/utils/sendEmail/sendEmail.js.map +1 -1
- package/dist/utils/verificationToken/verificationToken.js +16 -9
- package/dist/utils/verificationToken/verificationToken.js.map +1 -1
- package/package.json +59 -51
package/README.md
CHANGED
|
@@ -2171,6 +2171,7 @@ const payload = verifyVerificationToken(token, {
|
|
|
2171
2171
|
- `VERIFICATION_TOKEN_OTP_SECRET` (optional, defaults to `VERIFICATION_TOKEN_SECRET`)
|
|
2172
2172
|
- `VERIFICATION_TOKEN_ISSUER` (optional, default: `node-server-engine`)
|
|
2173
2173
|
- `VERIFICATION_TOKEN_AUDIENCE` (optional, used when `audience` is not provided)
|
|
2174
|
+
- `VERIFICATION_BYPASS_SUBJECT` / `VERIFICATION_BYPASS_OTP` (optional, both required to enable). Lets a single review account (for example an app store review login) pass verification with a fixed OTP when `verifyVerificationToken` is called with a matching `subject`. Disabled by default; only set these in environments that need it.
|
|
2174
2175
|
|
|
2175
2176
|
#### Multi-service setup
|
|
2176
2177
|
|
|
@@ -12,7 +12,8 @@ var _EngineError = require("../EngineError");
|
|
|
12
12
|
var _LifecycleController = require("../LifecycleController");
|
|
13
13
|
var _utils = require("../../utils");
|
|
14
14
|
var _checkEnvironment = require("../../utils/checkEnvironment");
|
|
15
|
-
|
|
15
|
+
var cache;
|
|
16
|
+
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
|
16
17
|
const namespace = 'engine:elasticsearch';
|
|
17
18
|
|
|
18
19
|
/** Elastic search client */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElasticSearch.js","names":["_fs","require","_path","_interopRequireDefault","_elasticsearch","_EngineError","_LifecycleController","_utils","_checkEnvironment","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","namespace","client","ElasticSearch","exports","init","checkEnvironment","ELASTIC_SEARCH_HOST","envAssert","isString","ELASTIC_SEARCH_USERNAME","ELASTIC_SEARCH_PASSWORD","ELASTIC_SEARCH_MIGRATION_PATH","process","env","EngineError","message","reportDebug","data","host","config","node","auth","username","password","maxRetries","requestTimeout","sniffOnStart","TLS_CA","tls","ca","rejectUnauthorized","NODE_ENV","Client","ping","error","indices","delete","index","migrate","LifecycleController","register","reportInfo","getClient","migrationPath","path","resolve","files","readdirSync","filter","endsWith","indexExists","exists","ran","file","result","search","query","match","total","hits","value","push","migration","specifier","Promise","then","s","id","document","ranAt","Date","toISOString","reportError","stack","length","shutdown","close","undefined"],"sources":["../../../src/entities/ElasticSearch/ElasticSearch.ts"],"sourcesContent":["import { readdirSync } from 'fs';\nimport path from 'path';\nimport { Client, ClientOptions } from '@elastic/elasticsearch';\nimport { ElasticSearchMigration } from './ElasticSearch.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { envAssert, reportError, reportInfo, reportDebug } from 'utils';\nimport { checkEnvironment } from 'utils/checkEnvironment';\n\nconst namespace = 'engine:elasticsearch';\n\n/** Elastic search client */\nlet client: undefined | Client;\n\nexport const ElasticSearch = {\n /**\n * Init function that should be called on server startup to establish the connection\n */\n async init(): Promise<void> {\n checkEnvironment({\n ELASTIC_SEARCH_HOST: envAssert.isString(),\n ELASTIC_SEARCH_USERNAME: envAssert.isString(),\n ELASTIC_SEARCH_PASSWORD: envAssert.isString(),\n ELASTIC_SEARCH_MIGRATION_PATH: envAssert.isString()\n });\n\n if (!process.env.ELASTIC_SEARCH_HOST)\n throw new EngineError({\n message: 'ElasticSearch Host not set in environment'\n });\n\n reportDebug({\n namespace,\n message: 'Initializing ElasticSearch client',\n data: { host: process.env.ELASTIC_SEARCH_HOST }\n });\n\n const config: ClientOptions = {\n node: process.env.ELASTIC_SEARCH_HOST,\n auth: {\n username: process.env.ELASTIC_SEARCH_USERNAME as string,\n password: process.env.ELASTIC_SEARCH_PASSWORD as string\n },\n maxRetries: 3,\n requestTimeout: 30000,\n sniffOnStart: false\n };\n\n // Add TLS configuration if TLS_CA is provided\n if (process.env.TLS_CA) {\n config.tls = {\n ca: process.env.TLS_CA,\n rejectUnauthorized: process.env.NODE_ENV === 'production'\n };\n reportDebug({\n namespace,\n message: 'TLS enabled for ElasticSearch connection'\n });\n }\n\n client = new Client(config);\n\n // Verify connection\n try {\n await client.ping();\n reportDebug({\n namespace,\n message: 'ElasticSearch connection established'\n });\n } catch (error) {\n throw new EngineError({\n message: 'Failed to connect to ElasticSearch',\n data: { error: (error as Error).message }\n });\n }\n\n // In test environment flush the database before running migrations\n if (process.env.NODE_ENV === 'test') {\n reportDebug({\n namespace,\n message: 'Test environment detected, flushing all indices'\n });\n await client.indices.delete({ index: '*' });\n }\n\n await this.migrate();\n LifecycleController.register(this);\n\n reportInfo({ message: 'ElasticSearch initialized successfully' });\n },\n\n /**\n * Get the ElasticSearch client (for advanced use cases)\n */\n getClient(): Client | undefined {\n return client;\n },\n\n /**\n * Migration function called during the init process\n * Manages the database structure\n */\n async migrate(): Promise<void> {\n if (!client) throw new EngineError({ message: 'ElasticSearch was not initialized' });\n\n reportDebug({\n namespace,\n message: 'Starting ElasticSearch migrations'\n });\n\n const migrationPath = path.resolve(\n process.env.ELASTIC_SEARCH_MIGRATION_PATH as string\n );\n\n let files: string[];\n try {\n files = readdirSync(migrationPath).filter(\n f => f.endsWith('.ts') || f.endsWith('.js')\n );\n } catch (error) {\n throw new EngineError({\n message: 'Failed to read migration directory',\n data: { path: migrationPath, error: (error as Error).message }\n });\n }\n\n const indexExists = await client.indices.exists({\n index: 'migrations'\n });\n\n const ran: string[] = [];\n\n for (const file of files) {\n if (indexExists) {\n const result = await client.search({\n index: 'migrations',\n query: { match: { file } }\n });\n\n const total = typeof result.hits.total === 'number'\n ? result.hits.total\n : result.hits.total?.value ?? 0;\n\n if (total > 0) {\n reportDebug({\n namespace,\n message: `Skipping migration ${file} (already ran)`\n });\n continue;\n }\n }\n\n reportDebug({\n namespace,\n message: `Running migration: ${file}`\n });\n\n ran.push(file);\n\n try {\n const migration = (await import(\n `${migrationPath}/${file}`\n )) as ElasticSearchMigration;\n\n await migration.migrate(client);\n\n await client.index({\n index: 'migrations',\n id: file,\n document: { file, ranAt: new Date().toISOString() }\n });\n\n reportDebug({\n namespace,\n message: `Successfully ran migration: ${file}`\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: `Migration failed: ${file}`,\n data: { error: (error as Error).message, stack: (error as Error).stack }\n })\n );\n throw error;\n }\n }\n\n reportInfo({\n message: `ElasticSearch: ran ${ran.length} migration(s)`,\n data: { files: ran }\n });\n },\n\n /**\n * Shutdown function that should be called on server stop to close the connection\n */\n async shutdown(): Promise<void> {\n if (client) {\n try {\n await client.close();\n reportDebug({\n namespace,\n message: 'ElasticSearch client disconnected'\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: 'Error during ElasticSearch shutdown',\n data: { error: (error as Error).message }\n })\n );\n }\n client = undefined;\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"ElasticSearch.js","names":["_fs","require","_path","_interopRequireDefault","_elasticsearch","_EngineError","_LifecycleController","_utils","_checkEnvironment","cache","_interopRequireWildcard","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","namespace","client","ElasticSearch","exports","init","checkEnvironment","ELASTIC_SEARCH_HOST","envAssert","isString","ELASTIC_SEARCH_USERNAME","ELASTIC_SEARCH_PASSWORD","ELASTIC_SEARCH_MIGRATION_PATH","process","env","EngineError","message","reportDebug","data","host","config","node","auth","username","password","maxRetries","requestTimeout","sniffOnStart","TLS_CA","tls","ca","rejectUnauthorized","NODE_ENV","Client","ping","error","indices","delete","index","migrate","LifecycleController","register","reportInfo","getClient","migrationPath","path","resolve","files","readdirSync","filter","f","endsWith","indexExists","exists","ran","file","result","search","query","match","total","hits","value","push","migration","specifier","Promise","then","s","id","document","ranAt","Date","toISOString","reportError","stack","length","shutdown","close","undefined"],"sources":["../../../src/entities/ElasticSearch/ElasticSearch.ts"],"sourcesContent":["import { readdirSync } from 'fs';\nimport path from 'path';\nimport { Client, ClientOptions } from '@elastic/elasticsearch';\nimport { ElasticSearchMigration } from './ElasticSearch.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { envAssert, reportError, reportInfo, reportDebug } from 'utils';\nimport { checkEnvironment } from 'utils/checkEnvironment';\n\nconst namespace = 'engine:elasticsearch';\n\n/** Elastic search client */\nlet client: undefined | Client;\n\nexport const ElasticSearch = {\n /**\n * Init function that should be called on server startup to establish the connection\n */\n async init(): Promise<void> {\n checkEnvironment({\n ELASTIC_SEARCH_HOST: envAssert.isString(),\n ELASTIC_SEARCH_USERNAME: envAssert.isString(),\n ELASTIC_SEARCH_PASSWORD: envAssert.isString(),\n ELASTIC_SEARCH_MIGRATION_PATH: envAssert.isString()\n });\n\n if (!process.env.ELASTIC_SEARCH_HOST)\n throw new EngineError({\n message: 'ElasticSearch Host not set in environment'\n });\n\n reportDebug({\n namespace,\n message: 'Initializing ElasticSearch client',\n data: { host: process.env.ELASTIC_SEARCH_HOST }\n });\n\n const config: ClientOptions = {\n node: process.env.ELASTIC_SEARCH_HOST,\n auth: {\n username: process.env.ELASTIC_SEARCH_USERNAME as string,\n password: process.env.ELASTIC_SEARCH_PASSWORD as string\n },\n maxRetries: 3,\n requestTimeout: 30000,\n sniffOnStart: false\n };\n\n // Add TLS configuration if TLS_CA is provided\n if (process.env.TLS_CA) {\n config.tls = {\n ca: process.env.TLS_CA,\n rejectUnauthorized: process.env.NODE_ENV === 'production'\n };\n reportDebug({\n namespace,\n message: 'TLS enabled for ElasticSearch connection'\n });\n }\n\n client = new Client(config);\n\n // Verify connection\n try {\n await client.ping();\n reportDebug({\n namespace,\n message: 'ElasticSearch connection established'\n });\n } catch (error) {\n throw new EngineError({\n message: 'Failed to connect to ElasticSearch',\n data: { error: (error as Error).message }\n });\n }\n\n // In test environment flush the database before running migrations\n if (process.env.NODE_ENV === 'test') {\n reportDebug({\n namespace,\n message: 'Test environment detected, flushing all indices'\n });\n await client.indices.delete({ index: '*' });\n }\n\n await this.migrate();\n LifecycleController.register(this);\n\n reportInfo({ message: 'ElasticSearch initialized successfully' });\n },\n\n /**\n * Get the ElasticSearch client (for advanced use cases)\n */\n getClient(): Client | undefined {\n return client;\n },\n\n /**\n * Migration function called during the init process\n * Manages the database structure\n */\n async migrate(): Promise<void> {\n if (!client) throw new EngineError({ message: 'ElasticSearch was not initialized' });\n\n reportDebug({\n namespace,\n message: 'Starting ElasticSearch migrations'\n });\n\n const migrationPath = path.resolve(\n process.env.ELASTIC_SEARCH_MIGRATION_PATH as string\n );\n\n let files: string[];\n try {\n files = readdirSync(migrationPath).filter(\n f => f.endsWith('.ts') || f.endsWith('.js')\n );\n } catch (error) {\n throw new EngineError({\n message: 'Failed to read migration directory',\n data: { path: migrationPath, error: (error as Error).message }\n });\n }\n\n const indexExists = await client.indices.exists({\n index: 'migrations'\n });\n\n const ran: string[] = [];\n\n for (const file of files) {\n if (indexExists) {\n const result = await client.search({\n index: 'migrations',\n query: { match: { file } }\n });\n\n const total = typeof result.hits.total === 'number'\n ? result.hits.total\n : result.hits.total?.value ?? 0;\n\n if (total > 0) {\n reportDebug({\n namespace,\n message: `Skipping migration ${file} (already ran)`\n });\n continue;\n }\n }\n\n reportDebug({\n namespace,\n message: `Running migration: ${file}`\n });\n\n ran.push(file);\n\n try {\n const migration = (await import(\n `${migrationPath}/${file}`\n )) as ElasticSearchMigration;\n\n await migration.migrate(client);\n\n await client.index({\n index: 'migrations',\n id: file,\n document: { file, ranAt: new Date().toISOString() }\n });\n\n reportDebug({\n namespace,\n message: `Successfully ran migration: ${file}`\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: `Migration failed: ${file}`,\n data: { error: (error as Error).message, stack: (error as Error).stack }\n })\n );\n throw error;\n }\n }\n\n reportInfo({\n message: `ElasticSearch: ran ${ran.length} migration(s)`,\n data: { files: ran }\n });\n },\n\n /**\n * Shutdown function that should be called on server stop to close the connection\n */\n async shutdown(): Promise<void> {\n if (client) {\n try {\n await client.close();\n reportDebug({\n namespace,\n message: 'ElasticSearch client disconnected'\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: 'Error during ElasticSearch shutdown',\n data: { error: (error as Error).message }\n })\n );\n }\n client = undefined;\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -57,9 +57,12 @@ const subscriptions = {};
|
|
|
57
57
|
* Associative containing all the topics registered for publishing
|
|
58
58
|
*/
|
|
59
59
|
const topics = {};
|
|
60
|
-
const pubSubClient = new _pubsub.PubSub(
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const pubSubClient = new _pubsub.PubSub({
|
|
61
|
+
...(resolvedProjectId ? {
|
|
62
|
+
projectId: resolvedProjectId
|
|
63
|
+
} : {}),
|
|
64
|
+
enableOpenTelemetryTracing: true
|
|
65
|
+
});
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
68
|
* This is a singleton service who's role is to manage pub/sub connections
|
|
@@ -167,7 +170,6 @@ const PubSub = exports.PubSub = {
|
|
|
167
170
|
for (const topic of topicArray) {
|
|
168
171
|
if (!Object.keys(topics).includes(topic)) {
|
|
169
172
|
topics[topic] = pubSubClient.topic(topic, {
|
|
170
|
-
enableOpenTelemetryTracing: true,
|
|
171
173
|
messageOrdering: options?.enableMessageOrdering ?? false,
|
|
172
174
|
batching: options?.batching ? {
|
|
173
175
|
maxMessages: options.batching.maxMessages ?? 100,
|
|
@@ -219,7 +221,6 @@ const PubSub = exports.PubSub = {
|
|
|
219
221
|
if (!Object.keys(subscriptions).includes(subscription)) {
|
|
220
222
|
subscriptions[subscription] = {
|
|
221
223
|
subscription: pubSubClient.subscription(subscription, {
|
|
222
|
-
enableOpenTelemetryTracing: true,
|
|
223
224
|
flowControl: flowControl ? {
|
|
224
225
|
maxMessages: flowControl.maxMessages ?? 1000,
|
|
225
226
|
maxBytes: flowControl.maxBytes ?? 100 * 1024 * 1024,
|
|
@@ -230,7 +231,13 @@ const PubSub = exports.PubSub = {
|
|
|
230
231
|
maxBytes: 100 * 1024 * 1024,
|
|
231
232
|
allowExcessMessages: true
|
|
232
233
|
},
|
|
233
|
-
|
|
234
|
+
// A fixed ack deadline (in seconds) is expressed as equal min/max deadlines
|
|
235
|
+
minAckDeadline: _pubsub.Duration.from({
|
|
236
|
+
seconds: ackDeadline ?? 60
|
|
237
|
+
}),
|
|
238
|
+
maxAckDeadline: _pubsub.Duration.from({
|
|
239
|
+
seconds: ackDeadline ?? 60
|
|
240
|
+
})
|
|
234
241
|
}),
|
|
235
242
|
handlers: []
|
|
236
243
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PubSub.js","names":["_pubsub","require","_handleMessage","_EngineError","_LifecycleController","_utils","namespace","RETRYABLE_ERROR_CODES","Set","resolvedProjectId","process","env","GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GCP_PROJECT_ID","isRetryableInitError","error","err","message","toLowerCase","code","Number","parseInt","has","includes","withRetry","operationName","fn","maxAttempts","Math","max","PUBSUB_INIT_MAX_ATTEMPTS","baseDelayMs","PUBSUB_INIT_RETRY_BASE_DELAY_MS","maxDelayMs","PUBSUB_INIT_RETRY_MAX_DELAY_MS","lastError","attempt","delayMs","min","reportError","reason","Error","String","Promise","resolve","setTimeout","subscriptions","topics","pubSubClient","PubsubClient","projectId","undefined","PubSub","exports","init","reportDebug","skipValidation","PUBSUB_SKIP_VALIDATION","all","Object","values","map","topic","exists","name","EngineError","permissions","iam","testPermissions","hasPermissions","every","success","subscription","handlers","isDebezium","on","handleMessage","catch","LifecycleController","register","shutdown","flush","close","keys","forEach","addPublisher","options","topicArray","Array","join","data","enableOpenTelemetryTracing","messageOrdering","enableMessageOrdering","batching","maxMessages","maxBytes","maxMilliseconds","gaxOpts","retry","retryCodes","backoffSettings","initialRetryDelayMillis","initialDelayMillis","maxRetryDelayMillis","maxDelayMillis","retryDelayMultiplier","delayMultiplier","initialRpcTimeoutMillis","maxRpcTimeoutMillis","rpcTimeoutMultiplier","totalTimeoutMillis","addSubscriber","handler","first","flowControl","ackDeadline","handlersCount","length","allowExcessMessages","push","unshift","publish","attributes","orderingKey","publishMessage","json"],"sources":["../../../src/entities/PubSub/PubSub.ts"],"sourcesContent":["import {\n Attributes,\n PubSub as PubsubClient,\n Message\n} from '@google-cloud/pubsub';\nimport { handleMessage } from './handleMessage';\nimport {\n PubSubTopicsMap,\n PubSubSubscriptionsMap,\n PubSubAddSubscriberOptions,\n PubSubMessageHandler,\n PubSubPublisherOptions\n} from './PubSub.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportError } from 'utils';\n\nconst namespace = 'engine:PubSub';\nconst RETRYABLE_ERROR_CODES = new Set([4, 8, 10, 13, 14]); // DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED, ABORTED, INTERNAL, UNAVAILABLE\nconst resolvedProjectId =\n process.env.GOOGLE_CLOUD_PROJECT ||\n process.env.GCLOUD_PROJECT ||\n process.env.GCP_PROJECT_ID;\n\nfunction isRetryableInitError(error: unknown): boolean {\n const err = error as { code?: number | string; message?: string } | undefined;\n const message = (err?.message ?? '').toLowerCase();\n const code =\n typeof err?.code === 'string' ? Number.parseInt(err.code, 10) : err?.code;\n return (\n (typeof code === 'number' && RETRYABLE_ERROR_CODES.has(code)) ||\n message.includes('deadline exceeded') ||\n message.includes('timed out') ||\n message.includes('timeout') ||\n message.includes('unavailable') ||\n message.includes('resource exhausted')\n );\n}\n\nasync function withRetry<T>(\n operationName: string,\n fn: () => Promise<T>\n): Promise<T> {\n const maxAttempts = Math.max(\n 1,\n Number.parseInt(process.env.PUBSUB_INIT_MAX_ATTEMPTS ?? '4', 10)\n );\n const baseDelayMs = Math.max(\n 100,\n Number.parseInt(process.env.PUBSUB_INIT_RETRY_BASE_DELAY_MS ?? '1000', 10)\n );\n const maxDelayMs = Math.max(\n baseDelayMs,\n Number.parseInt(process.env.PUBSUB_INIT_RETRY_MAX_DELAY_MS ?? '10000', 10)\n );\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n if (!isRetryableInitError(error) || attempt === maxAttempts) {\n throw error;\n }\n const delayMs = Math.min(baseDelayMs * 2 ** (attempt - 1), maxDelayMs);\n reportError({\n namespace,\n message: `Retrying Pub/Sub init operation '${operationName}'`,\n error: {\n attempt,\n maxAttempts,\n delayMs,\n reason: error instanceof Error ? error.message : String(error)\n }\n });\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(\n `Pub/Sub init operation '${operationName}' failed after retries`\n );\n}\n\n/**\n * Associative containing all the subscriptions sorted by topic registered for publishing\n */\nconst subscriptions: PubSubSubscriptionsMap = {};\n\n/**\n * Associative containing all the topics registered for publishing\n */\nconst topics: PubSubTopicsMap = {};\n\nconst pubSubClient = new PubsubClient(\n resolvedProjectId ? { projectId: resolvedProjectId } : undefined\n);\n\n/**\n * This is a singleton service who's role is to manage pub/sub connections\n * It is the preferred way to interact with Pub/Sub as it manages the underlying subscription and handler objects\n * It avoids potential subscription splitting on an instance\n */\nexport const PubSub = {\n /**\n * Initialize the registered publishers and subscribers\n */\n async init(): Promise<void> {\n reportDebug({ namespace, message: `Initializing Pub/Sub` });\n if (!resolvedProjectId) {\n reportDebug({\n namespace,\n message:\n 'Pub/Sub projectId not set in env, relying on ADC auto-detection'\n });\n }\n const skipValidation =\n process.env.PUBSUB_SKIP_VALIDATION?.toLowerCase() === 'true';\n // Check that all topics/permissions exist, and that we have permission on them\n if (!skipValidation) {\n await Promise.all([\n // Test that all topics actually exist and that we have permissions\n ...Object.values(topics).map(async (topic) => {\n const [exists] = await withRetry(\n `topic.exists:${topic.name}`,\n async () => topic.exists()\n );\n if (!exists)\n throw new EngineError(`Topic ${topic.name} does not exist`);\n // Test permission ton publish to topic\n const [permissions] = await withRetry(\n `topic.permissions:${topic.name}`,\n async () => topic.iam.testPermissions(['pubsub.topics.publish'])\n );\n const hasPermissions = Object.values(permissions).every(\n (success) => success\n );\n if (!hasPermissions)\n throw new EngineError(\n `Instance does not have appropriate permissions to publish to topic ${topic.name}`\n );\n }),\n // Test that all subscriptions actually exist and that we have permissions\n ...Object.values(subscriptions).map(async ({ subscription }) => {\n const [exists] = await withRetry(\n `subscription.exists:${subscription.name}`,\n async () => subscription.exists()\n );\n if (!exists)\n throw new EngineError(\n `Subscription ${subscription.name} does not exist`\n );\n // Test permission ton consume subscription\n const [permissions] = await withRetry(\n `subscription.permissions:${subscription.name}`,\n async () =>\n subscription.iam.testPermissions(['pubsub.subscriptions.consume'])\n );\n const hasPermissions = Object.values(permissions).every(\n (success) => success\n );\n if (!hasPermissions)\n throw new EngineError(\n `Instance does not have appropriate permissions to subscribe to subscription ${subscription.name}`\n );\n })\n ]);\n } else {\n reportDebug({\n namespace,\n message:\n 'Skipping Pub/Sub existence and permission validation (PUBSUB_SKIP_VALIDATION=true)'\n });\n }\n\n // Register handlers on the subscriptions to activate them\n for (const { subscription, handlers, isDebezium } of Object.values(\n subscriptions\n )) {\n subscription.on('message', (message) => {\n handleMessage(\n message as Message,\n subscription,\n handlers,\n isDebezium\n ).catch((error) => {\n reportError(error);\n });\n });\n subscription.on('error', (error) => {\n reportError({\n namespace,\n message: `Pub/Sub subscription stream error on '${subscription.name}'`,\n error\n });\n });\n }\n\n LifecycleController.register(PubSub);\n },\n\n /**\n * Shutdown the registered publishers and subscribers\n */\n async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Pub/Sub` });\n // Flush all pending messages and shut down connections\n await Promise.all([\n ...Object.values(topics).map(async (topic) => topic.flush()),\n ...Object.values(subscriptions).map(async ({ subscription }) =>\n subscription.close()\n )\n ]);\n // Delete the stored topics/subscriptions\n Object.keys(topics).forEach((topic) => delete topics[topic]);\n Object.keys(subscriptions).forEach(\n (subscription) => delete subscriptions[subscription]\n );\n // Close the client\n await pubSubClient.close();\n },\n\n /**\n * Creates a publisher if it does not exist yet\n * @param topic - Topic name or array of topic names\n * @param options - Publisher configuration options\n */\n addPublisher(\n topic: string | Array<string>,\n options?: PubSubPublisherOptions\n ): void {\n const topicArray = topic instanceof Array ? topic : [topic];\n reportDebug({\n namespace,\n message: `Registering publisher for topics '${topicArray.join(\"', '\")}'`,\n data: options\n });\n // Register a new topic if it does not exist yet\n for (const topic of topicArray) {\n if (!Object.keys(topics).includes(topic)) {\n topics[topic] = pubSubClient.topic(topic, {\n enableOpenTelemetryTracing: true,\n messageOrdering: options?.enableMessageOrdering ?? false,\n batching: options?.batching\n ? {\n maxMessages: options.batching.maxMessages ?? 100,\n maxBytes: options.batching.maxBytes ?? 1024 * 1024, // 1MB\n maxMilliseconds: options.batching.maxMilliseconds ?? 100\n }\n : undefined,\n gaxOpts: options?.retry\n ? {\n retry: {\n retryCodes: [10, 14], // ABORTED, UNAVAILABLE\n backoffSettings: {\n initialRetryDelayMillis:\n options.retry.initialDelayMillis ?? 100,\n maxRetryDelayMillis: options.retry.maxDelayMillis ?? 60000,\n retryDelayMultiplier: options.retry.delayMultiplier ?? 1.3,\n initialRpcTimeoutMillis: 60000,\n maxRpcTimeoutMillis: 600000,\n rpcTimeoutMultiplier: 1.0,\n totalTimeoutMillis: 600000\n }\n }\n }\n : undefined\n });\n }\n }\n },\n\n /**\n * Add message handlers to a subscription\n * @param subscription - Name of the Pub/Sub subscription\n * @param handler - Function or list of functions to set as message handlers\n * @param options - Indicates that the additional options need to handle on Subscriber\n */\n addSubscriber<T>(\n subscription: string,\n handler: PubSubMessageHandler<T> | Array<PubSubMessageHandler<T>>,\n options: PubSubAddSubscriberOptions = {}\n ): void {\n const handlers = handler instanceof Array ? handler : [handler];\n const isDebezium = options?.isDebezium ?? false;\n const first = options?.first ?? false;\n const flowControl = options?.flowControl;\n const ackDeadline = options?.ackDeadline;\n\n reportDebug({\n namespace,\n message: `Registering subscriber for subscription '${subscription}'`,\n data: {\n first,\n handlersCount: handlers.length,\n isDebezium,\n flowControl\n }\n });\n if (!Object.keys(subscriptions).includes(subscription)) {\n subscriptions[subscription] = {\n subscription: pubSubClient.subscription(subscription, {\n enableOpenTelemetryTracing: true,\n flowControl: flowControl\n ? {\n maxMessages: flowControl.maxMessages ?? 1000,\n maxBytes: flowControl.maxBytes ?? 100 * 1024 * 1024, // 100MB\n allowExcessMessages: flowControl.allowExcessMessages ?? true\n }\n : {\n maxMessages: 1000,\n maxBytes: 100 * 1024 * 1024,\n allowExcessMessages: true\n },\n ackDeadline: ackDeadline ?? 60\n }),\n handlers: []\n };\n }\n\n if (isDebezium) subscriptions[subscription].isDebezium = true;\n\n if (first) subscriptions[subscription].handlers.push(...handlers);\n else subscriptions[subscription].handlers.unshift(...handlers);\n },\n\n /**\n * Send a message to a Pub/Sub topic\n * @param topic - Name of the topic\n * @param message - Content of the message, must be an object that can be JSON stringified\n * @param attributes - Attributes for this message, can be used to filter messages on the subscription\n * @param orderingKey - Enforce order guarantee of messages sent with the same key\n */\n async publish(\n topic: string,\n message: unknown,\n attributes?: Attributes,\n orderingKey?: string\n ): Promise<void> {\n if (!topics[topic])\n throw new EngineError(`No publisher was registered for topic '${topic}'`);\n reportDebug({\n namespace,\n message: `Sending message to topic '${topic}'`,\n data: { message, attributes, orderingKey }\n });\n await topics[topic].publishMessage({\n json: message,\n attributes,\n orderingKey\n });\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"PubSub.js","names":["_pubsub","require","_handleMessage","_EngineError","_LifecycleController","_utils","namespace","RETRYABLE_ERROR_CODES","Set","resolvedProjectId","process","env","GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GCP_PROJECT_ID","isRetryableInitError","error","err","message","toLowerCase","code","Number","parseInt","has","includes","withRetry","operationName","fn","maxAttempts","Math","max","PUBSUB_INIT_MAX_ATTEMPTS","baseDelayMs","PUBSUB_INIT_RETRY_BASE_DELAY_MS","maxDelayMs","PUBSUB_INIT_RETRY_MAX_DELAY_MS","lastError","attempt","delayMs","min","reportError","reason","Error","String","Promise","resolve","setTimeout","subscriptions","topics","pubSubClient","PubsubClient","projectId","enableOpenTelemetryTracing","PubSub","exports","init","reportDebug","skipValidation","PUBSUB_SKIP_VALIDATION","all","Object","values","map","topic","exists","name","EngineError","permissions","iam","testPermissions","hasPermissions","every","success","subscription","handlers","isDebezium","on","handleMessage","catch","LifecycleController","register","shutdown","flush","close","keys","forEach","addPublisher","options","topicArray","Array","join","data","messageOrdering","enableMessageOrdering","batching","maxMessages","maxBytes","maxMilliseconds","undefined","gaxOpts","retry","retryCodes","backoffSettings","initialRetryDelayMillis","initialDelayMillis","maxRetryDelayMillis","maxDelayMillis","retryDelayMultiplier","delayMultiplier","initialRpcTimeoutMillis","maxRpcTimeoutMillis","rpcTimeoutMultiplier","totalTimeoutMillis","addSubscriber","handler","first","flowControl","ackDeadline","handlersCount","length","allowExcessMessages","minAckDeadline","Duration","from","seconds","maxAckDeadline","push","unshift","publish","attributes","orderingKey","publishMessage","json"],"sources":["../../../src/entities/PubSub/PubSub.ts"],"sourcesContent":["import {\n Attributes,\n Duration,\n PubSub as PubsubClient,\n Message\n} from '@google-cloud/pubsub';\nimport { handleMessage } from './handleMessage';\nimport {\n PubSubTopicsMap,\n PubSubSubscriptionsMap,\n PubSubAddSubscriberOptions,\n PubSubMessageHandler,\n PubSubPublisherOptions\n} from './PubSub.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportError } from 'utils';\n\nconst namespace = 'engine:PubSub';\nconst RETRYABLE_ERROR_CODES = new Set([4, 8, 10, 13, 14]); // DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED, ABORTED, INTERNAL, UNAVAILABLE\nconst resolvedProjectId =\n process.env.GOOGLE_CLOUD_PROJECT ||\n process.env.GCLOUD_PROJECT ||\n process.env.GCP_PROJECT_ID;\n\nfunction isRetryableInitError(error: unknown): boolean {\n const err = error as { code?: number | string; message?: string } | undefined;\n const message = (err?.message ?? '').toLowerCase();\n const code =\n typeof err?.code === 'string' ? Number.parseInt(err.code, 10) : err?.code;\n return (\n (typeof code === 'number' && RETRYABLE_ERROR_CODES.has(code)) ||\n message.includes('deadline exceeded') ||\n message.includes('timed out') ||\n message.includes('timeout') ||\n message.includes('unavailable') ||\n message.includes('resource exhausted')\n );\n}\n\nasync function withRetry<T>(\n operationName: string,\n fn: () => Promise<T>\n): Promise<T> {\n const maxAttempts = Math.max(\n 1,\n Number.parseInt(process.env.PUBSUB_INIT_MAX_ATTEMPTS ?? '4', 10)\n );\n const baseDelayMs = Math.max(\n 100,\n Number.parseInt(process.env.PUBSUB_INIT_RETRY_BASE_DELAY_MS ?? '1000', 10)\n );\n const maxDelayMs = Math.max(\n baseDelayMs,\n Number.parseInt(process.env.PUBSUB_INIT_RETRY_MAX_DELAY_MS ?? '10000', 10)\n );\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n if (!isRetryableInitError(error) || attempt === maxAttempts) {\n throw error;\n }\n const delayMs = Math.min(baseDelayMs * 2 ** (attempt - 1), maxDelayMs);\n reportError({\n namespace,\n message: `Retrying Pub/Sub init operation '${operationName}'`,\n error: {\n attempt,\n maxAttempts,\n delayMs,\n reason: error instanceof Error ? error.message : String(error)\n }\n });\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(\n `Pub/Sub init operation '${operationName}' failed after retries`\n );\n}\n\n/**\n * Associative containing all the subscriptions sorted by topic registered for publishing\n */\nconst subscriptions: PubSubSubscriptionsMap = {};\n\n/**\n * Associative containing all the topics registered for publishing\n */\nconst topics: PubSubTopicsMap = {};\n\nconst pubSubClient = new PubsubClient({\n ...(resolvedProjectId ? { projectId: resolvedProjectId } : {}),\n enableOpenTelemetryTracing: true\n});\n\n/**\n * This is a singleton service who's role is to manage pub/sub connections\n * It is the preferred way to interact with Pub/Sub as it manages the underlying subscription and handler objects\n * It avoids potential subscription splitting on an instance\n */\nexport const PubSub = {\n /**\n * Initialize the registered publishers and subscribers\n */\n async init(): Promise<void> {\n reportDebug({ namespace, message: `Initializing Pub/Sub` });\n if (!resolvedProjectId) {\n reportDebug({\n namespace,\n message:\n 'Pub/Sub projectId not set in env, relying on ADC auto-detection'\n });\n }\n const skipValidation =\n process.env.PUBSUB_SKIP_VALIDATION?.toLowerCase() === 'true';\n // Check that all topics/permissions exist, and that we have permission on them\n if (!skipValidation) {\n await Promise.all([\n // Test that all topics actually exist and that we have permissions\n ...Object.values(topics).map(async (topic) => {\n const [exists] = await withRetry(\n `topic.exists:${topic.name}`,\n async () => topic.exists()\n );\n if (!exists)\n throw new EngineError(`Topic ${topic.name} does not exist`);\n // Test permission ton publish to topic\n const [permissions] = await withRetry(\n `topic.permissions:${topic.name}`,\n async () => topic.iam.testPermissions(['pubsub.topics.publish'])\n );\n const hasPermissions = Object.values(permissions).every(\n (success) => success\n );\n if (!hasPermissions)\n throw new EngineError(\n `Instance does not have appropriate permissions to publish to topic ${topic.name}`\n );\n }),\n // Test that all subscriptions actually exist and that we have permissions\n ...Object.values(subscriptions).map(async ({ subscription }) => {\n const [exists] = await withRetry(\n `subscription.exists:${subscription.name}`,\n async () => subscription.exists()\n );\n if (!exists)\n throw new EngineError(\n `Subscription ${subscription.name} does not exist`\n );\n // Test permission ton consume subscription\n const [permissions] = await withRetry(\n `subscription.permissions:${subscription.name}`,\n async () =>\n subscription.iam.testPermissions(['pubsub.subscriptions.consume'])\n );\n const hasPermissions = Object.values(permissions).every(\n (success) => success\n );\n if (!hasPermissions)\n throw new EngineError(\n `Instance does not have appropriate permissions to subscribe to subscription ${subscription.name}`\n );\n })\n ]);\n } else {\n reportDebug({\n namespace,\n message:\n 'Skipping Pub/Sub existence and permission validation (PUBSUB_SKIP_VALIDATION=true)'\n });\n }\n\n // Register handlers on the subscriptions to activate them\n for (const { subscription, handlers, isDebezium } of Object.values(\n subscriptions\n )) {\n subscription.on('message', (message) => {\n handleMessage(\n message as Message,\n subscription,\n handlers,\n isDebezium\n ).catch((error) => {\n reportError(error);\n });\n });\n subscription.on('error', (error) => {\n reportError({\n namespace,\n message: `Pub/Sub subscription stream error on '${subscription.name}'`,\n error\n });\n });\n }\n\n LifecycleController.register(PubSub);\n },\n\n /**\n * Shutdown the registered publishers and subscribers\n */\n async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Pub/Sub` });\n // Flush all pending messages and shut down connections\n await Promise.all([\n ...Object.values(topics).map(async (topic) => topic.flush()),\n ...Object.values(subscriptions).map(async ({ subscription }) =>\n subscription.close()\n )\n ]);\n // Delete the stored topics/subscriptions\n Object.keys(topics).forEach((topic) => delete topics[topic]);\n Object.keys(subscriptions).forEach(\n (subscription) => delete subscriptions[subscription]\n );\n // Close the client\n await pubSubClient.close();\n },\n\n /**\n * Creates a publisher if it does not exist yet\n * @param topic - Topic name or array of topic names\n * @param options - Publisher configuration options\n */\n addPublisher(\n topic: string | Array<string>,\n options?: PubSubPublisherOptions\n ): void {\n const topicArray = topic instanceof Array ? topic : [topic];\n reportDebug({\n namespace,\n message: `Registering publisher for topics '${topicArray.join(\"', '\")}'`,\n data: options\n });\n // Register a new topic if it does not exist yet\n for (const topic of topicArray) {\n if (!Object.keys(topics).includes(topic)) {\n topics[topic] = pubSubClient.topic(topic, {\n messageOrdering: options?.enableMessageOrdering ?? false,\n batching: options?.batching\n ? {\n maxMessages: options.batching.maxMessages ?? 100,\n maxBytes: options.batching.maxBytes ?? 1024 * 1024, // 1MB\n maxMilliseconds: options.batching.maxMilliseconds ?? 100\n }\n : undefined,\n gaxOpts: options?.retry\n ? {\n retry: {\n retryCodes: [10, 14], // ABORTED, UNAVAILABLE\n backoffSettings: {\n initialRetryDelayMillis:\n options.retry.initialDelayMillis ?? 100,\n maxRetryDelayMillis: options.retry.maxDelayMillis ?? 60000,\n retryDelayMultiplier: options.retry.delayMultiplier ?? 1.3,\n initialRpcTimeoutMillis: 60000,\n maxRpcTimeoutMillis: 600000,\n rpcTimeoutMultiplier: 1.0,\n totalTimeoutMillis: 600000\n }\n }\n }\n : undefined\n });\n }\n }\n },\n\n /**\n * Add message handlers to a subscription\n * @param subscription - Name of the Pub/Sub subscription\n * @param handler - Function or list of functions to set as message handlers\n * @param options - Indicates that the additional options need to handle on Subscriber\n */\n addSubscriber<T>(\n subscription: string,\n handler: PubSubMessageHandler<T> | Array<PubSubMessageHandler<T>>,\n options: PubSubAddSubscriberOptions = {}\n ): void {\n const handlers = handler instanceof Array ? handler : [handler];\n const isDebezium = options?.isDebezium ?? false;\n const first = options?.first ?? false;\n const flowControl = options?.flowControl;\n const ackDeadline = options?.ackDeadline;\n\n reportDebug({\n namespace,\n message: `Registering subscriber for subscription '${subscription}'`,\n data: {\n first,\n handlersCount: handlers.length,\n isDebezium,\n flowControl\n }\n });\n if (!Object.keys(subscriptions).includes(subscription)) {\n subscriptions[subscription] = {\n subscription: pubSubClient.subscription(subscription, {\n flowControl: flowControl\n ? {\n maxMessages: flowControl.maxMessages ?? 1000,\n maxBytes: flowControl.maxBytes ?? 100 * 1024 * 1024, // 100MB\n allowExcessMessages: flowControl.allowExcessMessages ?? true\n }\n : {\n maxMessages: 1000,\n maxBytes: 100 * 1024 * 1024,\n allowExcessMessages: true\n },\n // A fixed ack deadline (in seconds) is expressed as equal min/max deadlines\n minAckDeadline: Duration.from({ seconds: ackDeadline ?? 60 }),\n maxAckDeadline: Duration.from({ seconds: ackDeadline ?? 60 })\n }),\n handlers: []\n };\n }\n\n if (isDebezium) subscriptions[subscription].isDebezium = true;\n\n if (first) subscriptions[subscription].handlers.push(...handlers);\n else subscriptions[subscription].handlers.unshift(...handlers);\n },\n\n /**\n * Send a message to a Pub/Sub topic\n * @param topic - Name of the topic\n * @param message - Content of the message, must be an object that can be JSON stringified\n * @param attributes - Attributes for this message, can be used to filter messages on the subscription\n * @param orderingKey - Enforce order guarantee of messages sent with the same key\n */\n async publish(\n topic: string,\n message: unknown,\n attributes?: Attributes,\n orderingKey?: string\n ): Promise<void> {\n if (!topics[topic])\n throw new EngineError(`No publisher was registered for topic '${topic}'`);\n reportDebug({\n namespace,\n message: `Sending message to topic '${topic}'`,\n data: { message, attributes, orderingKey }\n });\n await topics[topic].publishMessage({\n json: message,\n attributes,\n orderingKey\n });\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,6 +9,7 @@ exports.createSequelizeClient = createSequelizeClient;
|
|
|
9
9
|
exports.init = init;
|
|
10
10
|
exports.sequelizeClient = exports.sequelize = void 0;
|
|
11
11
|
exports.shutdown = shutdown;
|
|
12
|
+
var _path = _interopRequireDefault(require("path"));
|
|
12
13
|
var _sequelizeTypescript = require("sequelize-typescript");
|
|
13
14
|
var _Sequelize = _interopRequireDefault(require("./Sequelize.config"));
|
|
14
15
|
var _Sequelize2 = require("./Sequelize.validate");
|
|
@@ -52,7 +53,8 @@ async function init() {
|
|
|
52
53
|
user: process.env.SQL_USER,
|
|
53
54
|
port: process.env.SQL_PORT,
|
|
54
55
|
dialect: process.env.SQL_TYPE || 'postgres',
|
|
55
|
-
isUnixSocket: process.env.SQL_HOST?.startsWith('/')
|
|
56
|
+
isUnixSocket: process.env.SQL_HOST?.startsWith('/'),
|
|
57
|
+
sqlStorage: (process.env.SQL_TYPE ?? '').toLowerCase() === 'sqlite' ? process.env.SQL_STORAGE || _path.default.join(process.cwd(), 'database.sqlite') : undefined
|
|
56
58
|
}
|
|
57
59
|
});
|
|
58
60
|
exports.sequelizeClient = sequelizeClient = createSequelizeClient();
|
|
@@ -153,6 +155,24 @@ function createSequelizeClient() {
|
|
|
153
155
|
});
|
|
154
156
|
}
|
|
155
157
|
|
|
158
|
+
// File-based SQLite for local / offline dev (no SQL_HOST / live server)
|
|
159
|
+
const sqlType = (process.env.SQL_TYPE ?? '').toLowerCase();
|
|
160
|
+
if (sqlType === 'sqlite') {
|
|
161
|
+
const storage = process.env.SQL_STORAGE && process.env.SQL_STORAGE.trim().length > 0 ? process.env.SQL_STORAGE.trim() : _path.default.join(process.cwd(), 'database.sqlite');
|
|
162
|
+
(0, _report.reportInfo)({
|
|
163
|
+
message: 'Creating Sequelize client (SQLite file)',
|
|
164
|
+
data: {
|
|
165
|
+
storage,
|
|
166
|
+
dialect: 'sqlite'
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return new _sequelizeTypescript.Sequelize({
|
|
170
|
+
dialect: 'sqlite',
|
|
171
|
+
storage,
|
|
172
|
+
logging: process.env.SQL_LOGGING === 'true' ? console.log : false
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
156
176
|
// Throw an error if there is no host initial
|
|
157
177
|
(0, _Sequelize2.validateSequelizeEnvironment)();
|
|
158
178
|
(0, _report.reportInfo)({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sequelize.js","names":["_sequelizeTypescript","require","_Sequelize","_interopRequireDefault","_Sequelize2","_EngineError","_LifecycleController","_report","sequelizeClient","exports","sequelize","Proxy","get","target","property","init","shutdown","addModels","EngineError","message","reportInfo","data","host","process","env","SQL_HOST","database","SQL_DB","user","SQL_USER","port","SQL_PORT","dialect","SQL_TYPE","isUnixSocket","startsWith","createSequelizeClient","NODE_ENV","authenticate","getDialect","err","reportError","error","Error","String","stack","undefined","LifecycleController","register","close","console","models","addHook","result","convertToPlain","instance","modelInstance","toJSON","plain","Object","keys","forEach","key","Array","isArray","sync","Sequelize","storage","logging","validateSequelizeEnvironment","username","dbConfig","poolMax","pool","max","poolMin","min","SQL_PASSWORD"],"sources":["../../../src/entities/Sequelize/Sequelize.ts"],"sourcesContent":["import { Sequelize, ModelCtor } from 'sequelize-typescript';\nimport dbConfig from './Sequelize.config';\nimport { Sequelize as SequelizeInterface } from './Sequelize.types';\nimport { validateSequelizeEnvironment } from './Sequelize.validate';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportInfo, reportError } from 'utils/report';\n\nexport let sequelizeClient: undefined | Sequelize;\n\n/**\n * We use a proxy to extend the Sequelize behavior and allow initialization of the client only when needed while keeping the same interface\n */\nexport const sequelize = new Proxy<SequelizeInterface>(\n // Due to how we do the proxying, we are forced to ignore ts-errors, we could never create an object that respects the interface properly\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n {},\n {\n get: function (target, property): unknown {\n if (property === 'init') return init;\n if (property === 'shutdown') return shutdown;\n if (property === 'addModels') return addModels;\n // Create the sequelize client if it does not exist\n if (!sequelizeClient)\n throw new EngineError({\n message: 'Sequelize client was not initialized'\n });\n // Call the function on the sequelize client\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return sequelizeClient[property] as unknown;\n }\n }\n);\n\n/** On init create client and connect */\nexport async function init(): Promise<void> {\n // Ignore if already initialized\n if (sequelizeClient) return;\n \n reportInfo({\n message: 'Initializing Sequelize client',\n data: {\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n user: process.env.SQL_USER,\n port: process.env.SQL_PORT,\n dialect: process.env.SQL_TYPE || 'postgres',\n isUnixSocket: process.env.SQL_HOST?.startsWith('/')\n }\n });\n \n sequelizeClient = createSequelizeClient();\n \n // In test environment, authentication happens automatically with SQLite\n // For other environments, authenticate and log the result\n if (process.env.NODE_ENV !== 'test') {\n reportInfo({\n message: 'Starting database authentication'\n });\n\n try {\n await sequelizeClient.authenticate();\n reportInfo({ \n message: 'Connected to database successfully',\n data: {\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n dialect: sequelizeClient?.getDialect()\n }\n });\n } catch (err) {\n reportError({\n message: 'Failed to connect to database',\n data: {\n error: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n user: process.env.SQL_USER,\n port: process.env.SQL_PORT\n }\n });\n if (err instanceof Error) {\n reportError(err);\n }\n throw err;\n }\n }\n \n LifecycleController.register(sequelize);\n}\n\n/** On shutdown close connection and clear client */\nexport async function shutdown(): Promise<void> {\n if (sequelizeClient) {\n try {\n // For SQLite, just close the client (closing connection manager first causes SQLITE_MISUSE)\n // For other dialects, sequelize.close() handles everything properly\n await sequelizeClient.close();\n } catch (error) {\n // Ignore errors during shutdown\n if (process.env.NODE_ENV !== 'test') {\n console.error('Error closing sequelize client:', error);\n }\n }\n }\n sequelizeClient = undefined;\n}\n\nexport function addModels(models: Array<ModelCtor>): void {\n if (!sequelizeClient)\n throw new EngineError({\n message: 'Sequelize client was not initialized'\n });\n sequelizeClient.addModels(models);\n \n // Override toJSON behavior globally to ensure consistency between dev and prod\n // In dev (ts-node), property access works directly on instances\n // In prod (compiled), we need explicit serialization\n // This hook intercepts all afterFind results and converts them to plain objects\n sequelizeClient.addHook('afterFind', (result) => {\n if (!result) return;\n \n const convertToPlain = (instance: unknown) => {\n if (!instance || typeof instance !== 'object') return instance;\n const modelInstance = instance as { toJSON?: () => Record<string, unknown> } & Record<string, unknown>;\n if (!modelInstance.toJSON) return instance;\n const plain = modelInstance.toJSON();\n // Copy the plain object properties back to the instance\n // This makes property access work without .toJSON() in compiled code\n Object.keys(plain).forEach(key => {\n modelInstance[key] = plain[key];\n });\n };\n \n if (Array.isArray(result)) {\n result.forEach(convertToPlain);\n } else {\n convertToPlain(result);\n }\n });\n \n sequelizeClient.sync();\n}\n\n/** Create Sequelize client */\nexport function createSequelizeClient(): Sequelize {\n // Use in-memory SQLite for test environment to avoid real database connections\n if (process.env.NODE_ENV === 'test') {\n return new Sequelize({\n dialect: 'sqlite',\n storage: ':memory:',\n logging: false\n });\n }\n \n // Throw an error if there is no host initial\n validateSequelizeEnvironment();\n \n reportInfo({\n message: 'Creating Sequelize client with config',\n data: {\n database: process.env.SQL_DB,\n username: process.env.SQL_USER,\n host: process.env.SQL_HOST,\n port: dbConfig.port,\n dialect: dbConfig.dialect,\n isUnixSocket: process.env.SQL_HOST?.startsWith('/'),\n poolMax: dbConfig.pool?.max,\n poolMin: dbConfig.pool?.min\n }\n });\n \n return new Sequelize(\n process.env.SQL_DB as string,\n process.env.SQL_USER as string,\n process.env.SQL_PASSWORD as string,\n dbConfig\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Sequelize.js","names":["_path","_interopRequireDefault","require","_sequelizeTypescript","_Sequelize","_Sequelize2","_EngineError","_LifecycleController","_report","sequelizeClient","exports","sequelize","Proxy","get","target","property","init","shutdown","addModels","EngineError","message","reportInfo","data","host","process","env","SQL_HOST","database","SQL_DB","user","SQL_USER","port","SQL_PORT","dialect","SQL_TYPE","isUnixSocket","startsWith","sqlStorage","toLowerCase","SQL_STORAGE","path","join","cwd","undefined","createSequelizeClient","NODE_ENV","authenticate","getDialect","err","reportError","error","Error","String","stack","LifecycleController","register","close","console","models","addHook","result","convertToPlain","instance","modelInstance","toJSON","plain","Object","keys","forEach","key","Array","isArray","sync","Sequelize","storage","logging","sqlType","trim","length","SQL_LOGGING","log","validateSequelizeEnvironment","username","dbConfig","poolMax","pool","max","poolMin","min","SQL_PASSWORD"],"sources":["../../../src/entities/Sequelize/Sequelize.ts"],"sourcesContent":["import path from 'path';\nimport { Sequelize, ModelCtor } from 'sequelize-typescript';\nimport dbConfig from './Sequelize.config';\nimport { Sequelize as SequelizeInterface } from './Sequelize.types';\nimport { validateSequelizeEnvironment } from './Sequelize.validate';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportInfo, reportError } from 'utils/report';\n\nexport let sequelizeClient: undefined | Sequelize;\n\n/**\n * We use a proxy to extend the Sequelize behavior and allow initialization of the client only when needed while keeping the same interface\n */\nexport const sequelize = new Proxy<SequelizeInterface>(\n // Due to how we do the proxying, we are forced to ignore ts-errors, we could never create an object that respects the interface properly\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n {},\n {\n get: function (target, property): unknown {\n if (property === 'init') return init;\n if (property === 'shutdown') return shutdown;\n if (property === 'addModels') return addModels;\n // Create the sequelize client if it does not exist\n if (!sequelizeClient)\n throw new EngineError({\n message: 'Sequelize client was not initialized'\n });\n // Call the function on the sequelize client\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return sequelizeClient[property] as unknown;\n }\n }\n);\n\n/** On init create client and connect */\nexport async function init(): Promise<void> {\n // Ignore if already initialized\n if (sequelizeClient) return;\n \n reportInfo({\n message: 'Initializing Sequelize client',\n data: {\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n user: process.env.SQL_USER,\n port: process.env.SQL_PORT,\n dialect: process.env.SQL_TYPE || 'postgres',\n isUnixSocket: process.env.SQL_HOST?.startsWith('/'),\n sqlStorage:\n (process.env.SQL_TYPE ?? '').toLowerCase() === 'sqlite'\n ? process.env.SQL_STORAGE || path.join(process.cwd(), 'database.sqlite')\n : undefined\n }\n });\n \n sequelizeClient = createSequelizeClient();\n \n // In test environment, authentication happens automatically with SQLite\n // For other environments, authenticate and log the result\n if (process.env.NODE_ENV !== 'test') {\n reportInfo({\n message: 'Starting database authentication'\n });\n\n try {\n await sequelizeClient.authenticate();\n reportInfo({ \n message: 'Connected to database successfully',\n data: {\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n dialect: sequelizeClient?.getDialect()\n }\n });\n } catch (err) {\n reportError({\n message: 'Failed to connect to database',\n data: {\n error: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n host: process.env.SQL_HOST,\n database: process.env.SQL_DB,\n user: process.env.SQL_USER,\n port: process.env.SQL_PORT\n }\n });\n if (err instanceof Error) {\n reportError(err);\n }\n throw err;\n }\n }\n \n LifecycleController.register(sequelize);\n}\n\n/** On shutdown close connection and clear client */\nexport async function shutdown(): Promise<void> {\n if (sequelizeClient) {\n try {\n // For SQLite, just close the client (closing connection manager first causes SQLITE_MISUSE)\n // For other dialects, sequelize.close() handles everything properly\n await sequelizeClient.close();\n } catch (error) {\n // Ignore errors during shutdown\n if (process.env.NODE_ENV !== 'test') {\n console.error('Error closing sequelize client:', error);\n }\n }\n }\n sequelizeClient = undefined;\n}\n\nexport function addModels(models: Array<ModelCtor>): void {\n if (!sequelizeClient)\n throw new EngineError({\n message: 'Sequelize client was not initialized'\n });\n sequelizeClient.addModels(models);\n \n // Override toJSON behavior globally to ensure consistency between dev and prod\n // In dev (ts-node), property access works directly on instances\n // In prod (compiled), we need explicit serialization\n // This hook intercepts all afterFind results and converts them to plain objects\n sequelizeClient.addHook('afterFind', (result) => {\n if (!result) return;\n \n const convertToPlain = (instance: unknown) => {\n if (!instance || typeof instance !== 'object') return instance;\n const modelInstance = instance as { toJSON?: () => Record<string, unknown> } & Record<string, unknown>;\n if (!modelInstance.toJSON) return instance;\n const plain = modelInstance.toJSON();\n // Copy the plain object properties back to the instance\n // This makes property access work without .toJSON() in compiled code\n Object.keys(plain).forEach(key => {\n modelInstance[key] = plain[key];\n });\n };\n \n if (Array.isArray(result)) {\n result.forEach(convertToPlain);\n } else {\n convertToPlain(result);\n }\n });\n \n sequelizeClient.sync();\n}\n\n/** Create Sequelize client */\nexport function createSequelizeClient(): Sequelize {\n // Use in-memory SQLite for test environment to avoid real database connections\n if (process.env.NODE_ENV === 'test') {\n return new Sequelize({\n dialect: 'sqlite',\n storage: ':memory:',\n logging: false\n });\n }\n\n // File-based SQLite for local / offline dev (no SQL_HOST / live server)\n const sqlType = (process.env.SQL_TYPE ?? '').toLowerCase();\n if (sqlType === 'sqlite') {\n const storage =\n process.env.SQL_STORAGE && process.env.SQL_STORAGE.trim().length > 0\n ? process.env.SQL_STORAGE.trim()\n : path.join(process.cwd(), 'database.sqlite');\n reportInfo({\n message: 'Creating Sequelize client (SQLite file)',\n data: { storage, dialect: 'sqlite' }\n });\n return new Sequelize({\n dialect: 'sqlite',\n storage,\n logging: process.env.SQL_LOGGING === 'true' ? console.log : false\n });\n }\n\n // Throw an error if there is no host initial\n validateSequelizeEnvironment();\n \n reportInfo({\n message: 'Creating Sequelize client with config',\n data: {\n database: process.env.SQL_DB,\n username: process.env.SQL_USER,\n host: process.env.SQL_HOST,\n port: dbConfig.port,\n dialect: dbConfig.dialect,\n isUnixSocket: process.env.SQL_HOST?.startsWith('/'),\n poolMax: dbConfig.pool?.max,\n poolMin: dbConfig.pool?.min\n }\n });\n \n return new Sequelize(\n process.env.SQL_DB as string,\n process.env.SQL_USER as string,\n process.env.SQL_PASSWORD as string,\n dbConfig\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Application } from 'express';
|
|
2
2
|
import { ServerOptions } from './Server.types';
|
|
3
|
+
/** Parse the CORS_ORIGIN variable, which can hold a single origin or a comma separated list */
|
|
4
|
+
export declare function parseCorsOrigin(value?: string): string | Array<string>;
|
|
3
5
|
/** Main server class */
|
|
4
6
|
export declare class Server {
|
|
5
7
|
/** The express application powering the main endpoints */
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.Server = void 0;
|
|
8
|
+
exports.parseCorsOrigin = parseCorsOrigin;
|
|
8
9
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
10
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
11
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
@@ -27,6 +28,17 @@ var _report = require("../../utils/report");
|
|
|
27
28
|
var _tlsConfig = require("../../utils/tlsConfig");
|
|
28
29
|
const namespace = 'engine:Server';
|
|
29
30
|
|
|
31
|
+
/** Default maximum size (in bytes) of an incoming WebSocket message */
|
|
32
|
+
const DEFAULT_WS_MAX_PAYLOAD = 1024 * 1024;
|
|
33
|
+
|
|
34
|
+
/** Parse the CORS_ORIGIN variable, which can hold a single origin or a comma separated list */
|
|
35
|
+
function parseCorsOrigin(value) {
|
|
36
|
+
if (!value) return '*';
|
|
37
|
+
const origins = value.split(',').map(origin => origin.trim()).filter(Boolean);
|
|
38
|
+
if (origins.length === 0) return '*';
|
|
39
|
+
return origins.length === 1 ? origins[0] : origins;
|
|
40
|
+
}
|
|
41
|
+
|
|
30
42
|
/** Main server class */
|
|
31
43
|
let Server = exports.Server = /*#__PURE__*/function () {
|
|
32
44
|
/** Create a server */
|
|
@@ -103,7 +115,7 @@ let Server = exports.Server = /*#__PURE__*/function () {
|
|
|
103
115
|
// Create the primary express core that serves the business logic
|
|
104
116
|
this.app = (0, _express.default)();
|
|
105
117
|
this.app.use((0, _cors.default)({
|
|
106
|
-
origin: process.env.CORS_ORIGIN
|
|
118
|
+
origin: parseCorsOrigin(process.env.CORS_ORIGIN),
|
|
107
119
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
108
120
|
allowedHeaders: ['Content-Type', 'Authorization', 'x-verification-token', 'x-verification-otp', 'Access-Control-Allow-Origin'],
|
|
109
121
|
exposedHeaders: ['Access-Control-Allow-Origin']
|
|
@@ -346,6 +358,8 @@ let Server = exports.Server = /*#__PURE__*/function () {
|
|
|
346
358
|
key: "attachWebSocket",
|
|
347
359
|
value: function attachWebSocket(options) {
|
|
348
360
|
this.wss = new _ws.Server({
|
|
361
|
+
// Limit the size of incoming messages (ws defaults to 100MiB)
|
|
362
|
+
maxPayload: Number(process.env.WS_MAX_PAYLOAD) || DEFAULT_WS_MAX_PAYLOAD,
|
|
349
363
|
...options.server,
|
|
350
364
|
server: this.httpServer
|
|
351
365
|
}).on('connection', (webSocket, request) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Server.js","names":["_fs","_interopRequireDefault","require","_path","_promises","_express","_cors","_ws","_SocketClient","_Server2","_Endpoint","_EngineError","_LifecycleController","_PubSub","_SecretManager","_utils","_jwt","_report","_tlsConfig","namespace","Server","exports","config","_classCallCheck2","default","_defineProperty2","AbortController","validate","reportDebug","message","endpoints","globalMiddleware","errorMiddleware","initCallbacks","shutdownCallbacks","syncCallbacks","cron","auth","noFetch","secretManagerConfig","secretManager","checkEnvironment","process","env","RUN_MIGRATION","UNDO_MIGRATION","SQL_HOST","envAssert","isHost","SQL_USER","isString","SQL_PASSWORD","SQL_DB","NODE_ENV","PORT","isPort","SECONDARY_PORT","app","express","use","cors","origin","CORS_ORIGIN","methods","allowedHeaders","exposedHeaders","registerMiddleware","httpServer","createHttpServer","secondaryApp","secondaryMiddleware","defaultErrorMiddleware","forEach","middleware","secondaryHttpServer","disable","server","headersTimeout","keepAliveTimeout","webSocket","attachWebSocket","_createClass2","key","value","setupGlobalErrorLogging","on","err","reportError","reportInfo","setTimeout","exit","reason","Error","String","init","SecretManager","initKeySets","callback","runCallback","Promise","all","map","PubSub","job","runCronJob","resolve","listen","data","port","secondaryPort","nodeEnv","handleSignal","watchTlsCaFileChange","shutdown","reject","listening","address","close","error","wss","clients","socket","socketKillTimeout","WEBSOCKET_CLOSE_TIMEOUT","parseInt","setTimeoutPromise","readyState","CLOSING","OPEN","terminate","LifecycleController","shutdownRunningInstances","abortController","abort","fileWatchers","watcher","shutdownKeySets","shutdownSignals","signal","removeAllListeners","getApp","getSecondaryApp","defaultMiddleware","path","endpoint","register","options","WebSocketServer","request","SocketClient","client","isShuttingDown","then","catch","file","fs","watch","event","loadTlsConfig","setSecureContext","tlsConfig","push","handler","name","interval","undefined","function","apply","parameters","some","Endpoint","EngineError","Object","values","validator","Array"],"sources":["../../../src/entities/Server/Server.ts"],"sourcesContent":["import fs from 'fs';\nimport http from 'http';\nimport https from 'https';\nimport { AddressInfo } from 'net';\nimport path from 'path';\nimport { setTimeout as setTimeoutPromise } from 'timers/promises';\nimport { ValidatorSpec } from 'envalid';\nimport express, { Application } from 'express';\nimport cors from 'cors';\nimport { Server as WebSocketServer } from 'ws';\nimport { SocketClient } from '../SocketClient';\nimport {\n defaultMiddleware,\n defaultErrorMiddleware,\n secondaryMiddleware,\n shutdownSignals\n} from './Server.const';\nimport {\n ServerOptions,\n ServerCronJon,\n ServerAuthConfig,\n ServerWebSocketConfig,\n ServerGlobalMiddleware,\n ServerErrorMiddleWare,\n ServerCallback\n} from './Server.types';\nimport { Endpoint } from 'entities/Endpoint';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { PubSub } from 'entities/PubSub';\nimport { SecretManager } from 'entities/SecretManager';\nimport { checkEnvironment, envAssert, createHttpServer } from 'utils';\nimport { initKeySets, shutdownKeySets } from 'utils/jwt';\nimport { reportInfo, reportError, reportDebug } from 'utils/report';\nimport { tlsConfig, loadTlsConfig, TlsConfig } from 'utils/tlsConfig';\n\nconst namespace = 'engine:Server';\n\n/** Main server class */\nexport class Server {\n /** The express application powering the main endpoints */\n private app: Application;\n /** The node HTTP(S) server, serving the main express application */\n private httpServer: http.Server | https.Server;\n /** The express application powering the support endpoints */\n private secondaryApp: Application;\n /** The node HTTP(S) server, serving the secondary express application */\n private secondaryHttpServer: http.Server | https.Server;\n /** List of endpoint instances that the server should handle */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private endpoints: Array<Endpoint<any>>;\n /** Mapping of env variable name with functions that should run to check their validity */\n private checkEnvironment: Record<string, ValidatorSpec<unknown>>;\n /** Middleware that should run on every request before the endpoint specific logic */\n private globalMiddleware: Array<ServerGlobalMiddleware>;\n /** Error middleware that should run on every request after the endpoint specific logic, but before the generic global middleware */\n private errorMiddleware: Array<\n ServerGlobalMiddleware | ServerErrorMiddleWare\n >;\n /** Functions that should be called on server startup */\n private initCallbacks: Array<ServerCallback>;\n /** Functions that should be called on server shutdown */\n private shutdownCallbacks: Array<ServerCallback>;\n /** When set to true, this indicates that init callbacks should run synchronously in the order they are declared. By default they all run in parallel */\n private syncCallbacks: boolean;\n /** Config to set regularly running jobs on the server */\n private cron?: Array<ServerCronJon>;\n /** Global auth related configuration */\n private auth: ServerAuthConfig;\n /** Secret Manager configuration */\n private secretManagerConfig?: ServerOptions['secretManager'];\n /** WebSocket server instance, if configured */\n private wss?: WebSocketServer;\n /** Abort controller that handles signals for the server */\n private abortController = new AbortController();\n /** File system watchers for TLS certificate changes */\n private fileWatchers: Array<fs.FSWatcher> = [];\n\n /** Create a server */\n public constructor(config: ServerOptions) {\n this.validate(config);\n\n reportDebug({\n namespace,\n message: `Creating server`\n });\n\n this.endpoints = config.endpoints;\n this.globalMiddleware = config.globalMiddleware ?? [];\n this.errorMiddleware = config.errorMiddleware ?? [];\n this.initCallbacks = config.initCallbacks ?? [];\n this.shutdownCallbacks = config.shutdownCallbacks ?? [];\n this.syncCallbacks = config.syncCallbacks ?? false;\n this.cron = config.cron;\n this.auth = { noFetch: false, ...config.auth };\n this.secretManagerConfig = config.secretManager;\n\n // The minimal environment check is different between the migration modes of execution and the regular server execution mode\n // When running in migration mode, we only check that we have SQL related environment variables\n this.checkEnvironment =\n process.env.RUN_MIGRATION === 'true' ||\n process.env.UNDO_MIGRATION === 'true'\n ? {\n SQL_HOST: envAssert.isHost(),\n SQL_USER: envAssert.isString(),\n SQL_PASSWORD: envAssert.isString(),\n SQL_DB: envAssert.isString()\n }\n : {\n NODE_ENV: envAssert.isString(),\n PORT: envAssert.isPort(),\n SECONDARY_PORT: envAssert.isPort(),\n ...config.checkEnvironment\n };\n\n checkEnvironment(this.checkEnvironment);\n\n // Create the primary express core that serves the business logic\n this.app = express();\n this.app.use(\n cors({\n origin: process.env.CORS_ORIGIN ?? '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\n allowedHeaders: [\n 'Content-Type',\n 'Authorization',\n 'x-verification-token',\n 'x-verification-otp',\n 'Access-Control-Allow-Origin'\n ],\n exposedHeaders: ['Access-Control-Allow-Origin']\n })\n );\n this.registerMiddleware(this.app);\n this.httpServer = createHttpServer(this.app);\n\n // Create a secondary express core that servers metrics and analytics\n // This will be served on a different port, allowing to specify different firewall rules for these routes\n this.secondaryApp = express();\n [...secondaryMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (middleware) this.secondaryApp.use(middleware);\n }\n );\n this.secondaryHttpServer = createHttpServer(this.secondaryApp);\n\n // Remove the express headers\n this.app.disable('x-powered-by');\n this.secondaryApp.disable('x-powered-by');\n\n // We remove all node timeout on connections and requests\n // This responsibility is delegated to the front-facing load balancer\n [this.httpServer, this.secondaryHttpServer].forEach((server) => {\n server.headersTimeout = 0;\n server.keepAliveTimeout = 0;\n });\n\n if (config.webSocket) {\n this.attachWebSocket(config.webSocket);\n }\n }\n\n /**\n * Setup global error handlers for uncaught exceptions and unhandled rejections\n */\n private setupGlobalErrorLogging(): void {\n process.on('uncaughtException', (err) => {\n reportError(err);\n reportInfo('💥 Uncaught exception - process will exit');\n // Give time for logs to flush before exiting\n setTimeout(() => process.exit(1), 1000);\n });\n \n process.on('unhandledRejection', (reason: unknown) => {\n reportError(reason instanceof Error ? reason : new Error(String(reason)));\n reportInfo('💥 Unhandled rejection - process will exit');\n // Give time for logs to flush before exiting\n setTimeout(() => process.exit(1), 1000);\n });\n }\n\n /** Start the server */\n public async init(): Promise<void> {\n this.setupGlobalErrorLogging();\n reportDebug({ namespace, message: `Starting Server` });\n \n // Load secrets from Secret Manager FIRST (before anything else that might need them)\n if (this.secretManagerConfig) {\n await SecretManager.init(this.secretManagerConfig);\n }\n \n // Fetch the keys for JWT authentication\n // Ignore in test environment as we do symmetrical token signing\n if (process.env.NODE_ENV !== 'test' && !this.auth.noFetch)\n await initKeySets();\n // Run all the init callbacks\n // We can either run them all 1/1 synchronously or run them all in parallel (default)\n // Callback can either be direct function or an object with function and parameters attributes\n\n if (this.syncCallbacks) {\n for (const callback of this.initCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.initCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Initialize the Pub/Sub module\n await PubSub.init();\n // Run all the cronjob\n if (this.cron) {\n this.cron.forEach((job) => {\n this.runCronJob(job);\n });\n }\n\n // Start listening to requests\n await Promise.all([\n new Promise<void>((resolve) =>\n this.httpServer.listen(process.env.PORT, () => {\n resolve();\n })\n ),\n new Promise<void>((resolve) =>\n this.secondaryHttpServer.listen(process.env.SECONDARY_PORT, () => {\n resolve();\n })\n )\n ]);\n reportInfo({\n message: 'SERVER_RUNNING',\n data: {\n port: process.env.PORT,\n secondaryPort: process.env.SECONDARY_PORT,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n this.handleSignal();\n\n // Watch TSL config files changing\n this.watchTlsCaFileChange();\n }\n\n /** Graceful shutdown */\n public async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Server` });\n\n // Stop listening to HTTP requests\n await Promise.all(\n [this.httpServer, this.secondaryHttpServer].map(\n (server) =>\n new Promise<void>((resolve, reject) => {\n // Ignore if the server was already stopped\n // We have observed cases where SIGTERM was thrown multiple times\n if (!server.listening) {\n resolve();\n return;\n }\n \n const { port } = server.address() as AddressInfo;\n \n server.close((error) => {\n if (error) {\n reportError(error);\n reject(error);\n } else {\n reportInfo({\n message: `Stopped listening to requests on port ${port}`\n });\n resolve();\n }\n });\n })\n )\n );\n\n // Close all socket connections\n if (this.wss) {\n // First ask them to close gracefully\n this.wss.clients.forEach((socket) => {\n socket.close();\n });\n \n // Hard terminate all connections still open after a defined time\n const socketKillTimeout = process.env.WEBSOCKET_CLOSE_TIMEOUT\n ? parseInt(process.env.WEBSOCKET_CLOSE_TIMEOUT, 10)\n : 5000;\n \n await setTimeoutPromise(socketKillTimeout);\n \n this.wss.clients.forEach((socket) => {\n if (\n socket.readyState === socket.CLOSING ||\n socket.readyState === socket.OPEN\n ) {\n socket.terminate();\n }\n });\n \n // Close the WebSocket server itself\n await new Promise<void>((resolve, reject) => {\n this.wss?.close((error) => {\n if (error) {\n reportError(error);\n reject(error);\n } else {\n reportInfo({ message: 'WebSocket server closed' });\n resolve();\n }\n });\n });\n }\n\n // Run all the shutdown callback\n if (this.syncCallbacks) {\n for (const callback of this.shutdownCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.shutdownCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Shutdown all the running entities\n await LifecycleController.shutdownRunningInstances();\n\n // Abort all the cronjob\n if (this.abortController) this.abortController.abort();\n\n // Close all file watchers\n this.fileWatchers.forEach((watcher) => watcher.close());\n\n // Stop the keyset timers\n shutdownKeySets();\n\n shutdownSignals.forEach((signal) => process.removeAllListeners(signal));\n }\n\n /** Get the express app instance of the server */\n public getApp(): Application {\n return this.app;\n }\n\n /** Get the express app instance of the server */\n public getSecondaryApp(): Application {\n return this.secondaryApp;\n }\n\n /** Registers all the middleware with the express app */\n private registerMiddleware(app: Application): void {\n // Global middleware can specify a path to which they apply\n [...defaultMiddleware, ...this.globalMiddleware].forEach((middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n });\n // Call the register method of each endpoint\n this.endpoints.forEach((endpoint) => {\n endpoint.register(app);\n });\n // Add error middleware\n [...this.errorMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n }\n );\n }\n\n /** Add a handler for WebSocket connections */\n private attachWebSocket(options: ServerWebSocketConfig): void {\n this.wss = new WebSocketServer({\n ...options.server,\n server: this.httpServer\n })\n .on('connection', (webSocket, request) => {\n new SocketClient(webSocket, request, options.client);\n })\n .on('error', (error) => {\n reportError(error);\n });\n }\n\n /** Call shutdown if signal gets sent to the process */\n private handleSignal(): void {\n let isShuttingDown = false;\n \n shutdownSignals.forEach((signal) =>\n process.on(signal, () => {\n // Prevent multiple shutdown attempts\n if (isShuttingDown) {\n reportInfo(`Already shutting down, ignoring ${signal}`);\n return;\n }\n \n isShuttingDown = true;\n reportInfo(`Received shutdown signal [${signal}]`);\n \n this.shutdown()\n .then(() => {\n reportInfo('Graceful shutdown completed successfully');\n process.exit(0);\n })\n .catch((error) => {\n reportError(error);\n process.exit(1);\n });\n })\n );\n }\n\n /** Watch the TLS certificate change event */\n private watchTlsCaFileChange(): void {\n [\n 'TLS_REQUEST_KEY',\n 'TLS_REQUEST_CERT',\n 'TLS_REQUEST_CA',\n 'TLS_SERVER_KEY',\n 'TLS_SERVER_CERT',\n 'TLS_CA'\n ].forEach((key) => {\n const file = process.env[key];\n if (file) {\n const watcher = fs.watch(path.resolve(file), (event) => {\n if (event !== 'change') return;\n reportInfo(`Reloading TLS config [${file} changed]`);\n loadTlsConfig();\n (this.httpServer as https.Server).setSecureContext(\n tlsConfig as TlsConfig\n );\n });\n this.fileWatchers.push(watcher);\n }\n });\n }\n\n /** Executes a recurring job */\n private runCronJob(job: ServerCronJon): void {\n (async (): Promise<void> => {\n reportInfo({ message: `Starting scheduled job \"${job.handler.name}\"` });\n try {\n await job.handler();\n reportInfo({\n message: `Job \"${job.handler.name}\" finished, starting again in ${job.interval} seconds`\n });\n await setTimeoutPromise(job.interval * 1000, undefined, {\n signal: this.abortController.signal\n });\n this.runCronJob(job);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n reportDebug({\n namespace,\n message: `Scheduled job \"${job.handler?.name}\" has been aborted`\n });\n } else {\n throw error;\n }\n }\n })().catch((error) => {\n reportError(error);\n });\n }\n\n /** Run a shutdown/init callback */\n private runCallback(callback: ServerCallback): unknown {\n return typeof callback === 'function'\n ? callback()\n : callback.function.apply(null, callback.parameters ?? []);\n }\n\n /**\n * Validate the Server constructor configuration\n */\n private validate(config: ServerOptions): void {\n if (\n !config.endpoints ||\n config.endpoints.some((endpoint) => !(endpoint instanceof Endpoint))\n )\n throw new EngineError(\n 'Server endpoints should be declared and all be Endpoint instances'\n );\n\n if (\n config.checkEnvironment &&\n Object.values(config.checkEnvironment).some(\n (validator) => typeof validator !== 'function'\n )\n )\n throw new EngineError(\n 'Some of the environment checks are not valid functions'\n );\n\n if (\n config.initCallbacks &&\n (!(config.initCallbacks instanceof Array) ||\n config.initCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Init callbacks is not a list of functions');\n\n if (\n config.shutdownCallbacks &&\n (!(config.shutdownCallbacks instanceof Array) ||\n config.shutdownCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Shutdown callbacks is not a list of functions');\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Server.js","names":["_fs","_interopRequireDefault","require","_path","_promises","_express","_cors","_ws","_SocketClient","_Server2","_Endpoint","_EngineError","_LifecycleController","_PubSub","_SecretManager","_utils","_jwt","_report","_tlsConfig","namespace","DEFAULT_WS_MAX_PAYLOAD","parseCorsOrigin","value","origins","split","map","origin","trim","filter","Boolean","length","Server","exports","config","_classCallCheck2","default","_defineProperty2","AbortController","validate","reportDebug","message","endpoints","globalMiddleware","errorMiddleware","initCallbacks","shutdownCallbacks","syncCallbacks","cron","auth","noFetch","secretManagerConfig","secretManager","checkEnvironment","process","env","RUN_MIGRATION","UNDO_MIGRATION","SQL_HOST","envAssert","isHost","SQL_USER","isString","SQL_PASSWORD","SQL_DB","NODE_ENV","PORT","isPort","SECONDARY_PORT","app","express","use","cors","CORS_ORIGIN","methods","allowedHeaders","exposedHeaders","registerMiddleware","httpServer","createHttpServer","secondaryApp","secondaryMiddleware","defaultErrorMiddleware","forEach","middleware","secondaryHttpServer","disable","server","headersTimeout","keepAliveTimeout","webSocket","attachWebSocket","_createClass2","key","setupGlobalErrorLogging","on","err","reportError","reportInfo","setTimeout","exit","reason","Error","String","init","SecretManager","initKeySets","callback","runCallback","Promise","all","PubSub","job","runCronJob","resolve","listen","data","port","secondaryPort","nodeEnv","handleSignal","watchTlsCaFileChange","shutdown","reject","listening","address","close","error","wss","clients","socket","socketKillTimeout","WEBSOCKET_CLOSE_TIMEOUT","parseInt","setTimeoutPromise","readyState","CLOSING","OPEN","terminate","LifecycleController","shutdownRunningInstances","abortController","abort","fileWatchers","watcher","shutdownKeySets","shutdownSignals","signal","removeAllListeners","getApp","getSecondaryApp","defaultMiddleware","path","endpoint","register","options","WebSocketServer","maxPayload","Number","WS_MAX_PAYLOAD","request","SocketClient","client","isShuttingDown","then","catch","file","fs","watch","event","loadTlsConfig","setSecureContext","tlsConfig","push","handler","name","interval","undefined","function","apply","parameters","some","Endpoint","EngineError","Object","values","validator","Array"],"sources":["../../../src/entities/Server/Server.ts"],"sourcesContent":["import fs from 'fs';\nimport http from 'http';\nimport https from 'https';\nimport { AddressInfo } from 'net';\nimport path from 'path';\nimport { setTimeout as setTimeoutPromise } from 'timers/promises';\nimport { ValidatorSpec } from 'envalid';\nimport express, { Application } from 'express';\nimport cors from 'cors';\nimport { Server as WebSocketServer } from 'ws';\nimport { SocketClient } from '../SocketClient';\nimport {\n defaultMiddleware,\n defaultErrorMiddleware,\n secondaryMiddleware,\n shutdownSignals\n} from './Server.const';\nimport {\n ServerOptions,\n ServerCronJon,\n ServerAuthConfig,\n ServerWebSocketConfig,\n ServerGlobalMiddleware,\n ServerErrorMiddleWare,\n ServerCallback\n} from './Server.types';\nimport { Endpoint } from 'entities/Endpoint';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { PubSub } from 'entities/PubSub';\nimport { SecretManager } from 'entities/SecretManager';\nimport { checkEnvironment, envAssert, createHttpServer } from 'utils';\nimport { initKeySets, shutdownKeySets } from 'utils/jwt';\nimport { reportInfo, reportError, reportDebug } from 'utils/report';\nimport { tlsConfig, loadTlsConfig, TlsConfig } from 'utils/tlsConfig';\n\nconst namespace = 'engine:Server';\n\n/** Default maximum size (in bytes) of an incoming WebSocket message */\nconst DEFAULT_WS_MAX_PAYLOAD = 1024 * 1024;\n\n/** Parse the CORS_ORIGIN variable, which can hold a single origin or a comma separated list */\nexport function parseCorsOrigin(value?: string): string | Array<string> {\n if (!value) return '*';\n const origins = value\n .split(',')\n .map((origin) => origin.trim())\n .filter(Boolean);\n if (origins.length === 0) return '*';\n return origins.length === 1 ? origins[0] : origins;\n}\n\n/** Main server class */\nexport class Server {\n /** The express application powering the main endpoints */\n private app: Application;\n /** The node HTTP(S) server, serving the main express application */\n private httpServer: http.Server | https.Server;\n /** The express application powering the support endpoints */\n private secondaryApp: Application;\n /** The node HTTP(S) server, serving the secondary express application */\n private secondaryHttpServer: http.Server | https.Server;\n /** List of endpoint instances that the server should handle */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private endpoints: Array<Endpoint<any>>;\n /** Mapping of env variable name with functions that should run to check their validity */\n private checkEnvironment: Record<string, ValidatorSpec<unknown>>;\n /** Middleware that should run on every request before the endpoint specific logic */\n private globalMiddleware: Array<ServerGlobalMiddleware>;\n /** Error middleware that should run on every request after the endpoint specific logic, but before the generic global middleware */\n private errorMiddleware: Array<\n ServerGlobalMiddleware | ServerErrorMiddleWare\n >;\n /** Functions that should be called on server startup */\n private initCallbacks: Array<ServerCallback>;\n /** Functions that should be called on server shutdown */\n private shutdownCallbacks: Array<ServerCallback>;\n /** When set to true, this indicates that init callbacks should run synchronously in the order they are declared. By default they all run in parallel */\n private syncCallbacks: boolean;\n /** Config to set regularly running jobs on the server */\n private cron?: Array<ServerCronJon>;\n /** Global auth related configuration */\n private auth: ServerAuthConfig;\n /** Secret Manager configuration */\n private secretManagerConfig?: ServerOptions['secretManager'];\n /** WebSocket server instance, if configured */\n private wss?: WebSocketServer;\n /** Abort controller that handles signals for the server */\n private abortController = new AbortController();\n /** File system watchers for TLS certificate changes */\n private fileWatchers: Array<fs.FSWatcher> = [];\n\n /** Create a server */\n public constructor(config: ServerOptions) {\n this.validate(config);\n\n reportDebug({\n namespace,\n message: `Creating server`\n });\n\n this.endpoints = config.endpoints;\n this.globalMiddleware = config.globalMiddleware ?? [];\n this.errorMiddleware = config.errorMiddleware ?? [];\n this.initCallbacks = config.initCallbacks ?? [];\n this.shutdownCallbacks = config.shutdownCallbacks ?? [];\n this.syncCallbacks = config.syncCallbacks ?? false;\n this.cron = config.cron;\n this.auth = { noFetch: false, ...config.auth };\n this.secretManagerConfig = config.secretManager;\n\n // The minimal environment check is different between the migration modes of execution and the regular server execution mode\n // When running in migration mode, we only check that we have SQL related environment variables\n this.checkEnvironment =\n process.env.RUN_MIGRATION === 'true' ||\n process.env.UNDO_MIGRATION === 'true'\n ? {\n SQL_HOST: envAssert.isHost(),\n SQL_USER: envAssert.isString(),\n SQL_PASSWORD: envAssert.isString(),\n SQL_DB: envAssert.isString()\n }\n : {\n NODE_ENV: envAssert.isString(),\n PORT: envAssert.isPort(),\n SECONDARY_PORT: envAssert.isPort(),\n ...config.checkEnvironment\n };\n\n checkEnvironment(this.checkEnvironment);\n\n // Create the primary express core that serves the business logic\n this.app = express();\n this.app.use(\n cors({\n origin: parseCorsOrigin(process.env.CORS_ORIGIN),\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\n allowedHeaders: [\n 'Content-Type',\n 'Authorization',\n 'x-verification-token',\n 'x-verification-otp',\n 'Access-Control-Allow-Origin'\n ],\n exposedHeaders: ['Access-Control-Allow-Origin']\n })\n );\n this.registerMiddleware(this.app);\n this.httpServer = createHttpServer(this.app);\n\n // Create a secondary express core that servers metrics and analytics\n // This will be served on a different port, allowing to specify different firewall rules for these routes\n this.secondaryApp = express();\n [...secondaryMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (middleware) this.secondaryApp.use(middleware);\n }\n );\n this.secondaryHttpServer = createHttpServer(this.secondaryApp);\n\n // Remove the express headers\n this.app.disable('x-powered-by');\n this.secondaryApp.disable('x-powered-by');\n\n // We remove all node timeout on connections and requests\n // This responsibility is delegated to the front-facing load balancer\n [this.httpServer, this.secondaryHttpServer].forEach((server) => {\n server.headersTimeout = 0;\n server.keepAliveTimeout = 0;\n });\n\n if (config.webSocket) {\n this.attachWebSocket(config.webSocket);\n }\n }\n\n /**\n * Setup global error handlers for uncaught exceptions and unhandled rejections\n */\n private setupGlobalErrorLogging(): void {\n process.on('uncaughtException', (err) => {\n reportError(err);\n reportInfo('💥 Uncaught exception - process will exit');\n // Give time for logs to flush before exiting\n setTimeout(() => process.exit(1), 1000);\n });\n \n process.on('unhandledRejection', (reason: unknown) => {\n reportError(reason instanceof Error ? reason : new Error(String(reason)));\n reportInfo('💥 Unhandled rejection - process will exit');\n // Give time for logs to flush before exiting\n setTimeout(() => process.exit(1), 1000);\n });\n }\n\n /** Start the server */\n public async init(): Promise<void> {\n this.setupGlobalErrorLogging();\n reportDebug({ namespace, message: `Starting Server` });\n \n // Load secrets from Secret Manager FIRST (before anything else that might need them)\n if (this.secretManagerConfig) {\n await SecretManager.init(this.secretManagerConfig);\n }\n \n // Fetch the keys for JWT authentication\n // Ignore in test environment as we do symmetrical token signing\n if (process.env.NODE_ENV !== 'test' && !this.auth.noFetch)\n await initKeySets();\n // Run all the init callbacks\n // We can either run them all 1/1 synchronously or run them all in parallel (default)\n // Callback can either be direct function or an object with function and parameters attributes\n\n if (this.syncCallbacks) {\n for (const callback of this.initCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.initCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Initialize the Pub/Sub module\n await PubSub.init();\n // Run all the cronjob\n if (this.cron) {\n this.cron.forEach((job) => {\n this.runCronJob(job);\n });\n }\n\n // Start listening to requests\n await Promise.all([\n new Promise<void>((resolve) =>\n this.httpServer.listen(process.env.PORT, () => {\n resolve();\n })\n ),\n new Promise<void>((resolve) =>\n this.secondaryHttpServer.listen(process.env.SECONDARY_PORT, () => {\n resolve();\n })\n )\n ]);\n reportInfo({\n message: 'SERVER_RUNNING',\n data: {\n port: process.env.PORT,\n secondaryPort: process.env.SECONDARY_PORT,\n nodeEnv: process.env.NODE_ENV\n }\n });\n\n this.handleSignal();\n\n // Watch TSL config files changing\n this.watchTlsCaFileChange();\n }\n\n /** Graceful shutdown */\n public async shutdown(): Promise<void> {\n reportDebug({ namespace, message: `Shutting down Server` });\n\n // Stop listening to HTTP requests\n await Promise.all(\n [this.httpServer, this.secondaryHttpServer].map(\n (server) =>\n new Promise<void>((resolve, reject) => {\n // Ignore if the server was already stopped\n // We have observed cases where SIGTERM was thrown multiple times\n if (!server.listening) {\n resolve();\n return;\n }\n \n const { port } = server.address() as AddressInfo;\n \n server.close((error) => {\n if (error) {\n reportError(error);\n reject(error);\n } else {\n reportInfo({\n message: `Stopped listening to requests on port ${port}`\n });\n resolve();\n }\n });\n })\n )\n );\n\n // Close all socket connections\n if (this.wss) {\n // First ask them to close gracefully\n this.wss.clients.forEach((socket) => {\n socket.close();\n });\n \n // Hard terminate all connections still open after a defined time\n const socketKillTimeout = process.env.WEBSOCKET_CLOSE_TIMEOUT\n ? parseInt(process.env.WEBSOCKET_CLOSE_TIMEOUT, 10)\n : 5000;\n \n await setTimeoutPromise(socketKillTimeout);\n \n this.wss.clients.forEach((socket) => {\n if (\n socket.readyState === socket.CLOSING ||\n socket.readyState === socket.OPEN\n ) {\n socket.terminate();\n }\n });\n \n // Close the WebSocket server itself\n await new Promise<void>((resolve, reject) => {\n this.wss?.close((error) => {\n if (error) {\n reportError(error);\n reject(error);\n } else {\n reportInfo({ message: 'WebSocket server closed' });\n resolve();\n }\n });\n });\n }\n\n // Run all the shutdown callback\n if (this.syncCallbacks) {\n for (const callback of this.shutdownCallbacks) {\n await this.runCallback(callback);\n }\n } else {\n await Promise.all(\n this.shutdownCallbacks.map((callback) => this.runCallback(callback))\n );\n }\n\n // Shutdown all the running entities\n await LifecycleController.shutdownRunningInstances();\n\n // Abort all the cronjob\n if (this.abortController) this.abortController.abort();\n\n // Close all file watchers\n this.fileWatchers.forEach((watcher) => watcher.close());\n\n // Stop the keyset timers\n shutdownKeySets();\n\n shutdownSignals.forEach((signal) => process.removeAllListeners(signal));\n }\n\n /** Get the express app instance of the server */\n public getApp(): Application {\n return this.app;\n }\n\n /** Get the express app instance of the server */\n public getSecondaryApp(): Application {\n return this.secondaryApp;\n }\n\n /** Registers all the middleware with the express app */\n private registerMiddleware(app: Application): void {\n // Global middleware can specify a path to which they apply\n [...defaultMiddleware, ...this.globalMiddleware].forEach((middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n });\n // Call the register method of each endpoint\n this.endpoints.forEach((endpoint) => {\n endpoint.register(app);\n });\n // Add error middleware\n [...this.errorMiddleware, ...defaultErrorMiddleware].forEach(\n (middleware) => {\n if (typeof middleware === 'function') {\n app.use(middleware);\n } else {\n app.use(middleware.path, middleware.middleware);\n }\n }\n );\n }\n\n /** Add a handler for WebSocket connections */\n private attachWebSocket(options: ServerWebSocketConfig): void {\n this.wss = new WebSocketServer({\n // Limit the size of incoming messages (ws defaults to 100MiB)\n maxPayload: Number(process.env.WS_MAX_PAYLOAD) || DEFAULT_WS_MAX_PAYLOAD,\n ...options.server,\n server: this.httpServer\n })\n .on('connection', (webSocket, request) => {\n new SocketClient(webSocket, request, options.client);\n })\n .on('error', (error) => {\n reportError(error);\n });\n }\n\n /** Call shutdown if signal gets sent to the process */\n private handleSignal(): void {\n let isShuttingDown = false;\n \n shutdownSignals.forEach((signal) =>\n process.on(signal, () => {\n // Prevent multiple shutdown attempts\n if (isShuttingDown) {\n reportInfo(`Already shutting down, ignoring ${signal}`);\n return;\n }\n \n isShuttingDown = true;\n reportInfo(`Received shutdown signal [${signal}]`);\n \n this.shutdown()\n .then(() => {\n reportInfo('Graceful shutdown completed successfully');\n process.exit(0);\n })\n .catch((error) => {\n reportError(error);\n process.exit(1);\n });\n })\n );\n }\n\n /** Watch the TLS certificate change event */\n private watchTlsCaFileChange(): void {\n [\n 'TLS_REQUEST_KEY',\n 'TLS_REQUEST_CERT',\n 'TLS_REQUEST_CA',\n 'TLS_SERVER_KEY',\n 'TLS_SERVER_CERT',\n 'TLS_CA'\n ].forEach((key) => {\n const file = process.env[key];\n if (file) {\n const watcher = fs.watch(path.resolve(file), (event) => {\n if (event !== 'change') return;\n reportInfo(`Reloading TLS config [${file} changed]`);\n loadTlsConfig();\n (this.httpServer as https.Server).setSecureContext(\n tlsConfig as TlsConfig\n );\n });\n this.fileWatchers.push(watcher);\n }\n });\n }\n\n /** Executes a recurring job */\n private runCronJob(job: ServerCronJon): void {\n (async (): Promise<void> => {\n reportInfo({ message: `Starting scheduled job \"${job.handler.name}\"` });\n try {\n await job.handler();\n reportInfo({\n message: `Job \"${job.handler.name}\" finished, starting again in ${job.interval} seconds`\n });\n await setTimeoutPromise(job.interval * 1000, undefined, {\n signal: this.abortController.signal\n });\n this.runCronJob(job);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n reportDebug({\n namespace,\n message: `Scheduled job \"${job.handler?.name}\" has been aborted`\n });\n } else {\n throw error;\n }\n }\n })().catch((error) => {\n reportError(error);\n });\n }\n\n /** Run a shutdown/init callback */\n private runCallback(callback: ServerCallback): unknown {\n return typeof callback === 'function'\n ? callback()\n : callback.function.apply(null, callback.parameters ?? []);\n }\n\n /**\n * Validate the Server constructor configuration\n */\n private validate(config: ServerOptions): void {\n if (\n !config.endpoints ||\n config.endpoints.some((endpoint) => !(endpoint instanceof Endpoint))\n )\n throw new EngineError(\n 'Server endpoints should be declared and all be Endpoint instances'\n );\n\n if (\n config.checkEnvironment &&\n Object.values(config.checkEnvironment).some(\n (validator) => typeof validator !== 'function'\n )\n )\n throw new EngineError(\n 'Some of the environment checks are not valid functions'\n );\n\n if (\n config.initCallbacks &&\n (!(config.initCallbacks instanceof Array) ||\n config.initCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Init callbacks is not a list of functions');\n\n if (\n config.shutdownCallbacks &&\n (!(config.shutdownCallbacks instanceof Array) ||\n config.shutdownCallbacks.some(\n (callback) =>\n !(\n typeof callback === 'function' ||\n typeof callback?.function === 'function'\n )\n ))\n )\n throw new EngineError('Shutdown callbacks is not a list of functions');\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
package/dist/index.js
CHANGED
|
@@ -57,5 +57,6 @@ Object.keys(_tlsRequest).forEach(function (key) {
|
|
|
57
57
|
});
|
|
58
58
|
var _middleware = _interopRequireWildcard(require("./middleware"));
|
|
59
59
|
exports.middleware = _middleware;
|
|
60
|
-
|
|
60
|
+
var cache;
|
|
61
|
+
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
|
61
62
|
//# sourceMappingURL=index.js.map
|