@tsdevstack/nest-common 0.1.4
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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/auth/auth-user.interface.d.ts +62 -0
- package/dist/auth/auth.guard.d.ts +181 -0
- package/dist/auth/auth.guard.test.d.ts +1 -0
- package/dist/auth/auth.module.d.ts +45 -0
- package/dist/auth/index.d.ts +17 -0
- package/dist/auth/partner-api.decorator.d.ts +42 -0
- package/dist/auth/partner.decorator.d.ts +60 -0
- package/dist/auth/partner.decorator.test.d.ts +1 -0
- package/dist/auth/public.decorator.d.ts +42 -0
- package/dist/auth/public.decorator.test.d.ts +1 -0
- package/dist/auth/utils/extract-user-from-headers.d.ts +45 -0
- package/dist/auth/utils/extract-user-from-headers.test.d.ts +1 -0
- package/dist/auth/utils/index.d.ts +8 -0
- package/dist/auth/utils/parse-header-value.d.ts +40 -0
- package/dist/auth/utils/parse-header-value.test.d.ts +1 -0
- package/dist/auth/utils/to-camel-case.d.ts +18 -0
- package/dist/auth/utils/to-camel-case.test.d.ts +1 -0
- package/dist/bootstrap/create-app.d.ts +31 -0
- package/dist/bootstrap/create-app.test.d.ts +1 -0
- package/dist/bootstrap/start-worker.d.ts +24 -0
- package/dist/bootstrap/start-worker.test.d.ts +1 -0
- package/dist/bull/bull-config.module.d.ts +22 -0
- package/dist/bull/bull-config.module.test.d.ts +1 -0
- package/dist/bull/index.d.ts +1 -0
- package/dist/config/load-framework-config.d.ts +32 -0
- package/dist/config/load-framework-config.test.d.ts +1 -0
- package/dist/database/prisma-connection.d.ts +48 -0
- package/dist/database/prisma-connection.test.d.ts +1 -0
- package/dist/email-rate-limit/email-rate-limit.decorator.d.ts +8 -0
- package/dist/email-rate-limit/email-rate-limit.decorator.test.d.ts +1 -0
- package/dist/email-rate-limit/email-rate-limit.guard.d.ts +11 -0
- package/dist/email-rate-limit/email-rate-limit.guard.test.d.ts +1 -0
- package/dist/email-rate-limit/email-rate-limit.module.d.ts +2 -0
- package/dist/health/health.controller.d.ts +11 -0
- package/dist/health/health.controller.test.d.ts +1 -0
- package/dist/health/health.interface.d.ts +31 -0
- package/dist/health/health.module.d.ts +5 -0
- package/dist/health/health.service.d.ts +12 -0
- package/dist/health/health.service.test.d.ts +1 -0
- package/dist/health/index.d.ts +6 -0
- package/dist/health/indicators/memory.indicator.d.ts +7 -0
- package/dist/health/indicators/memory.indicator.test.d.ts +1 -0
- package/dist/health/indicators/redis.indicator.d.ts +7 -0
- package/dist/health/indicators/redis.indicator.test.d.ts +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +9 -0
- package/dist/index.mjs +9 -0
- package/dist/logging/index.d.ts +6 -0
- package/dist/logging/logger.interface.d.ts +29 -0
- package/dist/logging/logger.module.d.ts +14 -0
- package/dist/logging/logger.service.d.ts +31 -0
- package/dist/logging/logger.service.test.d.ts +1 -0
- package/dist/logging/logging.interceptor.d.ts +8 -0
- package/dist/logging/logging.interceptor.test.d.ts +1 -0
- package/dist/metrics/index.d.ts +5 -0
- package/dist/metrics/metrics.controller.d.ts +7 -0
- package/dist/metrics/metrics.controller.test.d.ts +1 -0
- package/dist/metrics/metrics.interceptor.d.ts +9 -0
- package/dist/metrics/metrics.interceptor.test.d.ts +1 -0
- package/dist/metrics/metrics.interface.d.ts +17 -0
- package/dist/metrics/metrics.module.d.ts +5 -0
- package/dist/metrics/metrics.service.d.ts +79 -0
- package/dist/metrics/metrics.service.test.d.ts +1 -0
- package/dist/notifications/index.d.ts +15 -0
- package/dist/notifications/interfaces/email-options.interface.d.ts +23 -0
- package/dist/notifications/interfaces/index.d.ts +6 -0
- package/dist/notifications/interfaces/push-options.interface.d.ts +16 -0
- package/dist/notifications/interfaces/sms-options.interface.d.ts +12 -0
- package/dist/notifications/notification.module.d.ts +2 -0
- package/dist/notifications/notification.module.test.d.ts +1 -0
- package/dist/notifications/notification.service.d.ts +28 -0
- package/dist/notifications/notification.service.test.d.ts +1 -0
- package/dist/notifications/providers/email/console.provider.d.ts +9 -0
- package/dist/notifications/providers/email/console.provider.test.d.ts +1 -0
- package/dist/notifications/providers/email/resend.provider.d.ts +24 -0
- package/dist/notifications/providers/email/resend.provider.test.d.ts +1 -0
- package/dist/notifications/providers/email-provider.interface.d.ts +17 -0
- package/dist/observability/index.d.ts +2 -0
- package/dist/observability/observability.interface.d.ts +32 -0
- package/dist/observability/observability.module.d.ts +24 -0
- package/dist/observability/observability.module.test.d.ts +1 -0
- package/dist/open-api-docs/create-swagger-document.d.ts +10 -0
- package/dist/open-api-docs/create-swagger-document.test.d.ts +1 -0
- package/dist/open-api-docs/generate-swagger-docs.d.ts +12 -0
- package/dist/open-api-docs/generate-swagger-docs.test.d.ts +1 -0
- package/dist/rate-limit/rate-limit-headers.interceptor.d.ts +5 -0
- package/dist/rate-limit/rate-limit-headers.interceptor.test.d.ts +1 -0
- package/dist/rate-limit/rate-limit.decorator.d.ts +11 -0
- package/dist/rate-limit/rate-limit.decorator.test.d.ts +1 -0
- package/dist/rate-limit/rate-limit.guard.d.ts +13 -0
- package/dist/rate-limit/rate-limit.guard.test.d.ts +1 -0
- package/dist/rate-limit/rate-limit.module.d.ts +2 -0
- package/dist/redis/redis.module.d.ts +2 -0
- package/dist/redis/redis.service.d.ts +17 -0
- package/dist/redis/redis.service.test.d.ts +1 -0
- package/dist/scheduler/index.d.ts +1 -0
- package/dist/scheduler/scheduler.guard.d.ts +73 -0
- package/dist/scheduler/scheduler.guard.test.d.ts +1 -0
- package/dist/secrets/index.d.ts +10 -0
- package/dist/secrets/providers/aws.provider.d.ts +56 -0
- package/dist/secrets/providers/aws.provider.test.d.ts +1 -0
- package/dist/secrets/providers/azure.provider.d.ts +70 -0
- package/dist/secrets/providers/azure.provider.test.d.ts +1 -0
- package/dist/secrets/providers/cloud-provider-adapter.d.ts +50 -0
- package/dist/secrets/providers/cloud-provider-adapter.test.d.ts +1 -0
- package/dist/secrets/providers/cloud-provider.interface.d.ts +86 -0
- package/dist/secrets/providers/gcp.provider.d.ts +64 -0
- package/dist/secrets/providers/gcp.provider.test.d.ts +1 -0
- package/dist/secrets/providers/local.provider.d.ts +82 -0
- package/dist/secrets/providers/local.provider.test.d.ts +1 -0
- package/dist/secrets/providers/provider-factory.d.ts +39 -0
- package/dist/secrets/providers/provider-factory.test.d.ts +1 -0
- package/dist/secrets/secrets.interface.d.ts +93 -0
- package/dist/secrets/secrets.module.d.ts +24 -0
- package/dist/secrets/secrets.service.d.ts +70 -0
- package/dist/secrets/secrets.service.test.d.ts +1 -0
- package/dist/service-client/base-service-client.d.ts +113 -0
- package/dist/service-client/base-service-client.test.d.ts +1 -0
- package/dist/service-client/filter-forward-headers.d.ts +11 -0
- package/dist/service-client/filter-forward-headers.test.d.ts +1 -0
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/telemetry/telemetry.interface.d.ts +33 -0
- package/dist/telemetry/telemetry.module.d.ts +5 -0
- package/dist/telemetry/telemetry.service.d.ts +39 -0
- package/dist/telemetry/telemetry.service.test.d.ts +1 -0
- package/dist/telemetry/tracing.interceptor.d.ts +11 -0
- package/dist/telemetry/tracing.interceptor.test.d.ts +1 -0
- package/dist/utils/package-json.d.ts +25 -0
- package/package.json +102 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";const __rslib_import_meta_url__="u"<typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{EmailRateLimitModule:()=>EmailRateLimitModule,PartnerApi:()=>PartnerApi,EmailRateLimitDecorator:()=>EmailRateLimitDecorator,RedisModule:()=>RedisModule,SecretsModule:()=>SecretsModule,loadEnvIfExists:()=>loadEnvIfExists,EmailRateLimitGuard:()=>EmailRateLimitGuard,generateSwaggerDocs:()=>generateSwaggerDocs,startWorker:()=>startWorker,SchedulerGuard:()=>SchedulerGuard,RateLimit:()=>RateLimitDecorator,RateLimitModule:()=>RateLimitModule,IS_PUBLIC_KEY:()=>IS_PUBLIC_KEY,ObservabilityModule:()=>ObservabilityModule,Public:()=>Public,Partner:()=>Partner,RateLimitDecorator:()=>RateLimitDecorator,RateLimitHeadersInterceptor:()=>RateLimitHeadersInterceptor,LoggerService:()=>LoggerService,RedisService:()=>RedisService,NotificationService:()=>NotificationService,BullConfigModule:()=>BullConfigModule,createPrismaConnection:()=>createPrismaConnection,AuthGuard:()=>AuthGuard,SecretsService:()=>SecretsService,NotificationModule:()=>NotificationModule,BaseServiceClient:()=>BaseServiceClient,IS_PARTNER_API_KEY:()=>IS_PARTNER_API_KEY,KongHeaders:()=>auth_user_interface_KongHeaders,filterForwardHeaders:()=>filterForwardHeaders,startApp:()=>startApp,RateLimitGuard:()=>RateLimitGuard,AuthModule:()=>AuthModule,MetricsService:()=>MetricsService});const common_namespaceObject=require("@nestjs/common"),core_namespaceObject=require("@nestjs/core"),external_crypto_namespaceObject=require("crypto"),IS_PUBLIC_KEY="isPublic",Public=()=>(0,common_namespaceObject.SetMetadata)(IS_PUBLIC_KEY,!0);var auth_user_interface_KongHeaders=function(e){return e.CONSUMER_ID="x-consumer-id",e.CONSUMER_USERNAME="x-consumer-username",e.CREDENTIAL_IDENTIFIER="x-credential-identifier",e.USERINFO="x-userinfo",e.JWT_CLAIM_PREFIX="x-jwt-claim-",e}({});const external_fs_namespaceObject=require("fs");var external_fs_default=__webpack_require__.n(external_fs_namespaceObject);const external_path_namespaceObject=require("path");var external_path_default=__webpack_require__.n(external_path_namespaceObject);const external_child_process_namespaceObject=require("child_process"),external_util_namespaceObject=require("util"),execAsync=(0,external_util_namespaceObject.promisify)(external_child_process_namespaceObject.exec);class LocalSecretsProvider{constructor(e=".secrets.local.json",t=6e4){this.cache=new Map,this.serviceCache=new Map,this.secretsFilePath=this.findProjectRoot(e),this.cacheTtl=t,this.secrets=this.loadSecretsFile();const r=this.secrets.secrets;r&&r.NODE_ENV&&(process.env.NODE_ENV=r.NODE_ENV)}setServiceName(e){this.serviceName=e;let t=this.secrets[e];t&&t.DATABASE_URL&&(process.env.DATABASE_URL=t.DATABASE_URL)}findProjectRoot(e){let t=process.cwd(),r=0;for(;r<10;){let a=external_path_namespaceObject.join(t,e);if(external_fs_namespaceObject.existsSync(a))return a;let i=external_path_namespaceObject.dirname(t);if(i===t)break;t=i,r++}return external_path_namespaceObject.join(process.cwd(),e)}loadSecretsFile(){try{if(!external_fs_namespaceObject.existsSync(this.secretsFilePath))throw Error(`Secrets file not found: ${this.secretsFilePath}
|
|
2
|
+
|
|
3
|
+
Please create .secrets.local.json in your project root.
|
|
4
|
+
See docs/secrets-management-strategy.md for details.`);let e=external_fs_namespaceObject.readFileSync(this.secretsFilePath,"utf-8"),t=JSON.parse(e);if("object"!=typeof t||null===t)throw Error(`Invalid secrets file format. Expected object, got ${typeof t}`);return t}catch(e){if(e instanceof SyntaxError)throw Error(`Failed to parse secrets file: ${this.secretsFilePath}
|
|
5
|
+
JSON syntax error: ${e.message}`);throw e}}async getAll(e){let t=this.secrets[e];if(!t)return{};if("object"!=typeof t)throw Error(`Invalid secrets format for "${e}". Expected object, got ${typeof t}`);let r={};for(let[a,i]of Object.entries(t))if("string"==typeof i)r[a]=i;else throw Error(`Invalid value for "${a}" in "${e}". Expected string, got ${typeof i}`);return r}getName(){return"local"}getSecretsFilePath(){return this.secretsFilePath}async get(e){let t,r=this.cache.get(e);if(r&&Date.now()<r.expiresAt)return r.value;if(this.secrets=this.loadSecretsFile(),this.serviceName){let r=this.secrets[this.serviceName];r&&"string"==typeof r[e]&&(t=r[e])}if(!t){let r=this.secrets.secrets;r&&"string"==typeof r[e]&&(t=r[e])}if(!t)throw Error(`Secret "${e}" not found. `+(this.serviceName?`Searched in service "${this.serviceName}" and top-level secrets.`:"Searched in top-level secrets only. Use setServiceName() to search in a specific service."));return this.cache.set(e,{value:t,expiresAt:Date.now()+this.cacheTtl}),t}async set(e,t){let r=external_path_namespaceObject.dirname(this.secretsFilePath),a=external_path_namespaceObject.join(r,".secrets.user.json"),i={};external_fs_namespaceObject.existsSync(a)&&(i=JSON.parse(external_fs_namespaceObject.readFileSync(a,"utf-8"))),i.secrets||(i.secrets={}),i.secrets[e]=t,external_fs_namespaceObject.writeFileSync(a,JSON.stringify(i,null,2),"utf-8");try{await execAsync("npx tsdevstack generate-secrets",{cwd:r})}catch{throw Error(`Failed to regenerate secrets after setting "${e}". Manual regeneration may be required: npx tsdevstack generate-secrets`)}this.clearCache()}async delete(e){let t=external_path_namespaceObject.dirname(this.secretsFilePath),r=external_path_namespaceObject.join(t,".secrets.user.json");if(!external_fs_namespaceObject.existsSync(r))throw Error(`Cannot delete secret: .secrets.user.json not found at ${r}`);let a=JSON.parse(external_fs_namespaceObject.readFileSync(r,"utf-8"));if(a.secrets&&a.secrets[e]){delete a.secrets[e],external_fs_namespaceObject.writeFileSync(r,JSON.stringify(a,null,2),"utf-8");try{await execAsync("npx tsdevstack generate-secrets",{cwd:t})}catch{throw Error(`Failed to regenerate secrets after deleting "${e}". Manual regeneration may be required: npx tsdevstack generate-secrets`)}this.clearCache()}else throw Error(`Secret "${e}" not found in .secrets.user.json`)}clearCache(){this.cache.clear(),this.serviceCache.clear()}}const secret_manager_namespaceObject=require("@google-cloud/secret-manager");class GCPSecretsProvider{constructor(e){if(this.logger=new common_namespaceObject.Logger("GCPSecretsProvider"),this.cache=new Map,this.CACHE_TTL_MS=3e5,console.log("[GCP] Constructor start"),this.projectName=e.projectName,this.serviceName=e.serviceName,this.gcpProjectId=process.env.GCP_PROJECT_ID||e.providerConfig?.projectId,!this.gcpProjectId)throw Error("GCP_PROJECT_ID environment variable is required for GCP secrets provider");console.log(`[GCP] Initializing for project: ${this.gcpProjectId}, service: ${this.serviceName}`),console.log("[GCP] Creating SecretManagerServiceClient..."),this.client=new secret_manager_namespaceObject.SecretManagerServiceClient,console.log("[GCP] SecretManagerServiceClient created")}async get(e){console.log(`[GCP] get() called for: ${e}`);let t=this.getFromCache(e);if(null!==t)return this.logger.debug(`Cache hit for: ${e}`),t;let r=null;if("API_KEY"===e){let e=`${this.serviceName.toUpperCase().replace(/-/g,"_")}_API_KEY`,t=this.buildSecretName(e,"shared");r=await this.fetchSecretFromGCP(t)}else{let t=this.buildSecretName(e,this.serviceName);if(null===(r=await this.fetchSecretFromGCP(t))){let t=this.buildSecretName(e,"shared");r=await this.fetchSecretFromGCP(t)}}return null!==r?(this.logger.debug(`Secret found: ${e}`),this.setCache(e,r)):this.logger.warn(`Secret not found: ${e}`),r}async set(e,t,r){let a=this.buildSecretName(e,this.serviceName),i=`projects/${this.gcpProjectId}`,c=this.extractSecretId(a);try{await this.exists(e)||await this.client.createSecret({parent:i,secretId:c,secret:{replication:{automatic:{}},labels:this.buildLabels(r)}}),await this.client.addSecretVersion({parent:`${i}/secrets/${c}`,payload:{data:Buffer.from(t,"utf8")}}),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${a} in GCP: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName),r=`projects/${this.gcpProjectId}`,a=this.extractSecretId(t);try{await this.client.deleteSecret({name:`${r}/secrets/${a}`}),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from GCP: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e=`projects/${this.gcpProjectId}`,t=[];try{let[r]=await this.client.listSecrets({parent:e,filter:`labels.project-name=${this.projectName}`});for(let e of r)if(e.name){let r=e.name.split("/").pop();if(r){let e=this.extractKeyFromSecretId(r);t.push(e)}}return t}catch(e){throw Error(`Failed to list secrets from GCP: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=`projects/${this.gcpProjectId}`,r=this.buildSecretName(e,this.serviceName),a=this.extractSecretId(r);try{return await this.client.getSecret({name:`${t}/secrets/${a}`}),!0}catch{}let i=this.buildSecretName(e,"shared"),c=this.extractSecretId(i);try{return await this.client.getSecret({name:`${t}/secrets/${c}`}),!0}catch{return!1}}getProviderName(){return"gcp"}buildSecretName(e,t){return`${this.projectName}-${t}-${e}`}extractSecretId(e){return e}extractKeyFromSecretId(e){return e.split("-").slice(2).join("-")}async fetchSecretFromGCP(e){let t=`projects/${this.gcpProjectId}`,r=this.extractSecretId(e),a=`${t}/secrets/${r}/versions/latest`;console.log(`[GCP] Fetching: ${r}`);try{let[e]=await this.client.accessSecretVersion({name:a});if(console.log(`[GCP] Fetched: ${r}`),!e.payload?.data)return null;return e.payload.data.toString()}catch(a){let e=a?.code;if(console.log(`[GCP] Error for ${r}: code=${e}`),5===e)return null;let t=a instanceof Error?a.message:String(a);return console.error(`[GCP] Failed: ${r}: ${t}`),null}}buildLabels(e){let t={"project-name":this.projectName,"service-name":this.serviceName,"managed-by":"tsdevstack"};if(e)for(let[r,a]of Object.entries(e))t[r.toLowerCase().replace(/[^a-z0-9-_]/g,"-").replace(/^[^a-z]/,"x")]=a;return t}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.isUrlValue(t)||this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}isUrlValue(e){return e.startsWith("https://")||e.startsWith("http://")}invalidateCache(e){this.cache.delete(e)}}const client_secrets_manager_namespaceObject=require("@aws-sdk/client-secrets-manager");class AWSSecretsProvider{constructor(e){this.cache=new Map,this.CACHE_TTL_MS=3e5,this.projectName=e.projectName,this.serviceName=e.serviceName,this.region=e.providerConfig?.region||"us-east-1",this.client=new client_secrets_manager_namespaceObject.SecretsManagerClient({region:this.region})}async get(e){let t=this.getFromCache(e);if(null!==t)return t;let r=this.buildSecretName(e,this.serviceName),a=await this.fetchSecretFromAWS(r);if(null===a){let t=this.buildSecretName(e,"shared");a=await this.fetchSecretFromAWS(t)}return null!==a&&this.setCache(e,a),a}async set(e,t,r){let a=this.buildSecretName(e,this.serviceName);try{await this.exists(e)?await this.client.send(new client_secrets_manager_namespaceObject.PutSecretValueCommand({SecretId:a,SecretString:t})):await this.client.send(new client_secrets_manager_namespaceObject.CreateSecretCommand({Name:a,SecretString:t,Tags:this.buildTags(r)})),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${a} in AWS: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName);try{await this.client.send(new client_secrets_manager_namespaceObject.DeleteSecretCommand({SecretId:t,ForceDeleteWithoutRecovery:!1,RecoveryWindowInDays:7})),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from AWS: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e,t=[];try{do{let r=await this.client.send(new client_secrets_manager_namespaceObject.ListSecretsCommand({Filters:[{Key:"tag-key",Values:["project-name"]},{Key:"tag-value",Values:[this.projectName]}],NextToken:e}));if(r.SecretList){for(let e of r.SecretList)if(e.Name){let r=this.extractKeyFromSecretName(e.Name);t.push(r)}}e=r.NextToken}while(e);return t}catch(e){throw Error(`Failed to list secrets from AWS: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=this.buildSecretName(e,this.serviceName);try{return await this.client.send(new client_secrets_manager_namespaceObject.DescribeSecretCommand({SecretId:t})),!0}catch{}let r=this.buildSecretName(e,"shared");try{return await this.client.send(new client_secrets_manager_namespaceObject.DescribeSecretCommand({SecretId:r})),!0}catch{return!1}}getProviderName(){return"aws"}buildSecretName(e,t){return`${this.projectName}-${t}-${e}`}extractKeyFromSecretName(e){let t=e.substring(this.projectName.length+1);if(t.startsWith(`${this.serviceName}-`))return t.substring(this.serviceName.length+1);if(t.startsWith("shared-"))return t.substring(7);let r=t.indexOf("-");return r>=0?t.substring(r+1):t}async fetchSecretFromAWS(e){try{return(await this.client.send(new client_secrets_manager_namespaceObject.GetSecretValueCommand({SecretId:e}))).SecretString||null}catch{return null}}buildTags(e){let t=[{Key:"project-name",Value:this.projectName},{Key:"service-name",Value:this.serviceName},{Key:"managed-by",Value:"tsdevstack"}];if(e)for(let[r,a]of Object.entries(e))t.push({Key:r,Value:a});return t}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}invalidateCache(e){this.cache.delete(e)}}const keyvault_secrets_namespaceObject=require("@azure/keyvault-secrets"),identity_namespaceObject=require("@azure/identity");class AzureSecretsProvider{constructor(e){if(this.cache=new Map,this.CACHE_TTL_MS=3e5,this.projectName=e.projectName,this.serviceName=e.serviceName,this.keyVaultName=process.env.AZURE_KEYVAULT_NAME||e.providerConfig?.keyVaultName||"",!this.keyVaultName)throw Error("Azure Key Vault name is required. Set AZURE_KEYVAULT_NAME environment variable.");const t=process.env.AZURE_TENANT_ID,r=process.env.AZURE_CLIENT_ID,a=process.env.AZURE_CLIENT_SECRET;if(!t||!r||!a)throw Error("Azure credentials are required. Set AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET environment variables.");const i=new identity_namespaceObject.ClientSecretCredential(t,r,a),c=`https://${this.keyVaultName}.vault.azure.net`;this.client=new keyvault_secrets_namespaceObject.SecretClient(c,i)}async get(e){let t=this.getFromCache(e);if(null!==t)return t;let r=this.buildSecretName(e,this.serviceName),a=await this.fetchSecretFromAzure(r);if(null===a){let t=this.buildSecretName(e,"shared");a=await this.fetchSecretFromAzure(t)}return null!==a&&this.setCache(e,a),a}async set(e,t,r){let a=this.buildSecretName(e,this.serviceName);try{let i=this.buildTags(r);await this.client.setSecret(a,t,{tags:i}),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${a} in Azure: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName);try{let r=await this.client.beginDeleteSecret(t);await r.pollUntilDone(),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from Azure: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e=[];try{for await(let t of this.client.listPropertiesOfSecrets())if(t.tags?.["project-name"]===this.projectName){let r=this.extractKeyFromSecretName(t.name);e.push(r)}return e}catch(e){throw Error(`Failed to list secrets from Azure: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=this.buildSecretName(e,this.serviceName);try{return await this.client.getSecret(t),!0}catch{}let r=this.buildSecretName(e,"shared");try{return await this.client.getSecret(r),!0}catch{return!1}}getProviderName(){return"azure"}buildSecretName(e,t){let r=this.transformKey(e);return`${this.projectName}-${t}-${r}`}extractKeyFromSecretName(e){let t,r=e.substring(this.projectName.length+1);if(r.startsWith(`${this.serviceName}-`))t=r.substring(this.serviceName.length+1);else if(r.startsWith("shared-"))t=r.substring(7);else{let e=r.indexOf("-");t=e>=0?r.substring(e+1):r}return this.reverseTransformKey(t)}async fetchSecretFromAzure(e){try{return(await this.client.getSecret(e)).value||null}catch{return null}}buildTags(e){let t={"project-name":this.projectName,"service-name":this.serviceName,"managed-by":"tsdevstack"};if(e)for(let[r,a]of Object.entries(e))t[r]=a;return t}transformKey(e){return e.replace(/_/g,"-")}reverseTransformKey(e){return e.replace(/-/g,"_")}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}invalidateCache(e){this.cache.delete(e)}}class SecretsProviderFactory{static createProvider(e){let t=this.getProviderType();if("local"===t)return null;let r=this.getProjectName();this.validateProviderEnvVars(t);let a={projectName:r,serviceName:e,providerConfig:{}};switch(t){case"gcp":return new GCPSecretsProvider(a);case"aws":return new AWSSecretsProvider(a);case"azure":return new AzureSecretsProvider(a);default:throw Error(`Unknown secrets provider type: ${t}`)}}static getProviderType(){let e=process.env.SECRETS_PROVIDER?.toLowerCase();if(!e)return"local";if(!["local","gcp","aws","azure"].includes(e))throw Error(`Invalid SECRETS_PROVIDER: ${e}. Must be one of: local, gcp, aws, azure`);return e}static getProjectName(){let e=process.env.PROJECT_NAME;if(!e)throw Error("PROJECT_NAME environment variable is required for cloud secrets providers. Set it in your deployment configuration or .env file.");return e}static validateProviderEnvVars(e){let t=[];switch(e){case"gcp":process.env.GCP_PROJECT_ID||t.push("GCP_PROJECT_ID"),process.env.K_SERVICE||process.env.GOOGLE_APPLICATION_CREDENTIALS||t.push("GOOGLE_APPLICATION_CREDENTIALS");break;case"aws":process.env.AWS_REGION||t.push("AWS_REGION"),process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI||process.env.AWS_ACCESS_KEY_ID||t.push("AWS_ACCESS_KEY_ID"),process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI||process.env.AWS_SECRET_ACCESS_KEY||t.push("AWS_SECRET_ACCESS_KEY");break;case"azure":process.env.AZURE_CLIENT_ID||t.push("AZURE_CLIENT_ID"),process.env.AZURE_CLIENT_SECRET||t.push("AZURE_CLIENT_SECRET"),process.env.AZURE_TENANT_ID||t.push("AZURE_TENANT_ID"),process.env.AZURE_KEYVAULT_NAME||t.push("AZURE_KEYVAULT_NAME")}if(t.length>0)throw Error(`Missing required environment variables for ${e.toUpperCase()}: ${t.join(", ")}. Set these in your deployment configuration or .env file.`)}}class CloudProviderAdapter{constructor(e,t){this.cloudProvider=e,this.serviceName=t}async get(e){let t=await this.cloudProvider.get(e);if(null===t)throw Error(`Secret "${e}" not found in ${this.cloudProvider.getProviderName()} for service "${this.serviceName}" or shared scope.`);return t}async getAll(){let e=await this.cloudProvider.list(),t={};for(let r of e)try{let e=await this.cloudProvider.get(r);null!==e&&(t[r]=e)}catch{continue}return t}async set(e,t){await this.cloudProvider.set(e,t,{"secret-type":"user","managed-by":"tsdevstack"})}async delete(e){await this.cloudProvider.remove(e)}getName(){return this.cloudProvider.getProviderName()}clearCache(){}}function _ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function _ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class SecretsService{constructor(e){this.config=e,this.provider=this.config.forceProvider||this.detectProvider(),"setServiceName"in this.provider&&"function"==typeof this.provider.setServiceName&&this.provider.setServiceName(this.config.serviceName)}getProvider(){return this.provider}async get(e){return this.provider.get(e)}async set(e,t){await this.provider.set(e,t)}async delete(e){await this.provider.delete(e)}clearCache(){this.provider.clearCache()}detectProvider(){let e=process.env.SECRETS_PROVIDER;if(!e)throw Error("SECRETS_PROVIDER environment variable is required.\nSet it to: local, aws, gcp, or azure\nFor local development, tsdevstack automatically sets this in .env file.");if("local"===e){let e=new LocalSecretsProvider(".secrets.local.json");return e.setServiceName(this.config.serviceName),e}let t=SecretsProviderFactory.createProvider(this.config.serviceName);if(!t){let e=new LocalSecretsProvider(".secrets.local.json");return e.setServiceName(this.config.serviceName),e}return new CloudProviderAdapter(t,this.config.serviceName)}}function auth_guard_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function auth_guard_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}SecretsService=_ts_decorate([(0,common_namespaceObject.Injectable)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",["u"<typeof SecretsConfig?Object:SecretsConfig])],SecretsService);class AuthGuard{constructor(e,t){this.reflector=e,this.secrets=t,this.logger=new common_namespaceObject.Logger(AuthGuard.name)}async canActivate(e){let t=e.switchToHttp().getRequest(),r=t.headers["x-api-key"],a=!!t.headers["x-kong-trust"];if(a?await this.verifyKongTrustHeader(t):r&&await this.validateServiceApiKey(t,r),this.reflector.getAllAndOverride(IS_PUBLIC_KEY,[e.getHandler(),e.getClass()]))return!0;let i=t.headers[auth_user_interface_KongHeaders.CONSUMER_ID],c=t.headers[auth_user_interface_KongHeaders.CONSUMER_USERNAME],o=t.headers[auth_user_interface_KongHeaders.CREDENTIAL_IDENTIFIER],s=t.headers[auth_user_interface_KongHeaders.USERINFO];if(i||c||o||s)return i||o||s?t.user=this.extractUserFromHeaders(t.headers):c&&(t.service=c),!0;if(a&&r)return t.service="partner",!0;if(r)return!0;throw new common_namespaceObject.UnauthorizedException("No authentication provided")}extractUserFromHeaders(e){let t=e[auth_user_interface_KongHeaders.USERINFO];if(t)try{let e=Buffer.from(t,"base64").toString("utf-8"),r=JSON.parse(e),a={id:r.sub};return Object.keys(r).forEach(e=>{"sub"!==e&&(a[e]=r[e])}),a}catch(e){console.error("Failed to parse X-Userinfo header:",e)}let r={id:e[auth_user_interface_KongHeaders.CONSUMER_ID]||e[auth_user_interface_KongHeaders.CREDENTIAL_IDENTIFIER]};return Object.keys(e).forEach(t=>{if(t.startsWith(auth_user_interface_KongHeaders.JWT_CLAIM_PREFIX)){let a=t.replace(auth_user_interface_KongHeaders.JWT_CLAIM_PREFIX,"");r[this.toCamelCase(a)]=this.parseValue(e[t])}}),r}toCamelCase(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}parseValue(e){return e.includes(",")?e.split(",").map(e=>e.trim()):/^\d+$/.test(e)?parseInt(e,10):"true"===e||"false"!==e&&e}async verifyKongTrustHeader(e){let t=e.url||e.path;if(t&&(t.includes("/.well-known/")||"/health"===t||t.startsWith("/health/")||"/metrics"===t))return void this.logger.debug(`Skipping Kong trust check for infrastructure endpoint: ${t}`);let r=e.headers["x-kong-trust"];if(!r)throw this.logger.warn("Missing Kong trust header - request did not come through gateway"),new common_namespaceObject.UnauthorizedException("Unauthorized request");let a=await this.secrets.get("KONG_TRUST_TOKEN");if(!a)throw this.logger.error("KONG_TRUST_TOKEN not configured in secrets"),new common_namespaceObject.UnauthorizedException("Authentication configuration error");let i=Buffer.from(r),c=Buffer.from(a);if(i.length!==c.length||!(0,external_crypto_namespaceObject.timingSafeEqual)(i,c))throw this.logger.warn("Invalid Kong trust header - possible bypass attempt"),new common_namespaceObject.UnauthorizedException("Unauthorized request");this.logger.debug("Kong trust header verified")}async validateServiceApiKey(e,t){let r={type:"service-to-service",method:e.method||"UNKNOWN",path:e.url||e.path||"UNKNOWN",caller:e.headers["x-service-name"]||"unknown",keyFingerprint:t.slice(0,8)+"..."},a=await this.secrets.get("API_KEY");if(!a)throw this.logger.error("API_KEY not configured in secrets"),new common_namespaceObject.UnauthorizedException("Server API key is not configured");let i=Buffer.from(t),c=Buffer.from(a);if(i.length!==c.length||!(0,external_crypto_namespaceObject.timingSafeEqual)(i,c))throw this.logger.warn("Invalid service API key attempt",r),new common_namespaceObject.ForbiddenException("Invalid API key");return e.service=e.headers["x-service-name"]||"internal",this.logger.log("Service-to-service request authenticated",r),!0}}function secrets_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}AuthGuard=auth_guard_ts_decorate([(0,common_namespaceObject.Injectable)(),auth_guard_ts_metadata("design:type",Function),auth_guard_ts_metadata("design:paramtypes",[void 0===core_namespaceObject.Reflector?Object:core_namespaceObject.Reflector,void 0===SecretsService?Object:SecretsService])],AuthGuard);class SecretsModule{}function auth_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}SecretsModule=secrets_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({providers:[{provide:SecretsService,useFactory:()=>{let e=process.env.SERVICE_NAME;if(!e)throw Error("SERVICE_NAME environment variable is required. This should be set automatically by startApp() during bootstrap.");return new SecretsService({serviceName:e})}}],exports:[SecretsService]})],SecretsModule);class AuthModule{}AuthModule=auth_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({imports:[SecretsModule],providers:[AuthGuard],exports:[AuthGuard]})],AuthModule);const swagger_namespaceObject=require("@nestjs/swagger"),IS_PARTNER_API_KEY="isPartnerApi",PartnerApi=()=>(0,common_namespaceObject.applyDecorators)((0,common_namespaceObject.SetMetadata)(IS_PARTNER_API_KEY,!0),(0,swagger_namespaceObject.ApiSecurity)("api-key")),Partner=(0,common_namespaceObject.createParamDecorator)((e,t)=>t.switchToHttp().getRequest().headers["x-consumer-username"]),external_ioredis_namespaceObject=require("ioredis");var external_ioredis_default=__webpack_require__.n(external_ioredis_namespaceObject);function redis_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function redis_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class RedisService{constructor(e){this.secrets=e,this.logger=new common_namespaceObject.Logger(RedisService.name)}async onModuleInit(){try{let e=await this.secrets.get("REDIS_HOST"),t=parseInt(await this.secrets.get("REDIS_PORT"),10)||6379,r=await this.secrets.get("REDIS_PASSWORD"),a=await this.secrets.get("REDIS_TLS");this.redis=new(external_ioredis_default())({host:e,port:t,password:r,..."true"===a&&{tls:{}},maxRetriesPerRequest:3,enableReadyCheck:!0,enableOfflineQueue:!1,lazyConnect:!0,keepAlive:3e4,connectTimeout:1e4,retryStrategy:e=>e>3?(this.logger.error("Max connection retries exceeded"),null):Math.min(50*e,2e3)}),this.redis.on("connect",()=>{this.logger.log("Connected to Redis")}),this.redis.on("error",e=>{this.logger.error("Redis connection error:",e)}),await this.redis.connect()}catch(e){throw this.logger.error("Failed to connect to Redis on startup",e),e}}getClient(){return this.redis}async get(e){try{return await this.redis.get(e)}catch(t){return this.logger.error(`Error getting key ${e}:`,t),null}}async set(e,t,r){try{return r?await this.redis.setex(e,r,t):await this.redis.set(e,t),!0}catch(t){return this.logger.error(`Error setting key ${e}:`,t),!1}}async incr(e){try{return await this.redis.incr(e)}catch(t){return this.logger.error(`Error incrementing key ${e}:`,t),null}}async expire(e,t){try{let r=await this.redis.expire(e,t);return 1===r}catch(t){return this.logger.error(`Error setting expiry for key ${e}:`,t),!1}}async del(e){try{return await this.redis.del(e)>0}catch(t){return this.logger.error(`Error deleting key ${e}:`,t),!1}}onModuleDestroy(){this.redis.disconnect()}}function redis_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}RedisService=redis_service_ts_decorate([(0,common_namespaceObject.Injectable)(),redis_service_ts_metadata("design:type",Function),redis_service_ts_metadata("design:paramtypes",[void 0===SecretsService?Object:SecretsService])],RedisService);class RedisModule{}RedisModule=redis_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({providers:[RedisService],exports:[RedisService]})],RedisModule);const RATE_LIMIT_KEY="rateLimit",RateLimitDecorator=e=>(0,common_namespaceObject.SetMetadata)(RATE_LIMIT_KEY,e);function rate_limit_guard_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function rate_limit_guard_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class RateLimitGuard{constructor(e,t){this.redisService=e,this.reflector=t,this.logger=new common_namespaceObject.Logger(RateLimitGuard.name)}async canActivate(e){let t=this.reflector.getAllAndOverride(RATE_LIMIT_KEY,[e.getHandler(),e.getClass()]);if(!t||t.skipIf&&t.skipIf(e))return!0;let r=e.switchToHttp().getRequest(),a=await this.checkRateLimit(e,t);if(!a.success){let e=t.message||"Too many requests";throw new common_namespaceObject.HttpException({statusCode:common_namespaceObject.HttpStatus.TOO_MANY_REQUESTS,message:e,error:"Too Many Requests",limit:a.limit,remaining:a.remaining,reset:a.reset},common_namespaceObject.HttpStatus.TOO_MANY_REQUESTS)}return r.rateLimit={limit:a.limit,remaining:a.remaining,reset:a.reset},!0}async checkRateLimit(e,t){let{windowMs:r=9e5,maxRequests:a=100}=t,i=this.generateKey(e,t),c=Math.floor(Date.now()/r),o=`rate_limit:${i}:${c}`;try{let e=this.redisService.getClient(),t=await e.incr(o);1===t&&await e.expire(o,Math.ceil(r/1e3));let i=Math.max(0,a-t);return{success:t<=a,limit:a,remaining:i,reset:(c+1)*r,current:t}}catch(e){return this.logger.error("Rate limit check failed:",e),{success:!0,limit:a,remaining:a,reset:Date.now()+r,current:0}}}generateKey(e,t){let r=e.switchToHttp().getRequest();if(t.customKeyGenerator)return t.customKeyGenerator(e);let a=r.headers["x-api-key"],i=Array.isArray(a)?a[0]:a,c=r.user?.id||r.user?.sub;switch(t.keyGenerator){case"ip":default:return this.getClientIp(r);case"apiKey":if(!i)throw new common_namespaceObject.UnauthorizedException("API key required for this endpoint");return`api:${i}`;case"userId":if(!c)throw new common_namespaceObject.UnauthorizedException("User authentication required for this endpoint");return`user:${c}`}}getClientIp(e){let t=e.headers["x-forwarded-for"]?.toString().split(",")[0]||e.headers["x-real-ip"]?.toString()||e.socket?.remoteAddress||"unknown";return`ip:${t.trim()}`}}function rate_limit_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}RateLimitGuard=rate_limit_guard_ts_decorate([(0,common_namespaceObject.Injectable)(),rate_limit_guard_ts_metadata("design:type",Function),rate_limit_guard_ts_metadata("design:paramtypes",[void 0===RedisService?Object:RedisService,void 0===core_namespaceObject.Reflector?Object:core_namespaceObject.Reflector])],RateLimitGuard);class RateLimitModule{}RateLimitModule=rate_limit_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({imports:[RedisModule],providers:[RateLimitGuard],exports:[RateLimitGuard]})],RateLimitModule);const operators_namespaceObject=require("rxjs/operators");function rate_limit_headers_interceptor_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}class RateLimitHeadersInterceptor{intercept(e,t){return t.handle().pipe((0,operators_namespaceObject.tap)(()=>{let t=e.switchToHttp().getRequest(),r=e.switchToHttp().getResponse();t.rateLimit&&(r.setHeader("X-RateLimit-Limit",t.rateLimit.limit.toString()),r.setHeader("X-RateLimit-Remaining",t.rateLimit.remaining.toString()),r.setHeader("X-RateLimit-Reset",t.rateLimit.reset.toString()))}))}}RateLimitHeadersInterceptor=rate_limit_headers_interceptor_ts_decorate([(0,common_namespaceObject.Injectable)()],RateLimitHeadersInterceptor);const EMAIL_RATE_LIMIT_KEY="emailRateLimit",EmailRateLimitDecorator=e=>(0,common_namespaceObject.SetMetadata)(EMAIL_RATE_LIMIT_KEY,e);function email_rate_limit_guard_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function email_rate_limit_guard_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class EmailRateLimitGuard{constructor(e,t){this.redisService=e,this.reflector=t,this.logger=new common_namespaceObject.Logger(EmailRateLimitGuard.name)}async canActivate(e){let t=this.reflector.get(EMAIL_RATE_LIMIT_KEY,e.getHandler());if(!t)return!0;let r=e.switchToHttp().getRequest(),a=await this.checkEmailRateLimit(r,t);if(!a.success){let e=t.message||"Too many requests for this email address";throw new common_namespaceObject.HttpException({statusCode:common_namespaceObject.HttpStatus.TOO_MANY_REQUESTS,message:e,error:"Email Rate Limit Exceeded",limit:a.limit,remaining:a.remaining,reset:a.reset},common_namespaceObject.HttpStatus.TOO_MANY_REQUESTS)}return!0}async checkEmailRateLimit(e,t){let{windowMs:r=9e5,maxRequests:a=5,emailField:i="email"}=t,c=e.body,o=c?.[i];if(!o||"string"!=typeof o)return{success:!0,limit:a,remaining:a,reset:Date.now()+r,current:0};let s=o.toLowerCase().trim(),n=Math.floor(Date.now()/r),l=`email_rate_limit:${s}:${n}`;try{let e=this.redisService.getClient(),t=await e.incr(l);1===t&&await e.expire(l,Math.ceil(r/1e3));let i=Math.max(0,a-t);return{success:t<=a,limit:a,remaining:i,reset:(n+1)*r,current:t}}catch(e){return this.logger.error("Email rate limit check failed:",e),{success:!0,limit:a,remaining:a,reset:Date.now()+r,current:0}}}}function email_rate_limit_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}EmailRateLimitGuard=email_rate_limit_guard_ts_decorate([(0,common_namespaceObject.Injectable)(),email_rate_limit_guard_ts_metadata("design:type",Function),email_rate_limit_guard_ts_metadata("design:paramtypes",[void 0===RedisService?Object:RedisService,void 0===core_namespaceObject.Reflector?Object:core_namespaceObject.Reflector])],EmailRateLimitGuard);class EmailRateLimitModule{}function base_service_client_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function base_service_client_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}EmailRateLimitModule=email_rate_limit_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({imports:[RedisModule],providers:[EmailRateLimitGuard],exports:[EmailRateLimitGuard]})],EmailRateLimitModule);class BaseServiceClient{constructor(){this.logger=new common_namespaceObject.Logger(this.constructor.name)}initialize(e){try{if(!e.baseURL)throw Error("Service base URL is required");if(!e.apiKey)throw Error("Service API key is required");this.client=e.createClient(e.baseURL,e.apiKey),this.logger.log(`Service client initialized: ${e.baseURL}`)}catch(e){throw this.logger.error(`Failed to initialize service client: ${e instanceof Error?e.message:"Unknown error"}`),e}}}BaseServiceClient=base_service_client_ts_decorate([(0,common_namespaceObject.Injectable)(),base_service_client_ts_metadata("design:type",Function),base_service_client_ts_metadata("design:paramtypes",[])],BaseServiceClient);const SKIP_HEADERS=new Set(["connection","keep-alive","transfer-encoding","upgrade","host","content-length","content-encoding","proxy-authenticate","proxy-authorization","te","trailer"]);function filterForwardHeaders(e){let t={};for(let[r,a]of Object.entries(e)){let e=r.toLowerCase();SKIP_HEADERS.has(e)||"string"==typeof a&&(t[r]=a)}return t}const external_helmet_namespaceObject=require("helmet");var external_helmet_default=__webpack_require__.n(external_helmet_namespaceObject);const external_compression_namespaceObject=require("compression");var external_compression_default=__webpack_require__.n(external_compression_namespaceObject);const external_express_namespaceObject=require("express");var external_express_default=__webpack_require__.n(external_express_namespaceObject);const external_dotenv_namespaceObject=require("dotenv");var external_dotenv_default=__webpack_require__.n(external_dotenv_namespaceObject);function createSwaggerDocument(e,t){let r=new swagger_namespaceObject.DocumentBuilder().setTitle(t.title).setDescription(t.description).setVersion(t.version||"1.0.0").addBearerAuth({type:"http",scheme:"bearer",bearerFormat:"JWT"},"bearer").addApiKey({type:"apiKey",in:"header",name:"x-api-key"},"api-key");return t.tags&&t.tags.forEach(e=>{r.addTag(e)}),swagger_namespaceObject.SwaggerModule.createDocument(e,r.build())}function loadFrameworkConfig(e){let t,r=findFrameworkConfigFile();if(!r)throw Error("Framework configuration not found.\nExpected .tsdevstack/config.json in project root.\nPlease ensure the file exists.");try{let e=external_fs_namespaceObject.readFileSync(r,"utf-8");t=JSON.parse(e)}catch(e){throw Error(`Failed to read framework configuration: ${r}
|
|
6
|
+
Error: ${e instanceof Error?e.message:String(e)}`)}if(!t.services||!Array.isArray(t.services))throw Error('Invalid framework configuration.\nExpected "services" array in .tsdevstack/config.json');let a=t.services.find(t=>t.name===e);if(!a){let r=t.services.map(e=>e.name).join(", ");throw Error(`Service "${e}" not found in framework configuration.
|
|
7
|
+
Available services: ${r}
|
|
8
|
+
Please add the service to .tsdevstack/config.json`)}return{serviceName:a.name,type:a.type,port:a.port,globalPrefix:a.globalPrefix,hasDatabase:a.hasDatabase,databaseType:a.databaseType}}function findFrameworkConfigFile(){let e=process.cwd(),t=0;for(;t<10;){let r=external_path_namespaceObject.join(e,".tsdevstack","config.json");if(external_fs_namespaceObject.existsSync(r))return r;let a=external_path_namespaceObject.dirname(e);if(a===e)break;e=a,t++}return null}function readPackageJson(){let e=external_path_namespaceObject.join(process.cwd(),"package.json");if(!external_fs_namespaceObject.existsSync(e))throw Error(`package.json not found at ${e}
|
|
9
|
+
Ensure the service is started from its directory (e.g., apps/auth-service/)`);try{let t=external_fs_namespaceObject.readFileSync(e,"utf-8");return JSON.parse(t)}catch(e){throw Error(`Failed to parse package.json: ${e instanceof Error?e.message:String(e)}`)}}function extractAuthor(e){return e.author?"string"==typeof e.author?e.author:e.author.name||"unknown":"unknown"}function titleCase(e){return e.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function createApp(e,t){let{globalPrefix:r,jsonLimit:a=1,urlLimit:i=1,enableShutdownHooks:c=!0,swagger:o}=t,s=await core_namespaceObject.NestFactory.create(e);if(s.setGlobalPrefix(r,{exclude:["health","health/ping","metrics"]}),s.enableVersioning({type:common_namespaceObject.VersioningType.URI,prefix:"v"}),s.use(external_helmet_default()({crossOriginEmbedderPolicy:!1,contentSecurityPolicy:{directives:{defaultSrc:["'self'"],styleSrc:["'self'","'unsafe-inline'"],scriptSrc:["'self'"],imgSrc:["'self'","data:","https:"]}}})),s.use(external_compression_default()()),s.use(external_express_default().json({limit:`${a}mb`})),s.use(external_express_default().urlencoded({limit:`${i}mb`,extended:!0})),s.useGlobalPipes(new common_namespaceObject.ValidationPipe({transform:!0,whitelist:!0,forbidNonWhitelisted:!0,disableErrorMessages:"production"===process.env.NODE_ENV,transformOptions:{enableImplicitConversion:!0}})),c&&s.enableShutdownHooks(),"production"!==process.env.NODE_ENV){let e=createSwaggerDocument(s,{...o,globalPrefix:r});swagger_namespaceObject.SwaggerModule.setup("api",s,e)}return s}function loadEnvIfExists(){if(process.env.SECRETS_PROVIDER)return;let e=process.cwd(),t=0;for(;t<10;){let r=external_path_default().join(e,".env");if(external_fs_default().existsSync(r)&&external_fs_default().readFileSync(r,"utf-8").includes("SECRETS_PROVIDER="))return void external_dotenv_default().config({path:r});let a=external_path_default().dirname(e);if(a===e)break;e=a,t++}}async function startApp(e,t){loadEnvIfExists();let r=readPackageJson(),a=r.name;process.env.SERVICE_NAME=a;let i=loadFrameworkConfig(a);console.log(`📋 Loaded framework config for ${a}`);let c=t?.swagger||{title:titleCase(a),description:r.description||"",version:r.version||"1.0.0"},o={port:process.env.PORT?parseInt(process.env.PORT,10):i.port,globalPrefix:i.globalPrefix,swagger:c,jsonLimit:t?.jsonLimit,urlLimit:t?.urlLimit,enableShutdownHooks:t?.enableShutdownHooks},s=await createApp(e,o);await s.listen(o.port,"0.0.0.0")}const external_http_namespaceObject=require("http");async function startWorker(e,t){let r=t?.healthPort??8080,a=new common_namespaceObject.Logger("Worker");loadEnvIfExists();let i=readPackageJson().name;process.env.SERVICE_NAME=i,a.log(`Starting worker for ${i}`);let c=await core_namespaceObject.NestFactory.createApplicationContext(e),o=external_http_namespaceObject.createServer((e,t)=>{"/health"===e.url?(t.writeHead(200),t.end("OK")):(t.writeHead(404),t.end())});o.listen(r),a.log(`Worker started, health on :${r}`);let s=async e=>{a.log(`${e} received, shutting down...`);let t=setTimeout(()=>{a.error("Shutdown timeout, forcing exit"),process.exit(1)},9e3);try{o.close(),await c.close(),clearTimeout(t),process.exit(0)}catch(e){a.error("Shutdown error",e),process.exit(1)}};process.on("SIGTERM",()=>void s("SIGTERM")),process.on("SIGINT",()=>void s("SIGINT"))}async function generateSwaggerDocs(e){loadEnvIfExists();let t=readPackageJson(),r=t.name;process.env.SERVICE_NAME=r;let a=loadFrameworkConfig(r),i=await core_namespaceObject.NestFactory.create(e,{logger:["error","warn"],preview:!0,abortOnError:!1});i.setGlobalPrefix(a.globalPrefix),i.enableVersioning({type:common_namespaceObject.VersioningType.URI,prefix:"v"});let c=createSwaggerDocument(i,{title:titleCase(r),description:t.description||"",version:t.version||"1.0.0",globalPrefix:a.globalPrefix});return await i.close(),c}const external_pino_namespaceObject=require("pino");var external_pino_default=__webpack_require__.n(external_pino_namespaceObject);const api_namespaceObject=require("@opentelemetry/api"),DEFAULT_REDACT_PATHS=["password","*.password","email","*.email","ssn","*.ssn","creditCard","*.creditCard","token","*.token","secret","*.secret","apiKey","*.apiKey"];function logger_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function logger_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function _ts_param(e,t){return function(r,a){t(r,a,e)}}class LoggerService{constructor(e){this.options=e||{};const t=this.options.level||process.env.LOG_LEVEL||"info",r="production"!==process.env.NODE_ENV,a=this.buildRedactPaths(),i={level:t,formatters:{level:e=>({level:e})},base:{service:process.env.SERVICE_NAME||"unknown"},timestamp:external_pino_default().stdTimeFunctions.isoTime,...a.length>0&&{redact:{paths:a,censor:this.options.redactCensor||"[REDACTED]"}}};r?this.logger=external_pino_default()({...i,transport:{target:"pino-pretty",options:{colorize:!0,translateTime:"SYS:standard",ignore:"pid,hostname"}}}):this.logger=external_pino_default()(i)}buildRedactPaths(){let e=[];this.options.disableDefaultRedaction||e.push(...DEFAULT_REDACT_PATHS),this.options.redactPaths&&e.push(...this.options.redactPaths);let t=process.env.LOG_REDACT_PATHS;return t&&e.push(...t.split(",").map(e=>e.trim())),[...new Set(e)]}setContext(e){this.context=e}setCorrelationId(e){this.correlationId=e}getTraceContext(){let e=api_namespaceObject.trace.getActiveSpan();if(!e)return{};let t=e.spanContext();return{trace_id:t.traceId,span_id:t.spanId}}formatMessage(e,t){let r=this.getTraceContext();return{...this.context&&{context:this.context},...r,...this.correlationId&&!r.trace_id&&{correlationId:this.correlationId},msg:e,...t}}debug(e,t){this.logger.debug(this.formatMessage(e,t))}info(e,t){this.logger.info(this.formatMessage(e,t))}warn(e,t){this.logger.warn(this.formatMessage(e,t))}error(e,t,r){let a={...r};t instanceof Error?a.error={name:t.name,message:t.message,stack:t.stack}:void 0!==t&&(a.error=t),this.logger.error(this.formatMessage(e,a))}child(e){let t=new LoggerService(this.options);return t.setContext(e),this.correlationId&&t.setCorrelationId(this.correlationId),t}}function logger_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}LoggerService=logger_service_ts_decorate([(0,common_namespaceObject.Injectable)({scope:common_namespaceObject.Scope.DEFAULT}),_ts_param(0,(0,common_namespaceObject.Optional)()),_ts_param(0,(0,common_namespaceObject.Inject)("LOGGER_MODULE_OPTIONS")),logger_service_ts_metadata("design:type",Function),logger_service_ts_metadata("design:paramtypes",["u"<typeof LoggerModuleOptions?Object:LoggerModuleOptions])],LoggerService);class LoggerModule{static forRoot(e={}){return{module:LoggerModule,global:!0,providers:[{provide:"LOGGER_MODULE_OPTIONS",useValue:e},LoggerService],exports:[LoggerService]}}}function logging_interceptor_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function logging_interceptor_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}LoggerModule=logger_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({providers:[{provide:"LOGGER_MODULE_OPTIONS",useValue:{}},LoggerService],exports:[LoggerService]})],LoggerModule);class LoggingInterceptor{constructor(e){this.logger=e.child("HTTP")}intercept(e,t){let r=e.switchToHttp().getRequest(),a=e.switchToHttp().getResponse(),i=r.headers["x-request-id"]||r.headers["x-correlation-id"]||crypto.randomUUID();r.correlationId=i,a.setHeader("X-Correlation-ID",i);let{method:c,url:o,ip:s}=r,n=r.get("user-agent")||"",l=Date.now();return this.logger.debug("Incoming request",{method:c,url:o,ip:s,userAgent:n}),t.handle().pipe((0,operators_namespaceObject.tap)({next:()=>{let e=Date.now()-l,t=a.statusCode;this.logger.info("Request completed",{method:c,url:o,statusCode:t,duration:e})},error:e=>{let t=Date.now()-l,r=a.statusCode||500;this.logger.error("Request failed",e,{method:c,url:o,statusCode:r,duration:t})}}))}}LoggingInterceptor=logging_interceptor_ts_decorate([(0,common_namespaceObject.Injectable)(),logging_interceptor_ts_metadata("design:type",Function),logging_interceptor_ts_metadata("design:paramtypes",[void 0===LoggerService?Object:LoggerService])],LoggingInterceptor);const resources_namespaceObject=require("@opentelemetry/resources"),semantic_conventions_namespaceObject=require("@opentelemetry/semantic-conventions"),exporter_prometheus_namespaceObject=require("@opentelemetry/exporter-prometheus"),sdk_metrics_namespaceObject=require("@opentelemetry/sdk-metrics"),sdk_trace_node_namespaceObject=require("@opentelemetry/sdk-trace-node"),exporter_trace_otlp_http_namespaceObject=require("@opentelemetry/exporter-trace-otlp-http");function telemetry_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function telemetry_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function telemetry_service_ts_param(e,t){return function(r,a){t(r,a,e)}}const DEFAULT_OTLP_ENDPOINT="http://localhost:4318";class TelemetryService{constructor(e){this.meterProvider=null,this.prometheusExporter=null,this.tracerProvider=null,this.serviceName=e.serviceName||process.env.SERVICE_NAME||"unknown-service",this.serviceVersion=e.serviceVersion||"1.0.0",this.metricsEnabled=!1!==e.metrics,this.tracingEnabled=!1!==e.tracing,this.tracingEndpoint=e.tracingEndpoint||process.env.OTEL_EXPORTER_OTLP_ENDPOINT||"http://localhost:4318"}onModuleInit(){let e=new resources_namespaceObject.Resource({[semantic_conventions_namespaceObject.ATTR_SERVICE_NAME]:this.serviceName,[semantic_conventions_namespaceObject.ATTR_SERVICE_VERSION]:this.serviceVersion});this.metricsEnabled&&this.initializeMetrics(e),this.tracingEnabled&&this.initializeTracing(e)}initializeMetrics(e){this.prometheusExporter=new exporter_prometheus_namespaceObject.PrometheusExporter({preventServerStart:!0}),this.meterProvider=new sdk_metrics_namespaceObject.MeterProvider({resource:e,readers:[this.prometheusExporter]}),api_namespaceObject.metrics.setGlobalMeterProvider(this.meterProvider)}initializeTracing(e){let t=new exporter_trace_otlp_http_namespaceObject.OTLPTraceExporter({url:`${this.tracingEndpoint}/v1/traces`});this.tracerProvider=new sdk_trace_node_namespaceObject.NodeTracerProvider({resource:e,spanProcessors:[new sdk_trace_node_namespaceObject.BatchSpanProcessor(t)]}),this.tracerProvider.register()}async onModuleDestroy(){let e=[];this.tracerProvider&&e.push(this.tracerProvider.shutdown()),this.meterProvider&&e.push(this.meterProvider.shutdown()),await Promise.all(e)}getMeter(e){return api_namespaceObject.metrics.getMeter(e||this.serviceName)}getTracer(e){return api_namespaceObject.trace.getTracer(e||this.serviceName)}getServiceName(){return this.serviceName}isTracingEnabled(){return this.tracingEnabled}getPrometheusExporter(){return this.prometheusExporter}}function telemetry_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}TelemetryService=telemetry_service_ts_decorate([(0,common_namespaceObject.Injectable)(),telemetry_service_ts_param(0,(0,common_namespaceObject.Inject)("TELEMETRY_MODULE_OPTIONS")),telemetry_service_ts_metadata("design:type",Function),telemetry_service_ts_metadata("design:paramtypes",["u"<typeof TelemetryModuleOptions?Object:TelemetryModuleOptions])],TelemetryService);class TelemetryModule{static forRoot(e={}){return{module:TelemetryModule,global:!0,providers:[{provide:"TELEMETRY_MODULE_OPTIONS",useValue:e},TelemetryService],exports:[TelemetryService]}}}function tracing_interceptor_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function tracing_interceptor_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}TelemetryModule=telemetry_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({providers:[{provide:"TELEMETRY_MODULE_OPTIONS",useValue:{}},TelemetryService],exports:[TelemetryService]})],TelemetryModule);class TracingInterceptor{constructor(e){this.telemetryService=e}intercept(e,t){if(!this.telemetryService.isTracingEnabled())return t.handle();let r=e.switchToHttp().getRequest(),a=e.switchToHttp().getResponse();if(this.isInfrastructureEndpoint(r.url))return t.handle();let i=api_namespaceObject.propagation.extract(api_namespaceObject.context.active(),r.headers),{method:c}=r,o=r.route?.path||r.url,s=this.telemetryService.getTracer();return api_namespaceObject.context.with(i,()=>{let e=s.startSpan(`${c} ${o}`,{kind:api_namespaceObject.SpanKind.SERVER,attributes:{[semantic_conventions_namespaceObject.ATTR_HTTP_REQUEST_METHOD]:c,[semantic_conventions_namespaceObject.ATTR_URL_PATH]:r.url,[semantic_conventions_namespaceObject.ATTR_HTTP_ROUTE]:o}},i),n=api_namespaceObject.trace.setSpan(api_namespaceObject.context.active(),e);return api_namespaceObject.context.with(n,()=>t.handle().pipe((0,operators_namespaceObject.tap)({next:()=>{this.finishSpan(e,a.statusCode)},error:t=>{this.finishSpanWithError(e,a.statusCode||500,t)}})))})}isInfrastructureEndpoint(e){return"/health"===e||e.startsWith("/health/")||"/metrics"===e||e.includes("/.well-known/")}finishSpan(e,t){e.setAttribute(semantic_conventions_namespaceObject.ATTR_HTTP_RESPONSE_STATUS_CODE,t),t>=400?e.setStatus({code:api_namespaceObject.SpanStatusCode.ERROR,message:`HTTP ${t}`}):e.setStatus({code:api_namespaceObject.SpanStatusCode.OK}),e.end()}finishSpanWithError(e,t,r){e.setAttribute(semantic_conventions_namespaceObject.ATTR_HTTP_RESPONSE_STATUS_CODE,t),e.setStatus({code:api_namespaceObject.SpanStatusCode.ERROR,message:r.message}),e.recordException(r),e.end()}}function metrics_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function metrics_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function metrics_service_ts_param(e,t){return function(r,a){t(r,a,e)}}TracingInterceptor=tracing_interceptor_ts_decorate([(0,common_namespaceObject.Injectable)(),tracing_interceptor_ts_metadata("design:type",Function),tracing_interceptor_ts_metadata("design:paramtypes",[void 0===TelemetryService?Object:TelemetryService])],TracingInterceptor);class MetricsService{constructor(e,t){this.telemetryService=t;const r=e.prefix||process.env.SERVICE_NAME||"";this.prefix=r.replace(/-/g,"_")}onModuleInit(){this.telemetryService?(this.meter=this.telemetryService.getMeter(),this._httpRequestDuration=this.meter.createHistogram(this.prefix?`${this.prefix}_http_request_duration_seconds`:"http_request_duration_seconds",{description:"Duration of HTTP requests in seconds",unit:"s"}),this._httpRequestTotal=this.meter.createCounter(this.prefix?`${this.prefix}_http_requests_total`:"http_requests_total",{description:"Total number of HTTP requests"}),this._httpActiveConnections=this.meter.createUpDownCounter(this.prefix?`${this.prefix}_http_active_connections`:"http_active_connections",{description:"Number of active HTTP connections"})):console.warn("MetricsService: TelemetryService not available. Import TelemetryModule before MetricsModule.")}recordHttpRequestDuration(e,t){this._httpRequestDuration&&this._httpRequestDuration.record(t,e)}incrementHttpRequestTotal(e){this._httpRequestTotal&&this._httpRequestTotal.add(1,e)}incrementActiveConnections(){this._httpActiveConnections&&this._httpActiveConnections.add(1)}decrementActiveConnections(){this._httpActiveConnections&&this._httpActiveConnections.add(-1)}getMeter(){return this.meter}createCounter(e,t){if(this.meter)return this.meter.createCounter(e,t)}createHistogram(e,t){if(this.meter)return this.meter.createHistogram(e,t)}createUpDownCounter(e,t){if(this.meter)return this.meter.createUpDownCounter(e,t)}async getMetrics(){return this.telemetryService?this.telemetryService.getPrometheusExporter()?this.collectMetrics():"# No prometheus exporter available\n":"# No telemetry service available\n"}async collectMetrics(){return"# Metrics collected via OpenTelemetry Prometheus Exporter\n"}getContentType(){return"text/plain; charset=utf-8"}getTelemetryService(){return this.telemetryService}}function metrics_controller_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function metrics_controller_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function metrics_controller_ts_param(e,t){return function(r,a){t(r,a,e)}}MetricsService=metrics_service_ts_decorate([(0,common_namespaceObject.Injectable)(),metrics_service_ts_param(0,(0,common_namespaceObject.Inject)("METRICS_MODULE_OPTIONS")),metrics_service_ts_param(1,(0,common_namespaceObject.Optional)()),metrics_service_ts_metadata("design:type",Function),metrics_service_ts_metadata("design:paramtypes",["u"<typeof MetricsModuleOptions?Object:MetricsModuleOptions,void 0===TelemetryService?Object:TelemetryService])],MetricsService);class MetricsController{constructor(e){this.metricsService=e}async getMetrics(e,t){let r=this.metricsService.getTelemetryService(),a=r?.getPrometheusExporter();if(!a){t.set("Content-Type","text/plain; charset=utf-8"),t.send("# OpenTelemetry not configured\n");return}a.getMetricsRequestHandler(e,t)}}function metrics_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}metrics_controller_ts_decorate([Public(),(0,common_namespaceObject.Get)(),metrics_controller_ts_param(0,(0,common_namespaceObject.Req)()),metrics_controller_ts_param(1,(0,common_namespaceObject.Res)()),metrics_controller_ts_metadata("design:type",Function),metrics_controller_ts_metadata("design:paramtypes",["u"<typeof Request?Object:Request,"u"<typeof Response?Object:Response]),metrics_controller_ts_metadata("design:returntype",Promise)],MetricsController.prototype,"getMetrics",null),MetricsController=metrics_controller_ts_decorate([(0,swagger_namespaceObject.ApiExcludeController)(),(0,common_namespaceObject.Controller)("metrics"),metrics_controller_ts_metadata("design:type",Function),metrics_controller_ts_metadata("design:paramtypes",[void 0===MetricsService?Object:MetricsService])],MetricsController);class MetricsModule{static forRoot(e={}){return{module:MetricsModule,global:!0,controllers:[MetricsController],providers:[{provide:"METRICS_MODULE_OPTIONS",useValue:e},MetricsService],exports:[MetricsService]}}}function metrics_interceptor_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function metrics_interceptor_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}MetricsModule=metrics_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({controllers:[MetricsController],providers:[{provide:"METRICS_MODULE_OPTIONS",useValue:{}},MetricsService],exports:[MetricsService]})],MetricsModule);class MetricsInterceptor{constructor(e){this.metricsService=e}intercept(e,t){let r=e.switchToHttp().getRequest(),a=e.switchToHttp().getResponse();if(r.url.includes("/metrics"))return t.handle();let{method:i}=r,c=r.route?.path||r.url,o=process.hrtime.bigint();return this.metricsService.incrementActiveConnections(),t.handle().pipe((0,operators_namespaceObject.tap)({next:()=>{this.recordMetrics(i,c,a.statusCode,o)},error:()=>{this.recordMetrics(i,c,a.statusCode||500,o)},finalize:()=>{this.metricsService.decrementActiveConnections()}}))}recordMetrics(e,t,r,a){let i=Number(process.hrtime.bigint()-a)/1e9,c={method:e,route:t,status_code:String(r)};this.metricsService.recordHttpRequestDuration(c,i),this.metricsService.incrementHttpRequestTotal(c)}}function redis_indicator_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function redis_indicator_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}MetricsInterceptor=metrics_interceptor_ts_decorate([(0,common_namespaceObject.Injectable)(),metrics_interceptor_ts_metadata("design:type",Function),metrics_interceptor_ts_metadata("design:paramtypes",[void 0===MetricsService?Object:MetricsService])],MetricsInterceptor);class RedisHealthIndicator{constructor(e){this.redisService=e}async check(){try{return await this.redisService.get("health-check"),{status:"up"}}catch{return{status:"down",details:{error:"Redis connection failed"}}}}}function memory_indicator_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function memory_indicator_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}RedisHealthIndicator=redis_indicator_ts_decorate([(0,common_namespaceObject.Injectable)(),redis_indicator_ts_metadata("design:type",Function),redis_indicator_ts_metadata("design:paramtypes",[void 0===RedisService?Object:RedisService])],RedisHealthIndicator);const DEFAULT_HEAP_THRESHOLD=524288e3;class MemoryHealthIndicator{constructor(){this.heapThreshold=524288e3}setThreshold(e){this.heapThreshold=e}check(){let e=process.memoryUsage(),t=e.heapUsed;return t>this.heapThreshold?{status:"down",details:{heapUsed:Math.round(t/1024/1024),heapThreshold:Math.round(this.heapThreshold/1024/1024),unit:"MB"}}:{status:"up",details:{heapUsed:Math.round(t/1024/1024),heapTotal:Math.round(e.heapTotal/1024/1024),unit:"MB"}}}}function health_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function health_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function health_service_ts_param(e,t){return function(r,a){t(r,a,e)}}MemoryHealthIndicator=memory_indicator_ts_decorate([(0,common_namespaceObject.Injectable)(),memory_indicator_ts_metadata("design:type",Function),memory_indicator_ts_metadata("design:paramtypes",[])],MemoryHealthIndicator);class HealthService{constructor(e,t,r){this.options=e,this.redisIndicator=t,this.memoryIndicator=r}onModuleInit(){this.options.memory?.heapThreshold&&this.memoryIndicator&&this.memoryIndicator.setThreshold(this.options.memory.heapThreshold)}async check(){let e={},t="ok";if(this.options.redis&&this.redisIndicator){let r=await this.redisIndicator.check();e.redis=r,"down"===r.status&&(t="degraded")}if(this.options.memory&&this.memoryIndicator){let r=this.memoryIndicator.check();e.memory=r,"down"===r.status&&(t="degraded")}let r=process.memoryUsage();return{status:t,timestamp:new Date().toISOString(),uptime:process.uptime(),checks:e,memory:{used:Math.round(r.heapUsed/1024/1024),total:Math.round(r.heapTotal/1024/1024)}}}}function health_controller_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function health_controller_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}HealthService=health_service_ts_decorate([(0,common_namespaceObject.Injectable)(),health_service_ts_param(0,(0,common_namespaceObject.Inject)("HEALTH_MODULE_OPTIONS")),health_service_ts_param(1,(0,common_namespaceObject.Optional)()),health_service_ts_param(2,(0,common_namespaceObject.Optional)()),health_service_ts_metadata("design:type",Function),health_service_ts_metadata("design:paramtypes",["u"<typeof HealthModuleOptions?Object:HealthModuleOptions,void 0===RedisHealthIndicator?Object:RedisHealthIndicator,void 0===MemoryHealthIndicator?Object:MemoryHealthIndicator])],HealthService);class HealthController{constructor(e){this.healthService=e}async healthCheck(){return this.healthService.check()}ping(){return{message:"pong",timestamp:new Date().toISOString()}}}function health_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}health_controller_ts_decorate([Public(),(0,common_namespaceObject.Get)(),health_controller_ts_metadata("design:type",Function),health_controller_ts_metadata("design:paramtypes",[]),health_controller_ts_metadata("design:returntype",Promise)],HealthController.prototype,"healthCheck",null),health_controller_ts_decorate([Public(),(0,common_namespaceObject.Get)("ping"),health_controller_ts_metadata("design:type",Function),health_controller_ts_metadata("design:paramtypes",[]),health_controller_ts_metadata("design:returntype",Object)],HealthController.prototype,"ping",null),HealthController=health_controller_ts_decorate([(0,swagger_namespaceObject.ApiExcludeController)(),(0,common_namespaceObject.Controller)("health"),health_controller_ts_metadata("design:type",Function),health_controller_ts_metadata("design:paramtypes",[void 0===HealthService?Object:HealthService])],HealthController);class HealthModule{static forRoot(e={}){let t=[HealthService,MemoryHealthIndicator];return e.redis&&t.push(RedisHealthIndicator),{module:HealthModule,controllers:[HealthController],providers:[...t,{provide:"HEALTH_MODULE_OPTIONS",useValue:e}],exports:[HealthService]}}}function observability_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}HealthModule=health_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({controllers:[HealthController],providers:[HealthService,MemoryHealthIndicator,{provide:"HEALTH_MODULE_OPTIONS",useValue:{}}],exports:[HealthService]})],HealthModule);class ObservabilityModule{static forRoot(e={}){let t=[],r=[],a=[];return!1!==e.logging&&(t.push(LoggerModule),a.push(LoggerModule),r.push({provide:core_namespaceObject.APP_INTERCEPTOR,useClass:LoggingInterceptor})),(!1!==e.metrics||!1!==e.tracing)&&(t.push(TelemetryModule.forRoot({serviceName:e.serviceName,metrics:e.metrics,tracing:e.tracing,tracingEndpoint:e.tracingEndpoint})),a.push(TelemetryModule)),!1!==e.metrics&&(t.push(MetricsModule),a.push(MetricsModule),r.push({provide:core_namespaceObject.APP_INTERCEPTOR,useClass:MetricsInterceptor})),!1!==e.tracing&&r.push({provide:core_namespaceObject.APP_INTERCEPTOR,useClass:TracingInterceptor}),!1!==e.health&&t.push(HealthModule),{module:ObservabilityModule,global:!0,imports:t,providers:r,exports:a}}}ObservabilityModule=observability_module_ts_decorate([(0,common_namespaceObject.Global)(),(0,common_namespaceObject.Module)({imports:[LoggerModule,TelemetryModule,MetricsModule,HealthModule],providers:[{provide:core_namespaceObject.APP_INTERCEPTOR,useClass:LoggingInterceptor},{provide:core_namespaceObject.APP_INTERCEPTOR,useClass:MetricsInterceptor},{provide:core_namespaceObject.APP_INTERCEPTOR,useClass:TracingInterceptor}],exports:[LoggerModule,TelemetryModule,MetricsModule]})],ObservabilityModule);const external_pg_namespaceObject=require("pg"),adapter_pg_namespaceObject=require("@prisma/adapter-pg");function createPrismaConnection(){let e="production"===process.env.NODE_ENV;if(e&&!process.env.DB_POOL_MAX)throw Error("DB_POOL_MAX is required in production");let t=e?parseInt(process.env.DB_POOL_MAX,10):5,r="aws"===process.env.CLOUD_PROVIDER?{rejectUnauthorized:!1}:void 0,a=new external_pg_namespaceObject.Pool({connectionString:process.env.DATABASE_URL,max:t,idleTimeoutMillis:3e4,connectionTimeoutMillis:1e4,ssl:r});return{config:{adapter:new adapter_pg_namespaceObject.PrismaPg(a)},pool:a}}function notification_service_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function notification_service_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function notification_service_ts_param(e,t){return function(r,a){t(r,a,e)}}const EMAIL_PROVIDER="EMAIL_PROVIDER";class NotificationService{constructor(e){this.emailProvider=e}async sendEmail(e){await this.emailProvider.send(e)}async sendSMS(e){throw Error("SMS notifications are not implemented. Coming in a future version.")}async sendPush(e){throw Error("Push notifications are not implemented. Coming in a future version.")}getEmailProviderName(){return this.emailProvider.getName()}}function console_provider_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function console_provider_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}NotificationService=notification_service_ts_decorate([(0,common_namespaceObject.Injectable)(),notification_service_ts_param(0,(0,common_namespaceObject.Inject)(EMAIL_PROVIDER)),notification_service_ts_metadata("design:type",Function),notification_service_ts_metadata("design:paramtypes",["u"<typeof EmailProvider?Object:EmailProvider])],NotificationService);class ConsoleEmailProvider{constructor(e){this.logger=e?.child("Email")??new LoggerService().child("Email")}async send(e){let t=Array.isArray(e.to)?e.to.join(", "):e.to,r=e.html||e.text||"(no content)";console.log("\n========================================"),console.log("\uD83D\uDCE7 EMAIL (console provider - not actually sent)"),console.log("========================================"),console.log(`To: ${t}`),console.log(`Subject: ${e.subject}`),e.from&&console.log(`From: ${e.from}`),e.replyTo&&console.log(`Reply-To: ${e.replyTo}`),console.log("----------------------------------------"),console.log("Body:"),console.log(r),console.log("========================================\n"),this.logger.info("Email sent via console provider",{to:t,subject:e.subject})}getName(){return"console"}}ConsoleEmailProvider=console_provider_ts_decorate([(0,common_namespaceObject.Injectable)(),console_provider_ts_metadata("design:type",Function),console_provider_ts_metadata("design:paramtypes",[void 0===LoggerService?Object:LoggerService])],ConsoleEmailProvider);const external_resend_namespaceObject=require("resend");function resend_provider_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function resend_provider_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class ResendEmailProvider{constructor(e){this.secrets=e,this.logger=new common_namespaceObject.Logger(ResendEmailProvider.name)}async onModuleInit(){let e=await this.secrets.get("RESEND_API_KEY");this.client=new external_resend_namespaceObject.Resend(e);try{this.defaultFrom=await this.secrets.get("EMAIL_FROM")}catch{this.defaultFrom="onboarding@resend.dev",this.logger.warn("EMAIL_FROM secret not set, using Resend default: onboarding@resend.dev")}this.logger.log("Resend email provider initialized")}async send(e){let t=e.from||this.defaultFrom,r=Array.isArray(e.to)?e.to:[e.to];this.logger.debug(`Sending email to ${r.join(", ")}: ${e.subject}`);let a={from:t,to:r,subject:e.subject};e.html&&(a.html=e.html),e.text&&(a.text=e.text),e.replyTo&&(a.replyTo=e.replyTo),a.html||a.text||(a.text="(no content)");let{error:i}=await this.client.emails.send(a);if(i)throw this.logger.error(`Failed to send email: ${i.message}`),Error(`Failed to send email: ${i.message}`);this.logger.debug(`Email sent successfully to ${r.join(", ")}`)}getName(){return"resend"}}function notification_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}ResendEmailProvider=resend_provider_ts_decorate([(0,common_namespaceObject.Injectable)(),resend_provider_ts_metadata("design:type",Function),resend_provider_ts_metadata("design:paramtypes",[void 0===SecretsService?Object:SecretsService])],ResendEmailProvider);class NotificationModule{}NotificationModule=notification_module_ts_decorate([(0,common_namespaceObject.Module)({providers:[NotificationService,{provide:EMAIL_PROVIDER,useFactory:async(e,t)=>{let r="console";try{r=await e.get("EMAIL_PROVIDER")}catch{}if("resend"===r){let t=new ResendEmailProvider(e);return await t.onModuleInit(),t}return new ConsoleEmailProvider(t)},inject:[SecretsService,LoggerService]}],exports:[NotificationService]})],NotificationModule);const bullmq_namespaceObject=require("@nestjs/bullmq");function bull_config_module_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}class BullConfigModule{static forRoot(){return bullmq_namespaceObject.BullModule.forRootAsync({imports:[SecretsModule],inject:[SecretsService],useFactory:async e=>{let t=await e.get("REDIS_TLS");return{prefix:"{bull}",connection:{host:await e.get("REDIS_HOST"),port:parseInt(await e.get("REDIS_PORT"),10)||6379,password:await e.get("REDIS_PASSWORD"),..."true"===t&&{tls:{}},maxRetriesPerRequest:null},defaultJobOptions:{removeOnComplete:{count:100},removeOnFail:{count:500},attempts:3,backoff:{type:"exponential",delay:1e3}}}}})}}BullConfigModule=bull_config_module_ts_decorate([(0,common_namespaceObject.Module)({})],BullConfigModule);const external_google_auth_library_namespaceObject=require("google-auth-library");function scheduler_guard_ts_decorate(e,t,r,a){var i,c=arguments.length,o=c<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,r):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,a);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(o=(c<3?i(o):c>3?i(t,r,o):i(t,r))||o);return c>3&&o&&Object.defineProperty(t,r,o),o}function scheduler_guard_ts_metadata(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class SchedulerGuard{constructor(e){this.secrets=e,this.logger=new common_namespaceObject.Logger(SchedulerGuard.name),this.oauth2Client=new external_google_auth_library_namespaceObject.OAuth2Client}async canActivate(e){let t=e.switchToHttp().getRequest(),r=process.env.SECRETS_PROVIDER;if("local"===r)return this.logger.warn("Skipping scheduler validation in local mode"),!0;switch(r){case"gcp":return this.validateGcpOidc(t);case"aws":return this.validateAwsJobSecret(t);case"azure":return this.validateAzureJobSecret(t);default:return this.logger.error(`Unknown or missing SECRETS_PROVIDER: ${r}`),!1}}async validateAwsJobSecret(e){let t=e.headers["x-job-secret"];if(!t)return this.logger.warn("Missing X-Job-Secret header"),!1;try{let e=await this.secrets.get("JOB_AUTH_SECRET");if(!e)return this.logger.error("JOB_AUTH_SECRET not configured"),!1;if(t===e)return this.logger.log("Validated AWS scheduler request via job secret"),!0;return this.logger.warn("Invalid X-Job-Secret header"),!1}catch(e){return this.logger.error("AWS job secret validation failed",e),!1}}async validateAzureJobSecret(e){let t=e.headers["x-job-secret"];if(!t)return this.logger.warn("Missing X-Job-Secret header"),!1;try{let e=await this.secrets.get("JOB_SECRET");if(!e)return this.logger.error("JOB_SECRET not configured"),!1;if(t===e)return this.logger.log("Validated Azure scheduler request via job secret"),!0;return this.logger.warn("Invalid X-Job-Secret header"),!1}catch(e){return this.logger.error("Azure job secret validation failed",e),!1}}async validateGcpOidc(e){let t=e.headers.authorization;if(!t?.startsWith("Bearer "))return this.logger.warn("Missing Authorization header"),!1;try{let e=process.env.SERVICE_NAME;if(!e)return this.logger.error("SERVICE_NAME environment variable not set"),!1;let r=`${e.toUpperCase().replace(/-/g,"_")}_URL`,a=await this.secrets.get(r),i=(await this.oauth2Client.verifyIdToken({idToken:t.substring(7),audience:a})).getPayload();return this.logger.log(`Validated GCP scheduler request from ${i?.email}`),!0}catch(e){return this.logger.error("GCP OIDC token validation failed",e),!1}}}for(var __rspack_i in SchedulerGuard=scheduler_guard_ts_decorate([(0,common_namespaceObject.Injectable)(),scheduler_guard_ts_metadata("design:type",Function),scheduler_guard_ts_metadata("design:paramtypes",[void 0===SecretsService?Object:SecretsService])],SchedulerGuard),exports.AuthGuard=__webpack_exports__.AuthGuard,exports.AuthModule=__webpack_exports__.AuthModule,exports.BaseServiceClient=__webpack_exports__.BaseServiceClient,exports.BullConfigModule=__webpack_exports__.BullConfigModule,exports.EmailRateLimitDecorator=__webpack_exports__.EmailRateLimitDecorator,exports.EmailRateLimitGuard=__webpack_exports__.EmailRateLimitGuard,exports.EmailRateLimitModule=__webpack_exports__.EmailRateLimitModule,exports.IS_PARTNER_API_KEY=__webpack_exports__.IS_PARTNER_API_KEY,exports.IS_PUBLIC_KEY=__webpack_exports__.IS_PUBLIC_KEY,exports.KongHeaders=__webpack_exports__.KongHeaders,exports.LoggerService=__webpack_exports__.LoggerService,exports.MetricsService=__webpack_exports__.MetricsService,exports.NotificationModule=__webpack_exports__.NotificationModule,exports.NotificationService=__webpack_exports__.NotificationService,exports.ObservabilityModule=__webpack_exports__.ObservabilityModule,exports.Partner=__webpack_exports__.Partner,exports.PartnerApi=__webpack_exports__.PartnerApi,exports.Public=__webpack_exports__.Public,exports.RateLimit=__webpack_exports__.RateLimit,exports.RateLimitDecorator=__webpack_exports__.RateLimitDecorator,exports.RateLimitGuard=__webpack_exports__.RateLimitGuard,exports.RateLimitHeadersInterceptor=__webpack_exports__.RateLimitHeadersInterceptor,exports.RateLimitModule=__webpack_exports__.RateLimitModule,exports.RedisModule=__webpack_exports__.RedisModule,exports.RedisService=__webpack_exports__.RedisService,exports.SchedulerGuard=__webpack_exports__.SchedulerGuard,exports.SecretsModule=__webpack_exports__.SecretsModule,exports.SecretsService=__webpack_exports__.SecretsService,exports.createPrismaConnection=__webpack_exports__.createPrismaConnection,exports.filterForwardHeaders=__webpack_exports__.filterForwardHeaders,exports.generateSwaggerDocs=__webpack_exports__.generateSwaggerDocs,exports.loadEnvIfExists=__webpack_exports__.loadEnvIfExists,exports.startApp=__webpack_exports__.startApp,exports.startWorker=__webpack_exports__.startWorker,__webpack_exports__)-1===["AuthGuard","AuthModule","BaseServiceClient","BullConfigModule","EmailRateLimitDecorator","EmailRateLimitGuard","EmailRateLimitModule","IS_PARTNER_API_KEY","IS_PUBLIC_KEY","KongHeaders","LoggerService","MetricsService","NotificationModule","NotificationService","ObservabilityModule","Partner","PartnerApi","Public","RateLimit","RateLimitDecorator","RateLimitGuard","RateLimitHeadersInterceptor","RateLimitModule","RedisModule","RedisService","SchedulerGuard","SecretsModule","SecretsService","createPrismaConnection","filterForwardHeaders","generateSwaggerDocs","loadEnvIfExists","startApp","startWorker"].indexOf(__rspack_i)&&(exports[__rspack_i]=__webpack_exports__[__rspack_i]);Object.defineProperty(exports,"__esModule",{value:!0});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{Controller as e,ForbiddenException as t,Get as r,Global as i,HttpException as s,HttpStatus as o,Inject as n,Injectable as c,Logger as a,Module as l,Optional as u,Req as h,Res as d,Scope as f,SetMetadata as p,UnauthorizedException as g,ValidationPipe as m,VersioningType as y,applyDecorators as v,createParamDecorator as R}from"@nestjs/common";import{APP_INTERCEPTOR as E,NestFactory as S,Reflector as w}from"@nestjs/core";import{timingSafeEqual as b}from"crypto";import O,{existsSync as P,readFileSync as j,writeFileSync as _}from"fs";import N,{dirname as T,join as C}from"path";import{exec as I}from"child_process";import{promisify as A}from"util";import{SecretManagerServiceClient as x}from"@google-cloud/secret-manager";import{CreateSecretCommand as D,DeleteSecretCommand as M,DescribeSecretCommand as $,GetSecretValueCommand as L,ListSecretsCommand as F,PutSecretValueCommand as k,SecretsManagerClient as U}from"@aws-sdk/client-secrets-manager";import{SecretClient as V}from"@azure/keyvault-secrets";import{ClientSecretCredential as H}from"@azure/identity";import{ApiExcludeController as K,ApiSecurity as q,DocumentBuilder as G,SwaggerModule as z}from"@nestjs/swagger";import W from"ioredis";import{tap as J}from"rxjs/operators";import B from"helmet";import Y from"compression";import X from"express";import Z from"dotenv";import{createServer as Q}from"http";import ee from"pino";import{SpanKind as et,SpanStatusCode as er,context as ei,metrics as es,propagation as eo,trace as en}from"@opentelemetry/api";import{Resource as ec}from"@opentelemetry/resources";import{ATTR_HTTP_REQUEST_METHOD as ea,ATTR_HTTP_RESPONSE_STATUS_CODE as el,ATTR_HTTP_ROUTE as eu,ATTR_SERVICE_NAME as eh,ATTR_SERVICE_VERSION as ed,ATTR_URL_PATH as ef}from"@opentelemetry/semantic-conventions";import{PrometheusExporter as ep}from"@opentelemetry/exporter-prometheus";import{MeterProvider as eg}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor as em,NodeTracerProvider as ey}from"@opentelemetry/sdk-trace-node";import{OTLPTraceExporter as ev}from"@opentelemetry/exporter-trace-otlp-http";import{Pool as eR}from"pg";import{PrismaPg as eE}from"@prisma/adapter-pg";import{Resend as eS}from"resend";import{BullModule as ew}from"@nestjs/bullmq";import{OAuth2Client as eb}from"google-auth-library";let eO="isPublic",eP=()=>p(eO,!0);var ej,e_,eN,eT=((ej={}).CONSUMER_ID="x-consumer-id",ej.CONSUMER_USERNAME="x-consumer-username",ej.CREDENTIAL_IDENTIFIER="x-credential-identifier",ej.USERINFO="x-userinfo",ej.JWT_CLAIM_PREFIX="x-jwt-claim-",ej);let eC=A(I);class eI{constructor(e=".secrets.local.json",t=6e4){this.cache=new Map,this.serviceCache=new Map,this.secretsFilePath=this.findProjectRoot(e),this.cacheTtl=t,this.secrets=this.loadSecretsFile();let r=this.secrets.secrets;r&&r.NODE_ENV&&(process.env.NODE_ENV=r.NODE_ENV)}setServiceName(e){this.serviceName=e;let t=this.secrets[e];t&&t.DATABASE_URL&&(process.env.DATABASE_URL=t.DATABASE_URL)}findProjectRoot(e){let t=process.cwd(),r=0;for(;r<10;){let i=C(t,e);if(P(i))return i;let s=T(t);if(s===t)break;t=s,r++}return C(process.cwd(),e)}loadSecretsFile(){try{if(!P(this.secretsFilePath))throw Error(`Secrets file not found: ${this.secretsFilePath}
|
|
2
|
+
|
|
3
|
+
Please create .secrets.local.json in your project root.
|
|
4
|
+
See docs/secrets-management-strategy.md for details.`);let e=j(this.secretsFilePath,"utf-8"),t=JSON.parse(e);if("object"!=typeof t||null===t)throw Error(`Invalid secrets file format. Expected object, got ${typeof t}`);return t}catch(e){if(e instanceof SyntaxError)throw Error(`Failed to parse secrets file: ${this.secretsFilePath}
|
|
5
|
+
JSON syntax error: ${e.message}`);throw e}}async getAll(e){let t=this.secrets[e];if(!t)return{};if("object"!=typeof t)throw Error(`Invalid secrets format for "${e}". Expected object, got ${typeof t}`);let r={};for(let[i,s]of Object.entries(t))if("string"==typeof s)r[i]=s;else throw Error(`Invalid value for "${i}" in "${e}". Expected string, got ${typeof s}`);return r}getName(){return"local"}getSecretsFilePath(){return this.secretsFilePath}async get(e){let t,r=this.cache.get(e);if(r&&Date.now()<r.expiresAt)return r.value;if(this.secrets=this.loadSecretsFile(),this.serviceName){let r=this.secrets[this.serviceName];r&&"string"==typeof r[e]&&(t=r[e])}if(!t){let r=this.secrets.secrets;r&&"string"==typeof r[e]&&(t=r[e])}if(!t)throw Error(`Secret "${e}" not found. `+(this.serviceName?`Searched in service "${this.serviceName}" and top-level secrets.`:"Searched in top-level secrets only. Use setServiceName() to search in a specific service."));return this.cache.set(e,{value:t,expiresAt:Date.now()+this.cacheTtl}),t}async set(e,t){let r=T(this.secretsFilePath),i=C(r,".secrets.user.json"),s={};P(i)&&(s=JSON.parse(j(i,"utf-8"))),s.secrets||(s.secrets={}),s.secrets[e]=t,_(i,JSON.stringify(s,null,2),"utf-8");try{await eC("npx tsdevstack generate-secrets",{cwd:r})}catch{throw Error(`Failed to regenerate secrets after setting "${e}". Manual regeneration may be required: npx tsdevstack generate-secrets`)}this.clearCache()}async delete(e){let t=T(this.secretsFilePath),r=C(t,".secrets.user.json");if(!P(r))throw Error(`Cannot delete secret: .secrets.user.json not found at ${r}`);let i=JSON.parse(j(r,"utf-8"));if(i.secrets&&i.secrets[e]){delete i.secrets[e],_(r,JSON.stringify(i,null,2),"utf-8");try{await eC("npx tsdevstack generate-secrets",{cwd:t})}catch{throw Error(`Failed to regenerate secrets after deleting "${e}". Manual regeneration may be required: npx tsdevstack generate-secrets`)}this.clearCache()}else throw Error(`Secret "${e}" not found in .secrets.user.json`)}clearCache(){this.cache.clear(),this.serviceCache.clear()}}class eA{constructor(e){if(this.logger=new a("GCPSecretsProvider"),this.cache=new Map,this.CACHE_TTL_MS=3e5,console.log("[GCP] Constructor start"),this.projectName=e.projectName,this.serviceName=e.serviceName,this.gcpProjectId=process.env.GCP_PROJECT_ID||e.providerConfig?.projectId,!this.gcpProjectId)throw Error("GCP_PROJECT_ID environment variable is required for GCP secrets provider");console.log(`[GCP] Initializing for project: ${this.gcpProjectId}, service: ${this.serviceName}`),console.log("[GCP] Creating SecretManagerServiceClient..."),this.client=new x,console.log("[GCP] SecretManagerServiceClient created")}async get(e){console.log(`[GCP] get() called for: ${e}`);let t=this.getFromCache(e);if(null!==t)return this.logger.debug(`Cache hit for: ${e}`),t;let r=null;if("API_KEY"===e){let e=`${this.serviceName.toUpperCase().replace(/-/g,"_")}_API_KEY`,t=this.buildSecretName(e,"shared");r=await this.fetchSecretFromGCP(t)}else{let t=this.buildSecretName(e,this.serviceName);if(null===(r=await this.fetchSecretFromGCP(t))){let t=this.buildSecretName(e,"shared");r=await this.fetchSecretFromGCP(t)}}return null!==r?(this.logger.debug(`Secret found: ${e}`),this.setCache(e,r)):this.logger.warn(`Secret not found: ${e}`),r}async set(e,t,r){let i=this.buildSecretName(e,this.serviceName),s=`projects/${this.gcpProjectId}`,o=this.extractSecretId(i);try{await this.exists(e)||await this.client.createSecret({parent:s,secretId:o,secret:{replication:{automatic:{}},labels:this.buildLabels(r)}}),await this.client.addSecretVersion({parent:`${s}/secrets/${o}`,payload:{data:Buffer.from(t,"utf8")}}),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${i} in GCP: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName),r=`projects/${this.gcpProjectId}`,i=this.extractSecretId(t);try{await this.client.deleteSecret({name:`${r}/secrets/${i}`}),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from GCP: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e=`projects/${this.gcpProjectId}`,t=[];try{let[r]=await this.client.listSecrets({parent:e,filter:`labels.project-name=${this.projectName}`});for(let e of r)if(e.name){let r=e.name.split("/").pop();if(r){let e=this.extractKeyFromSecretId(r);t.push(e)}}return t}catch(e){throw Error(`Failed to list secrets from GCP: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=`projects/${this.gcpProjectId}`,r=this.buildSecretName(e,this.serviceName),i=this.extractSecretId(r);try{return await this.client.getSecret({name:`${t}/secrets/${i}`}),!0}catch{}let s=this.buildSecretName(e,"shared"),o=this.extractSecretId(s);try{return await this.client.getSecret({name:`${t}/secrets/${o}`}),!0}catch{return!1}}getProviderName(){return"gcp"}buildSecretName(e,t){return`${this.projectName}-${t}-${e}`}extractSecretId(e){return e}extractKeyFromSecretId(e){return e.split("-").slice(2).join("-")}async fetchSecretFromGCP(e){let t=`projects/${this.gcpProjectId}`,r=this.extractSecretId(e),i=`${t}/secrets/${r}/versions/latest`;console.log(`[GCP] Fetching: ${r}`);try{let[e]=await this.client.accessSecretVersion({name:i});if(console.log(`[GCP] Fetched: ${r}`),!e.payload?.data)return null;return e.payload.data.toString()}catch(i){let e=i?.code;if(console.log(`[GCP] Error for ${r}: code=${e}`),5===e)return null;let t=i instanceof Error?i.message:String(i);return console.error(`[GCP] Failed: ${r}: ${t}`),null}}buildLabels(e){let t={"project-name":this.projectName,"service-name":this.serviceName,"managed-by":"tsdevstack"};if(e)for(let[r,i]of Object.entries(e))t[r.toLowerCase().replace(/[^a-z0-9-_]/g,"-").replace(/^[^a-z]/,"x")]=i;return t}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.isUrlValue(t)||this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}isUrlValue(e){return e.startsWith("https://")||e.startsWith("http://")}invalidateCache(e){this.cache.delete(e)}}class ex{constructor(e){this.cache=new Map,this.CACHE_TTL_MS=3e5,this.projectName=e.projectName,this.serviceName=e.serviceName,this.region=e.providerConfig?.region||"us-east-1",this.client=new U({region:this.region})}async get(e){let t=this.getFromCache(e);if(null!==t)return t;let r=this.buildSecretName(e,this.serviceName),i=await this.fetchSecretFromAWS(r);if(null===i){let t=this.buildSecretName(e,"shared");i=await this.fetchSecretFromAWS(t)}return null!==i&&this.setCache(e,i),i}async set(e,t,r){let i=this.buildSecretName(e,this.serviceName);try{await this.exists(e)?await this.client.send(new k({SecretId:i,SecretString:t})):await this.client.send(new D({Name:i,SecretString:t,Tags:this.buildTags(r)})),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${i} in AWS: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName);try{await this.client.send(new M({SecretId:t,ForceDeleteWithoutRecovery:!1,RecoveryWindowInDays:7})),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from AWS: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e,t=[];try{do{let r=await this.client.send(new F({Filters:[{Key:"tag-key",Values:["project-name"]},{Key:"tag-value",Values:[this.projectName]}],NextToken:e}));if(r.SecretList){for(let e of r.SecretList)if(e.Name){let r=this.extractKeyFromSecretName(e.Name);t.push(r)}}e=r.NextToken}while(e);return t}catch(e){throw Error(`Failed to list secrets from AWS: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=this.buildSecretName(e,this.serviceName);try{return await this.client.send(new $({SecretId:t})),!0}catch{}let r=this.buildSecretName(e,"shared");try{return await this.client.send(new $({SecretId:r})),!0}catch{return!1}}getProviderName(){return"aws"}buildSecretName(e,t){return`${this.projectName}-${t}-${e}`}extractKeyFromSecretName(e){let t=e.substring(this.projectName.length+1);if(t.startsWith(`${this.serviceName}-`))return t.substring(this.serviceName.length+1);if(t.startsWith("shared-"))return t.substring(7);let r=t.indexOf("-");return r>=0?t.substring(r+1):t}async fetchSecretFromAWS(e){try{return(await this.client.send(new L({SecretId:e}))).SecretString||null}catch{return null}}buildTags(e){let t=[{Key:"project-name",Value:this.projectName},{Key:"service-name",Value:this.serviceName},{Key:"managed-by",Value:"tsdevstack"}];if(e)for(let[r,i]of Object.entries(e))t.push({Key:r,Value:i});return t}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}invalidateCache(e){this.cache.delete(e)}}class eD{constructor(e){if(this.cache=new Map,this.CACHE_TTL_MS=3e5,this.projectName=e.projectName,this.serviceName=e.serviceName,this.keyVaultName=process.env.AZURE_KEYVAULT_NAME||e.providerConfig?.keyVaultName||"",!this.keyVaultName)throw Error("Azure Key Vault name is required. Set AZURE_KEYVAULT_NAME environment variable.");let t=process.env.AZURE_TENANT_ID,r=process.env.AZURE_CLIENT_ID,i=process.env.AZURE_CLIENT_SECRET;if(!t||!r||!i)throw Error("Azure credentials are required. Set AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET environment variables.");let s=new H(t,r,i),o=`https://${this.keyVaultName}.vault.azure.net`;this.client=new V(o,s)}async get(e){let t=this.getFromCache(e);if(null!==t)return t;let r=this.buildSecretName(e,this.serviceName),i=await this.fetchSecretFromAzure(r);if(null===i){let t=this.buildSecretName(e,"shared");i=await this.fetchSecretFromAzure(t)}return null!==i&&this.setCache(e,i),i}async set(e,t,r){let i=this.buildSecretName(e,this.serviceName);try{let s=this.buildTags(r);await this.client.setSecret(i,t,{tags:s}),this.invalidateCache(e)}catch(e){throw Error(`Failed to set secret ${i} in Azure: ${e instanceof Error?e.message:String(e)}`)}}async remove(e){let t=this.buildSecretName(e,this.serviceName);try{let r=await this.client.beginDeleteSecret(t);await r.pollUntilDone(),this.invalidateCache(e)}catch(e){throw Error(`Failed to remove secret ${t} from Azure: ${e instanceof Error?e.message:String(e)}`)}}async list(){let e=[];try{for await(let t of this.client.listPropertiesOfSecrets())if(t.tags?.["project-name"]===this.projectName){let r=this.extractKeyFromSecretName(t.name);e.push(r)}return e}catch(e){throw Error(`Failed to list secrets from Azure: ${e instanceof Error?e.message:String(e)}`)}}async exists(e){let t=this.buildSecretName(e,this.serviceName);try{return await this.client.getSecret(t),!0}catch{}let r=this.buildSecretName(e,"shared");try{return await this.client.getSecret(r),!0}catch{return!1}}getProviderName(){return"azure"}buildSecretName(e,t){let r=this.transformKey(e);return`${this.projectName}-${t}-${r}`}extractKeyFromSecretName(e){let t,r=e.substring(this.projectName.length+1);if(r.startsWith(`${this.serviceName}-`))t=r.substring(this.serviceName.length+1);else if(r.startsWith("shared-"))t=r.substring(7);else{let e=r.indexOf("-");t=e>=0?r.substring(e+1):r}return this.reverseTransformKey(t)}async fetchSecretFromAzure(e){try{return(await this.client.getSecret(e)).value||null}catch{return null}}buildTags(e){let t={"project-name":this.projectName,"service-name":this.serviceName,"managed-by":"tsdevstack"};if(e)for(let[r,i]of Object.entries(e))t[r]=i;return t}transformKey(e){return e.replace(/_/g,"-")}reverseTransformKey(e){return e.replace(/-/g,"_")}getFromCache(e){let t=this.cache.get(e);return t?Date.now()>t.expiresAt?(this.cache.delete(e),null):t.value:null}setCache(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.CACHE_TTL_MS})}invalidateCache(e){this.cache.delete(e)}}class eM{static createProvider(e){let t=this.getProviderType();if("local"===t)return null;let r=this.getProjectName();this.validateProviderEnvVars(t);let i={projectName:r,serviceName:e,providerConfig:{}};switch(t){case"gcp":return new eA(i);case"aws":return new ex(i);case"azure":return new eD(i);default:throw Error(`Unknown secrets provider type: ${t}`)}}static getProviderType(){let e=process.env.SECRETS_PROVIDER?.toLowerCase();if(!e)return"local";if(!["local","gcp","aws","azure"].includes(e))throw Error(`Invalid SECRETS_PROVIDER: ${e}. Must be one of: local, gcp, aws, azure`);return e}static getProjectName(){let e=process.env.PROJECT_NAME;if(!e)throw Error("PROJECT_NAME environment variable is required for cloud secrets providers. Set it in your deployment configuration or .env file.");return e}static validateProviderEnvVars(e){let t=[];switch(e){case"gcp":process.env.GCP_PROJECT_ID||t.push("GCP_PROJECT_ID"),process.env.K_SERVICE||process.env.GOOGLE_APPLICATION_CREDENTIALS||t.push("GOOGLE_APPLICATION_CREDENTIALS");break;case"aws":process.env.AWS_REGION||t.push("AWS_REGION"),process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI||process.env.AWS_ACCESS_KEY_ID||t.push("AWS_ACCESS_KEY_ID"),process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI||process.env.AWS_SECRET_ACCESS_KEY||t.push("AWS_SECRET_ACCESS_KEY");break;case"azure":process.env.AZURE_CLIENT_ID||t.push("AZURE_CLIENT_ID"),process.env.AZURE_CLIENT_SECRET||t.push("AZURE_CLIENT_SECRET"),process.env.AZURE_TENANT_ID||t.push("AZURE_TENANT_ID"),process.env.AZURE_KEYVAULT_NAME||t.push("AZURE_KEYVAULT_NAME")}if(t.length>0)throw Error(`Missing required environment variables for ${e.toUpperCase()}: ${t.join(", ")}. Set these in your deployment configuration or .env file.`)}}class e${constructor(e,t){this.cloudProvider=e,this.serviceName=t}async get(e){let t=await this.cloudProvider.get(e);if(null===t)throw Error(`Secret "${e}" not found in ${this.cloudProvider.getProviderName()} for service "${this.serviceName}" or shared scope.`);return t}async getAll(){let e=await this.cloudProvider.list(),t={};for(let r of e)try{let e=await this.cloudProvider.get(r);null!==e&&(t[r]=e)}catch{continue}return t}async set(e,t){await this.cloudProvider.set(e,t,{"secret-type":"user","managed-by":"tsdevstack"})}async delete(e){await this.cloudProvider.remove(e)}getName(){return this.cloudProvider.getProviderName()}clearCache(){}}function eL(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class eF{constructor(e){this.config=e,this.provider=this.config.forceProvider||this.detectProvider(),"setServiceName"in this.provider&&"function"==typeof this.provider.setServiceName&&this.provider.setServiceName(this.config.serviceName)}getProvider(){return this.provider}async get(e){return this.provider.get(e)}async set(e,t){await this.provider.set(e,t)}async delete(e){await this.provider.delete(e)}clearCache(){this.provider.clearCache()}detectProvider(){let e=process.env.SECRETS_PROVIDER;if(!e)throw Error("SECRETS_PROVIDER environment variable is required.\nSet it to: local, aws, gcp, or azure\nFor local development, tsdevstack automatically sets this in .env file.");if("local"===e){let e=new eI(".secrets.local.json");return e.setServiceName(this.config.serviceName),e}let t=eM.createProvider(this.config.serviceName);if(!t){let e=new eI(".secrets.local.json");return e.setServiceName(this.config.serviceName),e}return new e$(t,this.config.serviceName)}}function ek(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}eF=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),eL("design:type",Function),eL("design:paramtypes",["u"<typeof SecretsConfig?Object:SecretsConfig])],eF);class eU{constructor(e,t){this.reflector=e,this.secrets=t,this.logger=new a(eU.name)}async canActivate(e){let t=e.switchToHttp().getRequest(),r=t.headers["x-api-key"],i=!!t.headers["x-kong-trust"];if(i?await this.verifyKongTrustHeader(t):r&&await this.validateServiceApiKey(t,r),this.reflector.getAllAndOverride(eO,[e.getHandler(),e.getClass()]))return!0;let s=t.headers[eT.CONSUMER_ID],o=t.headers[eT.CONSUMER_USERNAME],n=t.headers[eT.CREDENTIAL_IDENTIFIER],c=t.headers[eT.USERINFO];if(s||o||n||c)return s||n||c?t.user=this.extractUserFromHeaders(t.headers):o&&(t.service=o),!0;if(i&&r)return t.service="partner",!0;if(r)return!0;throw new g("No authentication provided")}extractUserFromHeaders(e){let t=e[eT.USERINFO];if(t)try{let e=Buffer.from(t,"base64").toString("utf-8"),r=JSON.parse(e),i={id:r.sub};return Object.keys(r).forEach(e=>{"sub"!==e&&(i[e]=r[e])}),i}catch(e){console.error("Failed to parse X-Userinfo header:",e)}let r={id:e[eT.CONSUMER_ID]||e[eT.CREDENTIAL_IDENTIFIER]};return Object.keys(e).forEach(t=>{if(t.startsWith(eT.JWT_CLAIM_PREFIX)){let i=t.replace(eT.JWT_CLAIM_PREFIX,"");r[this.toCamelCase(i)]=this.parseValue(e[t])}}),r}toCamelCase(e){return e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}parseValue(e){return e.includes(",")?e.split(",").map(e=>e.trim()):/^\d+$/.test(e)?parseInt(e,10):"true"===e||"false"!==e&&e}async verifyKongTrustHeader(e){let t=e.url||e.path;if(t&&(t.includes("/.well-known/")||"/health"===t||t.startsWith("/health/")||"/metrics"===t))return void this.logger.debug(`Skipping Kong trust check for infrastructure endpoint: ${t}`);let r=e.headers["x-kong-trust"];if(!r)throw this.logger.warn("Missing Kong trust header - request did not come through gateway"),new g("Unauthorized request");let i=await this.secrets.get("KONG_TRUST_TOKEN");if(!i)throw this.logger.error("KONG_TRUST_TOKEN not configured in secrets"),new g("Authentication configuration error");let s=Buffer.from(r),o=Buffer.from(i);if(s.length!==o.length||!b(s,o))throw this.logger.warn("Invalid Kong trust header - possible bypass attempt"),new g("Unauthorized request");this.logger.debug("Kong trust header verified")}async validateServiceApiKey(e,r){let i={type:"service-to-service",method:e.method||"UNKNOWN",path:e.url||e.path||"UNKNOWN",caller:e.headers["x-service-name"]||"unknown",keyFingerprint:r.slice(0,8)+"..."},s=await this.secrets.get("API_KEY");if(!s)throw this.logger.error("API_KEY not configured in secrets"),new g("Server API key is not configured");let o=Buffer.from(r),n=Buffer.from(s);if(o.length!==n.length||!b(o,n))throw this.logger.warn("Invalid service API key attempt",i),new t("Invalid API key");return e.service=e.headers["x-service-name"]||"internal",this.logger.log("Service-to-service request authenticated",i),!0}}eU=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),ek("design:type",Function),ek("design:paramtypes",[void 0===w?Object:w,void 0===eF?Object:eF])],eU);class eV{}eV=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({providers:[{provide:eF,useFactory:()=>{let e=process.env.SERVICE_NAME;if(!e)throw Error("SERVICE_NAME environment variable is required. This should be set automatically by startApp() during bootstrap.");return new eF({serviceName:e})}}],exports:[eF]})],eV);class eH{}eH=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({imports:[eV],providers:[eU],exports:[eU]})],eH);let eK="isPartnerApi",eq=()=>v(p(eK,!0),q("api-key")),eG=R((e,t)=>t.switchToHttp().getRequest().headers["x-consumer-username"]);function ez(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class eW{constructor(e){this.secrets=e,this.logger=new a(eW.name)}async onModuleInit(){try{let e=await this.secrets.get("REDIS_HOST"),t=parseInt(await this.secrets.get("REDIS_PORT"),10)||6379,r=await this.secrets.get("REDIS_PASSWORD"),i=await this.secrets.get("REDIS_TLS");this.redis=new W({host:e,port:t,password:r,..."true"===i&&{tls:{}},maxRetriesPerRequest:3,enableReadyCheck:!0,enableOfflineQueue:!1,lazyConnect:!0,keepAlive:3e4,connectTimeout:1e4,retryStrategy:e=>e>3?(this.logger.error("Max connection retries exceeded"),null):Math.min(50*e,2e3)}),this.redis.on("connect",()=>{this.logger.log("Connected to Redis")}),this.redis.on("error",e=>{this.logger.error("Redis connection error:",e)}),await this.redis.connect()}catch(e){throw this.logger.error("Failed to connect to Redis on startup",e),e}}getClient(){return this.redis}async get(e){try{return await this.redis.get(e)}catch(t){return this.logger.error(`Error getting key ${e}:`,t),null}}async set(e,t,r){try{return r?await this.redis.setex(e,r,t):await this.redis.set(e,t),!0}catch(t){return this.logger.error(`Error setting key ${e}:`,t),!1}}async incr(e){try{return await this.redis.incr(e)}catch(t){return this.logger.error(`Error incrementing key ${e}:`,t),null}}async expire(e,t){try{let r=await this.redis.expire(e,t);return 1===r}catch(t){return this.logger.error(`Error setting expiry for key ${e}:`,t),!1}}async del(e){try{return await this.redis.del(e)>0}catch(t){return this.logger.error(`Error deleting key ${e}:`,t),!1}}onModuleDestroy(){this.redis.disconnect()}}eW=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),ez("design:type",Function),ez("design:paramtypes",[void 0===eF?Object:eF])],eW);class eJ{}eJ=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({providers:[eW],exports:[eW]})],eJ);let eB="rateLimit",eY=e=>p(eB,e);function eX(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class eZ{constructor(e,t){this.redisService=e,this.reflector=t,this.logger=new a(eZ.name)}async canActivate(e){let t=this.reflector.getAllAndOverride(eB,[e.getHandler(),e.getClass()]);if(!t||t.skipIf&&t.skipIf(e))return!0;let r=e.switchToHttp().getRequest(),i=await this.checkRateLimit(e,t);if(!i.success){let e=t.message||"Too many requests";throw new s({statusCode:o.TOO_MANY_REQUESTS,message:e,error:"Too Many Requests",limit:i.limit,remaining:i.remaining,reset:i.reset},o.TOO_MANY_REQUESTS)}return r.rateLimit={limit:i.limit,remaining:i.remaining,reset:i.reset},!0}async checkRateLimit(e,t){let{windowMs:r=9e5,maxRequests:i=100}=t,s=this.generateKey(e,t),o=Math.floor(Date.now()/r),n=`rate_limit:${s}:${o}`;try{let e=this.redisService.getClient(),t=await e.incr(n);1===t&&await e.expire(n,Math.ceil(r/1e3));let s=Math.max(0,i-t);return{success:t<=i,limit:i,remaining:s,reset:(o+1)*r,current:t}}catch(e){return this.logger.error("Rate limit check failed:",e),{success:!0,limit:i,remaining:i,reset:Date.now()+r,current:0}}}generateKey(e,t){let r=e.switchToHttp().getRequest();if(t.customKeyGenerator)return t.customKeyGenerator(e);let i=r.headers["x-api-key"],s=Array.isArray(i)?i[0]:i,o=r.user?.id||r.user?.sub;switch(t.keyGenerator){case"ip":default:return this.getClientIp(r);case"apiKey":if(!s)throw new g("API key required for this endpoint");return`api:${s}`;case"userId":if(!o)throw new g("User authentication required for this endpoint");return`user:${o}`}}getClientIp(e){let t=e.headers["x-forwarded-for"]?.toString().split(",")[0]||e.headers["x-real-ip"]?.toString()||e.socket?.remoteAddress||"unknown";return`ip:${t.trim()}`}}eZ=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),eX("design:type",Function),eX("design:paramtypes",[void 0===eW?Object:eW,void 0===w?Object:w])],eZ);class eQ{}eQ=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({imports:[eJ],providers:[eZ],exports:[eZ]})],eQ);class e0{intercept(e,t){return t.handle().pipe(J(()=>{let t=e.switchToHttp().getRequest(),r=e.switchToHttp().getResponse();t.rateLimit&&(r.setHeader("X-RateLimit-Limit",t.rateLimit.limit.toString()),r.setHeader("X-RateLimit-Remaining",t.rateLimit.remaining.toString()),r.setHeader("X-RateLimit-Reset",t.rateLimit.reset.toString()))}))}}e0=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c()],e0);let e3="emailRateLimit",e1=e=>p(e3,e);function e4(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}class e2{constructor(e,t){this.redisService=e,this.reflector=t,this.logger=new a(e2.name)}async canActivate(e){let t=this.reflector.get(e3,e.getHandler());if(!t)return!0;let r=e.switchToHttp().getRequest(),i=await this.checkEmailRateLimit(r,t);if(!i.success){let e=t.message||"Too many requests for this email address";throw new s({statusCode:o.TOO_MANY_REQUESTS,message:e,error:"Email Rate Limit Exceeded",limit:i.limit,remaining:i.remaining,reset:i.reset},o.TOO_MANY_REQUESTS)}return!0}async checkEmailRateLimit(e,t){let{windowMs:r=9e5,maxRequests:i=5,emailField:s="email"}=t,o=e.body,n=o?.[s];if(!n||"string"!=typeof n)return{success:!0,limit:i,remaining:i,reset:Date.now()+r,current:0};let c=n.toLowerCase().trim(),a=Math.floor(Date.now()/r),l=`email_rate_limit:${c}:${a}`;try{let e=this.redisService.getClient(),t=await e.incr(l);1===t&&await e.expire(l,Math.ceil(r/1e3));let s=Math.max(0,i-t);return{success:t<=i,limit:i,remaining:s,reset:(a+1)*r,current:t}}catch(e){return this.logger.error("Email rate limit check failed:",e),{success:!0,limit:i,remaining:i,reset:Date.now()+r,current:0}}}}e2=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),e4("design:type",Function),e4("design:paramtypes",[void 0===eW?Object:eW,void 0===w?Object:w])],e2);class e8{}function e5(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}e8=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({imports:[eJ],providers:[e2],exports:[e2]})],e8);class e9{constructor(){this.logger=new a(this.constructor.name)}initialize(e){try{if(!e.baseURL)throw Error("Service base URL is required");if(!e.apiKey)throw Error("Service API key is required");this.client=e.createClient(e.baseURL,e.apiKey),this.logger.log(`Service client initialized: ${e.baseURL}`)}catch(e){throw this.logger.error(`Failed to initialize service client: ${e instanceof Error?e.message:"Unknown error"}`),e}}}e9=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),e5("design:type",Function),e5("design:paramtypes",[])],e9);let e7=new Set(["connection","keep-alive","transfer-encoding","upgrade","host","content-length","content-encoding","proxy-authenticate","proxy-authorization","te","trailer"]);function e6(e){let t={};for(let[r,i]of Object.entries(e)){let e=r.toLowerCase();e7.has(e)||"string"==typeof i&&(t[r]=i)}return t}function te(e,t){let r=new G().setTitle(t.title).setDescription(t.description).setVersion(t.version||"1.0.0").addBearerAuth({type:"http",scheme:"bearer",bearerFormat:"JWT"},"bearer").addApiKey({type:"apiKey",in:"header",name:"x-api-key"},"api-key");return t.tags&&t.tags.forEach(e=>{r.addTag(e)}),z.createDocument(e,r.build())}function tt(e){let t,r=function(){let e=process.cwd(),t=0;for(;t<10;){let r=C(e,".tsdevstack","config.json");if(P(r))return r;let i=T(e);if(i===e)break;e=i,t++}return null}();if(!r)throw Error("Framework configuration not found.\nExpected .tsdevstack/config.json in project root.\nPlease ensure the file exists.");try{let e=j(r,"utf-8");t=JSON.parse(e)}catch(e){throw Error(`Failed to read framework configuration: ${r}
|
|
6
|
+
Error: ${e instanceof Error?e.message:String(e)}`)}if(!t.services||!Array.isArray(t.services))throw Error('Invalid framework configuration.\nExpected "services" array in .tsdevstack/config.json');let i=t.services.find(t=>t.name===e);if(!i){let r=t.services.map(e=>e.name).join(", ");throw Error(`Service "${e}" not found in framework configuration.
|
|
7
|
+
Available services: ${r}
|
|
8
|
+
Please add the service to .tsdevstack/config.json`)}return{serviceName:i.name,type:i.type,port:i.port,globalPrefix:i.globalPrefix,hasDatabase:i.hasDatabase,databaseType:i.databaseType}}function tr(){let e=C(process.cwd(),"package.json");if(!P(e))throw Error(`package.json not found at ${e}
|
|
9
|
+
Ensure the service is started from its directory (e.g., apps/auth-service/)`);try{let t=j(e,"utf-8");return JSON.parse(t)}catch(e){throw Error(`Failed to parse package.json: ${e instanceof Error?e.message:String(e)}`)}}function ti(e){return e.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}async function ts(e,t){let{globalPrefix:r,jsonLimit:i=1,urlLimit:s=1,enableShutdownHooks:o=!0,swagger:n}=t,c=await S.create(e);if(c.setGlobalPrefix(r,{exclude:["health","health/ping","metrics"]}),c.enableVersioning({type:y.URI,prefix:"v"}),c.use(B({crossOriginEmbedderPolicy:!1,contentSecurityPolicy:{directives:{defaultSrc:["'self'"],styleSrc:["'self'","'unsafe-inline'"],scriptSrc:["'self'"],imgSrc:["'self'","data:","https:"]}}})),c.use(Y()),c.use(X.json({limit:`${i}mb`})),c.use(X.urlencoded({limit:`${s}mb`,extended:!0})),c.useGlobalPipes(new m({transform:!0,whitelist:!0,forbidNonWhitelisted:!0,disableErrorMessages:"production"===process.env.NODE_ENV,transformOptions:{enableImplicitConversion:!0}})),o&&c.enableShutdownHooks(),"production"!==process.env.NODE_ENV){let e=te(c,{...n,globalPrefix:r});z.setup("api",c,e)}return c}function to(){if(process.env.SECRETS_PROVIDER)return;let e=process.cwd(),t=0;for(;t<10;){let r=N.join(e,".env");if(O.existsSync(r)&&O.readFileSync(r,"utf-8").includes("SECRETS_PROVIDER="))return void Z.config({path:r});let i=N.dirname(e);if(i===e)break;e=i,t++}}async function tn(e,t){to();let r=tr(),i=r.name;process.env.SERVICE_NAME=i;let s=tt(i);console.log(`📋 Loaded framework config for ${i}`);let o=t?.swagger||{title:ti(i),description:r.description||"",version:r.version||"1.0.0"},n={port:process.env.PORT?parseInt(process.env.PORT,10):s.port,globalPrefix:s.globalPrefix,swagger:o,jsonLimit:t?.jsonLimit,urlLimit:t?.urlLimit,enableShutdownHooks:t?.enableShutdownHooks},c=await ts(e,n);await c.listen(n.port,"0.0.0.0")}async function tc(e,t){let r=t?.healthPort??8080,i=new a("Worker");to();let s=tr().name;process.env.SERVICE_NAME=s,i.log(`Starting worker for ${s}`);let o=await S.createApplicationContext(e),n=Q((e,t)=>{"/health"===e.url?(t.writeHead(200),t.end("OK")):(t.writeHead(404),t.end())});n.listen(r),i.log(`Worker started, health on :${r}`);let c=async e=>{i.log(`${e} received, shutting down...`);let t=setTimeout(()=>{i.error("Shutdown timeout, forcing exit"),process.exit(1)},9e3);try{n.close(),await o.close(),clearTimeout(t),process.exit(0)}catch(e){i.error("Shutdown error",e),process.exit(1)}};process.on("SIGTERM",()=>void c("SIGTERM")),process.on("SIGINT",()=>void c("SIGINT"))}async function ta(e){to();let t=tr(),r=t.name;process.env.SERVICE_NAME=r;let i=tt(r),s=await S.create(e,{logger:["error","warn"],preview:!0,abortOnError:!1});s.setGlobalPrefix(i.globalPrefix),s.enableVersioning({type:y.URI,prefix:"v"});let o=te(s,{title:ti(r),description:t.description||"",version:t.version||"1.0.0",globalPrefix:i.globalPrefix});return await s.close(),o}let tl=["password","*.password","email","*.email","ssn","*.ssn","creditCard","*.creditCard","token","*.token","secret","*.secret","apiKey","*.apiKey"];function tu(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function th(e,t){return function(r,i){t(r,i,e)}}class td{constructor(e){this.options=e||{};let t=this.options.level||process.env.LOG_LEVEL||"info",r="production"!==process.env.NODE_ENV,i=this.buildRedactPaths(),s={level:t,formatters:{level:e=>({level:e})},base:{service:process.env.SERVICE_NAME||"unknown"},timestamp:ee.stdTimeFunctions.isoTime,...i.length>0&&{redact:{paths:i,censor:this.options.redactCensor||"[REDACTED]"}}};r?this.logger=ee({...s,transport:{target:"pino-pretty",options:{colorize:!0,translateTime:"SYS:standard",ignore:"pid,hostname"}}}):this.logger=ee(s)}buildRedactPaths(){let e=[];this.options.disableDefaultRedaction||e.push(...tl),this.options.redactPaths&&e.push(...this.options.redactPaths);let t=process.env.LOG_REDACT_PATHS;return t&&e.push(...t.split(",").map(e=>e.trim())),[...new Set(e)]}setContext(e){this.context=e}setCorrelationId(e){this.correlationId=e}getTraceContext(){let e=en.getActiveSpan();if(!e)return{};let t=e.spanContext();return{trace_id:t.traceId,span_id:t.spanId}}formatMessage(e,t){let r=this.getTraceContext();return{...this.context&&{context:this.context},...r,...this.correlationId&&!r.trace_id&&{correlationId:this.correlationId},msg:e,...t}}debug(e,t){this.logger.debug(this.formatMessage(e,t))}info(e,t){this.logger.info(this.formatMessage(e,t))}warn(e,t){this.logger.warn(this.formatMessage(e,t))}error(e,t,r){let i={...r};t instanceof Error?i.error={name:t.name,message:t.message,stack:t.stack}:void 0!==t&&(i.error=t),this.logger.error(this.formatMessage(e,i))}child(e){let t=new td(this.options);return t.setContext(e),this.correlationId&&t.setCorrelationId(this.correlationId),t}}td=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c({scope:f.DEFAULT}),th(0,u()),th(0,n("LOGGER_MODULE_OPTIONS")),tu("design:type",Function),tu("design:paramtypes",["u"<typeof LoggerModuleOptions?Object:LoggerModuleOptions])],td);class tf{static forRoot(e={}){return{module:tf,global:!0,providers:[{provide:"LOGGER_MODULE_OPTIONS",useValue:e},td],exports:[td]}}}function tp(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tf=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({providers:[{provide:"LOGGER_MODULE_OPTIONS",useValue:{}},td],exports:[td]})],tf);class tg{constructor(e){this.logger=e.child("HTTP")}intercept(e,t){let r=e.switchToHttp().getRequest(),i=e.switchToHttp().getResponse(),s=r.headers["x-request-id"]||r.headers["x-correlation-id"]||crypto.randomUUID();r.correlationId=s,i.setHeader("X-Correlation-ID",s);let{method:o,url:n,ip:c}=r,a=r.get("user-agent")||"",l=Date.now();return this.logger.debug("Incoming request",{method:o,url:n,ip:c,userAgent:a}),t.handle().pipe(J({next:()=>{let e=Date.now()-l,t=i.statusCode;this.logger.info("Request completed",{method:o,url:n,statusCode:t,duration:e})},error:e=>{let t=Date.now()-l,r=i.statusCode||500;this.logger.error("Request failed",e,{method:o,url:n,statusCode:r,duration:t})}}))}}function tm(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tg=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tp("design:type",Function),tp("design:paramtypes",[void 0===td?Object:td])],tg);class ty{constructor(e){this.meterProvider=null,this.prometheusExporter=null,this.tracerProvider=null,this.serviceName=e.serviceName||process.env.SERVICE_NAME||"unknown-service",this.serviceVersion=e.serviceVersion||"1.0.0",this.metricsEnabled=!1!==e.metrics,this.tracingEnabled=!1!==e.tracing,this.tracingEndpoint=e.tracingEndpoint||process.env.OTEL_EXPORTER_OTLP_ENDPOINT||"http://localhost:4318"}onModuleInit(){let e=new ec({[eh]:this.serviceName,[ed]:this.serviceVersion});this.metricsEnabled&&this.initializeMetrics(e),this.tracingEnabled&&this.initializeTracing(e)}initializeMetrics(e){this.prometheusExporter=new ep({preventServerStart:!0}),this.meterProvider=new eg({resource:e,readers:[this.prometheusExporter]}),es.setGlobalMeterProvider(this.meterProvider)}initializeTracing(e){let t=new ev({url:`${this.tracingEndpoint}/v1/traces`});this.tracerProvider=new ey({resource:e,spanProcessors:[new em(t)]}),this.tracerProvider.register()}async onModuleDestroy(){let e=[];this.tracerProvider&&e.push(this.tracerProvider.shutdown()),this.meterProvider&&e.push(this.meterProvider.shutdown()),await Promise.all(e)}getMeter(e){return es.getMeter(e||this.serviceName)}getTracer(e){return en.getTracer(e||this.serviceName)}getServiceName(){return this.serviceName}isTracingEnabled(){return this.tracingEnabled}getPrometheusExporter(){return this.prometheusExporter}}ty=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),(e_=n("TELEMETRY_MODULE_OPTIONS"),function(e,t){e_(e,t,0)}),tm("design:type",Function),tm("design:paramtypes",["u"<typeof TelemetryModuleOptions?Object:TelemetryModuleOptions])],ty);class tv{static forRoot(e={}){return{module:tv,global:!0,providers:[{provide:"TELEMETRY_MODULE_OPTIONS",useValue:e},ty],exports:[ty]}}}function tR(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tv=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({providers:[{provide:"TELEMETRY_MODULE_OPTIONS",useValue:{}},ty],exports:[ty]})],tv);class tE{constructor(e){this.telemetryService=e}intercept(e,t){if(!this.telemetryService.isTracingEnabled())return t.handle();let r=e.switchToHttp().getRequest(),i=e.switchToHttp().getResponse();if(this.isInfrastructureEndpoint(r.url))return t.handle();let s=eo.extract(ei.active(),r.headers),{method:o}=r,n=r.route?.path||r.url,c=this.telemetryService.getTracer();return ei.with(s,()=>{let e=c.startSpan(`${o} ${n}`,{kind:et.SERVER,attributes:{[ea]:o,[ef]:r.url,[eu]:n}},s),a=en.setSpan(ei.active(),e);return ei.with(a,()=>t.handle().pipe(J({next:()=>{this.finishSpan(e,i.statusCode)},error:t=>{this.finishSpanWithError(e,i.statusCode||500,t)}})))})}isInfrastructureEndpoint(e){return"/health"===e||e.startsWith("/health/")||"/metrics"===e||e.includes("/.well-known/")}finishSpan(e,t){e.setAttribute(el,t),t>=400?e.setStatus({code:er.ERROR,message:`HTTP ${t}`}):e.setStatus({code:er.OK}),e.end()}finishSpanWithError(e,t,r){e.setAttribute(el,t),e.setStatus({code:er.ERROR,message:r.message}),e.recordException(r),e.end()}}function tS(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function tw(e,t){return function(r,i){t(r,i,e)}}tE=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tR("design:type",Function),tR("design:paramtypes",[void 0===ty?Object:ty])],tE);class tb{constructor(e,t){this.telemetryService=t;let r=e.prefix||process.env.SERVICE_NAME||"";this.prefix=r.replace(/-/g,"_")}onModuleInit(){this.telemetryService?(this.meter=this.telemetryService.getMeter(),this._httpRequestDuration=this.meter.createHistogram(this.prefix?`${this.prefix}_http_request_duration_seconds`:"http_request_duration_seconds",{description:"Duration of HTTP requests in seconds",unit:"s"}),this._httpRequestTotal=this.meter.createCounter(this.prefix?`${this.prefix}_http_requests_total`:"http_requests_total",{description:"Total number of HTTP requests"}),this._httpActiveConnections=this.meter.createUpDownCounter(this.prefix?`${this.prefix}_http_active_connections`:"http_active_connections",{description:"Number of active HTTP connections"})):console.warn("MetricsService: TelemetryService not available. Import TelemetryModule before MetricsModule.")}recordHttpRequestDuration(e,t){this._httpRequestDuration&&this._httpRequestDuration.record(t,e)}incrementHttpRequestTotal(e){this._httpRequestTotal&&this._httpRequestTotal.add(1,e)}incrementActiveConnections(){this._httpActiveConnections&&this._httpActiveConnections.add(1)}decrementActiveConnections(){this._httpActiveConnections&&this._httpActiveConnections.add(-1)}getMeter(){return this.meter}createCounter(e,t){if(this.meter)return this.meter.createCounter(e,t)}createHistogram(e,t){if(this.meter)return this.meter.createHistogram(e,t)}createUpDownCounter(e,t){if(this.meter)return this.meter.createUpDownCounter(e,t)}async getMetrics(){return this.telemetryService?this.telemetryService.getPrometheusExporter()?this.collectMetrics():"# No prometheus exporter available\n":"# No telemetry service available\n"}async collectMetrics(){return"# Metrics collected via OpenTelemetry Prometheus Exporter\n"}getContentType(){return"text/plain; charset=utf-8"}getTelemetryService(){return this.telemetryService}}function tO(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}function tP(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function tj(e,t){return function(r,i){t(r,i,e)}}tb=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tw(0,n("METRICS_MODULE_OPTIONS")),tw(1,u()),tS("design:type",Function),tS("design:paramtypes",["u"<typeof MetricsModuleOptions?Object:MetricsModuleOptions,void 0===ty?Object:ty])],tb);class t_{constructor(e){this.metricsService=e}async getMetrics(e,t){let r=this.metricsService.getTelemetryService(),i=r?.getPrometheusExporter();if(!i){t.set("Content-Type","text/plain; charset=utf-8"),t.send("# OpenTelemetry not configured\n");return}i.getMetricsRequestHandler(e,t)}}tO([eP(),r(),tj(0,h()),tj(1,d()),tP("design:type",Function),tP("design:paramtypes",["u"<typeof Request?Object:Request,"u"<typeof Response?Object:Response]),tP("design:returntype",Promise)],t_.prototype,"getMetrics",null),t_=tO([K(),e("metrics"),tP("design:type",Function),tP("design:paramtypes",[void 0===tb?Object:tb])],t_);class tN{static forRoot(e={}){return{module:tN,global:!0,controllers:[t_],providers:[{provide:"METRICS_MODULE_OPTIONS",useValue:e},tb],exports:[tb]}}}function tT(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tN=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({controllers:[t_],providers:[{provide:"METRICS_MODULE_OPTIONS",useValue:{}},tb],exports:[tb]})],tN);class tC{constructor(e){this.metricsService=e}intercept(e,t){let r=e.switchToHttp().getRequest(),i=e.switchToHttp().getResponse();if(r.url.includes("/metrics"))return t.handle();let{method:s}=r,o=r.route?.path||r.url,n=process.hrtime.bigint();return this.metricsService.incrementActiveConnections(),t.handle().pipe(J({next:()=>{this.recordMetrics(s,o,i.statusCode,n)},error:()=>{this.recordMetrics(s,o,i.statusCode||500,n)},finalize:()=>{this.metricsService.decrementActiveConnections()}}))}recordMetrics(e,t,r,i){let s=Number(process.hrtime.bigint()-i)/1e9,o={method:e,route:t,status_code:String(r)};this.metricsService.recordHttpRequestDuration(o,s),this.metricsService.incrementHttpRequestTotal(o)}}function tI(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tC=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tT("design:type",Function),tT("design:paramtypes",[void 0===tb?Object:tb])],tC);class tA{constructor(e){this.redisService=e}async check(){try{return await this.redisService.get("health-check"),{status:"up"}}catch{return{status:"down",details:{error:"Redis connection failed"}}}}}function tx(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tA=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tI("design:type",Function),tI("design:paramtypes",[void 0===eW?Object:eW])],tA);class tD{constructor(){this.heapThreshold=524288e3}setThreshold(e){this.heapThreshold=e}check(){let e=process.memoryUsage(),t=e.heapUsed;return t>this.heapThreshold?{status:"down",details:{heapUsed:Math.round(t/1024/1024),heapThreshold:Math.round(this.heapThreshold/1024/1024),unit:"MB"}}:{status:"up",details:{heapUsed:Math.round(t/1024/1024),heapTotal:Math.round(e.heapTotal/1024/1024),unit:"MB"}}}}function tM(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function t$(e,t){return function(r,i){t(r,i,e)}}tD=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tx("design:type",Function),tx("design:paramtypes",[])],tD);class tL{constructor(e,t,r){this.options=e,this.redisIndicator=t,this.memoryIndicator=r}onModuleInit(){this.options.memory?.heapThreshold&&this.memoryIndicator&&this.memoryIndicator.setThreshold(this.options.memory.heapThreshold)}async check(){let e={},t="ok";if(this.options.redis&&this.redisIndicator){let r=await this.redisIndicator.check();e.redis=r,"down"===r.status&&(t="degraded")}if(this.options.memory&&this.memoryIndicator){let r=this.memoryIndicator.check();e.memory=r,"down"===r.status&&(t="degraded")}let r=process.memoryUsage();return{status:t,timestamp:new Date().toISOString(),uptime:process.uptime(),checks:e,memory:{used:Math.round(r.heapUsed/1024/1024),total:Math.round(r.heapTotal/1024/1024)}}}}function tF(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}function tk(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tL=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),t$(0,n("HEALTH_MODULE_OPTIONS")),t$(1,u()),t$(2,u()),tM("design:type",Function),tM("design:paramtypes",["u"<typeof HealthModuleOptions?Object:HealthModuleOptions,void 0===tA?Object:tA,void 0===tD?Object:tD])],tL);class tU{constructor(e){this.healthService=e}async healthCheck(){return this.healthService.check()}ping(){return{message:"pong",timestamp:new Date().toISOString()}}}tF([eP(),r(),tk("design:type",Function),tk("design:paramtypes",[]),tk("design:returntype",Promise)],tU.prototype,"healthCheck",null),tF([eP(),r("ping"),tk("design:type",Function),tk("design:paramtypes",[]),tk("design:returntype",Object)],tU.prototype,"ping",null),tU=tF([K(),e("health"),tk("design:type",Function),tk("design:paramtypes",[void 0===tL?Object:tL])],tU);class tV{static forRoot(e={}){let t=[tL,tD];return e.redis&&t.push(tA),{module:tV,controllers:[tU],providers:[...t,{provide:"HEALTH_MODULE_OPTIONS",useValue:e}],exports:[tL]}}}tV=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({controllers:[tU],providers:[tL,tD,{provide:"HEALTH_MODULE_OPTIONS",useValue:{}}],exports:[tL]})],tV);class tH{static forRoot(e={}){let t=[],r=[],i=[];return!1!==e.logging&&(t.push(tf),i.push(tf),r.push({provide:E,useClass:tg})),(!1!==e.metrics||!1!==e.tracing)&&(t.push(tv.forRoot({serviceName:e.serviceName,metrics:e.metrics,tracing:e.tracing,tracingEndpoint:e.tracingEndpoint})),i.push(tv)),!1!==e.metrics&&(t.push(tN),i.push(tN),r.push({provide:E,useClass:tC})),!1!==e.tracing&&r.push({provide:E,useClass:tE}),!1!==e.health&&t.push(tV),{module:tH,global:!0,imports:t,providers:r,exports:i}}}function tK(){let e="production"===process.env.NODE_ENV;if(e&&!process.env.DB_POOL_MAX)throw Error("DB_POOL_MAX is required in production");let t=e?parseInt(process.env.DB_POOL_MAX,10):5,r="aws"===process.env.CLOUD_PROVIDER?{rejectUnauthorized:!1}:void 0,i=new eR({connectionString:process.env.DATABASE_URL,max:t,idleTimeoutMillis:3e4,connectionTimeoutMillis:1e4,ssl:r});return{config:{adapter:new eE(i)},pool:i}}function tq(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tH=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([i(),l({imports:[tf,tv,tN,tV],providers:[{provide:E,useClass:tg},{provide:E,useClass:tC},{provide:E,useClass:tE}],exports:[tf,tv,tN]})],tH);let tG="EMAIL_PROVIDER";class tz{constructor(e){this.emailProvider=e}async sendEmail(e){await this.emailProvider.send(e)}async sendSMS(e){throw Error("SMS notifications are not implemented. Coming in a future version.")}async sendPush(e){throw Error("Push notifications are not implemented. Coming in a future version.")}getEmailProviderName(){return this.emailProvider.getName()}}function tW(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tz=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),(eN=n(tG),function(e,t){eN(e,t,0)}),tq("design:type",Function),tq("design:paramtypes",["u"<typeof EmailProvider?Object:EmailProvider])],tz);class tJ{constructor(e){this.logger=e?.child("Email")??new td().child("Email")}async send(e){let t=Array.isArray(e.to)?e.to.join(", "):e.to,r=e.html||e.text||"(no content)";console.log("\n========================================"),console.log("\uD83D\uDCE7 EMAIL (console provider - not actually sent)"),console.log("========================================"),console.log(`To: ${t}`),console.log(`Subject: ${e.subject}`),e.from&&console.log(`From: ${e.from}`),e.replyTo&&console.log(`Reply-To: ${e.replyTo}`),console.log("----------------------------------------"),console.log("Body:"),console.log(r),console.log("========================================\n"),this.logger.info("Email sent via console provider",{to:t,subject:e.subject})}getName(){return"console"}}function tB(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tJ=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tW("design:type",Function),tW("design:paramtypes",[void 0===td?Object:td])],tJ);class tY{constructor(e){this.secrets=e,this.logger=new a(tY.name)}async onModuleInit(){let e=await this.secrets.get("RESEND_API_KEY");this.client=new eS(e);try{this.defaultFrom=await this.secrets.get("EMAIL_FROM")}catch{this.defaultFrom="onboarding@resend.dev",this.logger.warn("EMAIL_FROM secret not set, using Resend default: onboarding@resend.dev")}this.logger.log("Resend email provider initialized")}async send(e){let t=e.from||this.defaultFrom,r=Array.isArray(e.to)?e.to:[e.to];this.logger.debug(`Sending email to ${r.join(", ")}: ${e.subject}`);let i={from:t,to:r,subject:e.subject};e.html&&(i.html=e.html),e.text&&(i.text=e.text),e.replyTo&&(i.replyTo=e.replyTo),i.html||i.text||(i.text="(no content)");let{error:s}=await this.client.emails.send(i);if(s)throw this.logger.error(`Failed to send email: ${s.message}`),Error(`Failed to send email: ${s.message}`);this.logger.debug(`Email sent successfully to ${r.join(", ")}`)}getName(){return"resend"}}tY=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tB("design:type",Function),tB("design:paramtypes",[void 0===eF?Object:eF])],tY);class tX{}tX=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([l({providers:[tz,{provide:tG,useFactory:async(e,t)=>{let r="console";try{r=await e.get("EMAIL_PROVIDER")}catch{}if("resend"===r){let t=new tY(e);return await t.onModuleInit(),t}return new tJ(t)},inject:[eF,td]}],exports:[tz]})],tX);class tZ{static forRoot(){return ew.forRootAsync({imports:[eV],inject:[eF],useFactory:async e=>{let t=await e.get("REDIS_TLS");return{prefix:"{bull}",connection:{host:await e.get("REDIS_HOST"),port:parseInt(await e.get("REDIS_PORT"),10)||6379,password:await e.get("REDIS_PASSWORD"),..."true"===t&&{tls:{}},maxRetriesPerRequest:null},defaultJobOptions:{removeOnComplete:{count:100},removeOnFail:{count:500},attempts:3,backoff:{type:"exponential",delay:1e3}}}}})}}function tQ(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}tZ=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([l({})],tZ);class t0{constructor(e){this.secrets=e,this.logger=new a(t0.name),this.oauth2Client=new eb}async canActivate(e){let t=e.switchToHttp().getRequest(),r=process.env.SECRETS_PROVIDER;if("local"===r)return this.logger.warn("Skipping scheduler validation in local mode"),!0;switch(r){case"gcp":return this.validateGcpOidc(t);case"aws":return this.validateAwsJobSecret(t);case"azure":return this.validateAzureJobSecret(t);default:return this.logger.error(`Unknown or missing SECRETS_PROVIDER: ${r}`),!1}}async validateAwsJobSecret(e){let t=e.headers["x-job-secret"];if(!t)return this.logger.warn("Missing X-Job-Secret header"),!1;try{let e=await this.secrets.get("JOB_AUTH_SECRET");if(!e)return this.logger.error("JOB_AUTH_SECRET not configured"),!1;if(t===e)return this.logger.log("Validated AWS scheduler request via job secret"),!0;return this.logger.warn("Invalid X-Job-Secret header"),!1}catch(e){return this.logger.error("AWS job secret validation failed",e),!1}}async validateAzureJobSecret(e){let t=e.headers["x-job-secret"];if(!t)return this.logger.warn("Missing X-Job-Secret header"),!1;try{let e=await this.secrets.get("JOB_SECRET");if(!e)return this.logger.error("JOB_SECRET not configured"),!1;if(t===e)return this.logger.log("Validated Azure scheduler request via job secret"),!0;return this.logger.warn("Invalid X-Job-Secret header"),!1}catch(e){return this.logger.error("Azure job secret validation failed",e),!1}}async validateGcpOidc(e){let t=e.headers.authorization;if(!t?.startsWith("Bearer "))return this.logger.warn("Missing Authorization header"),!1;try{let e=process.env.SERVICE_NAME;if(!e)return this.logger.error("SERVICE_NAME environment variable not set"),!1;let r=`${e.toUpperCase().replace(/-/g,"_")}_URL`,i=await this.secrets.get(r),s=(await this.oauth2Client.verifyIdToken({idToken:t.substring(7),audience:i})).getPayload();return this.logger.log(`Validated GCP scheduler request from ${s?.email}`),!0}catch(e){return this.logger.error("GCP OIDC token validation failed",e),!1}}}t0=function(e,t,r,i){var s,o=arguments.length,n=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,i);else for(var c=e.length-1;c>=0;c--)(s=e[c])&&(n=(o<3?s(n):o>3?s(t,r,n):s(t,r))||n);return o>3&&n&&Object.defineProperty(t,r,n),n}([c(),tQ("design:type",Function),tQ("design:paramtypes",[void 0===eF?Object:eF])],t0);export{eU as AuthGuard,eH as AuthModule,e9 as BaseServiceClient,tZ as BullConfigModule,e1 as EmailRateLimitDecorator,e2 as EmailRateLimitGuard,e8 as EmailRateLimitModule,eK as IS_PARTNER_API_KEY,eO as IS_PUBLIC_KEY,td as LoggerService,tb as MetricsService,tX as NotificationModule,tz as NotificationService,tH as ObservabilityModule,eG as Partner,eq as PartnerApi,eP as Public,eY as RateLimit,eY as RateLimitDecorator,eZ as RateLimitGuard,e0 as RateLimitHeadersInterceptor,eQ as RateLimitModule,eJ as RedisModule,eW as RedisService,t0 as SchedulerGuard,eV as SecretsModule,eF as SecretsService,eT as KongHeaders,tK as createPrismaConnection,e6 as filterForwardHeaders,ta as generateSwaggerDocs,to as loadEnvIfExists,tn as startApp,tc as startWorker};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { LoggerService } from './logger.service';
|
|
2
|
+
export type { LogContext } from './logger.service';
|
|
3
|
+
export { LoggerModule } from './logger.module';
|
|
4
|
+
export { LoggingInterceptor } from './logging.interceptor';
|
|
5
|
+
export type { LoggerModuleOptions } from './logger.interface';
|
|
6
|
+
export { DEFAULT_REDACT_PATHS } from './logger.interface';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface LoggerModuleOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Log level
|
|
4
|
+
* Default: LOG_LEVEL env var or 'info'
|
|
5
|
+
*/
|
|
6
|
+
level?: 'debug' | 'info' | 'warn' | 'error';
|
|
7
|
+
/**
|
|
8
|
+
* Paths to redact from logs (for PII protection)
|
|
9
|
+
* Supports nested paths: 'user.email', '*.password', 'data[*].ssn'
|
|
10
|
+
* Default: LOG_REDACT_PATHS env var (comma-separated) or common PII fields
|
|
11
|
+
*/
|
|
12
|
+
redactPaths?: string[];
|
|
13
|
+
/**
|
|
14
|
+
* String to replace redacted values with
|
|
15
|
+
* Default: '[REDACTED]'
|
|
16
|
+
*/
|
|
17
|
+
redactCensor?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Disable default PII redaction paths
|
|
20
|
+
* When false, common paths like 'password', 'email', 'ssn' are auto-redacted
|
|
21
|
+
* Default: false
|
|
22
|
+
*/
|
|
23
|
+
disableDefaultRedaction?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default paths to redact for common PII fields
|
|
27
|
+
* These are applied unless disableDefaultRedaction is true
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_REDACT_PATHS: string[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import type { LoggerModuleOptions } from './logger.interface';
|
|
3
|
+
export declare class LoggerModule {
|
|
4
|
+
/**
|
|
5
|
+
* Configure the logger module with custom options
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* LoggerModule.forRoot({
|
|
9
|
+
* redactPaths: ['user.phoneNumber', 'order.paymentInfo'],
|
|
10
|
+
* redactCensor: '***',
|
|
11
|
+
* })
|
|
12
|
+
*/
|
|
13
|
+
static forRoot(options?: LoggerModuleOptions): DynamicModule;
|
|
14
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type LoggerModuleOptions } from './logger.interface';
|
|
2
|
+
export interface LogContext {
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare class LoggerService {
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private context?;
|
|
8
|
+
private correlationId?;
|
|
9
|
+
private readonly options;
|
|
10
|
+
constructor(moduleOptions?: LoggerModuleOptions);
|
|
11
|
+
/**
|
|
12
|
+
* Build the list of paths to redact from logs
|
|
13
|
+
*/
|
|
14
|
+
private buildRedactPaths;
|
|
15
|
+
setContext(context: string): void;
|
|
16
|
+
setCorrelationId(correlationId: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Get trace context from active OTEL span
|
|
19
|
+
*/
|
|
20
|
+
private getTraceContext;
|
|
21
|
+
private formatMessage;
|
|
22
|
+
debug(message: string, context?: LogContext): void;
|
|
23
|
+
info(message: string, context?: LogContext): void;
|
|
24
|
+
warn(message: string, context?: LogContext): void;
|
|
25
|
+
error(message: string, error?: Error | unknown, context?: LogContext): void;
|
|
26
|
+
/**
|
|
27
|
+
* Create a child logger with a specific context
|
|
28
|
+
* Useful for class-level loggers
|
|
29
|
+
*/
|
|
30
|
+
child(context: string): LoggerService;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { LoggerService } from './logger.service';
|
|
4
|
+
export declare class LoggingInterceptor implements NestInterceptor {
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(logger: LoggerService);
|
|
7
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { MetricsModule } from './metrics.module';
|
|
2
|
+
export { MetricsService } from './metrics.service';
|
|
3
|
+
export { MetricsController } from './metrics.controller';
|
|
4
|
+
export { MetricsInterceptor } from './metrics.interceptor';
|
|
5
|
+
export type { MetricsModuleOptions } from './metrics.interface';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
import { MetricsService } from './metrics.service';
|
|
3
|
+
export declare class MetricsController {
|
|
4
|
+
private readonly metricsService;
|
|
5
|
+
constructor(metricsService: MetricsService);
|
|
6
|
+
getMetrics(req: Request, res: Response): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { MetricsService } from './metrics.service';
|
|
4
|
+
export declare class MetricsInterceptor implements NestInterceptor {
|
|
5
|
+
private readonly metricsService;
|
|
6
|
+
constructor(metricsService: MetricsService);
|
|
7
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
8
|
+
private recordMetrics;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface MetricsModuleOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Path to expose metrics endpoint
|
|
4
|
+
* Default: '/metrics'
|
|
5
|
+
*/
|
|
6
|
+
path?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Prefix for all metrics
|
|
9
|
+
* Default: service name from SERVICE_NAME env var
|
|
10
|
+
*/
|
|
11
|
+
prefix?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Enable default Node.js metrics (memory, CPU, event loop lag)
|
|
14
|
+
* Default: true
|
|
15
|
+
*/
|
|
16
|
+
defaultMetrics?: boolean;
|
|
17
|
+
}
|