@push.rocks/smartregistry 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/classes.smartregistry.d.ts +33 -2
  3. package/dist_ts/classes.smartregistry.js +38 -5
  4. package/dist_ts/core/classes.authmanager.d.ts +30 -80
  5. package/dist_ts/core/classes.authmanager.js +63 -337
  6. package/dist_ts/core/classes.defaultauthprovider.d.ts +78 -0
  7. package/dist_ts/core/classes.defaultauthprovider.js +311 -0
  8. package/dist_ts/core/classes.registrystorage.d.ts +70 -4
  9. package/dist_ts/core/classes.registrystorage.js +165 -5
  10. package/dist_ts/core/index.d.ts +3 -0
  11. package/dist_ts/core/index.js +7 -2
  12. package/dist_ts/core/interfaces.auth.d.ts +83 -0
  13. package/dist_ts/core/interfaces.auth.js +2 -0
  14. package/dist_ts/core/interfaces.core.d.ts +35 -0
  15. package/dist_ts/core/interfaces.storage.d.ts +120 -0
  16. package/dist_ts/core/interfaces.storage.js +2 -0
  17. package/dist_ts/upstream/classes.baseupstream.d.ts +2 -2
  18. package/dist_ts/upstream/classes.baseupstream.js +16 -14
  19. package/dist_ts/upstream/classes.upstreamcache.d.ts +69 -22
  20. package/dist_ts/upstream/classes.upstreamcache.js +207 -50
  21. package/package.json +1 -1
  22. package/ts/00_commitinfo_data.ts +1 -1
  23. package/ts/classes.smartregistry.ts +39 -4
  24. package/ts/core/classes.authmanager.ts +74 -412
  25. package/ts/core/classes.defaultauthprovider.ts +393 -0
  26. package/ts/core/classes.registrystorage.ts +199 -5
  27. package/ts/core/index.ts +8 -1
  28. package/ts/core/interfaces.auth.ts +91 -0
  29. package/ts/core/interfaces.core.ts +39 -0
  30. package/ts/core/interfaces.storage.ts +130 -0
  31. package/ts/upstream/classes.baseupstream.ts +20 -15
  32. package/ts/upstream/classes.upstreamcache.ts +256 -53
@@ -0,0 +1,120 @@
1
+ import type { TRegistryProtocol } from './interfaces.core.js';
2
+ /**
3
+ * Actor information from request context
4
+ */
5
+ export interface IStorageActor {
6
+ userId?: string;
7
+ tokenId?: string;
8
+ ip?: string;
9
+ userAgent?: string;
10
+ orgId?: string;
11
+ sessionId?: string;
12
+ }
13
+ /**
14
+ * Metadata about the storage operation
15
+ */
16
+ export interface IStorageMetadata {
17
+ /** Content type of the object */
18
+ contentType?: string;
19
+ /** Size in bytes */
20
+ size?: number;
21
+ /** Content digest (e.g., sha256:abc123) */
22
+ digest?: string;
23
+ /** Package/artifact name */
24
+ packageName?: string;
25
+ /** Version */
26
+ version?: string;
27
+ }
28
+ /**
29
+ * Context passed to storage hooks
30
+ */
31
+ export interface IStorageHookContext {
32
+ /** Type of operation */
33
+ operation: 'put' | 'delete' | 'get';
34
+ /** Storage key/path */
35
+ key: string;
36
+ /** Protocol that triggered this operation */
37
+ protocol: TRegistryProtocol;
38
+ /** Actor who performed the operation (if known) */
39
+ actor?: IStorageActor;
40
+ /** Metadata about the object */
41
+ metadata?: IStorageMetadata;
42
+ /** Timestamp of the operation */
43
+ timestamp: Date;
44
+ }
45
+ /**
46
+ * Result from a beforePut hook that can modify the operation
47
+ */
48
+ export interface IBeforePutResult {
49
+ /** Whether to allow the operation */
50
+ allowed: boolean;
51
+ /** Optional reason for rejection */
52
+ reason?: string;
53
+ /** Optional modified metadata */
54
+ metadata?: IStorageMetadata;
55
+ }
56
+ /**
57
+ * Result from a beforeDelete hook
58
+ */
59
+ export interface IBeforeDeleteResult {
60
+ /** Whether to allow the operation */
61
+ allowed: boolean;
62
+ /** Optional reason for rejection */
63
+ reason?: string;
64
+ }
65
+ /**
66
+ * Storage event hooks for quota tracking, audit logging, cache invalidation, etc.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const quotaHooks: IStorageHooks = {
71
+ * async beforePut(context) {
72
+ * const quota = await getQuota(context.actor?.orgId);
73
+ * const currentUsage = await getUsage(context.actor?.orgId);
74
+ * if (currentUsage + (context.metadata?.size || 0) > quota) {
75
+ * return { allowed: false, reason: 'Quota exceeded' };
76
+ * }
77
+ * return { allowed: true };
78
+ * },
79
+ *
80
+ * async afterPut(context) {
81
+ * await updateUsage(context.actor?.orgId, context.metadata?.size || 0);
82
+ * await auditLog('storage.put', context);
83
+ * },
84
+ *
85
+ * async afterDelete(context) {
86
+ * await invalidateCache(context.key);
87
+ * }
88
+ * };
89
+ * ```
90
+ */
91
+ export interface IStorageHooks {
92
+ /**
93
+ * Called before storing an object.
94
+ * Return { allowed: false } to reject the operation.
95
+ * Use for quota checks, virus scanning, validation, etc.
96
+ */
97
+ beforePut?(context: IStorageHookContext): Promise<IBeforePutResult>;
98
+ /**
99
+ * Called after successfully storing an object.
100
+ * Use for quota tracking, audit logging, notifications, etc.
101
+ */
102
+ afterPut?(context: IStorageHookContext): Promise<void>;
103
+ /**
104
+ * Called before deleting an object.
105
+ * Return { allowed: false } to reject the operation.
106
+ * Use for preventing deletion of protected resources.
107
+ */
108
+ beforeDelete?(context: IStorageHookContext): Promise<IBeforeDeleteResult>;
109
+ /**
110
+ * Called after successfully deleting an object.
111
+ * Use for quota updates, audit logging, cache invalidation, etc.
112
+ */
113
+ afterDelete?(context: IStorageHookContext): Promise<void>;
114
+ /**
115
+ * Called after reading an object.
116
+ * Use for access logging, analytics, etc.
117
+ * Note: This is called even for cache hits.
118
+ */
119
+ afterGet?(context: IStorageHookContext): Promise<void>;
120
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5zdG9yYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY29yZS9pbnRlcmZhY2VzLnN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -54,11 +54,11 @@ export declare abstract class BaseUpstream {
54
54
  /**
55
55
  * Invalidate cache for a resource pattern.
56
56
  */
57
- invalidateCache(pattern: RegExp): number;
57
+ invalidateCache(pattern: RegExp): Promise<number>;
58
58
  /**
59
59
  * Clear all cache entries.
60
60
  */
61
- clearCache(): void;
61
+ clearCache(): Promise<void>;
62
62
  /**
63
63
  * Stop the upstream (cleanup resources).
64
64
  */
@@ -79,8 +79,15 @@ export class BaseUpstream {
79
79
  if (!this.config.enabled) {
80
80
  return null;
81
81
  }
82
+ // Get applicable upstreams sorted by priority
83
+ const applicableUpstreams = this.getApplicableUpstreams(context.resource);
84
+ if (applicableUpstreams.length === 0) {
85
+ return null;
86
+ }
87
+ // Use the first applicable upstream's URL for cache key
88
+ const primaryUpstreamUrl = applicableUpstreams[0]?.url;
82
89
  // Check cache first
83
- const cached = this.cache.get(context);
90
+ const cached = await this.cache.get(context, primaryUpstreamUrl);
84
91
  if (cached && !cached.stale) {
85
92
  return {
86
93
  success: true,
@@ -93,7 +100,7 @@ export class BaseUpstream {
93
100
  };
94
101
  }
95
102
  // Check for negative cache (recent 404)
96
- if (this.cache.hasNegative(context)) {
103
+ if (await this.cache.hasNegative(context, primaryUpstreamUrl)) {
97
104
  return {
98
105
  success: false,
99
106
  status: 404,
@@ -103,11 +110,6 @@ export class BaseUpstream {
103
110
  latencyMs: 0,
104
111
  };
105
112
  }
106
- // Get applicable upstreams sorted by priority
107
- const applicableUpstreams = this.getApplicableUpstreams(context.resource);
108
- if (applicableUpstreams.length === 0) {
109
- return null;
110
- }
111
113
  // If we have stale cache, return it immediately and revalidate in background
112
114
  if (cached?.stale && this.cacheConfig.staleWhileRevalidate) {
113
115
  // Fire and forget revalidation
@@ -132,11 +134,11 @@ export class BaseUpstream {
132
134
  const result = await withCircuitBreaker(breaker, () => this.fetchFromUpstream(upstream, context));
133
135
  // Cache successful responses
134
136
  if (result.success && result.body) {
135
- this.cache.set(context, Buffer.isBuffer(result.body) ? result.body : Buffer.from(JSON.stringify(result.body)), result.headers['content-type'] || 'application/octet-stream', result.headers, upstream.id);
137
+ await this.cache.set(context, Buffer.isBuffer(result.body) ? result.body : Buffer.from(JSON.stringify(result.body)), result.headers['content-type'] || 'application/octet-stream', result.headers, upstream.id, upstream.url);
136
138
  }
137
139
  // Cache 404 responses
138
140
  if (result.status === 404) {
139
- this.cache.setNegative(context, upstream.id);
141
+ await this.cache.setNegative(context, upstream.id, upstream.url);
140
142
  }
141
143
  return result;
142
144
  }
@@ -160,14 +162,14 @@ export class BaseUpstream {
160
162
  /**
161
163
  * Invalidate cache for a resource pattern.
162
164
  */
163
- invalidateCache(pattern) {
165
+ async invalidateCache(pattern) {
164
166
  return this.cache.invalidatePattern(pattern);
165
167
  }
166
168
  /**
167
169
  * Clear all cache entries.
168
170
  */
169
- clearCache() {
170
- this.cache.clear();
171
+ async clearCache() {
172
+ await this.cache.clear();
171
173
  }
172
174
  /**
173
175
  * Stop the upstream (cleanup resources).
@@ -392,7 +394,7 @@ export class BaseUpstream {
392
394
  try {
393
395
  const result = await withCircuitBreaker(breaker, () => this.fetchFromUpstream(upstream, context));
394
396
  if (result.success && result.body) {
395
- this.cache.set(context, Buffer.isBuffer(result.body) ? result.body : Buffer.from(JSON.stringify(result.body)), result.headers['content-type'] || 'application/octet-stream', result.headers, upstream.id);
397
+ await this.cache.set(context, Buffer.isBuffer(result.body) ? result.body : Buffer.from(JSON.stringify(result.body)), result.headers['content-type'] || 'application/octet-stream', result.headers, upstream.id, upstream.url);
396
398
  return; // Successfully revalidated
397
399
  }
398
400
  }
@@ -406,4 +408,4 @@ export class BaseUpstream {
406
408
  }
407
409
  }
408
410
  }
409
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5iYXNldXBzdHJlYW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy91cHN0cmVhbS9jbGFzc2VzLmJhc2V1cHN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQVl6QyxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLHlCQUF5QixHQUMxQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNuRyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFM0Q7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLE9BQWdCLFlBQVk7SUFJaEMsNkJBQTZCO0lBQ1YsTUFBTSxDQUEwQjtJQUVuRCxtQ0FBbUM7SUFDaEIsV0FBVyxDQUF1QjtJQUVyRCx3Q0FBd0M7SUFDckIsZ0JBQWdCLENBQTRCO0lBRS9ELG9DQUFvQztJQUNqQixlQUFlLEdBQWdDLElBQUksR0FBRyxFQUFFLENBQUM7SUFFNUUscUJBQXFCO0lBQ0YsS0FBSyxDQUFnQjtJQUV4QyxzQkFBc0I7SUFDSCxNQUFNLENBQTRCO0lBRXJELFlBQVksTUFBK0IsRUFBRSxNQUFrQztRQUM3RSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsR0FBRyxvQkFBb0IsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLHlCQUF5QixFQUFFLEdBQUcsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQy9FLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxNQUFNLEdBQUcs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
411
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5iYXNldXBzdHJlYW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy91cHN0cmVhbS9jbGFzc2VzLmJhc2V1cHN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQVl6QyxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLHlCQUF5QixHQUMxQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNuRyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFM0Q7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLE9BQWdCLFlBQVk7SUFJaEMsNkJBQTZCO0lBQ1YsTUFBTSxDQUEwQjtJQUVuRCxtQ0FBbUM7SUFDaEIsV0FBVyxDQUF1QjtJQUVyRCx3Q0FBd0M7SUFDckIsZ0JBQWdCLENBQTRCO0lBRS9ELG9DQUFvQztJQUNqQixlQUFlLEdBQWdDLElBQUksR0FBRyxFQUFFLENBQUM7SUFFNUUscUJBQXFCO0lBQ0YsS0FBSyxDQUFnQjtJQUV4QyxzQkFBc0I7SUFDSCxNQUFNLENBQTRCO0lBRXJELFlBQVksTUFBK0IsRUFBRSxNQUFrQztRQUM3RSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsR0FBRyxvQkFBb0IsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLHlCQUF5QixFQUFFLEdBQUcsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQy9FLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxNQUFNLEdBQUcs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
@@ -1,6 +1,7 @@
1
1
  import type { ICacheEntry, IUpstreamCacheConfig, IUpstreamFetchContext } from './interfaces.upstream.js';
2
+ import type { IStorageBackend } from '../core/interfaces.core.js';
2
3
  /**
3
- * In-memory cache for upstream responses.
4
+ * S3-backed upstream cache with in-memory hot layer.
4
5
  *
5
6
  * Features:
6
7
  * - TTL-based expiration
@@ -8,58 +9,76 @@ import type { ICacheEntry, IUpstreamCacheConfig, IUpstreamFetchContext } from '.
8
9
  * - Negative caching (404s)
9
10
  * - Content-type aware caching
10
11
  * - ETag support for conditional requests
12
+ * - Multi-upstream support via URL-based cache paths
13
+ * - Persistent S3 storage with in-memory hot layer
11
14
  *
12
- * Note: This is an in-memory implementation. For production with persistence,
13
- * extend this class to use RegistryStorage for S3-backed caching.
15
+ * Cache paths are structured as:
16
+ * cache/{escaped-upstream-url}/{protocol}:{method}:{path}
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // In-memory only (default)
21
+ * const cache = new UpstreamCache(config);
22
+ *
23
+ * // With S3 persistence
24
+ * const cache = new UpstreamCache(config, 10000, storage);
25
+ * ```
14
26
  */
15
27
  export declare class UpstreamCache {
16
- /** Cache storage */
17
- private readonly cache;
28
+ /** In-memory hot cache */
29
+ private readonly memoryCache;
18
30
  /** Configuration */
19
31
  private readonly config;
20
- /** Maximum cache entries (prevents memory bloat) */
21
- private readonly maxEntries;
32
+ /** Maximum in-memory cache entries */
33
+ private readonly maxMemoryEntries;
34
+ /** S3 storage backend (optional) */
35
+ private readonly storage?;
22
36
  /** Cleanup interval handle */
23
37
  private cleanupInterval;
24
- constructor(config?: Partial<IUpstreamCacheConfig>, maxEntries?: number);
38
+ constructor(config?: Partial<IUpstreamCacheConfig>, maxMemoryEntries?: number, storage?: IStorageBackend);
25
39
  /**
26
40
  * Check if caching is enabled.
27
41
  */
28
42
  isEnabled(): boolean;
43
+ /**
44
+ * Check if S3 storage is configured.
45
+ */
46
+ hasStorage(): boolean;
29
47
  /**
30
48
  * Get cached entry for a request context.
49
+ * Checks memory first, then falls back to S3.
31
50
  * Returns null if not found or expired (unless stale-while-revalidate).
32
51
  */
33
- get(context: IUpstreamFetchContext): ICacheEntry | null;
52
+ get(context: IUpstreamFetchContext, upstreamUrl?: string): Promise<ICacheEntry | null>;
34
53
  /**
35
- * Store a response in the cache.
54
+ * Store a response in the cache (memory and optionally S3).
36
55
  */
37
- set(context: IUpstreamFetchContext, data: Buffer, contentType: string, headers: Record<string, string>, upstreamId: string, options?: ICacheSetOptions): void;
56
+ set(context: IUpstreamFetchContext, data: Buffer, contentType: string, headers: Record<string, string>, upstreamId: string, upstreamUrl: string, options?: ICacheSetOptions): Promise<void>;
38
57
  /**
39
58
  * Store a negative cache entry (404 response).
40
59
  */
41
- setNegative(context: IUpstreamFetchContext, upstreamId: string): void;
60
+ setNegative(context: IUpstreamFetchContext, upstreamId: string, upstreamUrl: string): Promise<void>;
42
61
  /**
43
62
  * Check if there's a negative cache entry for this context.
44
63
  */
45
- hasNegative(context: IUpstreamFetchContext): boolean;
64
+ hasNegative(context: IUpstreamFetchContext, upstreamUrl?: string): Promise<boolean>;
46
65
  /**
47
66
  * Invalidate a specific cache entry.
48
67
  */
49
- invalidate(context: IUpstreamFetchContext): boolean;
68
+ invalidate(context: IUpstreamFetchContext, upstreamUrl?: string): Promise<boolean>;
50
69
  /**
51
70
  * Invalidate all entries matching a pattern.
52
71
  * Useful for invalidating all versions of a package.
53
72
  */
54
- invalidatePattern(pattern: RegExp): number;
73
+ invalidatePattern(pattern: RegExp): Promise<number>;
55
74
  /**
56
75
  * Invalidate all entries from a specific upstream.
57
76
  */
58
- invalidateUpstream(upstreamId: string): number;
77
+ invalidateUpstream(upstreamId: string): Promise<number>;
59
78
  /**
60
- * Clear all cache entries.
79
+ * Clear all cache entries (memory and S3).
61
80
  */
62
- clear(): void;
81
+ clear(): Promise<void>;
63
82
  /**
64
83
  * Get cache statistics.
65
84
  */
@@ -68,8 +87,34 @@ export declare class UpstreamCache {
68
87
  * Stop the cache and cleanup.
69
88
  */
70
89
  stop(): void;
90
+ /**
91
+ * Build storage path for a cache key.
92
+ * Escapes upstream URL for safe use in S3 paths.
93
+ */
94
+ private buildStoragePath;
95
+ /**
96
+ * Build storage path for cache metadata.
97
+ */
98
+ private buildMetadataPath;
99
+ /**
100
+ * Load a cache entry from S3 storage.
101
+ */
102
+ private loadFromStorage;
103
+ /**
104
+ * Save a cache entry to S3 storage.
105
+ */
106
+ private saveToStorage;
107
+ /**
108
+ * Delete a cache entry from S3 storage.
109
+ */
110
+ private deleteFromStorage;
111
+ /**
112
+ * Escape a URL for safe use in storage paths.
113
+ */
114
+ private escapeUrl;
71
115
  /**
72
116
  * Build a unique cache key for a request context.
117
+ * Includes escaped upstream URL for multi-upstream support.
73
118
  */
74
119
  private buildCacheKey;
75
120
  /**
@@ -89,7 +134,7 @@ export declare class UpstreamCache {
89
134
  */
90
135
  private startCleanup;
91
136
  /**
92
- * Remove all expired entries.
137
+ * Remove all expired entries from memory cache.
93
138
  */
94
139
  private cleanup;
95
140
  }
@@ -106,7 +151,7 @@ export interface ICacheSetOptions {
106
151
  * Cache statistics.
107
152
  */
108
153
  export interface ICacheStats {
109
- /** Total number of cached entries */
154
+ /** Total number of cached entries in memory */
110
155
  totalEntries: number;
111
156
  /** Number of fresh (non-expired) entries */
112
157
  freshEntries: number;
@@ -114,10 +159,12 @@ export interface ICacheStats {
114
159
  staleEntries: number;
115
160
  /** Number of negative cache entries */
116
161
  negativeEntries: number;
117
- /** Total size of cached data in bytes */
162
+ /** Total size of cached data in bytes (memory only) */
118
163
  totalSizeBytes: number;
119
- /** Maximum allowed entries */
164
+ /** Maximum allowed memory entries */
120
165
  maxEntries: number;
121
166
  /** Whether caching is enabled */
122
167
  enabled: boolean;
168
+ /** Whether S3 storage is configured */
169
+ hasStorage: boolean;
123
170
  }