@goatlab/node-backend 0.0.16 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +54 -38
  2. package/dist/container/Container.d.ts +441 -0
  3. package/dist/container/Container.js +895 -0
  4. package/dist/container/Container.js.map +1 -0
  5. package/dist/container/DistributedCacheInvalidator.d.ts +84 -0
  6. package/dist/container/DistributedCacheInvalidator.js +213 -0
  7. package/dist/container/DistributedCacheInvalidator.js.map +1 -0
  8. package/dist/container/LruCache.d.ts +14 -0
  9. package/dist/container/LruCache.js +23 -0
  10. package/dist/container/LruCache.js.map +1 -0
  11. package/dist/container/types.d.ts +128 -0
  12. package/dist/container/types.js +6 -0
  13. package/dist/container/types.js.map +1 -0
  14. package/dist/index.d.ts +31 -0
  15. package/dist/index.js +53 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/server/bootstraps/getExpressTrpcApp.d.ts +17 -0
  18. package/dist/server/bootstraps/getExpressTrpcApp.js +98 -0
  19. package/dist/server/bootstraps/getExpressTrpcApp.js.map +1 -0
  20. package/dist/server/consts.d.ts +35 -0
  21. package/dist/server/consts.js +33 -0
  22. package/dist/server/consts.js.map +1 -0
  23. package/dist/server/context/context.model.d.ts +13 -0
  24. package/dist/server/context/context.model.js +3 -0
  25. package/dist/server/context/context.model.js.map +1 -0
  26. package/dist/server/context/request.context.d.ts +40 -0
  27. package/dist/server/context/request.context.js +91 -0
  28. package/dist/server/context/request.context.js.map +1 -0
  29. package/dist/server/context/trpc.context.d.ts +11 -0
  30. package/dist/server/context/trpc.context.js +67 -0
  31. package/dist/server/context/trpc.context.js.map +1 -0
  32. package/dist/server/initOpenApiDocs.d.ts +9 -0
  33. package/dist/server/initOpenApiDocs.js +18 -0
  34. package/dist/server/initOpenApiDocs.js.map +1 -0
  35. package/dist/server/middleware/cloudTaskDecrypt.middleware.d.ts +6 -0
  36. package/dist/server/middleware/cloudTaskDecrypt.middleware.js +44 -0
  37. package/dist/server/middleware/cloudTaskDecrypt.middleware.js.map +1 -0
  38. package/dist/server/middleware/error.middleware.d.ts +17 -0
  39. package/dist/server/middleware/error.middleware.js +66 -0
  40. package/dist/server/middleware/error.middleware.js.map +1 -0
  41. package/dist/server/middleware/handleRequest.middleware.d.ts +7 -0
  42. package/dist/server/middleware/handleRequest.middleware.js +40 -0
  43. package/dist/server/middleware/handleRequest.middleware.js.map +1 -0
  44. package/dist/server/middleware/logger/cloudRun.logger.d.ts +27 -0
  45. package/dist/server/middleware/logger/cloudRun.logger.js +87 -0
  46. package/dist/server/middleware/logger/cloudRun.logger.js.map +1 -0
  47. package/dist/server/middleware/logger/logger.service.d.ts +6 -0
  48. package/dist/server/middleware/logger/logger.service.js +17 -0
  49. package/dist/server/middleware/logger/logger.service.js.map +1 -0
  50. package/dist/server/middleware/logs.middleware.d.ts +7 -0
  51. package/dist/server/middleware/logs.middleware.js +130 -0
  52. package/dist/server/middleware/logs.middleware.js.map +1 -0
  53. package/dist/server/middleware/requireAuthenticated.d.ts +2 -0
  54. package/dist/server/middleware/requireAuthenticated.js +13 -0
  55. package/dist/server/middleware/requireAuthenticated.js.map +1 -0
  56. package/dist/server/middleware/trpcError.middleware.d.ts +4 -0
  57. package/dist/server/middleware/trpcError.middleware.js +38 -0
  58. package/dist/server/middleware/trpcError.middleware.js.map +1 -0
  59. package/dist/server/schemas/user.schema.d.ts +109 -0
  60. package/dist/server/schemas/user.schema.js +28 -0
  61. package/dist/server/schemas/user.schema.js.map +1 -0
  62. package/dist/server/sentry/getSentry.d.ts +6 -0
  63. package/dist/server/sentry/getSentry.js +45 -0
  64. package/dist/server/sentry/getSentry.js.map +1 -0
  65. package/dist/server/sentry/sentry.service.d.ts +34 -0
  66. package/dist/server/sentry/sentry.service.js +110 -0
  67. package/dist/server/sentry/sentry.service.js.map +1 -0
  68. package/dist/server/services/email/email.model.d.ts +84 -0
  69. package/dist/server/services/email/email.model.js +62 -0
  70. package/dist/server/services/email/email.model.js.map +1 -0
  71. package/dist/server/services/email/email.service.d.ts +23 -0
  72. package/dist/server/services/email/email.service.js +139 -0
  73. package/dist/server/services/email/email.service.js.map +1 -0
  74. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.d.ts +15 -0
  75. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.js +9 -0
  76. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.js.map +1 -0
  77. package/dist/server/services/secrets/secret.service.d.ts +32 -0
  78. package/dist/server/services/secrets/secret.service.js +220 -0
  79. package/dist/server/services/secrets/secret.service.js.map +1 -0
  80. package/dist/server/services/sendgrid/sendgrid.model.d.ts +118 -0
  81. package/dist/server/services/sendgrid/sendgrid.model.js +3 -0
  82. package/dist/server/services/sendgrid/sendgrid.model.js.map +1 -0
  83. package/dist/server/services/sendgrid/sendgridApi.service.d.ts +13 -0
  84. package/dist/server/services/sendgrid/sendgridApi.service.js +79 -0
  85. package/dist/server/services/sendgrid/sendgridApi.service.js.map +1 -0
  86. package/dist/server/services/sendgrid/sendgridHooks.model.d.ts +27 -0
  87. package/dist/server/services/sendgrid/sendgridHooks.model.js +19 -0
  88. package/dist/server/services/sendgrid/sendgridHooks.model.js.map +1 -0
  89. package/dist/server/services/translations/template.util.d.ts +7 -0
  90. package/dist/server/services/translations/template.util.js +11 -0
  91. package/dist/server/services/translations/template.util.js.map +1 -0
  92. package/dist/server/services/translations/translation.model.d.ts +4 -0
  93. package/dist/server/services/translations/translation.model.js +6 -0
  94. package/dist/server/services/translations/translation.model.js.map +1 -0
  95. package/dist/server/services/translations/translation.service.d.ts +25 -0
  96. package/dist/server/services/translations/translation.service.js +97 -0
  97. package/dist/server/services/translations/translation.service.js.map +1 -0
  98. package/dist/server/services/util/benchmarker.d.ts +13 -0
  99. package/dist/server/services/util/benchmarker.js +34 -0
  100. package/dist/server/services/util/benchmarker.js.map +1 -0
  101. package/dist/server/services/util/pagination.d.ts +50 -0
  102. package/dist/server/services/util/pagination.js +57 -0
  103. package/dist/server/services/util/pagination.js.map +1 -0
  104. package/dist/server/services/util/url.service.d.ts +75 -0
  105. package/dist/server/services/util/url.service.js +139 -0
  106. package/dist/server/services/util/url.service.js.map +1 -0
  107. package/dist/server/test/express.mock.d.ts +6 -0
  108. package/dist/server/test/express.mock.js +49 -0
  109. package/dist/server/test/express.mock.js.map +1 -0
  110. package/dist/server/test/firebase.mock.d.ts +4 -0
  111. package/dist/server/test/firebase.mock.js +30 -0
  112. package/dist/server/test/firebase.mock.js.map +1 -0
  113. package/dist/server/test/mock.model.d.ts +5 -0
  114. package/dist/server/test/mock.model.js +3 -0
  115. package/dist/server/test/mock.model.js.map +1 -0
  116. package/dist/server/test/trpc.mock.d.ts +6 -0
  117. package/dist/server/test/trpc.mock.js +14 -0
  118. package/dist/server/test/trpc.mock.js.map +1 -0
  119. package/dist/server/trpc.d.ts +364 -0
  120. package/dist/server/trpc.js +87 -0
  121. package/dist/server/trpc.js.map +1 -0
  122. package/dist/server/types/Envinronment.d.ts +1 -0
  123. package/dist/server/types/Envinronment.js +3 -0
  124. package/dist/server/types/Envinronment.js.map +1 -0
  125. package/dist/test/const.d.ts +4 -0
  126. package/dist/test/const.js +11 -1
  127. package/dist/test/const.js.map +1 -1
  128. package/dist/tsconfig.tsbuildinfo +1 -1
  129. package/package.json +34 -3
package/README.md CHANGED
@@ -1,45 +1,61 @@
1
- <!-- PROJECT SHIELDS -->
1
+ # @goatlab/node-backend
2
2
 
3
- [![Stargazers][stars-shield]][stars-url]
4
- [![Issues][issues-shield]][issues-url]
5
- [![MIT License][license-shield]][license-url]
6
- [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
3
+ A flexible caching solution for Node.js applications that supports both Redis and in-memory LRU caching with multi-tenancy support.
7
4
 
8
- <!-- PROJECT LOGO -->
9
- <br />
10
- <p align="center">
11
- <a href="https://github.com/github_username/repo">
12
- <img src="https://docs.goatlab.io/logo.png" alt="Logo" width="150" height="150">
13
- </a>
14
-
15
- <h3 align="center">GOAT - QUEUE</h3>
16
-
17
- <p align="center">
18
- Fluent - Time Saving (TS) utils
19
- <br />
20
- <a href="https://docs.goatlab.io/#/0.7.x/fluent/fluent"><strong>Explore the docs »</strong></a>
21
- <br />
22
- <br />
23
- ·
24
- <a href="https://github.com/goat-io/fluent/issues">Report Bug</a>
25
- ·
26
- <a href="https://github.com/goat-io/fluent/issues">Request Feature</a>
27
- </p>
28
- </p>
29
- </p>
30
-
31
- # Goat - JS UTILS
32
-
33
- Standard queue interfaces for different providers
34
-
35
- ### Installing
36
-
37
- To install this package in your project, you can use the following command within your terminal.
5
+ ## Installation
38
6
 
39
7
  ```bash
40
- yarn add @goatlab/queue
8
+ npm install @goatlab/node-backend
9
+ # or
10
+ yarn add @goatlab/node-backend
11
+ # or
12
+ pnpm add @goatlab/node-backend
13
+ ```
14
+
15
+ ## Basic Usage
16
+
17
+ ```typescript
18
+ import { Cache } from '@goatlab/node-backend'
19
+
20
+ // Use Redis cache
21
+ const redisCache = new Cache({
22
+ connection: 'redis://localhost:6379',
23
+ opts: { namespace: 'my-app' }
24
+ })
25
+
26
+ // Use in-memory LRU cache
27
+ const memoryCache = new Cache({
28
+ connection: undefined,
29
+ opts: { namespace: 'my-app' }
30
+ })
31
+
32
+ // Cache with LRU memory layer for improved performance
33
+ const hybridCache = new Cache({
34
+ connection: 'redis://localhost:6379',
35
+ opts: {
36
+ namespace: 'my-app',
37
+ usesLRUMemory: true // Adds LRU memory caching layer
38
+ }
39
+ })
40
+
41
+ // Basic operations
42
+ await cache.set('key', { data: 'value' }, 60000) // TTL in milliseconds
43
+ const value = await cache.get('key')
44
+ await cache.delete('key')
45
+
46
+ // Advanced operations
47
+ const result = await cache.remember('expensive-op', 300000, async () => {
48
+ // This function only runs if key doesn't exist
49
+ return await expensiveOperation()
50
+ })
41
51
  ```
42
52
 
43
- ### Documentation
53
+ ## Key Features
44
54
 
45
- To learn how to use this visit the [Goat Docs](https://docs.goatlab.io/#/0.7.x/fluent-helpers/overview)
55
+ - **Dual Storage**: Supports Redis for distributed caching or in-memory LRU for single instances
56
+ - **Multi-tenancy**: Built-in tenant isolation with namespace support
57
+ - **Memory Layer**: Optional LRU memory caching on top of Redis for improved performance
58
+ - **Cache Helpers**: Laravel-inspired helper methods like `remember()`, `rememberForever()`, and `pull()`
59
+ - **Namespace Operations**: Delete or retrieve values by key prefix with `deleteWhereStartsWith()` and `getValueWhereKeyStartsWith()`
60
+ - **Type Safety**: Full TypeScript support with generic types
61
+ - **Automatic Validation**: Skips caching of null, undefined, empty strings, empty arrays, and empty objects
@@ -0,0 +1,441 @@
1
+ import { ContainerOptions, InstancesStructure, PreloadStructure } from './types';
2
+ /**
3
+ * ═══════════════════════════════════════════════════════════════════════════════
4
+ * 🏗️ MULTI-TENANT DEPENDENCY INJECTION CONTAINER
5
+ * ═══════════════════════════════════════════════════════════════════════════════
6
+ *
7
+ * This Container provides a dependency injection system designed
8
+ * for multi-tenant applications. Each tenant gets their own isolated service
9
+ * instances while sharing the same factory definitions.
10
+ *
11
+ * Key Features:
12
+ * • 🔄 Tenant-isolated service instances using AsyncLocalStorage
13
+ * • ⚡ High-performance caching with LRU eviction
14
+ * • 🪞 Intelligent proxy system for lazy loading and error handling
15
+ * • 📊 Built-in performance metrics and debugging tools
16
+ * • 🛡️ Type-safe service resolution with full TypeScript support
17
+ * • 🔧 Support for both class constructors and factory functions
18
+ *
19
+ * Architecture Overview:
20
+ * ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
21
+ * │ Factories │ -> │ Container │ -> │ Instances │
22
+ * │ (Shared Defs) │ │ (Per-tenant) │ │ (Per-tenant) │
23
+ * └─────────────────┘ └─────────────────┘ └─────────────────┘
24
+ *
25
+ * Flow:
26
+ * 1. Define factories once (shared across all tenants)
27
+ * 2. Bootstrap container with tenant metadata
28
+ * 3. Services are lazy-loaded and cached per tenant
29
+ * 4. AsyncLocalStorage provides automatic context isolation
30
+ * ═══════════════════════════════════════════════════════════════════════════════
31
+ */
32
+ /**
33
+ * 🏗️ Multi-Tenant Dependency Injection Container
34
+ *
35
+ * The Container is the heart of the multi-tenant service architecture. It manages
36
+ * service instantiation, caching, and tenant isolation using AsyncLocalStorage.
37
+ *
38
+ * @template Defs - Factory definitions record (shared across tenants)
39
+ * @template TenantMetadata - Type of tenant-specific metadata (DB config, secrets, etc.)
40
+ *
41
+ * Key Responsibilities:
42
+ * 1. 🏭 **Factory Management**: Register and cache service factories
43
+ * 2. 🔄 **Tenant Isolation**: Each tenant gets isolated service instances
44
+ * 3. ⚡ **Performance**: Multi-level caching for optimal performance
45
+ * 4. 🪞 **Lazy Loading**: Services instantiated only when accessed
46
+ * 5. 🛡️ **Error Handling**: Clear error messages for missing services
47
+ * 6. 📊 **Observability**: Performance metrics and debugging tools
48
+ *
49
+ * Usage Pattern:
50
+ * ```typescript
51
+ * // 1. Define your services
52
+ * const factories = {
53
+ * database: DatabaseService,
54
+ * api: {
55
+ * users: UserApiService,
56
+ * auth: AuthApiService
57
+ * }
58
+ * }
59
+ *
60
+ * // 2. Create container with initializer
61
+ * const container = new Container(factories, async (preload, meta) => {
62
+ * const db = preload.database('main', meta.connectionString)
63
+ * return {
64
+ * database: db,
65
+ * api: {
66
+ * users: preload.api.users('users', db),
67
+ * auth: preload.api.auth('auth', db, meta.jwtSecret)
68
+ * }
69
+ * }
70
+ * })
71
+ *
72
+ * // 3. Bootstrap for a tenant and run code
73
+ * await container.bootstrap(tenantMeta, async () => {
74
+ * const { database, api } = container.context
75
+ * const users = await api.users.getAll()
76
+ * return users
77
+ * })
78
+ * ```
79
+ */
80
+ export declare class Container<Defs extends Record<string, unknown>, TenantMetadata> {
81
+ private readonly factories;
82
+ private readonly initializer;
83
+ /**
84
+ * Service instance cache managers - one per service type
85
+ * Each manager handles LRU caching for that specific service
86
+ */
87
+ private readonly managers;
88
+ /**
89
+ * AsyncLocalStorage provides automatic tenant context isolation
90
+ * Each async call tree gets its own isolated service instances
91
+ * Also stores tenant metadata for introspection
92
+ */
93
+ private readonly als;
94
+ /**
95
+ * Pre-resolved factory lookup cache for performance
96
+ * Avoids recursive object traversal on every service access
97
+ */
98
+ private readonly factoryCache;
99
+ /**
100
+ * Cached preload proxy to avoid recreating the same proxy structure
101
+ */
102
+ private preloadProxy;
103
+ /**
104
+ * Container configuration with sensible defaults
105
+ */
106
+ private readonly options;
107
+ /**
108
+ * Path string cache: converts ['user', 'repo'] -> "user.repo"
109
+ * Avoids repeated string joining operations
110
+ */
111
+ private readonly pathCache;
112
+ /**
113
+ * Proxy object cache: reuses proxy objects for the same paths
114
+ * Reduces memory allocation and improves performance
115
+ */
116
+ private readonly proxyCache;
117
+ /**
118
+ * Context proxy cache: reuses proxies for the same object instances
119
+ * Uses WeakMap for automatic garbage collection when objects are freed
120
+ */
121
+ private readonly contextProxyCache;
122
+ /**
123
+ * Initializer cache: stores initialized instances per tenant
124
+ * Avoids re-running the expensive initializer function for the same tenant
125
+ * Key is a serialized version of tenant metadata, value is the initialized instances
126
+ */
127
+ private readonly initializerCache;
128
+ /**
129
+ * Performance metrics for monitoring and optimization
130
+ * Only collected when enableMetrics is true
131
+ * Includes overflow protection for long-running services
132
+ */
133
+ private metrics;
134
+ /**
135
+ * Maximum safe value for metrics before overflow protection kicks in
136
+ * Set to 90% of MAX_SAFE_INTEGER to provide buffer
137
+ */
138
+ private readonly MAX_METRIC_VALUE;
139
+ /**
140
+ * Safely increment a metric with overflow protection
141
+ * When approaching MAX_SAFE_INTEGER, resets all metrics to prevent overflow
142
+ */
143
+ private safeIncrementMetric;
144
+ /**
145
+ * Create a new Container instance
146
+ *
147
+ * @param factories - Service factory definitions (shared across all tenants)
148
+ * @param initializer - Function that creates tenant-specific service instances
149
+ * @param options - Configuration options for performance and debugging
150
+ *
151
+ * The initializer function receives:
152
+ * - preload: Proxy object for creating service instances with parameters
153
+ * - meta: Tenant-specific metadata (DB config, secrets, etc.)
154
+ *
155
+ * And should return a structure matching your factory definitions but with
156
+ * actual service instances instead of factory functions.
157
+ */
158
+ constructor(factories: Defs, initializer: (preload: PreloadStructure<Defs>, meta: TenantMetadata) => Promise<Partial<InstancesStructure<Defs>>>, options?: ContainerOptions);
159
+ /**
160
+ * Recursively create cache managers for all services in the factory tree
161
+ * Each service gets its own LRU cache with the configured size limit
162
+ */
163
+ private createManagers;
164
+ /**
165
+ * Efficiently cache path string conversions
166
+ * Converts ['user', 'service'] to "user.service" and caches the result
167
+ *
168
+ * Uses different separators for cache key vs final path to avoid conflicts
169
+ */
170
+ private getOrCachePath;
171
+ /**
172
+ * Pre-populate the factory cache by walking the entire factory tree
173
+ * This eliminates the need for recursive object traversal during runtime
174
+ */
175
+ private preloadFactoryCache;
176
+ /**
177
+ * Recursive factory tree walker that builds the flat factory cache
178
+ * Converts nested object structure to flat dot-notation keys
179
+ */
180
+ private walkFactories;
181
+ /**
182
+ * Get the preload proxy for service instantiation
183
+ * The preload proxy allows you to create services with parameters:
184
+ *
185
+ * ```typescript
186
+ * const db = preload.database('main', connectionString)
187
+ * const userApi = preload.api.users('users', db, config)
188
+ * ```
189
+ *
190
+ * This is used during the initialization phase to wire up dependencies
191
+ */
192
+ get preload(): PreloadStructure<Defs>;
193
+ /**
194
+ * Create a proxy that intercepts property access and provides factory functions
195
+ *
196
+ * The proxy works by:
197
+ * 1. Intercepting property access (e.g., preload.database)
198
+ * 2. Looking up the factory for that path
199
+ * 3. Returning a function that creates and caches instances
200
+ * 4. For nested paths, returning another proxy
201
+ *
202
+ * This enables natural dot-notation access while maintaining lazy loading
203
+ */
204
+ private createPreloadProxy;
205
+ /**
206
+ * Run a function within a specific tenant context
207
+ * This is usually called internally by bootstrap, but can be used directly
208
+ * for testing or advanced use cases
209
+ */
210
+ runWithContext<T>(instances: Partial<InstancesStructure<Defs>>, tenantMetadata: TenantMetadata, fn: () => Promise<T>): Promise<T>;
211
+ /**
212
+ * Get the current tenant's service context
213
+ *
214
+ * This is the main way to access services within a tenant context:
215
+ * ```typescript
216
+ * const { database, api } = container.context
217
+ * const users = await api.users.getAll()
218
+ * ```
219
+ *
220
+ * Throws an error if called outside of a tenant context
221
+ */
222
+ get context(): InstancesStructure<Defs>;
223
+ /**
224
+ * Create a proxy for the runtime context that provides intelligent error handling
225
+ *
226
+ * The context proxy:
227
+ * 1. Provides helpful error messages when services are missing
228
+ * 2. Handles nested object access gracefully
229
+ * 3. Avoids wrapping Promises or arrays (which would break them)
230
+ * 4. Uses WeakMap caching for automatic memory management
231
+ *
232
+ * This ensures that accessing container.context.someService either works
233
+ * or gives you a clear error message about what's available
234
+ */
235
+ private createContextProxy;
236
+ /**
237
+ * Create a stable cache key from tenant metadata
238
+ * Uses a deterministic approach focusing on tenant identity
239
+ */
240
+ private createTenantCacheKey;
241
+ /**
242
+ * Simple hash function for cache keys
243
+ * Not cryptographically secure, but good enough for cache key generation
244
+ */
245
+ private simpleHash;
246
+ /**
247
+ * Get or create initialized instances for a tenant
248
+ * Uses caching to avoid re-running the expensive initializer function
249
+ */
250
+ private getOrCreateInstances;
251
+ /**
252
+ * Bootstrap the container for a specific tenant and execute a function
253
+ *
254
+ * This is the main entry point for tenant-specific operations:
255
+ *
256
+ * @param meta - Tenant-specific metadata (DB config, secrets, etc.)
257
+ * @param fn - Function to execute within the tenant context (optional)
258
+ * @returns Object containing the initialized instances and function result
259
+ *
260
+ * ```typescript
261
+ * // Example: Process a user request for tenant "acme"
262
+ * const result = await container.bootstrap(acmeTenantMeta, async () => {
263
+ * const { api } = container.context
264
+ * return await api.users.getById(userId)
265
+ * })
266
+ *
267
+ * console.log(result.instances) // All initialized services
268
+ * console.log(result.result) // Return value from the function
269
+ * ```
270
+ *
271
+ * The bootstrap process:
272
+ * 1. Gets or creates initialized services for this tenant (with caching)
273
+ * 2. Sets up AsyncLocalStorage context with the service instances
274
+ * 3. Executes your function within that context
275
+ * 4. Returns both the instances and your function's result
276
+ */
277
+ bootstrap<T>(meta: TenantMetadata, fn?: () => Promise<T>): Promise<{
278
+ instances: InstancesStructure<Defs>;
279
+ result?: T;
280
+ }>;
281
+ /**
282
+ * Get current performance metrics
283
+ * Useful for monitoring cache effectiveness and performance tuning
284
+ */
285
+ getMetrics(): {
286
+ cacheHits: number;
287
+ cacheMisses: number;
288
+ instanceCreations: number;
289
+ contextAccesses: number;
290
+ pathCacheHits: number;
291
+ proxyCacheHits: number;
292
+ initializerCacheHits: number;
293
+ };
294
+ /**
295
+ * Reset all performance metrics to zero
296
+ * Useful for benchmarking specific operations
297
+ */
298
+ resetMetrics(): void;
299
+ /**
300
+ * Clear all service instance caches
301
+ * Forces fresh instantiation of all services on next access
302
+ * Useful for testing or when you need to ensure clean state
303
+ */
304
+ clearCaches(): void;
305
+ /**
306
+ * Setup distributed cache invalidation system
307
+ * Connects to Redis pub/sub for coordinating cache invalidation across instances
308
+ */
309
+ private setupDistributedInvalidation;
310
+ /**
311
+ * Invalidate all cached data for a specific tenant across all instances
312
+ * This sends a distributed invalidation message via Redis pub/sub
313
+ */
314
+ invalidateTenantDistributed(tenantId: string, reason?: string): Promise<void>;
315
+ /**
316
+ * Invalidate all cached data for a specific service type across all instances
317
+ */
318
+ invalidateServiceDistributed(serviceType: string, reason?: string): Promise<void>;
319
+ /**
320
+ * Invalidate all cached data across all instances
321
+ */
322
+ invalidateAllDistributed(reason?: string): Promise<void>;
323
+ /**
324
+ * Invalidate cached data for a specific tenant (local only)
325
+ * This only affects the current instance
326
+ */
327
+ private invalidateTenantLocally;
328
+ /**
329
+ * Invalidate cached data for a specific service type (local only)
330
+ */
331
+ private invalidateServiceLocally;
332
+ /**
333
+ * Invalidate all cached data (local only)
334
+ */
335
+ private invalidateAllLocally;
336
+ /**
337
+ * Get detailed cache statistics for each service
338
+ * Shows how many instances are cached and the cache limits
339
+ */
340
+ getCacheStats(): Record<string, {
341
+ size: number;
342
+ maxSize?: number;
343
+ }>;
344
+ /**
345
+ * Get comprehensive performance statistics
346
+ * Combines metrics, cache stats, and computed ratios for full observability
347
+ */
348
+ getPerformanceStats(): {
349
+ cacheStats: Record<string, {
350
+ size: number;
351
+ maxSize?: number;
352
+ }>;
353
+ totalCacheSize: number;
354
+ pathCacheSize: number;
355
+ proxyCacheSize: number;
356
+ factoryCacheSize: number;
357
+ initializerCacheSize: number;
358
+ cacheHitRatio: number;
359
+ cacheHits: number;
360
+ cacheMisses: number;
361
+ instanceCreations: number;
362
+ contextAccesses: number;
363
+ pathCacheHits: number;
364
+ proxyCacheHits: number;
365
+ initializerCacheHits: number;
366
+ };
367
+ /**
368
+ * Check if there's an active tenant context
369
+ *
370
+ * @returns true if called within a tenant context, false otherwise
371
+ *
372
+ * ```typescript
373
+ * if (container.hasActiveContext()) {
374
+ * const services = container.context
375
+ * // Safe to access services
376
+ * }
377
+ * ```
378
+ */
379
+ hasActiveContext(): boolean;
380
+ /**
381
+ * Check if a service is available in the current tenant context
382
+ *
383
+ * @param servicePath - Dot-notation path to the service (e.g., "api.users")
384
+ * @returns true if the service exists and is initialized, false otherwise
385
+ *
386
+ * ```typescript
387
+ * if (container.hasService('api.users')) {
388
+ * const users = container.context.api.users
389
+ * // Safe to use users service
390
+ * }
391
+ * ```
392
+ */
393
+ hasService(servicePath: string): boolean;
394
+ /**
395
+ * Get the current tenant's metadata
396
+ *
397
+ * This allows access to tenant-specific configuration, credentials, and other
398
+ * metadata that was passed to the bootstrap method:
399
+ *
400
+ * ```typescript
401
+ * await container.bootstrap(tenantMeta, async () => {
402
+ * const meta = container.getCurrentTenantMetadata()
403
+ * console.log('Current tenant:', meta.id)
404
+ * console.log('DB URL:', meta.connectionString)
405
+ * })
406
+ * ```
407
+ *
408
+ * @returns The tenant metadata that was passed to bootstrap
409
+ * @throws Error if called outside of a tenant context
410
+ */
411
+ getCurrentTenantMetadata(): TenantMetadata;
412
+ /**
413
+ * Get the current tenant ID from metadata
414
+ *
415
+ * This is a convenience method that extracts the tenant ID from the metadata.
416
+ * It assumes the metadata has an 'id' property (common pattern).
417
+ *
418
+ * ```typescript
419
+ * await container.bootstrap(tenantMeta, async () => {
420
+ * const tenantId = container.getCurrentTenantId()
421
+ * console.log('Processing request for tenant:', tenantId)
422
+ * })
423
+ * ```
424
+ *
425
+ * @returns The tenant ID if metadata has an 'id' property, undefined otherwise
426
+ * @throws Error if called outside of a tenant context
427
+ */
428
+ getCurrentTenantId(): string | undefined;
429
+ /**
430
+ * Get a list of all available services in the current tenant context
431
+ * Useful for debugging, testing, or dynamic service discovery
432
+ *
433
+ * @returns Array of dot-notation service paths (e.g., ["database", "api.users", "api.auth"])
434
+ */
435
+ getAvailableServices(): string[];
436
+ /**
437
+ * Recursively collect all service paths from the current context
438
+ * Helper method for getAvailableServices()
439
+ */
440
+ private collectServices;
441
+ }