claude-flow-novice 1.6.1 → 1.6.2

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 (244) hide show
  1. package/.claude/agents/cfn-loop/product-owner.md +54 -4
  2. package/.claude/commands/cfn-claude-sync.md +303 -0
  3. package/.claude/commands/cfn-loop-epic.md +290 -0
  4. package/.claude/commands/cfn-loop-single.md +168 -0
  5. package/.claude/commands/cfn-loop-sprints.md +384 -0
  6. package/.claude/commands/cfn-loop.md +180 -0
  7. package/.claude/commands/metrics-summary.md +58 -0
  8. package/.claude/commands/parse-epic.md +357 -0
  9. package/.claude/settings.json +4 -4
  10. package/.claude/settings.local.json +9 -2
  11. package/.claude-flow-novice/.claude/agents/cfn-loop/product-owner.md +792 -0
  12. package/.claude-flow-novice/dist/mcp/server.js +21 -2
  13. package/.claude-flow-novice/dist/src/api/claude-client.js +138 -3
  14. package/.claude-flow-novice/dist/src/api/claude-client.js.map +1 -1
  15. package/.claude-flow-novice/dist/src/cfn-loop/phase-orchestrator-example.js +1 -1
  16. package/.claude-flow-novice/dist/src/cfn-loop/scope-control.js +247 -0
  17. package/.claude-flow-novice/dist/src/cfn-loop/scope-control.js.map +1 -0
  18. package/.claude-flow-novice/dist/src/cli/commands/swarm.js +32 -15
  19. package/.claude-flow-novice/dist/src/cli/commands/swarm.js.map +1 -1
  20. package/.claude-flow-novice/dist/src/cli/commands/transparency.js +455 -0
  21. package/.claude-flow-novice/dist/src/cli/commands/transparency.js.map +1 -0
  22. package/.claude-flow-novice/dist/src/cli/simple-commands/init/templates/CLAUDE.md +129 -13
  23. package/.claude-flow-novice/dist/src/components/visualizations/index.js +9 -0
  24. package/.claude-flow-novice/dist/src/components/visualizations/index.js.map +1 -0
  25. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js +462 -0
  26. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js.map +1 -0
  27. package/.claude-flow-novice/dist/src/coordination/config-translator.js +248 -0
  28. package/.claude-flow-novice/dist/src/coordination/config-translator.js.map +1 -0
  29. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js +287 -0
  30. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js.map +1 -0
  31. package/.claude-flow-novice/dist/src/coordination/distributed-consensus.js +68 -9
  32. package/.claude-flow-novice/dist/src/coordination/distributed-consensus.js.map +1 -1
  33. package/.claude-flow-novice/dist/src/coordination/feature-flags.js +166 -0
  34. package/.claude-flow-novice/dist/src/coordination/feature-flags.js.map +1 -0
  35. package/.claude-flow-novice/dist/src/coordination/queen-agent.js +18 -4
  36. package/.claude-flow-novice/dist/src/coordination/queen-agent.js.map +1 -1
  37. package/.claude-flow-novice/dist/src/coordination/role-assignment.js +6 -110
  38. package/.claude-flow-novice/dist/src/coordination/role-assignment.js.map +1 -1
  39. package/.claude-flow-novice/dist/src/coordination/v2/cache/artifact-cache-optimizer.js +632 -0
  40. package/.claude-flow-novice/dist/src/coordination/v2/cache/artifact-cache-optimizer.js.map +1 -0
  41. package/.claude-flow-novice/dist/src/coordination/v2/cache/index.js +11 -0
  42. package/.claude-flow-novice/dist/src/coordination/v2/cache/index.js.map +1 -0
  43. package/.claude-flow-novice/dist/src/coordination/v2/checkpoints/checkpoint-compressor.js +318 -0
  44. package/.claude-flow-novice/dist/src/coordination/v2/checkpoints/checkpoint-compressor.js.map +1 -0
  45. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.example.js +364 -0
  46. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.example.js.map +1 -0
  47. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.js +492 -0
  48. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.js.map +1 -0
  49. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/hierarchical-coordinator.js +786 -0
  50. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/hierarchical-coordinator.js.map +1 -0
  51. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/index.js +16 -0
  52. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/index.js.map +1 -0
  53. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/parent-child-manager.js +342 -0
  54. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/parent-child-manager.js.map +1 -0
  55. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/swarm-coordinator-v2.js +601 -0
  56. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/swarm-coordinator-v2.js.map +1 -0
  57. package/.claude-flow-novice/dist/src/coordination/v2/core/help-request-metrics.js +211 -0
  58. package/.claude-flow-novice/dist/src/coordination/v2/core/help-request-metrics.js.map +1 -0
  59. package/.claude-flow-novice/dist/src/coordination/v2/core/index.js +1 -0
  60. package/.claude-flow-novice/dist/src/coordination/v2/core/index.js.map +1 -1
  61. package/.claude-flow-novice/dist/src/coordination/v2/core/message-broker.js +365 -6
  62. package/.claude-flow-novice/dist/src/coordination/v2/core/message-broker.js.map +1 -1
  63. package/.claude-flow-novice/dist/src/coordination/v2/core/resource-manager-safe.js +478 -0
  64. package/.claude-flow-novice/dist/src/coordination/v2/core/resource-manager-safe.js.map +1 -0
  65. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine-config.js +5 -2
  66. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine-config.js.map +1 -1
  67. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine.js +189 -0
  68. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine.js.map +1 -1
  69. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/deadlock-detector.js +424 -0
  70. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/deadlock-detector.js.map +1 -0
  71. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/index.js +9 -0
  72. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/index.js.map +1 -0
  73. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/resource-manager.js +669 -0
  74. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/resource-manager.js.map +1 -0
  75. package/.claude-flow-novice/dist/src/coordination/v2/dependency/artifact-storage.js +451 -0
  76. package/.claude-flow-novice/dist/src/coordination/v2/dependency/artifact-storage.js.map +1 -0
  77. package/.claude-flow-novice/dist/src/coordination/v2/dependency/cycle-detector.js +271 -0
  78. package/.claude-flow-novice/dist/src/coordination/v2/dependency/cycle-detector.js.map +1 -0
  79. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-graph.js +335 -0
  80. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-graph.js.map +1 -0
  81. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-manager.js +439 -0
  82. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-manager.js.map +1 -0
  83. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-request.js +92 -0
  84. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-request.js.map +1 -0
  85. package/.claude-flow-novice/dist/src/coordination/v2/dependency/index.js +21 -0
  86. package/.claude-flow-novice/dist/src/coordination/v2/dependency/index.js.map +1 -0
  87. package/.claude-flow-novice/dist/src/coordination/v2/dependency/topological-sort.js +223 -0
  88. package/.claude-flow-novice/dist/src/coordination/v2/dependency/topological-sort.js.map +1 -0
  89. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-coordinator.js +436 -0
  90. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-coordinator.js.map +1 -0
  91. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-matcher.js +278 -0
  92. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-matcher.js.map +1 -0
  93. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request-handler.js +317 -0
  94. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request-handler.js.map +1 -0
  95. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request.js +273 -0
  96. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request.js.map +1 -0
  97. package/.claude-flow-novice/dist/src/coordination/v2/help-system/index.js +15 -0
  98. package/.claude-flow-novice/dist/src/coordination/v2/help-system/index.js.map +1 -0
  99. package/.claude-flow-novice/dist/src/coordination/v2/help-system/waiting-agent-pool.js +512 -0
  100. package/.claude-flow-novice/dist/src/coordination/v2/help-system/waiting-agent-pool.js.map +1 -0
  101. package/.claude-flow-novice/dist/src/coordination/v2/index.js +6 -0
  102. package/.claude-flow-novice/dist/src/coordination/v2/index.js.map +1 -1
  103. package/.claude-flow-novice/dist/src/coordination/v2/integration/help-deadlock-integration.js +557 -0
  104. package/.claude-flow-novice/dist/src/coordination/v2/integration/help-deadlock-integration.js.map +1 -0
  105. package/.claude-flow-novice/dist/src/coordination/v2/integration/index.js +14 -0
  106. package/.claude-flow-novice/dist/src/coordination/v2/integration/index.js.map +1 -0
  107. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.example.js +212 -0
  108. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.example.js.map +1 -0
  109. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.js +552 -0
  110. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.js.map +1 -0
  111. package/.claude-flow-novice/dist/src/coordination/v2/memory/dependency-storage.js +367 -0
  112. package/.claude-flow-novice/dist/src/coordination/v2/memory/dependency-storage.js.map +1 -0
  113. package/.claude-flow-novice/dist/src/coordination/v2/memory/index.js +1 -0
  114. package/.claude-flow-novice/dist/src/coordination/v2/memory/index.js.map +1 -1
  115. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channel.js +371 -0
  116. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channel.js.map +1 -0
  117. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/dependency-channel.js +355 -0
  118. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/dependency-channel.js.map +1 -0
  119. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/help-channel.js +424 -0
  120. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/help-channel.js.map +1 -0
  121. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/index.js +16 -0
  122. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/index.js.map +1 -0
  123. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/state-channel.js +295 -0
  124. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/state-channel.js.map +1 -0
  125. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/task-channel.js +411 -0
  126. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/task-channel.js.map +1 -0
  127. package/.claude-flow-novice/dist/src/coordination/v2/messaging/index.js +14 -0
  128. package/.claude-flow-novice/dist/src/coordination/v2/messaging/index.js.map +1 -0
  129. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-bus.js +387 -0
  130. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-bus.js.map +1 -0
  131. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-persistence.js +589 -0
  132. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-persistence.js.map +1 -0
  133. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-router.js +444 -0
  134. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-router.js.map +1 -0
  135. package/.claude-flow-novice/dist/src/coordination/v2/sdk/checkpoint-manager.js +29 -8
  136. package/.claude-flow-novice/dist/src/coordination/v2/sdk/checkpoint-manager.js.map +1 -1
  137. package/.claude-flow-novice/dist/src/coordination/v2/sdk/help-coordinator.js +470 -0
  138. package/.claude-flow-novice/dist/src/coordination/v2/sdk/help-coordinator.js.map +1 -0
  139. package/.claude-flow-novice/dist/src/coordination/v2/sdk/hierarchical-background-integration.js +450 -0
  140. package/.claude-flow-novice/dist/src/coordination/v2/sdk/hierarchical-background-integration.js.map +1 -0
  141. package/.claude-flow-novice/dist/src/coordination/v2/sdk/index.js +5 -0
  142. package/.claude-flow-novice/dist/src/coordination/v2/sdk/index.js.map +1 -1
  143. package/.claude-flow-novice/dist/src/coordination/v2/sdk/multi-level-control.js +545 -0
  144. package/.claude-flow-novice/dist/src/coordination/v2/sdk/multi-level-control.js.map +1 -0
  145. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-controller.js +44 -0
  146. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-controller.js.map +1 -1
  147. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-message-integration.js +415 -0
  148. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-message-integration.js.map +1 -0
  149. package/.claude-flow-novice/dist/src/coordination/v2/sdk/session-pool-optimizer.js +615 -0
  150. package/.claude-flow-novice/dist/src/coordination/v2/sdk/session-pool-optimizer.js.map +1 -0
  151. package/.claude-flow-novice/dist/src/coordination/v2/security/payload-validator.js +259 -0
  152. package/.claude-flow-novice/dist/src/coordination/v2/security/payload-validator.js.map +1 -0
  153. package/.claude-flow-novice/dist/src/coordination/v2/transparency/index.js +17 -0
  154. package/.claude-flow-novice/dist/src/coordination/v2/transparency/index.js.map +1 -0
  155. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-integration.js +357 -0
  156. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-integration.js.map +1 -0
  157. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-system.js +679 -0
  158. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-system.js.map +1 -0
  159. package/.claude-flow-novice/dist/src/core/agent-manager.js +30 -0
  160. package/.claude-flow-novice/dist/src/core/agent-manager.js.map +1 -1
  161. package/.claude-flow-novice/dist/src/mcp/server.js +21 -2
  162. package/.claude-flow-novice/dist/src/mcp/server.js.map +1 -1
  163. package/.claude-flow-novice/dist/src/observability/metrics-counter.js +268 -0
  164. package/.claude-flow-novice/dist/src/observability/metrics-counter.js.map +1 -0
  165. package/.claude-flow-novice/dist/src/observability/metrics-storage.js +265 -0
  166. package/.claude-flow-novice/dist/src/observability/metrics-storage.js.map +1 -0
  167. package/.claude-flow-novice/dist/src/observability/telemetry.js +26 -0
  168. package/.claude-flow-novice/dist/src/observability/telemetry.js.map +1 -1
  169. package/.claude-flow-novice/dist/src/providers/tiered-router.js +64 -10
  170. package/.claude-flow-novice/dist/src/providers/tiered-router.js.map +1 -1
  171. package/.claude-flow-novice/dist/src/providers/zai-provider.js +196 -97
  172. package/.claude-flow-novice/dist/src/providers/zai-provider.js.map +1 -1
  173. package/.claude-flow-novice/dist/src/slash-commands/cfn-claude-sync.js +533 -0
  174. package/.claude-flow-novice/dist/src/slash-commands/index.js +5 -0
  175. package/.claude-flow-novice/dist/src/slash-commands/metrics-summary-class.js +74 -0
  176. package/.claude-flow-novice/dist/src/slash-commands/metrics-summary.js +335 -0
  177. package/.claude-flow-novice/dist/src/slash-commands/register-all-commands.js +12 -0
  178. package/.claude-flow-novice/dist/src/verification/checkpoint-compression-demo.js +96 -0
  179. package/.claude-flow-novice/dist/src/verification/checkpoint-compression-demo.js.map +1 -0
  180. package/.claude-flow-novice/dist/src/verification/checkpoint-compression.js +406 -0
  181. package/.claude-flow-novice/dist/src/verification/checkpoint-compression.js.map +1 -0
  182. package/.claude-flow-novice/dist/src/verification/checkpoint-manager.js +35 -5
  183. package/.claude-flow-novice/dist/src/verification/checkpoint-manager.js.map +1 -1
  184. package/.claude-flow-novice/dist/src/web/api/config/api-config.js +186 -0
  185. package/.claude-flow-novice/dist/src/web/api/config/api-config.js.map +1 -0
  186. package/.claude-flow-novice/dist/src/web/api/middleware/auth.js +205 -0
  187. package/.claude-flow-novice/dist/src/web/api/middleware/auth.js.map +1 -0
  188. package/.claude-flow-novice/dist/src/web/api/middleware/cache.js +262 -0
  189. package/.claude-flow-novice/dist/src/web/api/middleware/cache.js.map +1 -0
  190. package/.claude-flow-novice/dist/src/web/api/middleware/error-handler.js +250 -0
  191. package/.claude-flow-novice/dist/src/web/api/middleware/error-handler.js.map +1 -0
  192. package/.claude-flow-novice/dist/src/web/api/middleware/request-logger.js +217 -0
  193. package/.claude-flow-novice/dist/src/web/api/middleware/request-logger.js.map +1 -0
  194. package/.claude-flow-novice/dist/src/web/api/middleware/validation.js +325 -0
  195. package/.claude-flow-novice/dist/src/web/api/middleware/validation.js.map +1 -0
  196. package/.claude-flow-novice/dist/src/web/api/routes/events.js +465 -0
  197. package/.claude-flow-novice/dist/src/web/api/routes/events.js.map +1 -0
  198. package/.claude-flow-novice/dist/src/web/api/routes/hierarchy.js +302 -0
  199. package/.claude-flow-novice/dist/src/web/api/routes/hierarchy.js.map +1 -0
  200. package/.claude-flow-novice/dist/src/web/api/routes/index.js +14 -0
  201. package/.claude-flow-novice/dist/src/web/api/routes/index.js.map +1 -0
  202. package/.claude-flow-novice/dist/src/web/api/routes/metrics.js +561 -0
  203. package/.claude-flow-novice/dist/src/web/api/routes/metrics.js.map +1 -0
  204. package/.claude-flow-novice/dist/src/web/api/routes/status.js +450 -0
  205. package/.claude-flow-novice/dist/src/web/api/routes/status.js.map +1 -0
  206. package/.claude-flow-novice/dist/src/web/api/server.js +451 -0
  207. package/.claude-flow-novice/dist/src/web/api/server.js.map +1 -0
  208. package/.claude-flow-novice/dist/src/web/dashboard/hooks/useWebSocket.js +385 -0
  209. package/.claude-flow-novice/dist/src/web/dashboard/hooks/useWebSocket.js.map +1 -0
  210. package/.claude-flow-novice/dist/src/web/dashboard/index.js +87 -0
  211. package/.claude-flow-novice/dist/src/web/dashboard/index.js.map +1 -0
  212. package/.claude-flow-novice/dist/src/web/dashboard/types.js +6 -0
  213. package/.claude-flow-novice/dist/src/web/dashboard/types.js.map +1 -0
  214. package/.claude-flow-novice/metrics.db +0 -0
  215. package/.claude-flow-novice/metrics.db-shm +0 -0
  216. package/.claude-flow-novice/metrics.db-wal +0 -0
  217. package/CLAUDE.md +29 -0
  218. package/README.md +27 -0
  219. package/config/hooks/post-edit-pipeline.js +36 -2
  220. package/examples/metrics-counter-demo.ts +106 -0
  221. package/examples/persistent-metrics-demo.ts +83 -0
  222. package/examples/phase-5-multi-level-control.ts +282 -0
  223. package/examples/session-pool-optimizer-example.ts +311 -0
  224. package/package.json +15 -3
  225. package/scripts/check-routing-stats.cjs +122 -0
  226. package/scripts/pre-publish-validation.cjs +212 -0
  227. package/scripts/test-provider-routing.cjs +228 -0
  228. package/scripts/test-routing-telemetry.cjs +147 -0
  229. package/scripts/test-zai-10k.cjs +81 -0
  230. package/scripts/test-zai-api.cjs +191 -0
  231. package/scripts/test-zai-diagnostic.cjs +151 -0
  232. package/scripts/test-zai-final.cjs +128 -0
  233. package/scripts/test-zai-with-env.cjs +85 -0
  234. package/scripts/validate-coordination-cli.js +69 -0
  235. package/scripts/validate-coordination-toggle-integration.cjs +501 -0
  236. package/src/cli/simple-commands/init/templates/CLAUDE.md +29 -0
  237. package/src/observability/metrics-counter.ts +347 -0
  238. package/src/observability/metrics-storage.ts +356 -0
  239. package/src/observability/telemetry.ts +658 -0
  240. package/src/slash-commands/cfn-claude-sync.js +533 -0
  241. package/src/slash-commands/index.js +5 -0
  242. package/src/slash-commands/metrics-summary-class.js +74 -0
  243. package/src/slash-commands/metrics-summary.js +335 -0
  244. package/src/slash-commands/register-all-commands.js +12 -0
@@ -0,0 +1,186 @@
1
+ /**
2
+ * API Server Configuration
3
+ *
4
+ * Configuration settings for the transparency API server
5
+ * including security, CORS, rate limiting, and other options.
6
+ *
7
+ * @module web/api/config/api-config
8
+ */ /**
9
+ * Create default API configuration
10
+ */ export function createApiConfig() {
11
+ const env = process.env.NODE_ENV || 'development';
12
+ return {
13
+ port: parseInt(process.env.API_PORT || '3001', 10),
14
+ host: process.env.API_HOST || 'localhost',
15
+ environment: env,
16
+ // CORS configuration
17
+ corsOrigins: env === 'production' ? process.env.CORS_ORIGINS?.split(',') || [
18
+ 'https://localhost:3000'
19
+ ] : [
20
+ 'http://localhost:3000',
21
+ 'http://localhost:3001',
22
+ 'http://127.0.0.1:3000'
23
+ ],
24
+ // Rate limiting
25
+ rateLimitWindowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000', 10),
26
+ rateLimitMax: parseInt(process.env.RATE_LIMIT_MAX || '100', 10),
27
+ // Security
28
+ sessionSecret: process.env.SESSION_SECRET || 'change-me-in-production',
29
+ jwtSecret: process.env.JWT_SECRET || 'change-me-in-production',
30
+ jwtExpiration: process.env.JWT_EXPIRATION || '24h',
31
+ apiKey: process.env.API_KEY || 'change-me-in-production',
32
+ // Logging
33
+ logLevel: process.env.LOG_LEVEL || 'info',
34
+ // Performance
35
+ cacheTtl: parseInt(process.env.CACHE_TTL || '5000', 10),
36
+ enableCompression: process.env.ENABLE_COMPRESSION !== 'false',
37
+ // HTTPS
38
+ enableHttps: process.env.ENABLE_HTTPS === 'true',
39
+ sslCertPath: process.env.SSL_CERT_PATH,
40
+ sslKeyPath: process.env.SSL_KEY_PATH,
41
+ // Metrics
42
+ enableMetrics: process.env.ENABLE_METRICS !== 'false',
43
+ metricsIntervalMs: parseInt(process.env.METRICS_INTERVAL_MS || '60000', 10),
44
+ // Request handling
45
+ maxRequestBodySize: process.env.MAX_REQUEST_BODY_SIZE || '10mb',
46
+ requestTimeoutMs: parseInt(process.env.REQUEST_TIMEOUT_MS || '30000', 10),
47
+ // WebSocket
48
+ websocketPingTimeoutMs: parseInt(process.env.WS_PING_TIMEOUT_MS || '60000', 10),
49
+ websocketPingIntervalMs: parseInt(process.env.WS_PING_INTERVAL_MS || '25000', 10),
50
+ maxWebSocketConnections: parseInt(process.env.MAX_WS_CONNECTIONS || '100', 10),
51
+ // Features
52
+ enableRequestLogging: process.env.ENABLE_REQUEST_LOGGING !== 'false',
53
+ enableDetailedErrors: env === 'development',
54
+ // API info
55
+ apiVersion: process.env.API_VERSION || '1.0.0',
56
+ serverName: process.env.SERVER_NAME || 'Transparency API Server'
57
+ };
58
+ }
59
+ /**
60
+ * Validate API configuration
61
+ */ export function validateApiConfig(config) {
62
+ const errors = [];
63
+ if (config.port < 1 || config.port > 65535) {
64
+ errors.push('Port must be between 1 and 65535');
65
+ }
66
+ if (config.rateLimitWindowMs < 1000) {
67
+ errors.push('Rate limit window must be at least 1000ms');
68
+ }
69
+ if (config.rateLimitMax < 1) {
70
+ errors.push('Rate limit max must be at least 1');
71
+ }
72
+ if (config.cacheTtl < 0) {
73
+ errors.push('Cache TTL cannot be negative');
74
+ }
75
+ if (config.requestTimeoutMs < 1000) {
76
+ errors.push('Request timeout must be at least 1000ms');
77
+ }
78
+ if (config.websocketPingTimeoutMs < 5000) {
79
+ errors.push('WebSocket ping timeout must be at least 5000ms');
80
+ }
81
+ if (config.websocketPingIntervalMs < 1000) {
82
+ errors.push('WebSocket ping interval must be at least 1000ms');
83
+ }
84
+ if (config.maxWebSocketConnections < 1) {
85
+ errors.push('Max WebSocket connections must be at least 1');
86
+ }
87
+ if (config.enableHttps && (!config.sslCertPath || !config.sslKeyPath)) {
88
+ errors.push('SSL certificate and key paths are required when HTTPS is enabled');
89
+ }
90
+ // In production, check for proper security settings
91
+ if (config.environment === 'production') {
92
+ const insecureDefaults = [
93
+ config.sessionSecret === 'change-me-in-production',
94
+ config.jwtSecret === 'change-me-in-production',
95
+ config.apiKey === 'change-me-in-production'
96
+ ];
97
+ if (insecureDefaults.some(Boolean)) {
98
+ errors.push('Production environment requires secure secrets and API keys');
99
+ }
100
+ if (config.corsOrigins.includes('*') || config.corsOrigins.includes('http://localhost:*')) {
101
+ errors.push('Production environment should not use wildcard or localhost CORS origins');
102
+ }
103
+ if (config.enableDetailedErrors) {
104
+ errors.push('Detailed errors should be disabled in production');
105
+ }
106
+ }
107
+ return errors;
108
+ }
109
+ /**
110
+ * Create CORS options from configuration
111
+ */ export function createCorsOptions(config) {
112
+ return {
113
+ origin: (origin, callback)=>{
114
+ // Allow requests with no origin (like mobile apps or curl requests)
115
+ if (!origin) return callback(null, true);
116
+ if (config.corsOrigins.includes('*') || config.corsOrigins.includes(origin) || config.corsOrigins.some((allowed)=>{
117
+ // Support wildcard patterns like http://localhost:*
118
+ if (allowed.includes('*')) {
119
+ const pattern = allowed.replace('*', '.*');
120
+ const regex = new RegExp(`^${pattern}$`);
121
+ return regex.test(origin);
122
+ }
123
+ return false;
124
+ })) {
125
+ callback(null, true);
126
+ } else {
127
+ callback(new Error('Not allowed by CORS'), false);
128
+ }
129
+ },
130
+ methods: [
131
+ 'GET',
132
+ 'POST',
133
+ 'PUT',
134
+ 'DELETE',
135
+ 'PATCH',
136
+ 'OPTIONS'
137
+ ],
138
+ allowedHeaders: [
139
+ 'Content-Type',
140
+ 'Authorization',
141
+ 'X-Requested-With',
142
+ 'X-API-Key'
143
+ ],
144
+ credentials: true,
145
+ preflightContinue: false,
146
+ optionsSuccessStatus: 204
147
+ };
148
+ }
149
+ /**
150
+ * Get environment-specific configuration overrides
151
+ */ export function getEnvironmentOverrides(env) {
152
+ switch(env){
153
+ case 'production':
154
+ return {
155
+ logLevel: 'warn',
156
+ enableDetailedErrors: false,
157
+ enableRequestLogging: false,
158
+ cacheTtl: 30000,
159
+ rateLimitMax: 1000,
160
+ requestTimeoutMs: 60000
161
+ };
162
+ case 'test':
163
+ return {
164
+ port: 0,
165
+ host: '127.0.0.1',
166
+ logLevel: 'error',
167
+ enableRequestLogging: false,
168
+ enableMetrics: false,
169
+ cacheTtl: 100,
170
+ rateLimitMax: 1000,
171
+ maxWebSocketConnections: 10
172
+ };
173
+ case 'development':
174
+ default:
175
+ return {
176
+ logLevel: 'debug',
177
+ enableDetailedErrors: true,
178
+ enableRequestLogging: true,
179
+ enableMetrics: true,
180
+ cacheTtl: 5000,
181
+ rateLimitMax: 1000
182
+ };
183
+ }
184
+ }
185
+
186
+ //# sourceMappingURL=api-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/web/api/config/api-config.ts"],"names":["createApiConfig","env","process","NODE_ENV","port","parseInt","API_PORT","host","API_HOST","environment","corsOrigins","CORS_ORIGINS","split","rateLimitWindowMs","RATE_LIMIT_WINDOW_MS","rateLimitMax","RATE_LIMIT_MAX","sessionSecret","SESSION_SECRET","jwtSecret","JWT_SECRET","jwtExpiration","JWT_EXPIRATION","apiKey","API_KEY","logLevel","LOG_LEVEL","cacheTtl","CACHE_TTL","enableCompression","ENABLE_COMPRESSION","enableHttps","ENABLE_HTTPS","sslCertPath","SSL_CERT_PATH","sslKeyPath","SSL_KEY_PATH","enableMetrics","ENABLE_METRICS","metricsIntervalMs","METRICS_INTERVAL_MS","maxRequestBodySize","MAX_REQUEST_BODY_SIZE","requestTimeoutMs","REQUEST_TIMEOUT_MS","websocketPingTimeoutMs","WS_PING_TIMEOUT_MS","websocketPingIntervalMs","WS_PING_INTERVAL_MS","maxWebSocketConnections","MAX_WS_CONNECTIONS","enableRequestLogging","ENABLE_REQUEST_LOGGING","enableDetailedErrors","apiVersion","API_VERSION","serverName","SERVER_NAME","validateApiConfig","config","errors","push","insecureDefaults","some","Boolean","includes","createCorsOptions","origin","callback","allowed","pattern","replace","regex","RegExp","test","Error","methods","allowedHeaders","credentials","preflightContinue","optionsSuccessStatus","getEnvironmentOverrides"],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Authentication Middleware
3
+ *
4
+ * JWT and API key authentication for the transparency API server
5
+ *
6
+ * @module web/api/middleware/auth
7
+ */ import jwt from 'jsonwebtoken';
8
+ /**
9
+ * JWT Authentication Middleware
10
+ */ export function authMiddleware(config) {
11
+ return (req, res, next)=>{
12
+ // Skip authentication for health check and API documentation
13
+ if (req.path === '/health' || req.path === '/api') {
14
+ return next();
15
+ }
16
+ // Try JWT authentication first
17
+ const authHeader = req.headers.authorization;
18
+ if (authHeader && authHeader.startsWith('Bearer ')) {
19
+ const token = authHeader.substring(7);
20
+ try {
21
+ const decoded = jwt.verify(token, config.jwtSecret);
22
+ req.user = {
23
+ id: decoded.sub || decoded.id,
24
+ username: decoded.username,
25
+ role: decoded.role || 'user',
26
+ permissions: decoded.permissions || []
27
+ };
28
+ return next();
29
+ } catch (error) {
30
+ // Invalid JWT, try API key authentication
31
+ }
32
+ }
33
+ // Try API key authentication
34
+ const apiKey = req.headers['x-api-key'];
35
+ if (apiKey && apiKey === config.apiKey) {
36
+ req.apiKey = apiKey;
37
+ return next();
38
+ }
39
+ // Check for basic auth (for development/testing)
40
+ const basicAuth = req.headers.authorization;
41
+ if (basicAuth && basicAuth.startsWith('Basic ')) {
42
+ try {
43
+ const credentials = Buffer.from(basicAuth.substring(6), 'base64').toString();
44
+ const [username, password] = credentials.split(':');
45
+ // Simple development authentication (replace with proper auth in production)
46
+ if (config.environment === 'development' && username === 'admin' && password === 'admin') {
47
+ req.user = {
48
+ id: 'dev-admin',
49
+ username: 'admin',
50
+ role: 'admin',
51
+ permissions: [
52
+ 'read',
53
+ 'write',
54
+ 'admin'
55
+ ]
56
+ };
57
+ return next();
58
+ }
59
+ } catch (error) {
60
+ // Invalid basic auth
61
+ }
62
+ }
63
+ // No valid authentication found
64
+ if (config.environment === 'development') {
65
+ // Allow unauthenticated access in development with warning
66
+ console.warn('Unauthenticated request in development mode:', req.method, req.path);
67
+ req.user = {
68
+ id: 'dev-anonymous',
69
+ username: 'anonymous',
70
+ role: 'user',
71
+ permissions: [
72
+ 'read'
73
+ ]
74
+ };
75
+ return next();
76
+ }
77
+ return res.status(401).json({
78
+ error: 'Unauthorized',
79
+ message: 'Authentication required',
80
+ timestamp: new Date().toISOString()
81
+ });
82
+ };
83
+ }
84
+ /**
85
+ * Role-based authorization middleware
86
+ */ export function requireRole(requiredRole) {
87
+ return (req, res, next)=>{
88
+ if (!req.user) {
89
+ return res.status(401).json({
90
+ error: 'Unauthorized',
91
+ message: 'Authentication required',
92
+ timestamp: new Date().toISOString()
93
+ });
94
+ }
95
+ if (req.user.role !== requiredRole && req.user.role !== 'admin') {
96
+ return res.status(403).json({
97
+ error: 'Forbidden',
98
+ message: `Requires ${requiredRole} role`,
99
+ timestamp: new Date().toISOString()
100
+ });
101
+ }
102
+ next();
103
+ };
104
+ }
105
+ /**
106
+ * Permission-based authorization middleware
107
+ */ export function requirePermission(permission) {
108
+ return (req, res, next)=>{
109
+ if (!req.user) {
110
+ return res.status(401).json({
111
+ error: 'Unauthorized',
112
+ message: 'Authentication required',
113
+ timestamp: new Date().toISOString()
114
+ });
115
+ }
116
+ const hasPermission = req.user.permissions?.includes(permission) || req.user.role === 'admin' || req.user.permissions?.includes('*');
117
+ if (!hasPermission) {
118
+ return res.status(403).json({
119
+ error: 'Forbidden',
120
+ message: `Requires ${permission} permission`,
121
+ timestamp: new Date().toISOString()
122
+ });
123
+ }
124
+ next();
125
+ };
126
+ }
127
+ /**
128
+ * Optional authentication middleware (doesn't fail if no auth)
129
+ */ export function optionalAuth(config) {
130
+ return (req, res, next)=>{
131
+ // Try JWT authentication
132
+ const authHeader = req.headers.authorization;
133
+ if (authHeader && authHeader.startsWith('Bearer ')) {
134
+ const token = authHeader.substring(7);
135
+ try {
136
+ const decoded = jwt.verify(token, config.jwtSecret);
137
+ req.user = {
138
+ id: decoded.sub || decoded.id,
139
+ username: decoded.username,
140
+ role: decoded.role || 'user',
141
+ permissions: decoded.permissions || []
142
+ };
143
+ } catch (error) {
144
+ // Invalid JWT, ignore
145
+ }
146
+ }
147
+ // Try API key authentication
148
+ const apiKey = req.headers['x-api-key'];
149
+ if (apiKey && apiKey === config.apiKey) {
150
+ req.apiKey = apiKey;
151
+ }
152
+ next();
153
+ };
154
+ }
155
+ /**
156
+ * WebSocket authentication helper
157
+ */ export function authenticateWebSocket(socket, config) {
158
+ const token = socket.handshake.auth.token || socket.handshake.headers.authorization?.replace('Bearer ', '');
159
+ if (!token) {
160
+ return false;
161
+ }
162
+ try {
163
+ // JWT authentication
164
+ const decoded = jwt.verify(token, config.jwtSecret);
165
+ socket.data.user = {
166
+ id: decoded.sub || decoded.id,
167
+ username: decoded.username,
168
+ role: decoded.role || 'user',
169
+ permissions: decoded.permissions || []
170
+ };
171
+ return true;
172
+ } catch (error) {
173
+ // API key authentication
174
+ if (token === config.apiKey) {
175
+ socket.data.apiKey = token;
176
+ socket.data.user = {
177
+ id: 'api-key-user',
178
+ username: 'api-key',
179
+ role: 'service',
180
+ permissions: [
181
+ 'read',
182
+ 'write'
183
+ ]
184
+ };
185
+ return true;
186
+ }
187
+ }
188
+ return false;
189
+ }
190
+ /**
191
+ * Generate JWT token for user
192
+ */ export function generateToken(user, config) {
193
+ return jwt.sign({
194
+ sub: user.id,
195
+ username: user.username,
196
+ role: user.role,
197
+ permissions: user.permissions
198
+ }, config.jwtSecret, {
199
+ expiresIn: config.jwtExpiration,
200
+ issuer: 'transparency-api',
201
+ audience: 'transparency-dashboard'
202
+ });
203
+ }
204
+
205
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/web/api/middleware/auth.ts"],"names":["jwt","authMiddleware","config","req","res","next","path","authHeader","headers","authorization","startsWith","token","substring","decoded","verify","jwtSecret","user","id","sub","username","role","permissions","error","apiKey","basicAuth","credentials","Buffer","from","toString","password","split","environment","console","warn","method","status","json","message","timestamp","Date","toISOString","requireRole","requiredRole","requirePermission","permission","hasPermission","includes","optionalAuth","authenticateWebSocket","socket","handshake","auth","replace","data","generateToken","sign","expiresIn","jwtExpiration","issuer","audience"],"mappings":"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"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Cache Middleware
3
+ *
4
+ * Response caching middleware for the transparency API server
5
+ *
6
+ * @module web/api/middleware/cache
7
+ */ /**
8
+ * Cache middleware factory
9
+ */ export function cacheMiddleware(cache, defaultTtl = 5000 // 5 seconds
10
+ ) {
11
+ return (req, res, next)=>{
12
+ // Only cache GET requests
13
+ if (req.method !== 'GET') {
14
+ return next();
15
+ }
16
+ // Generate cache key
17
+ const cacheKey = generateCacheKey(req);
18
+ // Check if we have a valid cached response
19
+ const cached = cache.get(cacheKey);
20
+ if (cached && Date.now() - cached.timestamp < cached.ttl) {
21
+ // Add cache headers
22
+ res.setHeader('X-Cache', 'HIT');
23
+ res.setHeader('X-Cache-Age', Math.floor((Date.now() - cached.timestamp) / 1000));
24
+ if (cached.etag) {
25
+ res.setHeader('ETag', cached.etag);
26
+ }
27
+ return res.json(cached.data);
28
+ }
29
+ // Intercept res.json to cache the response
30
+ const originalJson = res.json;
31
+ res.json = function(data) {
32
+ // Only cache successful responses
33
+ if (res.statusCode >= 200 && res.statusCode < 300) {
34
+ const ttl = getCacheTtl(req, defaultTtl);
35
+ const etag = generateETag(data);
36
+ // Cache the response
37
+ cache.set(cacheKey, {
38
+ data,
39
+ timestamp: Date.now(),
40
+ ttl,
41
+ etag
42
+ });
43
+ // Add cache headers
44
+ res.setHeader('X-Cache', 'MISS');
45
+ res.setHeader('X-Cache-TTL', Math.floor(ttl / 1000));
46
+ res.setHeader('Cache-Control', `public, max-age=${Math.floor(ttl / 1000)}`);
47
+ if (etag) {
48
+ res.setHeader('ETag', etag);
49
+ }
50
+ }
51
+ return originalJson.call(this, data);
52
+ };
53
+ next();
54
+ };
55
+ }
56
+ /**
57
+ * Generate cache key from request
58
+ */ function generateCacheKey(req) {
59
+ const url = new URL(req.originalUrl, `http://${req.headers.host}`);
60
+ // Include query parameters in cache key
61
+ const queryParams = new URLSearchParams(url.search);
62
+ queryParams.sort(); // Sort for consistent keys
63
+ const queryString = queryParams.toString();
64
+ const path = url.pathname;
65
+ // Include user ID if authenticated (for user-specific caching)
66
+ const userId = req.user?.id || 'anonymous';
67
+ return `${req.method}:${path}:${queryString}:${userId}`;
68
+ }
69
+ /**
70
+ * Get cache TTL based on request characteristics
71
+ */ function getCacheTtl(req, defaultTtl) {
72
+ // Different TTLs for different endpoints
73
+ const path = req.path;
74
+ if (path.includes('/metrics')) {
75
+ return 10000; // 10 seconds for metrics
76
+ }
77
+ if (path.includes('/status')) {
78
+ return 2000; // 2 seconds for status
79
+ }
80
+ if (path.includes('/events')) {
81
+ return 5000; // 5 seconds for events
82
+ }
83
+ if (path.includes('/hierarchy')) {
84
+ return 30000; // 30 seconds for hierarchy (changes less frequently)
85
+ }
86
+ if (path.includes('/analytics')) {
87
+ return 60000; // 1 minute for analytics
88
+ }
89
+ return defaultTtl;
90
+ }
91
+ /**
92
+ * Generate ETag for response data
93
+ */ function generateETag(data) {
94
+ const crypto = require('crypto');
95
+ const hash = crypto.createHash('md5');
96
+ hash.update(JSON.stringify(data));
97
+ return `"${hash.digest('hex')}"`;
98
+ }
99
+ /**
100
+ * Conditional request middleware (ETag support)
101
+ */ export function conditionalRequest() {
102
+ return (req, res, next)=>{
103
+ const ifNoneMatch = req.get('If-None-Match');
104
+ // This will be checked in the cache middleware
105
+ if (ifNoneMatch) {
106
+ req.ifNoneMatch = ifNoneMatch;
107
+ }
108
+ next();
109
+ };
110
+ }
111
+ /**
112
+ * Cache invalidation middleware
113
+ */ export function invalidateCache(cache) {
114
+ return (req, res, next)=>{
115
+ // Invalidate cache for POST, PUT, DELETE, PATCH requests
116
+ if ([
117
+ 'POST',
118
+ 'PUT',
119
+ 'DELETE',
120
+ 'PATCH'
121
+ ].includes(req.method)) {
122
+ const pattern = getInvalidationPattern(req);
123
+ // Remove matching cache entries
124
+ for (const key of cache.keys()){
125
+ if (key.includes(pattern)) {
126
+ cache.delete(key);
127
+ }
128
+ }
129
+ }
130
+ next();
131
+ };
132
+ }
133
+ /**
134
+ * Get cache invalidation pattern for request
135
+ */ function getInvalidationPattern(req) {
136
+ const path = req.path;
137
+ if (path.includes('/agents')) {
138
+ return '/agents';
139
+ }
140
+ if (path.includes('/status')) {
141
+ return '/status';
142
+ }
143
+ if (path.includes('/events')) {
144
+ return '/events';
145
+ }
146
+ if (path.includes('/metrics')) {
147
+ return '/metrics';
148
+ }
149
+ if (path.includes('/hierarchy')) {
150
+ return '/hierarchy';
151
+ }
152
+ return path;
153
+ }
154
+ /**
155
+ * Cache warming middleware
156
+ */ export function warmCache(cache, warmupFn) {
157
+ return async (req, res, next)=>{
158
+ // Run cache warmup on first request
159
+ if (cache.size === 0 && req.path === '/health') {
160
+ try {
161
+ await warmupFn();
162
+ } catch (error) {
163
+ console.error('Cache warmup failed:', error);
164
+ }
165
+ }
166
+ next();
167
+ };
168
+ }
169
+ /**
170
+ * Memory-based cache store
171
+ */ export class MemoryCache {
172
+ cache = new Map();
173
+ maxSize;
174
+ cleanupInterval;
175
+ constructor(maxSize = 1000, cleanupIntervalMs = 60000){
176
+ this.maxSize = maxSize;
177
+ // Clean up expired entries periodically
178
+ this.cleanupInterval = setInterval(()=>{
179
+ this.cleanup();
180
+ }, cleanupIntervalMs);
181
+ }
182
+ /**
183
+ * Get cache entry
184
+ */ get(key) {
185
+ const entry = this.cache.get(key);
186
+ if (entry && Date.now() - entry.timestamp < entry.ttl) {
187
+ return entry;
188
+ }
189
+ if (entry) {
190
+ this.cache.delete(key);
191
+ }
192
+ return undefined;
193
+ }
194
+ /**
195
+ * Set cache entry
196
+ */ set(key, data, ttl = 5000) {
197
+ // Remove oldest entries if cache is full
198
+ if (this.cache.size >= this.maxSize) {
199
+ const oldestKey = this.cache.keys().next().value;
200
+ this.cache.delete(oldestKey);
201
+ }
202
+ this.cache.set(key, {
203
+ data,
204
+ timestamp: Date.now(),
205
+ ttl
206
+ });
207
+ }
208
+ /**
209
+ * Delete cache entry
210
+ */ delete(key) {
211
+ return this.cache.delete(key);
212
+ }
213
+ /**
214
+ * Clear cache
215
+ */ clear() {
216
+ this.cache.clear();
217
+ }
218
+ /**
219
+ * Get cache size
220
+ */ size() {
221
+ return this.cache.size;
222
+ }
223
+ /**
224
+ * Get cache statistics
225
+ */ getStats() {
226
+ const entries = Array.from(this.cache.entries()).map(([key, entry])=>({
227
+ key,
228
+ age: Date.now() - entry.timestamp,
229
+ ttl: entry.ttl,
230
+ size: JSON.stringify(entry.data).length
231
+ }));
232
+ return {
233
+ size: this.cache.size,
234
+ maxSize: this.maxSize,
235
+ entries
236
+ };
237
+ }
238
+ /**
239
+ * Clean up expired entries
240
+ */ cleanup() {
241
+ const now = Date.now();
242
+ const keysToDelete = [];
243
+ for (const [key, entry] of this.cache.entries()){
244
+ if (now - entry.timestamp >= entry.ttl) {
245
+ keysToDelete.push(key);
246
+ }
247
+ }
248
+ for (const key of keysToDelete){
249
+ this.cache.delete(key);
250
+ }
251
+ }
252
+ /**
253
+ * Destroy cache store
254
+ */ destroy() {
255
+ if (this.cleanupInterval) {
256
+ clearInterval(this.cleanupInterval);
257
+ }
258
+ this.clear();
259
+ }
260
+ }
261
+
262
+ //# sourceMappingURL=cache.js.map