node-server-engine 2.0.1 → 2.1.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/.commitlintrc.js +10 -10
- package/.nycrc +1 -3
- package/.releaserc.js +2 -1
- package/README.md +206 -146
- package/dist/const/metrics.js.map +1 -1
- package/dist/db/models/index.js.map +1 -1
- package/dist/entities/AWSS3/AWSS3.js +12 -12
- package/dist/entities/AWSS3/AWSS3.js.map +1 -1
- package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
- package/dist/entities/Endpoint/Endpoint.types.js.map +1 -1
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js +11 -11
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js.map +1 -1
- package/dist/entities/KeySet/KeySet.js.map +1 -1
- package/dist/entities/PubSub/PubSub.js.map +1 -1
- package/dist/entities/PushNotification/PushNotification.js.map +1 -1
- package/dist/entities/Redis/Redis.js +3 -3
- package/dist/entities/Redis/Redis.js.map +1 -1
- package/dist/entities/SecretManager/SecretManager.js +3 -3
- package/dist/entities/SecretManager/SecretManager.js.map +1 -1
- package/dist/entities/Sequelize/Sequelize.config.js +11 -7
- package/dist/entities/Sequelize/Sequelize.config.js.map +1 -1
- package/dist/entities/Sequelize/Sequelize.js.map +1 -1
- package/dist/entities/Server/Server.js.map +1 -1
- package/dist/entities/Server/Server.types.js.map +1 -1
- package/dist/entities/SocketClient/SocketClient.d.ts +12 -0
- package/dist/entities/SocketClient/SocketClient.js +34 -3
- package/dist/entities/SocketClient/SocketClient.js.map +1 -1
- package/dist/entities/SocketClient/SocketClient.types.d.ts +6 -0
- package/dist/entities/SocketClient/SocketClient.types.js.map +1 -1
- package/dist/entities/index.js.map +1 -1
- package/dist/middleware/checkPermission/checkPermission.js.map +1 -1
- package/dist/middleware/checkPermission/index.js.map +1 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js.map +1 -1
- package/dist/middleware/requestMetrics/requestMetrics.js.map +1 -1
- package/dist/middleware/swaggerDocs/swaggerDocs.js.map +1 -1
- package/dist/middleware/verificationToken/verificationToken.js.map +1 -1
- package/dist/utils/createSortedObject/createSortedObject.js.map +1 -1
- package/dist/utils/dbMigration/dbMigration.js.map +1 -1
- package/dist/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.js.map +1 -1
- package/dist/utils/jwt/jwt.js.map +1 -1
- package/dist/utils/jwt/jwt.types.js.map +1 -1
- package/dist/utils/report/output.js.map +1 -1
- package/dist/utils/report/report.js.map +1 -1
- package/dist/utils/semverCompare/semverCompare.js.map +1 -1
- package/dist/utils/verificationToken/verificationToken.js.map +1 -1
- package/package.json +1 -1
|
@@ -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","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":[]}
|
|
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":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PushNotification.js","names":["_","require","_PubSub","_utils","namespace","PushNotification","exports","init","reportDebug","message","process","env","PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC","EngineError","PubSub","addPublisher","enableMessageOrdering","batching","maxMessages","maxBytes","maxMilliseconds","retry","initialDelayMillis","maxDelayMillis","delayMultiplier","sendPush","userId","notification","data","publish","error","reportError"],"sources":["../../../src/entities/PushNotification/PushNotification.ts"],"sourcesContent":["import { PushNotificationNotification } from './PushNotification.types';\nimport { EngineError } from 'entities';\nimport { PubSub } from 'entities/PubSub';\nimport { reportDebug, reportError } from 'utils';\n\nconst namespace = 'engine:PushNotification';\n\nexport const PushNotification = {\n /**\n * Initialize the push notification entity\n * Registers the publisher with optimal settings for push notifications\n */\n async init(): Promise<void> {\n reportDebug({ namespace, message: 'Initializing PushNotification' });\n if (!process.env.PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC)\n throw new EngineError({\n message:\n 'Environment variable PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC is not defined'\n });\n
|
|
1
|
+
{"version":3,"file":"PushNotification.js","names":["_","require","_PubSub","_utils","namespace","PushNotification","exports","init","reportDebug","message","process","env","PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC","EngineError","PubSub","addPublisher","enableMessageOrdering","batching","maxMessages","maxBytes","maxMilliseconds","retry","initialDelayMillis","maxDelayMillis","delayMultiplier","sendPush","userId","notification","data","publish","error","reportError"],"sources":["../../../src/entities/PushNotification/PushNotification.ts"],"sourcesContent":["import { PushNotificationNotification } from './PushNotification.types';\nimport { EngineError } from 'entities';\nimport { PubSub } from 'entities/PubSub';\nimport { reportDebug, reportError } from 'utils';\n\nconst namespace = 'engine:PushNotification';\n\nexport const PushNotification = {\n /**\n * Initialize the push notification entity\n * Registers the publisher with optimal settings for push notifications\n */\n async init(): Promise<void> {\n reportDebug({ namespace, message: 'Initializing PushNotification' });\n if (!process.env.PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC)\n throw new EngineError({\n message:\n 'Environment variable PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC is not defined'\n });\n\n // Register publisher with optimized settings for push notifications\n PubSub.addPublisher(process.env.PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC, {\n enableMessageOrdering: false, // Push notifications don't need strict ordering\n batching: {\n maxMessages: 100,\n maxBytes: 1024 * 1024, // 1MB\n maxMilliseconds: 50 // Fast delivery for notifications\n },\n retry: {\n initialDelayMillis: 100,\n maxDelayMillis: 60000,\n delayMultiplier: 1.3\n }\n });\n },\n\n /**\n * Send a push notification through the push service\n * @param userId - ID of the user that should receive the notification\n * @param notification - Notification that should be sent\n * @throws {EngineError} If the topic is not initialized or publish fails\n */\n async sendPush(\n userId: string,\n notification: PushNotificationNotification\n ): Promise<void> {\n if (!userId) {\n throw new EngineError({\n message: 'userId is required to send push notification'\n });\n }\n\n reportDebug({\n namespace,\n message: `Sending push notification to user '${userId}'`,\n data: { userId, notification }\n });\n\n try {\n await PubSub.publish(\n process.env.PUBSUB_PUSH_NOTIFICATION_QUEUE_TOPIC as string,\n {\n ...notification,\n userId\n }\n );\n } catch (error) {\n reportError(\n new EngineError({\n message: `Failed to send push notification to user '${userId}'`,\n data: { userId, notification, error }\n })\n );\n throw error;\n }\n }\n};\n"],"mappings":";;;;;;AACA,IAAAA,CAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAEA,MAAMG,SAAS,GAAG,yBAAyB;AAEpC,MAAMC,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG;EAC9B;AACF;AACA;AACA;EACE,MAAME,IAAIA,CAAA,EAAkB;IAC1B,IAAAC,kBAAW,EAAC;MAAEJ,SAAS;MAAEK,OAAO,EAAE;IAAgC,CAAC,CAAC;IACpE,IAAI,CAACC,OAAO,CAACC,GAAG,CAACC,oCAAoC,EACnD,MAAM,IAAIC,aAAW,CAAC;MACpBJ,OAAO,EACL;IACJ,CAAC,CAAC;;IAEJ;IACAK,cAAM,CAACC,YAAY,CAACL,OAAO,CAACC,GAAG,CAACC,oCAAoC,EAAE;MACpEI,qBAAqB,EAAE,KAAK;MAAE;MAC9BC,QAAQ,EAAE;QACRC,WAAW,EAAE,GAAG;QAChBC,QAAQ,EAAE,IAAI,GAAG,IAAI;QAAE;QACvBC,eAAe,EAAE,EAAE,CAAC;MACtB,CAAC;MACDC,KAAK,EAAE;QACLC,kBAAkB,EAAE,GAAG;QACvBC,cAAc,EAAE,KAAK;QACrBC,eAAe,EAAE;MACnB;IACF,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,QAAQA,CACZC,MAAc,EACdC,YAA0C,EAC3B;IACf,IAAI,CAACD,MAAM,EAAE;MACX,MAAM,IAAIb,aAAW,CAAC;QACpBJ,OAAO,EAAE;MACX,CAAC,CAAC;IACJ;IAEA,IAAAD,kBAAW,EAAC;MACVJ,SAAS;MACTK,OAAO,EAAE,sCAAsCiB,MAAM,GAAG;MACxDE,IAAI,EAAE;QAAEF,MAAM;QAAEC;MAAa;IAC/B,CAAC,CAAC;IAEF,IAAI;MACF,MAAMb,cAAM,CAACe,OAAO,CAClBnB,OAAO,CAACC,GAAG,CAACC,oCAAoC,EAChD;QACE,GAAGe,YAAY;QACfD;MACF,CACF,CAAC;IACH,CAAC,CAAC,OAAOI,KAAK,EAAE;MACd,IAAAC,kBAAW,EACT,IAAIlB,aAAW,CAAC;QACdJ,OAAO,EAAE,6CAA6CiB,MAAM,GAAG;QAC/DE,IAAI,EAAE;UAAEF,MAAM;UAAEC,YAAY;UAAEG;QAAM;MACtC,CAAC,CACH,CAAC;MACD,MAAMA,KAAK;IACb;EACF;AACF,CAAC","ignoreList":[]}
|
|
@@ -14,16 +14,16 @@ const namespace = 'engine:redis';
|
|
|
14
14
|
/**
|
|
15
15
|
* Generic Redis wrapper for caching and data storage
|
|
16
16
|
* Provides methods for initialization, connection management, and cleanup
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```typescript
|
|
20
20
|
* // Initialize Redis connection
|
|
21
21
|
* Redis.init();
|
|
22
|
-
*
|
|
22
|
+
*
|
|
23
23
|
* // Use Redis client
|
|
24
24
|
* await Redis.set('key', 'value');
|
|
25
25
|
* const value = await Redis.get('key');
|
|
26
|
-
*
|
|
26
|
+
*
|
|
27
27
|
* // Get underlying client for advanced operations
|
|
28
28
|
* const client = Redis.getClient();
|
|
29
29
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Redis.js","names":["_ioredis","require","_Redis","_EngineError","_LifecycleController","_report","namespace","Redis","exports","client","undefined","init","options","reportDebug","message","createRedisClient","on","err","reportError","EngineError","data","error","LifecycleController","register","shutdown","quit","getClient","validateRedisEnvironment","process","env","REDIS_HOST","config","port","REDIS_PORT","parseInt","host","username","REDIS_USERNAME","password","REDIS_PASSWORD","db","retryStrategy","times","delay","Math","min","reconnectOnError","targetErrors","some","targetError","includes","maxRetriesPerRequest","enableReadyCheck","lazyConnect","NODE_ENV","redis","TLS_CA","tls","ca","rejectUnauthorized","RedisClient","get","key","set","value","args","del","keys","exists","expire","seconds","ttl","incr","decr","hget","field","hset","hgetall","lpush","values","rpush","lpop","count","rpop","lrange","start","stop","sadd","members","smembers","sismember","member","bind","redisClient","Object","defineProperty"],"sources":["../../../src/entities/Redis/Redis.ts"],"sourcesContent":["import { Redis as RedisClient, RedisOptions } from 'ioredis';\nimport { RedisCreateOptions } from './Redis.types';\nimport { validateRedisEnvironment } from './Redis.validate';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportError } from 'utils/report';\n\nconst namespace = 'engine:redis';\n\n/**\n * Generic Redis wrapper for caching and data storage\n * Provides methods for initialization, connection management, and cleanup\n * \n * @example\n * ```typescript\n * // Initialize Redis connection\n * Redis.init();\n * \n * // Use Redis client\n * await Redis.set('key', 'value');\n * const value = await Redis.get('key');\n * \n * // Get underlying client for advanced operations\n * const client = Redis.getClient();\n * ```\n */\nexport const Redis = {\n /** Redis client instance */\n client: undefined as RedisClient | undefined,\n\n /**\n * Initialize Redis connection\n * @param options - Redis configuration options\n */\n init(options: RedisCreateOptions = {}): void {\n // Ignore if already initialized\n if (this.client) {\n reportDebug({\n namespace,\n message: 'Redis client already initialized'\n });\n return;\n }\n \n this.client = this.createRedisClient(options);\n \n // Setup event listeners\n this.client.on('connect', () => {\n reportDebug({\n namespace,\n message: 'Redis client connecting'\n });\n });\n \n this.client.on('ready', () => {\n reportDebug({\n namespace,\n message: 'Redis client ready'\n });\n });\n \n this.client.on('error', (err) => {\n reportError(new EngineError({\n message: 'Redis client error',\n data: { error: err.message }\n }));\n });\n \n this.client.on('close', () => {\n reportDebug({\n namespace,\n message: 'Redis connection closed'\n });\n });\n \n this.client.on('reconnecting', () => {\n reportDebug({\n namespace,\n message: 'Redis client reconnecting'\n });\n });\n \n LifecycleController.register({ shutdown: () => this.shutdown() });\n },\n\n /**\n * Shutdown Redis connection and cleanup\n * @returns Promise that resolves when shutdown is complete\n */\n async shutdown(): Promise<void> {\n if (this.client) {\n try {\n await this.client.quit();\n reportDebug({\n namespace,\n message: 'Redis client disconnected'\n });\n } catch (error) {\n reportError(new EngineError({\n message: 'Error during Redis shutdown',\n data: { error: (error as Error).message }\n }));\n }\n }\n this.client = undefined;\n },\n\n /**\n * Get the underlying Redis client\n * @returns Redis client instance or undefined\n */\n getClient(): RedisClient | undefined {\n return this.client;\n },\n\n /**\n * Create Redis client with configuration\n * @param options - Redis creation options\n * @returns Redis client instance\n * @private\n */\n createRedisClient(options: RedisCreateOptions = {}): RedisClient {\n // Check that environment variables are correctly set\n validateRedisEnvironment(options);\n \n // Throw an error if there is no host\n if (!process.env.REDIS_HOST) {\n throw new EngineError({\n message: 'Host required to initialize Redis connection'\n });\n }\n\n const config: RedisOptions = {\n port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379,\n host: process.env.REDIS_HOST,\n username: process.env.REDIS_USERNAME,\n password: process.env.REDIS_PASSWORD,\n db: options.db ?? 0,\n retryStrategy: (times: number) => {\n const delay = Math.min(times * 50, 2000);\n return delay;\n },\n reconnectOnError: (err: Error) => {\n const targetErrors = ['READONLY', 'ECONNRESET', 'ETIMEDOUT'];\n return targetErrors.some(targetError => err.message.includes(targetError));\n },\n maxRetriesPerRequest: 3,\n enableReadyCheck: options.enableReadyCheck ?? true,\n lazyConnect: options.lazyConnect ?? (process.env.NODE_ENV === 'test'),\n ...options.redis\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 }\n\n return new RedisClient(config);\n },\n\n // Proxy common Redis methods to the client\n async get(key: string): Promise<string | null> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.get(key);\n },\n\n async set(key: string, value: string | number | Buffer, ...args: unknown[]): Promise<'OK' | null> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.set(key, value, ...args as []);\n },\n\n async del(...keys: string[]): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.del(...keys);\n },\n\n async exists(...keys: string[]): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.exists(...keys);\n },\n\n async expire(key: string, seconds: number): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.expire(key, seconds);\n },\n\n async ttl(key: string): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.ttl(key);\n },\n\n async incr(key: string): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.incr(key);\n },\n\n async decr(key: string): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.decr(key);\n },\n\n async hget(key: string, field: string): Promise<string | null> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hget(key, field);\n },\n\n async hset(key: string, field: string, value: string | number | Buffer): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hset(key, field, value);\n },\n\n async hgetall(key: string): Promise<Record<string, string>> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hgetall(key);\n },\n\n async lpush(key: string, ...values: (string | Buffer | number)[]): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.lpush(key, ...values);\n },\n\n async rpush(key: string, ...values: (string | Buffer | number)[]): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.rpush(key, ...values);\n },\n\n async lpop(key: string, count?: number): Promise<string | string[] | null> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n if (count !== undefined) {\n return this.client.lpop(key, count);\n }\n return this.client.lpop(key);\n },\n\n async rpop(key: string, count?: number): Promise<string | string[] | null> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n if (count !== undefined) {\n return this.client.rpop(key, count);\n }\n return this.client.rpop(key);\n },\n\n async lrange(key: string, start: number, stop: number): Promise<string[]> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.lrange(key, start, stop);\n },\n\n async sadd(key: string, ...members: (string | Buffer | number)[]): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.sadd(key, ...members);\n },\n\n async smembers(key: string): Promise<string[]> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.smembers(key);\n },\n\n async sismember(key: string, member: string | Buffer | number): Promise<number> {\n if (!this.client) throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.sismember(key, member);\n }\n};\n\n// Export backward compatibility functions\nexport const createRedisClient = Redis.createRedisClient.bind(Redis);\nexport const getClient = Redis.getClient.bind(Redis);\nexport const init = Redis.init.bind(Redis);\nexport const shutdown = Redis.shutdown.bind(Redis);\n\n// For tests that need direct access to the client\nexport let redisClient: RedisClient | undefined;\nObject.defineProperty(Redis, 'client', {\n get: () => redisClient,\n set: (value) => { redisClient = value; }\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Redis.js","names":["_ioredis","require","_Redis","_EngineError","_LifecycleController","_report","namespace","Redis","exports","client","undefined","init","options","reportDebug","message","createRedisClient","on","err","reportError","EngineError","data","error","LifecycleController","register","shutdown","quit","getClient","validateRedisEnvironment","process","env","REDIS_HOST","config","port","REDIS_PORT","parseInt","host","username","REDIS_USERNAME","password","REDIS_PASSWORD","db","retryStrategy","times","delay","Math","min","reconnectOnError","targetErrors","some","targetError","includes","maxRetriesPerRequest","enableReadyCheck","lazyConnect","NODE_ENV","redis","TLS_CA","tls","ca","rejectUnauthorized","RedisClient","get","key","set","value","args","del","keys","exists","expire","seconds","ttl","incr","decr","hget","field","hset","hgetall","lpush","values","rpush","lpop","count","rpop","lrange","start","stop","sadd","members","smembers","sismember","member","bind","redisClient","Object","defineProperty"],"sources":["../../../src/entities/Redis/Redis.ts"],"sourcesContent":["import { Redis as RedisClient, RedisOptions } from 'ioredis';\nimport { RedisCreateOptions } from './Redis.types';\nimport { validateRedisEnvironment } from './Redis.validate';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportError } from 'utils/report';\n\nconst namespace = 'engine:redis';\n\n/**\n * Generic Redis wrapper for caching and data storage\n * Provides methods for initialization, connection management, and cleanup\n *\n * @example\n * ```typescript\n * // Initialize Redis connection\n * Redis.init();\n *\n * // Use Redis client\n * await Redis.set('key', 'value');\n * const value = await Redis.get('key');\n *\n * // Get underlying client for advanced operations\n * const client = Redis.getClient();\n * ```\n */\nexport const Redis = {\n /** Redis client instance */\n client: undefined as RedisClient | undefined,\n\n /**\n * Initialize Redis connection\n * @param options - Redis configuration options\n */\n init(options: RedisCreateOptions = {}): void {\n // Ignore if already initialized\n if (this.client) {\n reportDebug({\n namespace,\n message: 'Redis client already initialized'\n });\n return;\n }\n\n this.client = this.createRedisClient(options);\n\n // Setup event listeners\n this.client.on('connect', () => {\n reportDebug({\n namespace,\n message: 'Redis client connecting'\n });\n });\n\n this.client.on('ready', () => {\n reportDebug({\n namespace,\n message: 'Redis client ready'\n });\n });\n\n this.client.on('error', (err) => {\n reportError(\n new EngineError({\n message: 'Redis client error',\n data: { error: err.message }\n })\n );\n });\n\n this.client.on('close', () => {\n reportDebug({\n namespace,\n message: 'Redis connection closed'\n });\n });\n\n this.client.on('reconnecting', () => {\n reportDebug({\n namespace,\n message: 'Redis client reconnecting'\n });\n });\n\n LifecycleController.register({ shutdown: () => this.shutdown() });\n },\n\n /**\n * Shutdown Redis connection and cleanup\n * @returns Promise that resolves when shutdown is complete\n */\n async shutdown(): Promise<void> {\n if (this.client) {\n try {\n await this.client.quit();\n reportDebug({\n namespace,\n message: 'Redis client disconnected'\n });\n } catch (error) {\n reportError(\n new EngineError({\n message: 'Error during Redis shutdown',\n data: { error: (error as Error).message }\n })\n );\n }\n }\n this.client = undefined;\n },\n\n /**\n * Get the underlying Redis client\n * @returns Redis client instance or undefined\n */\n getClient(): RedisClient | undefined {\n return this.client;\n },\n\n /**\n * Create Redis client with configuration\n * @param options - Redis creation options\n * @returns Redis client instance\n * @private\n */\n createRedisClient(options: RedisCreateOptions = {}): RedisClient {\n // Check that environment variables are correctly set\n validateRedisEnvironment(options);\n\n // Throw an error if there is no host\n if (!process.env.REDIS_HOST) {\n throw new EngineError({\n message: 'Host required to initialize Redis connection'\n });\n }\n\n const config: RedisOptions = {\n port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379,\n host: process.env.REDIS_HOST,\n username: process.env.REDIS_USERNAME,\n password: process.env.REDIS_PASSWORD,\n db: options.db ?? 0,\n retryStrategy: (times: number) => {\n const delay = Math.min(times * 50, 2000);\n return delay;\n },\n reconnectOnError: (err: Error) => {\n const targetErrors = ['READONLY', 'ECONNRESET', 'ETIMEDOUT'];\n return targetErrors.some((targetError) =>\n err.message.includes(targetError)\n );\n },\n maxRetriesPerRequest: 3,\n enableReadyCheck: options.enableReadyCheck ?? true,\n lazyConnect: options.lazyConnect ?? process.env.NODE_ENV === 'test',\n ...options.redis\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 }\n\n return new RedisClient(config);\n },\n\n // Proxy common Redis methods to the client\n async get(key: string): Promise<string | null> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.get(key);\n },\n\n async set(\n key: string,\n value: string | number | Buffer,\n ...args: unknown[]\n ): Promise<'OK' | null> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.set(key, value, ...(args as []));\n },\n\n async del(...keys: string[]): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.del(...keys);\n },\n\n async exists(...keys: string[]): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.exists(...keys);\n },\n\n async expire(key: string, seconds: number): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.expire(key, seconds);\n },\n\n async ttl(key: string): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.ttl(key);\n },\n\n async incr(key: string): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.incr(key);\n },\n\n async decr(key: string): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.decr(key);\n },\n\n async hget(key: string, field: string): Promise<string | null> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hget(key, field);\n },\n\n async hset(\n key: string,\n field: string,\n value: string | number | Buffer\n ): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hset(key, field, value);\n },\n\n async hgetall(key: string): Promise<Record<string, string>> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.hgetall(key);\n },\n\n async lpush(\n key: string,\n ...values: (string | Buffer | number)[]\n ): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.lpush(key, ...values);\n },\n\n async rpush(\n key: string,\n ...values: (string | Buffer | number)[]\n ): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.rpush(key, ...values);\n },\n\n async lpop(key: string, count?: number): Promise<string | string[] | null> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n if (count !== undefined) {\n return this.client.lpop(key, count);\n }\n return this.client.lpop(key);\n },\n\n async rpop(key: string, count?: number): Promise<string | string[] | null> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n if (count !== undefined) {\n return this.client.rpop(key, count);\n }\n return this.client.rpop(key);\n },\n\n async lrange(key: string, start: number, stop: number): Promise<string[]> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.lrange(key, start, stop);\n },\n\n async sadd(\n key: string,\n ...members: (string | Buffer | number)[]\n ): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.sadd(key, ...members);\n },\n\n async smembers(key: string): Promise<string[]> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.smembers(key);\n },\n\n async sismember(\n key: string,\n member: string | Buffer | number\n ): Promise<number> {\n if (!this.client)\n throw new EngineError({ message: 'Redis client was not initialized' });\n return this.client.sismember(key, member);\n }\n};\n\n// Export backward compatibility functions\nexport const createRedisClient = Redis.createRedisClient.bind(Redis);\nexport const getClient = Redis.getClient.bind(Redis);\nexport const init = Redis.init.bind(Redis);\nexport const shutdown = Redis.shutdown.bind(Redis);\n\n// For tests that need direct access to the client\nexport let redisClient: RedisClient | undefined;\nObject.defineProperty(Redis, 'client', {\n get: () => redisClient,\n set: (value) => {\n redisClient = value;\n }\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -17,7 +17,7 @@ const namespace = 'engine:SecretManager';
|
|
|
17
17
|
/**
|
|
18
18
|
* Generic GCP Secret Manager wrapper for managing application secrets
|
|
19
19
|
* Provides methods for loading secrets at startup, runtime fetching, and cleanup
|
|
20
|
-
*
|
|
20
|
+
*
|
|
21
21
|
* @example
|
|
22
22
|
* ```typescript
|
|
23
23
|
* // Initialize with configuration
|
|
@@ -27,10 +27,10 @@ const namespace = 'engine:SecretManager';
|
|
|
27
27
|
* prefix: 'my-service',
|
|
28
28
|
* secrets: ['DB_PASSWORD', { name: 'PRIVATE_KEY', type: 'file' }]
|
|
29
29
|
* });
|
|
30
|
-
*
|
|
30
|
+
*
|
|
31
31
|
* // Get a cached secret
|
|
32
32
|
* const password = SecretManager.getSecret('DB_PASSWORD');
|
|
33
|
-
*
|
|
33
|
+
*
|
|
34
34
|
* // Fetch a secret on-demand
|
|
35
35
|
* const apiKey = await SecretManager.fetchSecret('API_KEY');
|
|
36
36
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecretManager.js","names":["_secretManager","require","_promises","_interopRequireDefault","_path","_os","_EngineError","_LifecycleController","_report","namespace","SecretManager","exports","client","undefined","options","secretCache","Map","tempFiles","init","config","reportDebug","message","enabled","process","env","NODE_ENV","projectId","GCP_PROJECT_ID","cache","fallbackToEnv","tempDir","os","tmpdir","reportInfo","data","nodeEnv","loaded","failed","fallback","details","EngineError","SecretManagerServiceClient","LifecycleController","register","shutdown","result","loadSecrets","secrets","length","secretConfigs","map","normalizeSecretConfig","secretConfig","loadSecret","push","name","type","source","filePath","set","error","reportError","targetEnvVar","globalConfig","secretName","common","prefix","version","response","accessSecretVersion","payload","secretValue","toString","value","envVarName","filename","path","join","fs","writeFile","mode","envVar","code","input","getSecret","cached","get","fetchSecret","secretPath","reload","clear","unlink","close","isInitialized","getConfig"],"sources":["../../../src/entities/SecretManager/SecretManager.ts"],"sourcesContent":["import { SecretManagerServiceClient } from '@google-cloud/secret-manager';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport {\n SecretManagerOptions,\n SecretConfig,\n LoadedSecret,\n SecretLoadResult\n} from './SecretManager.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportInfo, reportError } from 'utils/report';\n\nconst namespace = 'engine:SecretManager';\n\n/**\n * Generic GCP Secret Manager wrapper for managing application secrets\n * Provides methods for loading secrets at startup, runtime fetching, and cleanup\n * \n * @example\n * ```typescript\n * // Initialize with configuration\n * await SecretManager.init({\n * enabled: true,\n * projectId: 'my-project',\n * prefix: 'my-service',\n * secrets: ['DB_PASSWORD', { name: 'PRIVATE_KEY', type: 'file' }]\n * });\n * \n * // Get a cached secret\n * const password = SecretManager.getSecret('DB_PASSWORD');\n * \n * // Fetch a secret on-demand\n * const apiKey = await SecretManager.fetchSecret('API_KEY');\n * ```\n */\nexport const SecretManager = {\n /** Singleton client instance */\n client: undefined as SecretManagerServiceClient | undefined,\n\n /** Configuration options */\n options: undefined as SecretManagerOptions | undefined,\n\n /** Cache of loaded secrets */\n secretCache: new Map<string, LoadedSecret>(),\n\n /** Temporary files created by Secret Manager */\n tempFiles: [] as string[],\n\n /**\n * Initialize the Secret Manager\n * @param config - Secret Manager configuration options\n * @returns Promise with load results\n */\n async init(config: SecretManagerOptions = {}): Promise<SecretLoadResult> {\n reportDebug({ namespace, message: 'Initializing Secret Manager' });\n\n // Set default options\n this.options = {\n enabled: process.env.NODE_ENV === 'production',\n projectId: process.env.GCP_PROJECT_ID,\n cache: true,\n fallbackToEnv: true,\n tempDir: os.tmpdir(),\n ...config\n };\n\n // Skip if disabled\n if (!this.options.enabled) {\n reportInfo({\n message: 'Secret Manager disabled - using environment variables',\n data: { nodeEnv: process.env.NODE_ENV }\n });\n return {\n loaded: 0,\n failed: 0,\n fallback: 0,\n details: []\n };\n }\n\n // Validate configuration\n if (!this.options.projectId) {\n throw new EngineError({\n message: 'GCP_PROJECT_ID is required when Secret Manager is enabled'\n });\n }\n\n // Create client\n this.client = new SecretManagerServiceClient();\n\n // Register for shutdown\n LifecycleController.register({ shutdown: () => this.shutdown() });\n\n // Load secrets\n const result = await this.loadSecrets(this.options);\n\n reportInfo({\n message: 'Secret Manager initialized',\n data: {\n loaded: result.loaded,\n failed: result.failed,\n fallback: result.fallback\n }\n });\n\n return result;\n },\n\n /**\n * Load secrets from Secret Manager\n * @private\n */\n async loadSecrets(config: SecretManagerOptions): Promise<SecretLoadResult> {\n const result: SecretLoadResult = {\n loaded: 0,\n failed: 0,\n fallback: 0,\n details: []\n };\n\n if (!config.secrets || config.secrets.length === 0) {\n reportInfo('No secrets configured to load');\n return result;\n }\n\n // Normalize secret configurations\n const secretConfigs: SecretConfig[] = config.secrets.map(this.normalizeSecretConfig);\n\n // Load each secret\n for (const secretConfig of secretConfigs) {\n try {\n const loaded = await this.loadSecret(secretConfig, config);\n \n if (loaded) {\n result.loaded++;\n result.details.push({\n name: loaded.name,\n type: loaded.config.type,\n source: 'secret-manager',\n filePath: loaded.filePath\n });\n\n // Cache if enabled\n if (config.cache) {\n this.secretCache.set(loaded.name, loaded);\n }\n }\n } catch (error) {\n reportError(error);\n \n // Try fallback\n if (config.fallbackToEnv && process.env[secretConfig.targetEnvVar || secretConfig.name]) {\n result.fallback++;\n result.details.push({\n name: secretConfig.name,\n type: secretConfig.type,\n source: 'fallback'\n });\n reportInfo(`Using fallback value for secret: ${secretConfig.name}`);\n } else {\n result.failed++;\n reportError(new EngineError({\n message: `Failed to load secret: ${secretConfig.name}`,\n data: { error: (error as Error).message }\n }));\n }\n }\n }\n\n return result;\n },\n\n /**\n * Load a single secret from Secret Manager\n * @private\n */\n async loadSecret(\n config: SecretConfig,\n globalConfig: SecretManagerOptions\n ): Promise<LoadedSecret | null> {\n if (!this.client || !globalConfig.projectId) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n // Build secret name with prefix (unless it's a common secret)\n const secretName = config.common || !globalConfig.prefix\n ? config.name\n : `${globalConfig.prefix}-${config.name}`;\n\n const version = config.version || 'latest';\n const name = `projects/${globalConfig.projectId}/secrets/${secretName}/versions/${version}`;\n\n reportDebug({\n namespace,\n message: `Loading secret: ${secretName}`,\n data: { version, type: config.type, common: config.common }\n });\n\n try {\n // Access the secret\n const [response] = await this.client.accessSecretVersion({ name });\n \n if (!response.payload?.data) {\n throw new EngineError({\n message: `Secret ${secretName} has no data`\n });\n }\n\n // Convert to string\n const secretValue = response.payload.data.toString('utf8');\n\n const loaded: LoadedSecret = {\n name: config.name,\n value: secretValue,\n config\n };\n\n // Handle based on type\n if (config.type === 'env') {\n // Set environment variable\n const envVarName = config.targetEnvVar || config.name;\n process.env[envVarName] = secretValue;\n \n reportDebug({\n namespace,\n message: `Set environment variable: ${envVarName}`\n });\n } else if (config.type === 'file') {\n // Write to temp file\n const filename = config.filename || config.name;\n const filePath = path.join(globalConfig.tempDir!, filename);\n \n await fs.writeFile(filePath, secretValue, {\n mode: config.mode || 0o600\n });\n \n loaded.filePath = filePath;\n this.tempFiles.push(filePath);\n\n // Update environment variable to point to file\n const envVarName = config.targetEnvVar || `${config.name}_PATH`;\n process.env[envVarName] = filePath;\n \n reportDebug({\n namespace,\n message: `Wrote secret to file: ${filePath}`,\n data: { envVar: envVarName }\n });\n }\n\n return loaded;\n } catch (error) {\n if ((error as { code?: number }).code === 5) {\n // NOT_FOUND error\n reportInfo(`Secret not found in Secret Manager: ${secretName}`);\n }\n throw error;\n }\n },\n\n /**\n * Normalize secret configuration\n * @private\n */\n normalizeSecretConfig(input: SecretConfig | string): SecretConfig {\n if (typeof input === 'string') {\n // Simple string becomes an env type secret\n return {\n name: input,\n type: 'env'\n };\n }\n return input;\n },\n\n /**\n * Get a secret value from cache (if caching is enabled)\n * @param name - Secret name\n * @returns Secret value or undefined\n */\n getSecret(name: string): string | undefined {\n const cached = this.secretCache.get(name);\n if (cached) {\n return cached.value;\n }\n \n // Fallback to environment variable\n return process.env[name];\n },\n\n /**\n * Get secret from Secret Manager on-demand (useful for runtime secret rotation)\n * @param name - Secret name\n * @param version - Secret version (default: 'latest')\n * @returns Promise with secret value\n */\n async fetchSecret(\n name: string,\n version: string = 'latest'\n ): Promise<string> {\n if (!this.client || !this.options?.projectId) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n const secretName = this.options.prefix ? `${this.options.prefix}-${name}` : name;\n const secretPath = `projects/${this.options.projectId}/secrets/${secretName}/versions/${version}`;\n\n const [response] = await this.client.accessSecretVersion({ name: secretPath });\n \n if (!response.payload?.data) {\n throw new EngineError({ message: `Secret ${secretName} has no data` });\n }\n\n return response.payload.data.toString('utf8');\n },\n\n /**\n * Reload all secrets (useful for secret rotation)\n * @returns Promise with reload results\n */\n async reload(): Promise<SecretLoadResult> {\n reportInfo({ message: 'Reloading secrets from Secret Manager' });\n \n if (!this.options) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n // Clear cache\n this.secretCache.clear();\n\n // Reload secrets\n return this.loadSecrets(this.options);\n },\n\n /**\n * Shutdown Secret Manager and cleanup\n * @returns Promise that resolves when cleanup is complete\n */\n async shutdown(): Promise<void> {\n reportDebug({ namespace, message: 'Shutting down Secret Manager' });\n\n // Delete temporary files\n for (const filePath of this.tempFiles) {\n try {\n await fs.unlink(filePath);\n reportDebug({\n namespace,\n message: `Deleted temporary file: ${filePath}`\n });\n } catch {\n reportInfo(`Failed to delete temporary file: ${filePath}`);\n }\n }\n\n this.tempFiles.length = 0;\n this.secretCache.clear();\n\n // Close client\n if (this.client) {\n await this.client.close();\n this.client = undefined;\n }\n\n this.options = undefined;\n \n reportDebug({ namespace, message: 'Secret Manager shut down' });\n },\n\n /**\n * Check if Secret Manager is initialized\n * @returns True if initialized\n */\n isInitialized(): boolean {\n return this.client !== undefined;\n },\n\n /**\n * Get current configuration (without sensitive data)\n * @returns Configuration object or undefined\n */\n getConfig(): Partial<SecretManagerOptions> | undefined {\n if (!this.options) return undefined;\n \n return {\n enabled: this.options.enabled,\n projectId: this.options.projectId,\n prefix: this.options.prefix,\n cache: this.options.cache,\n fallbackToEnv: this.options.fallbackToEnv\n };\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"SecretManager.js","names":["_secretManager","require","_promises","_interopRequireDefault","_path","_os","_EngineError","_LifecycleController","_report","namespace","SecretManager","exports","client","undefined","options","secretCache","Map","tempFiles","init","config","reportDebug","message","enabled","process","env","NODE_ENV","projectId","GCP_PROJECT_ID","cache","fallbackToEnv","tempDir","os","tmpdir","reportInfo","data","nodeEnv","loaded","failed","fallback","details","EngineError","SecretManagerServiceClient","LifecycleController","register","shutdown","result","loadSecrets","secrets","length","secretConfigs","map","normalizeSecretConfig","secretConfig","loadSecret","push","name","type","source","filePath","set","error","reportError","targetEnvVar","globalConfig","secretName","common","prefix","version","response","accessSecretVersion","payload","secretValue","toString","value","envVarName","filename","path","join","fs","writeFile","mode","envVar","code","input","getSecret","cached","get","fetchSecret","secretPath","reload","clear","unlink","close","isInitialized","getConfig"],"sources":["../../../src/entities/SecretManager/SecretManager.ts"],"sourcesContent":["import { SecretManagerServiceClient } from '@google-cloud/secret-manager';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport {\n SecretManagerOptions,\n SecretConfig,\n LoadedSecret,\n SecretLoadResult\n} from './SecretManager.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportInfo, reportError } from 'utils/report';\n\nconst namespace = 'engine:SecretManager';\n\n/**\n * Generic GCP Secret Manager wrapper for managing application secrets\n * Provides methods for loading secrets at startup, runtime fetching, and cleanup\n *\n * @example\n * ```typescript\n * // Initialize with configuration\n * await SecretManager.init({\n * enabled: true,\n * projectId: 'my-project',\n * prefix: 'my-service',\n * secrets: ['DB_PASSWORD', { name: 'PRIVATE_KEY', type: 'file' }]\n * });\n *\n * // Get a cached secret\n * const password = SecretManager.getSecret('DB_PASSWORD');\n *\n * // Fetch a secret on-demand\n * const apiKey = await SecretManager.fetchSecret('API_KEY');\n * ```\n */\nexport const SecretManager = {\n /** Singleton client instance */\n client: undefined as SecretManagerServiceClient | undefined,\n\n /** Configuration options */\n options: undefined as SecretManagerOptions | undefined,\n\n /** Cache of loaded secrets */\n secretCache: new Map<string, LoadedSecret>(),\n\n /** Temporary files created by Secret Manager */\n tempFiles: [] as string[],\n\n /**\n * Initialize the Secret Manager\n * @param config - Secret Manager configuration options\n * @returns Promise with load results\n */\n async init(config: SecretManagerOptions = {}): Promise<SecretLoadResult> {\n reportDebug({ namespace, message: 'Initializing Secret Manager' });\n\n // Set default options\n this.options = {\n enabled: process.env.NODE_ENV === 'production',\n projectId: process.env.GCP_PROJECT_ID,\n cache: true,\n fallbackToEnv: true,\n tempDir: os.tmpdir(),\n ...config\n };\n\n // Skip if disabled\n if (!this.options.enabled) {\n reportInfo({\n message: 'Secret Manager disabled - using environment variables',\n data: { nodeEnv: process.env.NODE_ENV }\n });\n return {\n loaded: 0,\n failed: 0,\n fallback: 0,\n details: []\n };\n }\n\n // Validate configuration\n if (!this.options.projectId) {\n throw new EngineError({\n message: 'GCP_PROJECT_ID is required when Secret Manager is enabled'\n });\n }\n\n // Create client\n this.client = new SecretManagerServiceClient();\n\n // Register for shutdown\n LifecycleController.register({ shutdown: () => this.shutdown() });\n\n // Load secrets\n const result = await this.loadSecrets(this.options);\n\n reportInfo({\n message: 'Secret Manager initialized',\n data: {\n loaded: result.loaded,\n failed: result.failed,\n fallback: result.fallback\n }\n });\n\n return result;\n },\n\n /**\n * Load secrets from Secret Manager\n * @private\n */\n async loadSecrets(config: SecretManagerOptions): Promise<SecretLoadResult> {\n const result: SecretLoadResult = {\n loaded: 0,\n failed: 0,\n fallback: 0,\n details: []\n };\n\n if (!config.secrets || config.secrets.length === 0) {\n reportInfo('No secrets configured to load');\n return result;\n }\n\n // Normalize secret configurations\n const secretConfigs: SecretConfig[] = config.secrets.map(\n this.normalizeSecretConfig\n );\n\n // Load each secret\n for (const secretConfig of secretConfigs) {\n try {\n const loaded = await this.loadSecret(secretConfig, config);\n\n if (loaded) {\n result.loaded++;\n result.details.push({\n name: loaded.name,\n type: loaded.config.type,\n source: 'secret-manager',\n filePath: loaded.filePath\n });\n\n // Cache if enabled\n if (config.cache) {\n this.secretCache.set(loaded.name, loaded);\n }\n }\n } catch (error) {\n reportError(error);\n\n // Try fallback\n if (\n config.fallbackToEnv &&\n process.env[secretConfig.targetEnvVar || secretConfig.name]\n ) {\n result.fallback++;\n result.details.push({\n name: secretConfig.name,\n type: secretConfig.type,\n source: 'fallback'\n });\n reportInfo(`Using fallback value for secret: ${secretConfig.name}`);\n } else {\n result.failed++;\n reportError(\n new EngineError({\n message: `Failed to load secret: ${secretConfig.name}`,\n data: { error: (error as Error).message }\n })\n );\n }\n }\n }\n\n return result;\n },\n\n /**\n * Load a single secret from Secret Manager\n * @private\n */\n async loadSecret(\n config: SecretConfig,\n globalConfig: SecretManagerOptions\n ): Promise<LoadedSecret | null> {\n if (!this.client || !globalConfig.projectId) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n // Build secret name with prefix (unless it's a common secret)\n const secretName =\n config.common || !globalConfig.prefix\n ? config.name\n : `${globalConfig.prefix}-${config.name}`;\n\n const version = config.version || 'latest';\n const name = `projects/${globalConfig.projectId}/secrets/${secretName}/versions/${version}`;\n\n reportDebug({\n namespace,\n message: `Loading secret: ${secretName}`,\n data: { version, type: config.type, common: config.common }\n });\n\n try {\n // Access the secret\n const [response] = await this.client.accessSecretVersion({ name });\n\n if (!response.payload?.data) {\n throw new EngineError({\n message: `Secret ${secretName} has no data`\n });\n }\n\n // Convert to string\n const secretValue = response.payload.data.toString('utf8');\n\n const loaded: LoadedSecret = {\n name: config.name,\n value: secretValue,\n config\n };\n\n // Handle based on type\n if (config.type === 'env') {\n // Set environment variable\n const envVarName = config.targetEnvVar || config.name;\n process.env[envVarName] = secretValue;\n\n reportDebug({\n namespace,\n message: `Set environment variable: ${envVarName}`\n });\n } else if (config.type === 'file') {\n // Write to temp file\n const filename = config.filename || config.name;\n const filePath = path.join(globalConfig.tempDir!, filename);\n\n await fs.writeFile(filePath, secretValue, {\n mode: config.mode || 0o600\n });\n\n loaded.filePath = filePath;\n this.tempFiles.push(filePath);\n\n // Update environment variable to point to file\n const envVarName = config.targetEnvVar || `${config.name}_PATH`;\n process.env[envVarName] = filePath;\n\n reportDebug({\n namespace,\n message: `Wrote secret to file: ${filePath}`,\n data: { envVar: envVarName }\n });\n }\n\n return loaded;\n } catch (error) {\n if ((error as { code?: number }).code === 5) {\n // NOT_FOUND error\n reportInfo(`Secret not found in Secret Manager: ${secretName}`);\n }\n throw error;\n }\n },\n\n /**\n * Normalize secret configuration\n * @private\n */\n normalizeSecretConfig(input: SecretConfig | string): SecretConfig {\n if (typeof input === 'string') {\n // Simple string becomes an env type secret\n return {\n name: input,\n type: 'env'\n };\n }\n return input;\n },\n\n /**\n * Get a secret value from cache (if caching is enabled)\n * @param name - Secret name\n * @returns Secret value or undefined\n */\n getSecret(name: string): string | undefined {\n const cached = this.secretCache.get(name);\n if (cached) {\n return cached.value;\n }\n\n // Fallback to environment variable\n return process.env[name];\n },\n\n /**\n * Get secret from Secret Manager on-demand (useful for runtime secret rotation)\n * @param name - Secret name\n * @param version - Secret version (default: 'latest')\n * @returns Promise with secret value\n */\n async fetchSecret(name: string, version: string = 'latest'): Promise<string> {\n if (!this.client || !this.options?.projectId) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n const secretName = this.options.prefix\n ? `${this.options.prefix}-${name}`\n : name;\n const secretPath = `projects/${this.options.projectId}/secrets/${secretName}/versions/${version}`;\n\n const [response] = await this.client.accessSecretVersion({\n name: secretPath\n });\n\n if (!response.payload?.data) {\n throw new EngineError({ message: `Secret ${secretName} has no data` });\n }\n\n return response.payload.data.toString('utf8');\n },\n\n /**\n * Reload all secrets (useful for secret rotation)\n * @returns Promise with reload results\n */\n async reload(): Promise<SecretLoadResult> {\n reportInfo({ message: 'Reloading secrets from Secret Manager' });\n\n if (!this.options) {\n throw new EngineError({ message: 'Secret Manager not initialized' });\n }\n\n // Clear cache\n this.secretCache.clear();\n\n // Reload secrets\n return this.loadSecrets(this.options);\n },\n\n /**\n * Shutdown Secret Manager and cleanup\n * @returns Promise that resolves when cleanup is complete\n */\n async shutdown(): Promise<void> {\n reportDebug({ namespace, message: 'Shutting down Secret Manager' });\n\n // Delete temporary files\n for (const filePath of this.tempFiles) {\n try {\n await fs.unlink(filePath);\n reportDebug({\n namespace,\n message: `Deleted temporary file: ${filePath}`\n });\n } catch {\n reportInfo(`Failed to delete temporary file: ${filePath}`);\n }\n }\n\n this.tempFiles.length = 0;\n this.secretCache.clear();\n\n // Close client\n if (this.client) {\n await this.client.close();\n this.client = undefined;\n }\n\n this.options = undefined;\n\n reportDebug({ namespace, message: 'Secret Manager shut down' });\n },\n\n /**\n * Check if Secret Manager is initialized\n * @returns True if initialized\n */\n isInitialized(): boolean {\n return this.client !== undefined;\n },\n\n /**\n * Get current configuration (without sensitive data)\n * @returns Configuration object or undefined\n */\n getConfig(): Partial<SecretManagerOptions> | undefined {\n if (!this.options) return undefined;\n\n return {\n enabled: this.options.enabled,\n projectId: this.options.projectId,\n prefix: this.options.prefix,\n cache: this.options.cache,\n fallbackToEnv: this.options.fallbackToEnv\n };\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -45,14 +45,18 @@ const config = {
|
|
|
45
45
|
|
|
46
46
|
// Additional configurations for MSSQL
|
|
47
47
|
if (config.dialect === 'mssql') {
|
|
48
|
+
// tedious connection options live under dialectOptions.options
|
|
48
49
|
config.dialectOptions = {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
options: {
|
|
51
|
+
requestTimeout: 30000,
|
|
52
|
+
// Increase request timeout for MSSQL
|
|
53
|
+
connectTimeout: 30000,
|
|
54
|
+
// Increase connection timeout for MSSQL
|
|
55
|
+
// Encrypted connections by default; SQL_ENCRYPT=false only for servers without TLS
|
|
56
|
+
encrypt: process.env.SQL_ENCRYPT !== 'false',
|
|
57
|
+
// The server certificate is verified unless SQL_TRUST_SERVER_CERT=true (self-signed development servers)
|
|
58
|
+
trustServerCertificate: process.env.SQL_TRUST_SERVER_CERT === 'true'
|
|
59
|
+
}
|
|
56
60
|
};
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sequelize.config.js","names":["_Sequelize","require","validateSequelizeEnvironment","isUnixSocket","process","env","SQL_HOST","startsWith","config","username","SQL_USER","password","SQL_PASSWORD","database","SQL_DB","host","port","undefined","SQL_PORT","parseInt","dialect","SQL_TYPE","logging","SQL_LOGGING","console","log","define","freezeTableName","charset","collate","retry","max","NODE_ENV","dialectOptions","pool","min","acquire","idle","evict","requestTimeout","connectTimeout","encrypt","trustServerCertificate","timezone","ssl","PG_SSL","rejectUnauthorized","development","exports","staging","production","test","_default","default"],"sources":["../../../src/entities/Sequelize/Sequelize.config.ts"],"sourcesContent":["import { Options, Dialect } from 'sequelize';\nimport { validateSequelizeEnvironment } from './Sequelize.validate';\n\n// Check that environment variables are correctly set\nvalidateSequelizeEnvironment();\n\n// Check if SQL_HOST is a Unix socket path (Cloud SQL)\nconst isUnixSocket = process.env.SQL_HOST?.startsWith('/');\n\nconst config: Options = {\n username: process.env.SQL_USER,\n password: process.env.SQL_PASSWORD,\n database: process.env.SQL_DB,\n host: process.env.SQL_HOST,\n // Don't set port for Unix socket connections (Cloud SQL)\n port: isUnixSocket
|
|
1
|
+
{"version":3,"file":"Sequelize.config.js","names":["_Sequelize","require","validateSequelizeEnvironment","isUnixSocket","process","env","SQL_HOST","startsWith","config","username","SQL_USER","password","SQL_PASSWORD","database","SQL_DB","host","port","undefined","SQL_PORT","parseInt","dialect","SQL_TYPE","logging","SQL_LOGGING","console","log","define","freezeTableName","charset","collate","retry","max","NODE_ENV","dialectOptions","pool","min","acquire","idle","evict","options","requestTimeout","connectTimeout","encrypt","SQL_ENCRYPT","trustServerCertificate","SQL_TRUST_SERVER_CERT","timezone","ssl","PG_SSL","rejectUnauthorized","development","exports","staging","production","test","_default","default"],"sources":["../../../src/entities/Sequelize/Sequelize.config.ts"],"sourcesContent":["import { Options, Dialect } from 'sequelize';\nimport { validateSequelizeEnvironment } from './Sequelize.validate';\n\n// Check that environment variables are correctly set\nvalidateSequelizeEnvironment();\n\n// Check if SQL_HOST is a Unix socket path (Cloud SQL)\nconst isUnixSocket = process.env.SQL_HOST?.startsWith('/');\n\nconst config: Options = {\n username: process.env.SQL_USER,\n password: process.env.SQL_PASSWORD,\n database: process.env.SQL_DB,\n host: process.env.SQL_HOST,\n // Don't set port for Unix socket connections (Cloud SQL)\n port: isUnixSocket\n ? undefined\n : process.env.SQL_PORT\n ? parseInt(process.env.SQL_PORT)\n : 5432,\n dialect: (process.env.SQL_TYPE ?? 'postgres') as Dialect, // Dynamically set the dialect (postgres, mysql, mssql)\n logging: process.env.SQL_LOGGING === 'true' ? console.log : false, // Enable SQL logging with SQL_LOGGING=true\n define: {\n freezeTableName: false, // Prevent automatic pluralization of table names\n charset: 'utf8mb4', // Set character set for MySQL/MariaDB\n collate: 'utf8mb4_unicode_ci' // Set collation for MySQL/MariaDB\n },\n retry: {\n max: process.env.NODE_ENV === 'test' ? 0 : 3 // Disable retries in test environment to prevent unhandled rejections\n },\n dialectOptions: {},\n pool: {\n max: process.env.NODE_ENV === 'test' ? 1 : 5,\n min: 0,\n acquire: process.env.NODE_ENV === 'test' ? 1000 : 30000, // Reduce acquire timeout in test\n idle: process.env.NODE_ENV === 'test' ? 1000 : 10000, // Reduce idle time in test\n evict: process.env.NODE_ENV === 'test' ? 100 : 1000 // How often to check for idle connections\n }\n};\n\n// Additional configurations for MSSQL\nif (config.dialect === 'mssql') {\n // tedious connection options live under dialectOptions.options\n config.dialectOptions = {\n options: {\n requestTimeout: 30000, // Increase request timeout for MSSQL\n connectTimeout: 30000, // Increase connection timeout for MSSQL\n // Encrypted connections by default; SQL_ENCRYPT=false only for servers without TLS\n encrypt: process.env.SQL_ENCRYPT !== 'false',\n // The server certificate is verified unless SQL_TRUST_SERVER_CERT=true (self-signed development servers)\n trustServerCertificate: process.env.SQL_TRUST_SERVER_CERT === 'true'\n }\n };\n}\n\n// Add specific dialect configurations if necessary for MySQL/PostgreSQL\nif (config.dialect === 'mysql') {\n config.dialectOptions = {\n timezone: 'Z' // Set timezone for MySQL\n };\n}\n\nif (config.dialect === 'postgres') {\n config.dialectOptions = {\n ssl: process.env.PG_SSL === 'true' ? { rejectUnauthorized: false } : false // SSL options for PostgreSQL (if required)\n };\n}\n\nexport const development = config;\nexport const staging = config;\nexport const production = config;\nexport const test = config;\nexport default config;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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 ||\n 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 {\n toJSON?: () => Record<string, unknown>;\n } & 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":[]}
|