specweave 0.23.8 → 0.23.12

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 (130) hide show
  1. package/.claude-plugin/marketplace.json +7 -7
  2. package/CLAUDE.md +391 -1338
  3. package/dist/src/cli/commands/cleanup-cache.d.ts +14 -0
  4. package/dist/src/cli/commands/cleanup-cache.d.ts.map +1 -0
  5. package/dist/src/cli/commands/cleanup-cache.js +63 -0
  6. package/dist/src/cli/commands/cleanup-cache.js.map +1 -0
  7. package/dist/src/cli/commands/init.js +40 -0
  8. package/dist/src/cli/commands/init.js.map +1 -1
  9. package/dist/src/cli/commands/migrate-config.d.ts +22 -0
  10. package/dist/src/cli/commands/migrate-config.d.ts.map +1 -0
  11. package/dist/src/cli/commands/migrate-config.js +149 -0
  12. package/dist/src/cli/commands/migrate-config.js.map +1 -0
  13. package/dist/src/cli/helpers/async-project-loader.d.ts +148 -0
  14. package/dist/src/cli/helpers/async-project-loader.d.ts.map +1 -0
  15. package/dist/src/cli/helpers/async-project-loader.js +351 -0
  16. package/dist/src/cli/helpers/async-project-loader.js.map +1 -0
  17. package/dist/src/cli/helpers/cancelation-handler.d.ts +123 -0
  18. package/dist/src/cli/helpers/cancelation-handler.d.ts.map +1 -0
  19. package/dist/src/cli/helpers/cancelation-handler.js +187 -0
  20. package/dist/src/cli/helpers/cancelation-handler.js.map +1 -0
  21. package/dist/src/cli/helpers/import-strategy-prompter.d.ts +43 -0
  22. package/dist/src/cli/helpers/import-strategy-prompter.d.ts.map +1 -0
  23. package/dist/src/cli/helpers/import-strategy-prompter.js +136 -0
  24. package/dist/src/cli/helpers/import-strategy-prompter.js.map +1 -0
  25. package/dist/src/cli/helpers/issue-tracker/ado.d.ts +5 -2
  26. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  27. package/dist/src/cli/helpers/issue-tracker/ado.js +90 -40
  28. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  29. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  30. package/dist/src/cli/helpers/issue-tracker/index.js +112 -60
  31. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  32. package/dist/src/cli/helpers/issue-tracker/jira.d.ts +26 -2
  33. package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
  34. package/dist/src/cli/helpers/issue-tracker/jira.js +197 -132
  35. package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
  36. package/dist/src/cli/helpers/progress-tracker.d.ts +121 -0
  37. package/dist/src/cli/helpers/progress-tracker.d.ts.map +1 -0
  38. package/dist/src/cli/helpers/progress-tracker.js +202 -0
  39. package/dist/src/cli/helpers/progress-tracker.js.map +1 -0
  40. package/dist/src/cli/helpers/project-count-fetcher.d.ts +69 -0
  41. package/dist/src/cli/helpers/project-count-fetcher.d.ts.map +1 -0
  42. package/dist/src/cli/helpers/project-count-fetcher.js +173 -0
  43. package/dist/src/cli/helpers/project-count-fetcher.js.map +1 -0
  44. package/dist/src/config/types.d.ts +14 -14
  45. package/dist/src/core/cache/cache-manager.d.ts +119 -0
  46. package/dist/src/core/cache/cache-manager.d.ts.map +1 -0
  47. package/dist/src/core/cache/cache-manager.js +304 -0
  48. package/dist/src/core/cache/cache-manager.js.map +1 -0
  49. package/dist/src/core/cache/rate-limit-checker.d.ts +92 -0
  50. package/dist/src/core/cache/rate-limit-checker.d.ts.map +1 -0
  51. package/dist/src/core/cache/rate-limit-checker.js +160 -0
  52. package/dist/src/core/cache/rate-limit-checker.js.map +1 -0
  53. package/dist/src/core/config/config-manager.d.ts +135 -0
  54. package/dist/src/core/config/config-manager.d.ts.map +1 -0
  55. package/dist/src/core/config/config-manager.js +341 -0
  56. package/dist/src/core/config/config-manager.js.map +1 -0
  57. package/dist/src/core/config/config-migrator.d.ts +102 -0
  58. package/dist/src/core/config/config-migrator.d.ts.map +1 -0
  59. package/dist/src/core/config/config-migrator.js +367 -0
  60. package/dist/src/core/config/config-migrator.js.map +1 -0
  61. package/dist/src/core/config/index.d.ts +10 -0
  62. package/dist/src/core/config/index.d.ts.map +1 -0
  63. package/dist/src/core/config/index.js +10 -0
  64. package/dist/src/core/config/index.js.map +1 -0
  65. package/dist/src/core/config/types.d.ts +216 -0
  66. package/dist/src/core/config/types.d.ts.map +1 -0
  67. package/dist/src/core/config/types.js +32 -0
  68. package/dist/src/core/config/types.js.map +1 -0
  69. package/dist/src/core/progress/cancelation-handler.d.ts +79 -0
  70. package/dist/src/core/progress/cancelation-handler.d.ts.map +1 -0
  71. package/dist/src/core/progress/cancelation-handler.js +111 -0
  72. package/dist/src/core/progress/cancelation-handler.js.map +1 -0
  73. package/dist/src/core/progress/import-state.d.ts +71 -0
  74. package/dist/src/core/progress/import-state.d.ts.map +1 -0
  75. package/dist/src/core/progress/import-state.js +96 -0
  76. package/dist/src/core/progress/import-state.js.map +1 -0
  77. package/dist/src/core/progress/progress-tracker.d.ts +139 -0
  78. package/dist/src/core/progress/progress-tracker.d.ts.map +1 -0
  79. package/dist/src/core/progress/progress-tracker.js +223 -0
  80. package/dist/src/core/progress/progress-tracker.js.map +1 -0
  81. package/dist/src/init/architecture/types.d.ts +6 -6
  82. package/dist/src/integrations/ado/ado-client.d.ts +25 -0
  83. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  84. package/dist/src/integrations/ado/ado-client.js +67 -0
  85. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  86. package/dist/src/integrations/ado/ado-dependency-loader.d.ts +99 -0
  87. package/dist/src/integrations/ado/ado-dependency-loader.d.ts.map +1 -0
  88. package/dist/src/integrations/ado/ado-dependency-loader.js +207 -0
  89. package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -0
  90. package/dist/src/integrations/jira/jira-client.d.ts +32 -0
  91. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  92. package/dist/src/integrations/jira/jira-client.js +81 -0
  93. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  94. package/dist/src/integrations/jira/jira-dependency-loader.d.ts +101 -0
  95. package/dist/src/integrations/jira/jira-dependency-loader.d.ts.map +1 -0
  96. package/dist/src/integrations/jira/jira-dependency-loader.js +200 -0
  97. package/dist/src/integrations/jira/jira-dependency-loader.js.map +1 -0
  98. package/dist/src/integrations/jira/jira-hierarchy-mapper.d.ts +104 -0
  99. package/dist/src/integrations/jira/jira-hierarchy-mapper.d.ts.map +1 -0
  100. package/dist/src/integrations/jira/jira-hierarchy-mapper.js +178 -0
  101. package/dist/src/integrations/jira/jira-hierarchy-mapper.js.map +1 -0
  102. package/package.json +1 -1
  103. package/plugins/specweave/.claude-plugin/plugin.json +20 -0
  104. package/plugins/specweave/agents/architect/AGENT.md +100 -602
  105. package/plugins/specweave/agents/pm/AGENT.md +96 -597
  106. package/plugins/specweave/agents/pm/AGENT.md.bak +1893 -0
  107. package/plugins/specweave/agents/pm/AGENT.md.bak2 +1754 -0
  108. package/plugins/specweave/commands/check-hooks.md +257 -0
  109. package/plugins/specweave/commands/migrate-config.md +104 -0
  110. package/plugins/specweave/hooks/post-edit-spec.sh +202 -31
  111. package/plugins/specweave/hooks/post-task-completion.sh +225 -228
  112. package/plugins/specweave/hooks/post-write-spec.sh +207 -31
  113. package/plugins/specweave/hooks/pre-edit-spec.sh +151 -0
  114. package/plugins/specweave/hooks/pre-task-completion.sh +5 -7
  115. package/plugins/specweave/hooks/pre-write-spec.sh +151 -0
  116. package/plugins/specweave/hooks/test-pretooluse-env.sh +72 -0
  117. package/plugins/specweave/skills/compliance-architecture/SKILL.md +374 -0
  118. package/plugins/specweave/skills/external-sync-wizard/SKILL.md +610 -0
  119. package/plugins/specweave/skills/pm-closure-validation/SKILL.md +541 -0
  120. package/plugins/specweave/skills/roadmap-planner/SKILL.md +473 -0
  121. package/plugins/specweave-ado/commands/refresh-cache.js +25 -0
  122. package/plugins/specweave-ado/commands/refresh-cache.ts +40 -0
  123. package/plugins/specweave-ado/hooks/post-task-completion.sh +1 -1
  124. package/plugins/specweave-github/hooks/post-task-completion.sh +1 -1
  125. package/plugins/specweave-jira/commands/refresh-cache.js +25 -0
  126. package/plugins/specweave-jira/commands/refresh-cache.ts +40 -0
  127. package/plugins/specweave-jira/hooks/post-task-completion.sh +1 -1
  128. package/plugins/specweave-kafka-streams/commands/topology.md +437 -0
  129. package/plugins/specweave-n8n/commands/workflow-template.md +262 -0
  130. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +228 -6333
@@ -0,0 +1,119 @@
1
+ import { Logger } from '../../utils/logger.js';
2
+ /**
3
+ * Cached data wrapper with TTL metadata
4
+ */
5
+ export interface CachedData<T> {
6
+ data: T;
7
+ timestamp: number;
8
+ ttl: number;
9
+ }
10
+ /**
11
+ * Cache statistics for monitoring and debugging
12
+ */
13
+ export interface CacheStats {
14
+ totalFiles: number;
15
+ totalSize: number;
16
+ oldestCache: string | null;
17
+ oldestCacheAge: number | null;
18
+ providers: {
19
+ [provider: string]: {
20
+ files: number;
21
+ size: number;
22
+ };
23
+ };
24
+ }
25
+ /**
26
+ * CacheManager - Manages file-based caching with TTL validation
27
+ *
28
+ * Features:
29
+ * - 24-hour TTL by default (configurable)
30
+ * - Atomic writes (temp file + rename)
31
+ * - Corruption detection and auto-recovery
32
+ * - Per-project cache separation
33
+ * - Thread-safe operations
34
+ *
35
+ * Cache file format:
36
+ * {
37
+ * "data": <T>,
38
+ * "timestamp": 1700000000000,
39
+ * "ttl": 86400000
40
+ * }
41
+ */
42
+ export declare class CacheManager {
43
+ private cacheDir;
44
+ private logger;
45
+ private defaultTTL;
46
+ constructor(projectRoot: string, options?: {
47
+ logger?: Logger;
48
+ ttl?: number;
49
+ });
50
+ /**
51
+ * Get cached data if valid (within TTL)
52
+ *
53
+ * @param key Cache key (e.g., "jira-projects", "jira-BACKEND-deps")
54
+ * @returns Cached data or null if cache miss/expired/corrupted
55
+ */
56
+ get<T>(key: string): Promise<T | null>;
57
+ /**
58
+ * Get cached data even if expired (stale cache fallback)
59
+ *
60
+ * Used for rate limit fallback: when API rate limit hit,
61
+ * use stale cache instead of failing
62
+ *
63
+ * @param key Cache key
64
+ * @returns Cached data or null if missing/corrupted (ignores TTL)
65
+ */
66
+ getStale<T>(key: string): Promise<T | null>;
67
+ /**
68
+ * Set cached data with current timestamp and TTL
69
+ *
70
+ * Uses atomic write pattern (temp file + rename) to prevent corruption
71
+ *
72
+ * @param key Cache key
73
+ * @param data Data to cache
74
+ * @param ttl Optional custom TTL (overrides default)
75
+ */
76
+ set<T>(key: string, data: T, ttl?: number): Promise<void>;
77
+ /**
78
+ * Delete cached data
79
+ *
80
+ * @param key Cache key
81
+ */
82
+ delete(key: string): Promise<void>;
83
+ /**
84
+ * Clear all cached data
85
+ */
86
+ clearAll(): Promise<void>;
87
+ /**
88
+ * Get cache statistics for monitoring
89
+ */
90
+ getStats(): Promise<CacheStats>;
91
+ /**
92
+ * Delete caches older than specified age
93
+ *
94
+ * @param maxAgeMs Maximum age in milliseconds
95
+ * @returns Count of deleted caches
96
+ */
97
+ deleteOlderThan(maxAgeMs: number): Promise<number>;
98
+ /**
99
+ * Check if cached data is still valid (within TTL)
100
+ */
101
+ private isValid;
102
+ /**
103
+ * Validate cache structure has required fields
104
+ */
105
+ private isValidCacheStructure;
106
+ /**
107
+ * Get full cache file path for a key
108
+ */
109
+ private getCachePath;
110
+ /**
111
+ * Ensure cache directory exists
112
+ */
113
+ private ensureCacheDir;
114
+ /**
115
+ * Log cache errors to dedicated error log
116
+ */
117
+ private logCacheError;
118
+ }
119
+ //# sourceMappingURL=cache-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE;QACT,CAAC,QAAQ,EAAE,MAAM,GAAG;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;KACH,CAAC;CACH;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAA+B;gBAG/C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;KACT;IASR;;;;;OAKG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA0C5C;;;;;;;;OAQG;IACG,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAkCjD;;;;;;;;OAQG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC/D;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAwDrC;;;;;OAKG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkCxD;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;YACW,cAAc;IAM5B;;OAEG;YACW,aAAa;CAa5B"}
@@ -0,0 +1,304 @@
1
+ import { promises as fs } from 'fs';
2
+ import { existsSync } from 'fs';
3
+ import path from 'path';
4
+ import { consoleLogger } from '../../utils/logger.js';
5
+ /**
6
+ * CacheManager - Manages file-based caching with TTL validation
7
+ *
8
+ * Features:
9
+ * - 24-hour TTL by default (configurable)
10
+ * - Atomic writes (temp file + rename)
11
+ * - Corruption detection and auto-recovery
12
+ * - Per-project cache separation
13
+ * - Thread-safe operations
14
+ *
15
+ * Cache file format:
16
+ * {
17
+ * "data": <T>,
18
+ * "timestamp": 1700000000000,
19
+ * "ttl": 86400000
20
+ * }
21
+ */
22
+ export class CacheManager {
23
+ constructor(projectRoot, options = {}) {
24
+ this.defaultTTL = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
25
+ this.cacheDir = path.join(projectRoot, '.specweave', 'cache');
26
+ this.logger = options.logger ?? consoleLogger;
27
+ if (options.ttl) {
28
+ this.defaultTTL = options.ttl;
29
+ }
30
+ }
31
+ /**
32
+ * Get cached data if valid (within TTL)
33
+ *
34
+ * @param key Cache key (e.g., "jira-projects", "jira-BACKEND-deps")
35
+ * @returns Cached data or null if cache miss/expired/corrupted
36
+ */
37
+ async get(key) {
38
+ const filePath = this.getCachePath(key);
39
+ if (!existsSync(filePath)) {
40
+ this.logger.log(`Cache miss: ${key}`);
41
+ return null;
42
+ }
43
+ try {
44
+ const content = await fs.readFile(filePath, 'utf-8');
45
+ const cached = JSON.parse(content);
46
+ // Validate cache structure
47
+ if (!this.isValidCacheStructure(cached)) {
48
+ this.logger.error(`Invalid cache structure for ${key}, deleting...`);
49
+ await this.delete(key);
50
+ return null;
51
+ }
52
+ // Check TTL
53
+ if (!this.isValid(cached)) {
54
+ const age = Date.now() - cached.timestamp;
55
+ const ageHours = (age / (1000 * 60 * 60)).toFixed(1);
56
+ this.logger.log(`Cache expired: ${key} (age: ${ageHours}h, TTL: ${cached.ttl / (1000 * 60 * 60)}h)`);
57
+ // Don't delete expired cache immediately - might be used as stale fallback
58
+ return null;
59
+ }
60
+ const remaining = cached.timestamp + cached.ttl - Date.now();
61
+ const remainingHours = (remaining / (1000 * 60 * 60)).toFixed(1);
62
+ this.logger.log(`Cache hit: ${key} (TTL remaining: ${remainingHours}h)`);
63
+ return cached.data;
64
+ }
65
+ catch (error) {
66
+ // Corruption detected
67
+ this.logger.error(`Cache corruption detected for ${key}: ${error.message}`);
68
+ await this.logCacheError(key, error);
69
+ await this.delete(key);
70
+ return null;
71
+ }
72
+ }
73
+ /**
74
+ * Get cached data even if expired (stale cache fallback)
75
+ *
76
+ * Used for rate limit fallback: when API rate limit hit,
77
+ * use stale cache instead of failing
78
+ *
79
+ * @param key Cache key
80
+ * @returns Cached data or null if missing/corrupted (ignores TTL)
81
+ */
82
+ async getStale(key) {
83
+ const filePath = this.getCachePath(key);
84
+ if (!existsSync(filePath)) {
85
+ this.logger.log(`No stale cache available: ${key}`);
86
+ return null;
87
+ }
88
+ try {
89
+ const content = await fs.readFile(filePath, 'utf-8');
90
+ const cached = JSON.parse(content);
91
+ // Validate structure only (ignore TTL)
92
+ if (!this.isValidCacheStructure(cached)) {
93
+ this.logger.error(`Invalid cache structure for ${key}, deleting...`);
94
+ await this.delete(key);
95
+ return null;
96
+ }
97
+ const age = Date.now() - cached.timestamp;
98
+ const ageHours = (age / (1000 * 60 * 60)).toFixed(1);
99
+ const ttlHours = cached.ttl / (1000 * 60 * 60);
100
+ const expiredHoursAgo = (parseFloat(ageHours) - ttlHours).toFixed(1);
101
+ this.logger.warn(`Using stale cache: ${key} (age: ${ageHours}h, expired ${expiredHoursAgo}h ago)`);
102
+ return cached.data;
103
+ }
104
+ catch (error) {
105
+ this.logger.error(`Failed to read stale cache for ${key}: ${error.message}`);
106
+ return null;
107
+ }
108
+ }
109
+ /**
110
+ * Set cached data with current timestamp and TTL
111
+ *
112
+ * Uses atomic write pattern (temp file + rename) to prevent corruption
113
+ *
114
+ * @param key Cache key
115
+ * @param data Data to cache
116
+ * @param ttl Optional custom TTL (overrides default)
117
+ */
118
+ async set(key, data, ttl) {
119
+ await this.ensureCacheDir();
120
+ const filePath = this.getCachePath(key);
121
+ const tempPath = `${filePath}.tmp`;
122
+ const cached = {
123
+ data,
124
+ timestamp: Date.now(),
125
+ ttl: ttl ?? this.defaultTTL,
126
+ };
127
+ try {
128
+ // Write to temp file first (atomic write pattern)
129
+ await fs.writeFile(tempPath, JSON.stringify(cached, null, 2), 'utf-8');
130
+ // Rename temp file to final name (atomic operation)
131
+ await fs.rename(tempPath, filePath);
132
+ this.logger.log(`Cache set: ${key} (TTL: ${cached.ttl / (1000 * 60 * 60)}h)`);
133
+ }
134
+ catch (error) {
135
+ this.logger.error(`Failed to write cache for ${key}: ${error.message}`);
136
+ // Cleanup temp file if exists
137
+ if (existsSync(tempPath)) {
138
+ await fs.unlink(tempPath).catch(() => { });
139
+ }
140
+ throw error;
141
+ }
142
+ }
143
+ /**
144
+ * Delete cached data
145
+ *
146
+ * @param key Cache key
147
+ */
148
+ async delete(key) {
149
+ const filePath = this.getCachePath(key);
150
+ if (existsSync(filePath)) {
151
+ await fs.unlink(filePath);
152
+ this.logger.log(`Cache deleted: ${key}`);
153
+ }
154
+ }
155
+ /**
156
+ * Clear all cached data
157
+ */
158
+ async clearAll() {
159
+ if (!existsSync(this.cacheDir)) {
160
+ return;
161
+ }
162
+ const files = await fs.readdir(this.cacheDir);
163
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
164
+ for (const file of jsonFiles) {
165
+ const filePath = path.join(this.cacheDir, file);
166
+ await fs.unlink(filePath);
167
+ }
168
+ this.logger.log(`Cleared ${jsonFiles.length} cache files`);
169
+ }
170
+ /**
171
+ * Get cache statistics for monitoring
172
+ */
173
+ async getStats() {
174
+ const stats = {
175
+ totalFiles: 0,
176
+ totalSize: 0,
177
+ oldestCache: null,
178
+ oldestCacheAge: null,
179
+ providers: {},
180
+ };
181
+ if (!existsSync(this.cacheDir)) {
182
+ return stats;
183
+ }
184
+ const files = await fs.readdir(this.cacheDir);
185
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
186
+ let oldestTimestamp = Date.now();
187
+ let oldestFile = null;
188
+ for (const file of jsonFiles) {
189
+ const filePath = path.join(this.cacheDir, file);
190
+ const fileStats = await fs.stat(filePath);
191
+ stats.totalFiles++;
192
+ stats.totalSize += fileStats.size;
193
+ // Determine provider from filename (e.g., "jira-projects.json" → "jira")
194
+ const provider = file.split('-')[0];
195
+ if (!stats.providers[provider]) {
196
+ stats.providers[provider] = { files: 0, size: 0 };
197
+ }
198
+ stats.providers[provider].files++;
199
+ stats.providers[provider].size += fileStats.size;
200
+ // Find oldest cache
201
+ try {
202
+ const content = await fs.readFile(filePath, 'utf-8');
203
+ const cached = JSON.parse(content);
204
+ if (cached.timestamp < oldestTimestamp) {
205
+ oldestTimestamp = cached.timestamp;
206
+ oldestFile = file;
207
+ }
208
+ }
209
+ catch {
210
+ // Ignore corrupted files
211
+ }
212
+ }
213
+ if (oldestFile) {
214
+ stats.oldestCache = oldestFile;
215
+ stats.oldestCacheAge = (Date.now() - oldestTimestamp) / (1000 * 60 * 60); // hours
216
+ }
217
+ return stats;
218
+ }
219
+ /**
220
+ * Delete caches older than specified age
221
+ *
222
+ * @param maxAgeMs Maximum age in milliseconds
223
+ * @returns Count of deleted caches
224
+ */
225
+ async deleteOlderThan(maxAgeMs) {
226
+ if (!existsSync(this.cacheDir)) {
227
+ return 0;
228
+ }
229
+ const files = await fs.readdir(this.cacheDir);
230
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
231
+ let deletedCount = 0;
232
+ const cutoffTime = Date.now() - maxAgeMs;
233
+ for (const file of jsonFiles) {
234
+ const filePath = path.join(this.cacheDir, file);
235
+ try {
236
+ const content = await fs.readFile(filePath, 'utf-8');
237
+ const cached = JSON.parse(content);
238
+ if (cached.timestamp < cutoffTime) {
239
+ await fs.unlink(filePath);
240
+ deletedCount++;
241
+ this.logger.log(`Deleted old cache: ${file}`);
242
+ }
243
+ }
244
+ catch {
245
+ // Delete corrupted files too
246
+ await fs.unlink(filePath);
247
+ deletedCount++;
248
+ this.logger.log(`Deleted corrupted cache: ${file}`);
249
+ }
250
+ }
251
+ return deletedCount;
252
+ }
253
+ /**
254
+ * Check if cached data is still valid (within TTL)
255
+ */
256
+ isValid(cached) {
257
+ const now = Date.now();
258
+ const age = now - cached.timestamp;
259
+ return age < cached.ttl;
260
+ }
261
+ /**
262
+ * Validate cache structure has required fields
263
+ */
264
+ isValidCacheStructure(cached) {
265
+ return (cached &&
266
+ typeof cached === 'object' &&
267
+ 'data' in cached &&
268
+ 'timestamp' in cached &&
269
+ 'ttl' in cached &&
270
+ typeof cached.timestamp === 'number' &&
271
+ typeof cached.ttl === 'number');
272
+ }
273
+ /**
274
+ * Get full cache file path for a key
275
+ */
276
+ getCachePath(key) {
277
+ return path.join(this.cacheDir, `${key}.json`);
278
+ }
279
+ /**
280
+ * Ensure cache directory exists
281
+ */
282
+ async ensureCacheDir() {
283
+ if (!existsSync(this.cacheDir)) {
284
+ await fs.mkdir(this.cacheDir, { recursive: true });
285
+ }
286
+ }
287
+ /**
288
+ * Log cache errors to dedicated error log
289
+ */
290
+ async logCacheError(key, error) {
291
+ const logDir = path.join(path.dirname(this.cacheDir), 'logs');
292
+ const logPath = path.join(logDir, 'cache-errors.log');
293
+ try {
294
+ await fs.mkdir(logDir, { recursive: true });
295
+ const timestamp = new Date().toISOString();
296
+ const logEntry = `[${timestamp}] Cache error for ${key}: ${error.message}\n`;
297
+ await fs.appendFile(logPath, logEntry, 'utf-8');
298
+ }
299
+ catch {
300
+ // Ignore logging errors
301
+ }
302
+ }
303
+ }
304
+ //# sourceMappingURL=cache-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-manager.js","sourceRoot":"","sources":["../../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAU,aAAa,EAAE,MAAM,uBAAuB,CAAC;AA2B9D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,YAAY;IAKvB,YACE,WAAmB,EACnB,UAGI,EAAE;QAPA,eAAU,GAAW,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,2BAA2B;QAS3E,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;QAC9C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;QAChC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,MAAM,GAAkB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAElD,2BAA2B;YAC3B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,GAAG,eAAe,CAAC,CAAC;gBACrE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,YAAY;YACZ,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;gBAC1C,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,GAAG,UAAU,QAAQ,WAAW,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrG,2EAA2E;gBAC3E,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7D,MAAM,cAAc,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,GAAG,oBAAoB,cAAc,IAAI,CAAC,CAAC;YAEzE,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,sBAAsB;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,QAAQ,CAAI,GAAW;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,MAAM,GAAkB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAElD,uCAAuC;YACvC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,GAAG,eAAe,CAAC,CAAC;gBACrE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;YAC1C,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/C,MAAM,eAAe,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,sBAAsB,GAAG,UAAU,QAAQ,cAAc,eAAe,QAAQ,CACjF,CAAC;YAEF,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,GAAY;QAC7C,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAE5B,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,GAAG,QAAQ,MAAM,CAAC;QAEnC,MAAM,MAAM,GAAkB;YAC5B,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,UAAU;SAC5B,CAAC;QAEF,IAAI,CAAC;YACH,kDAAkD;YAClD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEvE,oDAAoD;YACpD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,GAAG,UAAU,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAExE,8BAA8B;YAC9B,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzB,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAEzD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAChD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,SAAS,CAAC,MAAM,cAAc,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,KAAK,GAAe;YACxB,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,IAAI;YACjB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE,EAAE;SACd,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAEzD,IAAI,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjC,IAAI,UAAU,GAAkB,IAAI,CAAC;QAErC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAE1C,KAAK,CAAC,UAAU,EAAE,CAAC;YACnB,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC;YAElC,yEAAyE;YACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/B,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACpD,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;YAClC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC;YAEjD,oBAAoB;YACpB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAoB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAEpD,IAAI,MAAM,CAAC,SAAS,GAAG,eAAe,EAAE,CAAC;oBACvC,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC;oBACnC,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;QACH,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;YAC/B,KAAK,CAAC,cAAc,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ;QACpF,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,eAAe,CAAC,QAAgB;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAEzD,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAEhD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAoB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAEpD,IAAI,MAAM,CAAC,SAAS,GAAG,UAAU,EAAE,CAAC;oBAClC,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAC1B,YAAY,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,6BAA6B;gBAC7B,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1B,YAAY,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,OAAO,CAAC,MAAuB;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC;QACnC,OAAO,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IAC1B,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,MAAW;QACvC,OAAO,CACL,MAAM;YACN,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,IAAI,MAAM;YAChB,WAAW,IAAI,MAAM;YACrB,KAAK,IAAI,MAAM;YACf,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YACpC,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAC/B,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,GAAW;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc;QAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,KAAY;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,IAAI,SAAS,qBAAqB,GAAG,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC;YAC7E,MAAM,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,92 @@
1
+ import { Logger } from '../../utils/logger.js';
2
+ /**
3
+ * Rate limit response headers (JIRA, GitHub, ADO)
4
+ */
5
+ export interface RateLimitHeaders {
6
+ remaining?: number;
7
+ reset?: number;
8
+ retryAfter?: number;
9
+ }
10
+ /**
11
+ * Rate limit check result
12
+ */
13
+ export interface RateLimitCheckResult {
14
+ canProceed: boolean;
15
+ reason?: string;
16
+ retryAfter?: number;
17
+ remaining?: number;
18
+ }
19
+ /**
20
+ * RateLimitChecker - Detects API rate limits and prevents hitting limits
21
+ *
22
+ * Features:
23
+ * - Parses rate limit headers from JIRA, GitHub, ADO
24
+ * - Handles 429 (Too Many Requests) errors
25
+ * - Suggests using stale cache when rate limit low
26
+ * - Supports exponential backoff
27
+ *
28
+ * Supported headers:
29
+ * - X-RateLimit-Remaining (JIRA Cloud, GitHub)
30
+ * - X-RateLimit-Reset (JIRA Cloud, GitHub)
31
+ * - Retry-After (Standard HTTP, JIRA Server, ADO)
32
+ * - x-ms-ratelimit-remaining (Azure DevOps)
33
+ *
34
+ * Threshold: 10 requests remaining (configurable)
35
+ */
36
+ export declare class RateLimitChecker {
37
+ private logger;
38
+ private threshold;
39
+ constructor(options?: {
40
+ logger?: Logger;
41
+ threshold?: number;
42
+ });
43
+ /**
44
+ * Check if safe to proceed with API call based on response headers
45
+ *
46
+ * @param headers Response headers from previous API call
47
+ * @returns RateLimitCheckResult with canProceed flag
48
+ */
49
+ shouldProceed(headers: RateLimitHeaders): RateLimitCheckResult;
50
+ /**
51
+ * Handle 429 (Too Many Requests) error
52
+ *
53
+ * @param error Error object with response headers
54
+ * @returns Promise<void>
55
+ */
56
+ handleRateLimitError(error: any): Promise<void>;
57
+ /**
58
+ * Extract rate limit headers from HTTP response
59
+ *
60
+ * Supports multiple header formats:
61
+ * - JIRA Cloud: X-RateLimit-Remaining, X-RateLimit-Reset
62
+ * - GitHub: X-RateLimit-Remaining, X-RateLimit-Reset
63
+ * - ADO: x-ms-ratelimit-remaining-resource, Retry-After
64
+ * - Standard: Retry-After
65
+ *
66
+ * @param response HTTP response or response-like object
67
+ * @returns RateLimitHeaders object
68
+ */
69
+ extractHeaders(response: any): RateLimitHeaders;
70
+ /**
71
+ * Extract Retry-After from error response
72
+ *
73
+ * @param error Error object
74
+ * @returns Retry-After in seconds, or null
75
+ */
76
+ private extractRetryAfter;
77
+ /**
78
+ * Extract X-RateLimit-Reset from error response
79
+ *
80
+ * @param error Error object
81
+ * @returns Reset timestamp (Unix seconds), or null
82
+ */
83
+ private extractReset;
84
+ /**
85
+ * Check if error is a rate limit error (429 status)
86
+ *
87
+ * @param error Error object
88
+ * @returns True if 429 error
89
+ */
90
+ isRateLimitError(error: any): boolean;
91
+ }
92
+ //# sourceMappingURL=rate-limit-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-checker.d.ts","sourceRoot":"","sources":["../../../../src/core/cache/rate-limit-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;IAKjE;;;;;OAKG;IACH,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,oBAAoB;IA4B9D;;;;;OAKG;IACG,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrD;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,gBAAgB;IAsC/C;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAYpB;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;CAGtC"}