@kya-os/mcp-i 0.1.0-alpha.3.9 → 1.2.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 (328) hide show
  1. package/README.md +350 -213
  2. package/dist/149.js +1 -0
  3. package/dist/189.js +1 -0
  4. package/dist/261.js +1 -0
  5. package/dist/28.js +1 -0
  6. package/dist/295.js +1 -0
  7. package/dist/460.js +1 -0
  8. package/dist/570.js +1 -0
  9. package/dist/634.js +1 -0
  10. package/dist/647.js +1 -0
  11. package/dist/67.js +1 -0
  12. package/dist/739.js +1 -0
  13. package/dist/742.js +1 -0
  14. package/dist/904.js +1 -0
  15. package/dist/938.js +1 -0
  16. package/dist/auth/api-key.d.ts +16 -0
  17. package/dist/auth/api-key.js +82 -0
  18. package/dist/auth/jwt.d.ts +43 -0
  19. package/dist/auth/jwt.js +51 -0
  20. package/dist/auth/oauth/factory.d.ts +12 -0
  21. package/dist/auth/oauth/factory.js +36 -0
  22. package/dist/auth/oauth/index.d.ts +5 -0
  23. package/dist/auth/oauth/index.js +27 -0
  24. package/dist/auth/oauth/providers/proxy-provider.d.ts +13 -0
  25. package/dist/auth/oauth/providers/proxy-provider.js +159 -0
  26. package/dist/auth/oauth/router.d.ts +4 -0
  27. package/dist/auth/oauth/router.js +294 -0
  28. package/dist/auth/oauth/storage/memory-storage.d.ts +12 -0
  29. package/dist/auth/oauth/storage/memory-storage.js +40 -0
  30. package/dist/auth/oauth/types.d.ts +112 -0
  31. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.d.ts +4 -0
  32. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.js +176 -0
  33. package/dist/cache/__tests__/concurrency.test.d.ts +5 -0
  34. package/dist/cache/__tests__/concurrency.test.js +300 -0
  35. package/dist/cache/__tests__/dynamodb-nonce-cache.test.d.ts +4 -0
  36. package/dist/cache/__tests__/dynamodb-nonce-cache.test.js +176 -0
  37. package/dist/cache/__tests__/memory-nonce-cache.test.d.ts +4 -0
  38. package/dist/cache/__tests__/memory-nonce-cache.test.js +132 -0
  39. package/dist/cache/__tests__/nonce-cache-factory-simple.test.d.ts +4 -0
  40. package/dist/cache/__tests__/nonce-cache-factory-simple.test.js +133 -0
  41. package/dist/cache/__tests__/nonce-cache-factory.test.d.ts +4 -0
  42. package/dist/cache/__tests__/nonce-cache-factory.test.js +252 -0
  43. package/dist/cache/__tests__/redis-nonce-cache.test.d.ts +4 -0
  44. package/dist/cache/__tests__/redis-nonce-cache.test.js +95 -0
  45. package/dist/cache/cloudflare-kv-nonce-cache.d.ts +14 -0
  46. package/dist/cache/cloudflare-kv-nonce-cache.js +93 -0
  47. package/dist/cache/dynamodb-nonce-cache.d.ts +15 -0
  48. package/dist/cache/dynamodb-nonce-cache.js +92 -0
  49. package/dist/cache/index.d.ts +16 -0
  50. package/dist/cache/index.js +32 -0
  51. package/dist/cache/memory-nonce-cache.d.ts +44 -0
  52. package/dist/cache/memory-nonce-cache.js +105 -0
  53. package/dist/cache/nonce-cache-factory.d.ts +20 -0
  54. package/dist/cache/nonce-cache-factory.js +208 -0
  55. package/dist/cache/redis-nonce-cache.d.ts +14 -0
  56. package/dist/cache/redis-nonce-cache.js +53 -0
  57. package/dist/compiler/compiler-context.d.ts +23 -0
  58. package/dist/compiler/compiler-context.js +24 -0
  59. package/dist/compiler/config/constants.d.ts +41 -0
  60. package/dist/compiler/config/constants.js +45 -0
  61. package/dist/compiler/config/index.d.ts +252 -0
  62. package/dist/compiler/config/index.js +15 -0
  63. package/dist/compiler/config/injection.d.ts +26 -0
  64. package/dist/compiler/config/injection.js +58 -0
  65. package/dist/compiler/config/schemas/experimental/index.d.ts +91 -0
  66. package/dist/compiler/config/schemas/experimental/index.js +16 -0
  67. package/dist/compiler/config/schemas/experimental/oauth.d.ts +74 -0
  68. package/dist/compiler/config/schemas/experimental/oauth.js +25 -0
  69. package/dist/compiler/config/schemas/index.d.ts +6 -0
  70. package/dist/compiler/config/schemas/index.js +17 -0
  71. package/dist/compiler/config/schemas/paths.d.ts +9 -0
  72. package/dist/compiler/config/schemas/paths.js +12 -0
  73. package/dist/compiler/config/schemas/transport/http.d.ts +82 -0
  74. package/dist/compiler/config/schemas/transport/http.js +33 -0
  75. package/dist/compiler/config/schemas/transport/stdio.d.ts +9 -0
  76. package/dist/compiler/config/schemas/transport/stdio.js +15 -0
  77. package/dist/compiler/config/schemas/webpack.d.ts +3 -0
  78. package/dist/compiler/config/schemas/webpack.js +15 -0
  79. package/dist/compiler/config/types.d.ts +1 -0
  80. package/dist/compiler/config/types.js +2 -0
  81. package/dist/compiler/config/utils.d.ts +20 -0
  82. package/dist/compiler/config/utils.js +36 -0
  83. package/dist/compiler/generate-env-code.d.ts +1 -0
  84. package/dist/compiler/generate-env-code.js +8 -0
  85. package/dist/compiler/generate-import-code.d.ts +1 -0
  86. package/dist/compiler/generate-import-code.js +24 -0
  87. package/dist/compiler/get-webpack-config/get-entries.d.ts +3 -0
  88. package/dist/compiler/get-webpack-config/get-entries.js +29 -0
  89. package/dist/compiler/get-webpack-config/get-externals.d.ts +7 -0
  90. package/dist/compiler/get-webpack-config/get-externals.js +88 -0
  91. package/dist/compiler/get-webpack-config/get-injected-variables.d.ts +8 -0
  92. package/dist/compiler/get-webpack-config/get-injected-variables.js +25 -0
  93. package/dist/compiler/get-webpack-config/index.d.ts +4 -0
  94. package/dist/compiler/get-webpack-config/index.js +101 -0
  95. package/dist/compiler/get-webpack-config/plugins.d.ts +8 -0
  96. package/dist/compiler/get-webpack-config/plugins.js +132 -0
  97. package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.d.ts +9 -0
  98. package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.js +40 -0
  99. package/dist/compiler/index.d.ts +6 -0
  100. package/dist/compiler/index.js +194 -0
  101. package/dist/compiler/on-first-build.d.ts +3 -0
  102. package/dist/compiler/on-first-build.js +58 -0
  103. package/dist/compiler/parse-xmcp-config.d.ts +9 -0
  104. package/dist/compiler/parse-xmcp-config.js +155 -0
  105. package/dist/compiler/start-http-server.d.ts +1 -0
  106. package/dist/compiler/start-http-server.js +34 -0
  107. package/dist/index.d.ts +12 -0
  108. package/dist/index.js +38 -0
  109. package/dist/index.js.LICENSE.txt +49 -0
  110. package/dist/runtime/__tests__/audit.test.d.ts +4 -0
  111. package/dist/runtime/__tests__/audit.test.js +328 -0
  112. package/dist/runtime/__tests__/identity.test.d.ts +4 -0
  113. package/dist/runtime/__tests__/identity.test.js +164 -0
  114. package/dist/runtime/__tests__/mcpi-runtime.test.d.ts +4 -0
  115. package/dist/runtime/__tests__/mcpi-runtime.test.js +372 -0
  116. package/dist/runtime/__tests__/proof.test.d.ts +4 -0
  117. package/dist/runtime/__tests__/proof.test.js +302 -0
  118. package/dist/runtime/__tests__/session.test.d.ts +4 -0
  119. package/dist/runtime/__tests__/session.test.js +254 -0
  120. package/dist/runtime/__tests__/well-known.test.d.ts +4 -0
  121. package/dist/runtime/__tests__/well-known.test.js +312 -0
  122. package/dist/runtime/adapter-express.js +2 -0
  123. package/dist/runtime/adapter-express.js.LICENSE.txt +252 -0
  124. package/dist/runtime/adapter-nextjs.js +2 -0
  125. package/dist/runtime/adapter-nextjs.js.LICENSE.txt +53 -0
  126. package/dist/runtime/adapters/express/index.d.ts +2 -0
  127. package/dist/runtime/adapters/express/index.js +48 -0
  128. package/dist/runtime/adapters/nextjs/index.d.ts +8 -0
  129. package/dist/runtime/adapters/nextjs/index.js +18 -0
  130. package/dist/runtime/audit.d.ts +93 -0
  131. package/dist/runtime/audit.js +212 -0
  132. package/dist/runtime/debug.d.ts +118 -0
  133. package/dist/runtime/debug.js +612 -0
  134. package/dist/runtime/delegation-hooks.d.ts +85 -0
  135. package/dist/runtime/delegation-hooks.js +116 -0
  136. package/dist/runtime/demo.d.ts +71 -0
  137. package/dist/runtime/demo.js +135 -0
  138. package/dist/runtime/headers.d.ts +1 -0
  139. package/dist/runtime/headers.js +9 -0
  140. package/dist/runtime/http.js +2 -0
  141. package/dist/runtime/http.js.LICENSE.txt +252 -0
  142. package/dist/runtime/identity.d.ts +105 -0
  143. package/dist/runtime/identity.js +232 -0
  144. package/dist/runtime/index.d.ts +16 -0
  145. package/dist/runtime/index.js +56 -0
  146. package/dist/runtime/mcpi-runtime.d.ts +164 -0
  147. package/dist/runtime/mcpi-runtime.js +352 -0
  148. package/dist/runtime/proof.d.ts +87 -0
  149. package/dist/runtime/proof.js +223 -0
  150. package/dist/runtime/session.d.ts +88 -0
  151. package/dist/runtime/session.js +216 -0
  152. package/dist/runtime/stdio.js +2 -0
  153. package/dist/runtime/stdio.js.LICENSE.txt +1 -0
  154. package/dist/runtime/templates/home.d.ts +2 -0
  155. package/dist/runtime/templates/home.js +50 -0
  156. package/dist/runtime/transports/http/base-streamable-http.d.ts +25 -0
  157. package/dist/runtime/transports/http/base-streamable-http.js +16 -0
  158. package/dist/runtime/transports/http/http-context.d.ts +9 -0
  159. package/dist/runtime/transports/http/http-context.js +8 -0
  160. package/dist/runtime/transports/http/index.js +55 -0
  161. package/dist/runtime/transports/http/setup-cors.d.ts +4 -0
  162. package/dist/runtime/transports/http/setup-cors.js +24 -0
  163. package/dist/runtime/transports/http/stateless-streamable-http.d.ts +39 -0
  164. package/dist/runtime/transports/http/stateless-streamable-http.js +331 -0
  165. package/dist/runtime/transports/stdio/index.d.ts +1 -0
  166. package/dist/runtime/transports/stdio/index.js +51 -0
  167. package/dist/runtime/utils/server.d.ts +42 -0
  168. package/dist/runtime/utils/server.js +39 -0
  169. package/dist/runtime/utils/tools.d.ts +8 -0
  170. package/dist/runtime/utils/tools.js +115 -0
  171. package/dist/runtime/verifier-middleware.d.ts +76 -0
  172. package/dist/runtime/verifier-middleware.js +322 -0
  173. package/dist/runtime/well-known.d.ts +151 -0
  174. package/dist/runtime/well-known.js +258 -0
  175. package/dist/storage/config.d.ts +28 -0
  176. package/dist/storage/config.js +79 -0
  177. package/dist/storage/delegation.d.ts +59 -0
  178. package/dist/storage/delegation.js +130 -0
  179. package/dist/storage/merkle-verifier.d.ts +84 -0
  180. package/dist/storage/merkle-verifier.js +261 -0
  181. package/dist/test/__tests__/nonce-cache-integration.test.d.ts +1 -0
  182. package/dist/test/__tests__/nonce-cache-integration.test.js +116 -0
  183. package/dist/test/__tests__/nonce-cache.test.d.ts +1 -0
  184. package/dist/test/__tests__/nonce-cache.test.js +122 -0
  185. package/dist/test/__tests__/runtime-integration.test.d.ts +4 -0
  186. package/dist/test/__tests__/runtime-integration.test.js +192 -0
  187. package/dist/test/__tests__/test-infrastructure.test.d.ts +4 -0
  188. package/dist/test/__tests__/test-infrastructure.test.js +178 -0
  189. package/dist/test/deterministic-keys.d.ts +31 -0
  190. package/dist/test/deterministic-keys.js +108 -0
  191. package/dist/test/examples/test-usage-example.d.ts +140 -0
  192. package/dist/test/examples/test-usage-example.js +175 -0
  193. package/dist/test/index.d.ts +11 -0
  194. package/dist/test/index.js +27 -0
  195. package/dist/test/local-verification.d.ts +28 -0
  196. package/dist/test/local-verification.js +342 -0
  197. package/dist/test/mock-identity-provider.d.ts +96 -0
  198. package/dist/test/mock-identity-provider.js +243 -0
  199. package/dist/test/runtime-integration.d.ts +63 -0
  200. package/dist/test/runtime-integration.js +140 -0
  201. package/dist/test/test-environment.d.ts +26 -0
  202. package/dist/test/test-environment.js +50 -0
  203. package/dist/types/declarations.d.ts +1 -0
  204. package/dist/types/declarations.js +6 -0
  205. package/dist/types/middleware.d.ts +2 -0
  206. package/dist/types/middleware.js +2 -0
  207. package/dist/types/tool.d.ts +80 -0
  208. package/dist/types/tool.js +2 -0
  209. package/dist/utils/cli-icons.d.ts +3 -0
  210. package/dist/utils/cli-icons.js +7 -0
  211. package/dist/utils/constants.d.ts +6 -0
  212. package/dist/utils/constants.js +13 -0
  213. package/dist/utils/context.d.ts +33 -0
  214. package/dist/utils/context.js +58 -0
  215. package/dist/utils/file-watcher.d.ts +19 -0
  216. package/dist/utils/file-watcher.js +49 -0
  217. package/dist/utils/fs-utils.d.ts +2 -0
  218. package/dist/utils/fs-utils.js +22 -0
  219. package/dist/utils/path-validation.d.ts +3 -0
  220. package/dist/utils/path-validation.js +56 -0
  221. package/dist/utils/spawn-process.d.ts +9 -0
  222. package/dist/utils/spawn-process.js +50 -0
  223. package/dist/utils/subscribable.d.ts +12 -0
  224. package/dist/utils/subscribable.js +44 -0
  225. package/package.json +91 -77
  226. package/dist/cjs/auto.js +0 -16
  227. package/dist/cjs/cli-mode.d.ts +0 -16
  228. package/dist/cjs/cli-mode.js +0 -32
  229. package/dist/cjs/crypto.d.ts +0 -16
  230. package/dist/cjs/crypto.js +0 -212
  231. package/dist/cjs/dev-helper.d.ts +0 -3
  232. package/dist/cjs/dev-helper.js +0 -46
  233. package/dist/cjs/encrypted-storage.d.ts +0 -11
  234. package/dist/cjs/encrypted-storage.js +0 -73
  235. package/dist/cjs/index.d.ts +0 -56
  236. package/dist/cjs/index.js +0 -727
  237. package/dist/cjs/logger.d.ts +0 -32
  238. package/dist/cjs/logger.js +0 -85
  239. package/dist/cjs/nextjs.d.ts +0 -10
  240. package/dist/cjs/nextjs.js +0 -83
  241. package/dist/cjs/platform-info.d.ts +0 -36
  242. package/dist/cjs/platform-info.js +0 -274
  243. package/dist/cjs/polling.d.ts +0 -13
  244. package/dist/cjs/polling.js +0 -52
  245. package/dist/cjs/registry/index.d.ts +0 -12
  246. package/dist/cjs/registry/index.js +0 -56
  247. package/dist/cjs/registry/knowthat.d.ts +0 -17
  248. package/dist/cjs/registry/knowthat.js +0 -173
  249. package/dist/cjs/rotation.d.ts +0 -35
  250. package/dist/cjs/rotation.js +0 -102
  251. package/dist/cjs/storage.d.ts +0 -41
  252. package/dist/cjs/storage.js +0 -163
  253. package/dist/cjs/transport.d.ts +0 -35
  254. package/dist/cjs/transport.js +0 -300
  255. package/dist/cjs/types.d.ts +0 -206
  256. package/dist/cjs/vercel-adapter.d.ts +0 -8
  257. package/dist/cjs/vercel-adapter.js +0 -67
  258. package/dist/esm/auto.d.ts +0 -13
  259. package/dist/esm/auto.d.ts.map +0 -1
  260. package/dist/esm/auto.js +0 -30
  261. package/dist/esm/auto.js.map +0 -1
  262. package/dist/esm/cli-mode.d.ts +0 -52
  263. package/dist/esm/cli-mode.d.ts.map +0 -1
  264. package/dist/esm/cli-mode.js +0 -59
  265. package/dist/esm/cli-mode.js.map +0 -1
  266. package/dist/esm/crypto.d.ts +0 -51
  267. package/dist/esm/crypto.d.ts.map +0 -1
  268. package/dist/esm/crypto.js +0 -230
  269. package/dist/esm/crypto.js.map +0 -1
  270. package/dist/esm/dev-helper.d.ts +0 -15
  271. package/dist/esm/dev-helper.d.ts.map +0 -1
  272. package/dist/esm/dev-helper.js +0 -63
  273. package/dist/esm/dev-helper.js.map +0 -1
  274. package/dist/esm/encrypted-storage.d.ts +0 -19
  275. package/dist/esm/encrypted-storage.d.ts.map +0 -1
  276. package/dist/esm/encrypted-storage.js +0 -48
  277. package/dist/esm/encrypted-storage.js.map +0 -1
  278. package/dist/esm/index.d.ts +0 -129
  279. package/dist/esm/index.d.ts.map +0 -1
  280. package/dist/esm/index.js +0 -853
  281. package/dist/esm/index.js.map +0 -1
  282. package/dist/esm/logger.d.ts +0 -46
  283. package/dist/esm/logger.d.ts.map +0 -1
  284. package/dist/esm/logger.js +0 -100
  285. package/dist/esm/logger.js.map +0 -1
  286. package/dist/esm/nextjs.d.ts +0 -22
  287. package/dist/esm/nextjs.d.ts.map +0 -1
  288. package/dist/esm/nextjs.js +0 -83
  289. package/dist/esm/nextjs.js.map +0 -1
  290. package/dist/esm/package.json +0 -1
  291. package/dist/esm/platform-info.d.ts +0 -74
  292. package/dist/esm/platform-info.d.ts.map +0 -1
  293. package/dist/esm/platform-info.js +0 -293
  294. package/dist/esm/platform-info.js.map +0 -1
  295. package/dist/esm/polling.d.ts +0 -29
  296. package/dist/esm/polling.d.ts.map +0 -1
  297. package/dist/esm/polling.js +0 -76
  298. package/dist/esm/polling.js.map +0 -1
  299. package/dist/esm/registry/index.d.ts +0 -43
  300. package/dist/esm/registry/index.d.ts.map +0 -1
  301. package/dist/esm/registry/index.js +0 -89
  302. package/dist/esm/registry/index.js.map +0 -1
  303. package/dist/esm/registry/knowthat.d.ts +0 -44
  304. package/dist/esm/registry/knowthat.d.ts.map +0 -1
  305. package/dist/esm/registry/knowthat.js +0 -220
  306. package/dist/esm/registry/knowthat.js.map +0 -1
  307. package/dist/esm/rotation.d.ts +0 -57
  308. package/dist/esm/rotation.d.ts.map +0 -1
  309. package/dist/esm/rotation.js +0 -133
  310. package/dist/esm/rotation.js.map +0 -1
  311. package/dist/esm/storage.d.ts +0 -65
  312. package/dist/esm/storage.d.ts.map +0 -1
  313. package/dist/esm/storage.js +0 -160
  314. package/dist/esm/storage.js.map +0 -1
  315. package/dist/esm/transport.d.ts +0 -52
  316. package/dist/esm/transport.d.ts.map +0 -1
  317. package/dist/esm/transport.js +0 -340
  318. package/dist/esm/transport.js.map +0 -1
  319. package/dist/esm/types.d.ts +0 -293
  320. package/dist/esm/types.d.ts.map +0 -1
  321. package/dist/esm/types.js +0 -5
  322. package/dist/esm/types.js.map +0 -1
  323. package/dist/esm/vercel-adapter.d.ts +0 -26
  324. package/dist/esm/vercel-adapter.d.ts.map +0 -1
  325. package/dist/esm/vercel-adapter.js +0 -80
  326. package/dist/esm/vercel-adapter.js.map +0 -1
  327. /package/dist/{cjs → auth/oauth}/types.js +0 -0
  328. /package/dist/{cjs/auto.d.ts → runtime/transports/http/index.d.ts} +0 -0
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for Memory Nonce Cache
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const memory_nonce_cache_js_1 = require("../memory-nonce-cache.js");
8
+ (0, vitest_1.describe)("MemoryNonceCache", () => {
9
+ let cache;
10
+ (0, vitest_1.beforeEach)(() => {
11
+ cache = new memory_nonce_cache_js_1.MemoryNonceCache(100); // Short cleanup interval for testing
12
+ });
13
+ (0, vitest_1.afterEach)(() => {
14
+ cache.destroy();
15
+ });
16
+ (0, vitest_1.describe)("Basic Operations", () => {
17
+ (0, vitest_1.it)("should add and check nonce existence", async () => {
18
+ const nonce = "test-nonce-123";
19
+ // Initially should not exist
20
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
21
+ // Add nonce
22
+ await cache.add(nonce, 60); // 60 seconds TTL
23
+ // Should now exist
24
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(true);
25
+ });
26
+ (0, vitest_1.it)("should prevent duplicate nonce addition", async () => {
27
+ const nonce = "duplicate-nonce";
28
+ // Add nonce first time
29
+ await cache.add(nonce, 60);
30
+ // Adding same nonce should throw
31
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Nonce duplicate-nonce already exists");
32
+ });
33
+ (0, vitest_1.it)("should handle TTL expiration", async () => {
34
+ const nonce = "expiring-nonce";
35
+ // Add nonce with very short TTL
36
+ await cache.add(nonce, 0.1); // 0.1 seconds
37
+ // Should exist initially
38
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(true);
39
+ // Wait for expiration
40
+ await new Promise((resolve) => setTimeout(resolve, 200));
41
+ // Should be expired
42
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
43
+ });
44
+ });
45
+ (0, vitest_1.describe)("Cleanup", () => {
46
+ (0, vitest_1.it)("should clean up expired entries", async () => {
47
+ const nonce1 = "nonce-1";
48
+ const nonce2 = "nonce-2";
49
+ // Add nonces with different TTLs
50
+ await cache.add(nonce1, 0.1); // Short TTL
51
+ await cache.add(nonce2, 60); // Long TTL
52
+ // Both should exist initially
53
+ (0, vitest_1.expect)(await cache.has(nonce1)).toBe(true);
54
+ (0, vitest_1.expect)(await cache.has(nonce2)).toBe(true);
55
+ // Wait for first nonce to expire
56
+ await new Promise((resolve) => setTimeout(resolve, 200));
57
+ // Manual cleanup
58
+ await cache.cleanup();
59
+ // First should be gone, second should remain
60
+ (0, vitest_1.expect)(await cache.has(nonce1)).toBe(false);
61
+ (0, vitest_1.expect)(await cache.has(nonce2)).toBe(true);
62
+ });
63
+ (0, vitest_1.it)("should provide accurate statistics", async () => {
64
+ const nonce1 = "stats-nonce-1";
65
+ const nonce2 = "stats-nonce-2";
66
+ // Add nonces
67
+ await cache.add(nonce1, 60);
68
+ await cache.add(nonce2, 0.1); // This will expire quickly
69
+ // Wait for one to expire
70
+ await new Promise((resolve) => setTimeout(resolve, 200));
71
+ const stats = cache.getStats();
72
+ (0, vitest_1.expect)(stats.size).toBeGreaterThanOrEqual(1); // At least one still in cache
73
+ (0, vitest_1.expect)(stats.expired).toBeGreaterThanOrEqual(0); // Some may be expired
74
+ });
75
+ });
76
+ (0, vitest_1.describe)("Atomic Operations", () => {
77
+ (0, vitest_1.it)("should prevent duplicate nonce addition", async () => {
78
+ const nonce = "atomic-test-nonce";
79
+ // Add nonce first time
80
+ await cache.add(nonce, 60);
81
+ // Second attempt should fail
82
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Nonce atomic-test-nonce already exists");
83
+ // Nonce should still exist
84
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(true);
85
+ });
86
+ });
87
+ (0, vitest_1.describe)("Memory Management", () => {
88
+ (0, vitest_1.it)("should clear all entries", async () => {
89
+ // Add multiple nonces
90
+ await cache.add("nonce-1", 60);
91
+ await cache.add("nonce-2", 60);
92
+ await cache.add("nonce-3", 60);
93
+ // All should exist
94
+ (0, vitest_1.expect)(await cache.has("nonce-1")).toBe(true);
95
+ (0, vitest_1.expect)(await cache.has("nonce-2")).toBe(true);
96
+ (0, vitest_1.expect)(await cache.has("nonce-3")).toBe(true);
97
+ // Clear cache
98
+ cache.clear();
99
+ // None should exist
100
+ (0, vitest_1.expect)(await cache.has("nonce-1")).toBe(false);
101
+ (0, vitest_1.expect)(await cache.has("nonce-2")).toBe(false);
102
+ (0, vitest_1.expect)(await cache.has("nonce-3")).toBe(false);
103
+ });
104
+ (0, vitest_1.it)("should properly destroy cache and stop cleanup", async () => {
105
+ const cache2 = new memory_nonce_cache_js_1.MemoryNonceCache(50);
106
+ await cache2.add("test-nonce", 60);
107
+ (0, vitest_1.expect)(await cache2.has("test-nonce")).toBe(true);
108
+ // Destroy should clear cache and stop intervals
109
+ cache2.destroy();
110
+ (0, vitest_1.expect)(await cache2.has("test-nonce")).toBe(false);
111
+ });
112
+ });
113
+ (0, vitest_1.describe)("Edge Cases", () => {
114
+ (0, vitest_1.it)("should handle empty nonce strings", async () => {
115
+ await (0, vitest_1.expect)(cache.add("", 60)).resolves.not.toThrow();
116
+ (0, vitest_1.expect)(await cache.has("")).toBe(true);
117
+ });
118
+ (0, vitest_1.it)("should handle zero TTL", async () => {
119
+ const nonce = "zero-ttl-nonce";
120
+ await cache.add(nonce, 0);
121
+ // Zero TTL means it should be expired immediately
122
+ // The implementation stores it but it should be considered expired
123
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
124
+ });
125
+ (0, vitest_1.it)("should handle negative TTL", async () => {
126
+ const nonce = "negative-ttl-nonce";
127
+ await cache.add(nonce, -1);
128
+ // Should be immediately expired
129
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
130
+ });
131
+ });
132
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Simplified tests for Nonce Cache Factory
3
+ */
4
+ export {};
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ /**
3
+ * Simplified tests for Nonce Cache Factory
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const nonce_cache_factory_js_1 = require("../nonce-cache-factory.js");
8
+ const memory_nonce_cache_js_1 = require("../memory-nonce-cache.js");
9
+ // Mock environment variables
10
+ const originalEnv = process.env;
11
+ (0, vitest_1.describe)("Nonce Cache Factory (Simplified)", () => {
12
+ (0, vitest_1.beforeEach)(() => {
13
+ vitest_1.vi.clearAllMocks();
14
+ // Reset environment
15
+ process.env = { ...originalEnv };
16
+ });
17
+ (0, vitest_1.afterEach)(() => {
18
+ process.env = originalEnv;
19
+ });
20
+ (0, vitest_1.describe)("detectCacheType", () => {
21
+ (0, vitest_1.it)("should detect explicit cache type from environment", () => {
22
+ process.env.mcpi_NONCE_CACHE_TYPE = "redis";
23
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
24
+ process.env.mcpi_NONCE_CACHE_TYPE = "dynamodb";
25
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
26
+ process.env.mcpi_NONCE_CACHE_TYPE = "cloudflare-kv";
27
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("cloudflare-kv");
28
+ process.env.mcpi_NONCE_CACHE_TYPE = "memory";
29
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
30
+ });
31
+ (0, vitest_1.it)("should ignore invalid explicit cache types", () => {
32
+ process.env.mcpi_NONCE_CACHE_TYPE = "invalid-type";
33
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
34
+ });
35
+ (0, vitest_1.it)("should detect Redis from environment variables", () => {
36
+ process.env.REDIS_URL = "redis://localhost:6379";
37
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
38
+ delete process.env.REDIS_URL;
39
+ process.env.mcpi_REDIS_URL = "redis://localhost:6379";
40
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
41
+ });
42
+ (0, vitest_1.it)("should detect DynamoDB from environment variables", () => {
43
+ process.env.AWS_REGION = "us-east-1";
44
+ process.env.mcpi_DYNAMODB_TABLE = "nonce-cache";
45
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
46
+ delete process.env.AWS_REGION;
47
+ process.env.AWS_DEFAULT_REGION = "us-west-2";
48
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
49
+ });
50
+ (0, vitest_1.it)("should default to memory cache", () => {
51
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
52
+ });
53
+ (0, vitest_1.it)("should warn about memory cache in production", () => {
54
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
55
+ process.env.NODE_ENV = "production";
56
+ (0, nonce_cache_factory_js_1.detectCacheType)();
57
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Using memory cache in production"));
58
+ consoleSpy.mockRestore();
59
+ });
60
+ });
61
+ (0, vitest_1.describe)("createNonceCache", () => {
62
+ (0, vitest_1.it)("should create memory cache by default", async () => {
63
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)();
64
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
65
+ // Cleanup
66
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
67
+ cache.destroy();
68
+ }
69
+ });
70
+ (0, vitest_1.it)("should create memory cache when explicitly configured", async () => {
71
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "memory" });
72
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
73
+ // Cleanup
74
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
75
+ cache.destroy();
76
+ }
77
+ });
78
+ (0, vitest_1.it)("should fall back to memory cache when Redis URL is missing", async () => {
79
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
80
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "redis" });
81
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
82
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("Redis URL not found, falling back to memory cache");
83
+ consoleSpy.mockRestore();
84
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
85
+ cache.destroy();
86
+ }
87
+ });
88
+ (0, vitest_1.it)("should fall back to memory cache when DynamoDB table is missing", async () => {
89
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
90
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "dynamodb" });
91
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
92
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("DynamoDB table name not found, falling back to memory cache");
93
+ consoleSpy.mockRestore();
94
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
95
+ cache.destroy();
96
+ }
97
+ });
98
+ (0, vitest_1.it)("should fall back to memory cache when KV namespace is missing", async () => {
99
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
100
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "cloudflare-kv" });
101
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
102
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("Cloudflare KV namespace not found, falling back to memory cache");
103
+ consoleSpy.mockRestore();
104
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
105
+ cache.destroy();
106
+ }
107
+ });
108
+ });
109
+ (0, vitest_1.describe)("createNonceCacheWithConfig", () => {
110
+ (0, vitest_1.it)("should create cache with default options", async () => {
111
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCacheWithConfig)();
112
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
113
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
114
+ cache.destroy();
115
+ }
116
+ });
117
+ (0, vitest_1.it)("should fall back to memory cache on errors by default", async () => {
118
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
119
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCacheWithConfig)({
120
+ config: {
121
+ type: "redis",
122
+ // No URL provided, should cause fallback
123
+ },
124
+ });
125
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
126
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalled();
127
+ consoleSpy.mockRestore();
128
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
129
+ cache.destroy();
130
+ }
131
+ });
132
+ });
133
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Tests for Nonce Cache Factory
3
+ */
4
+ export {};
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for Nonce Cache Factory
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const nonce_cache_factory_js_1 = require("../nonce-cache-factory.js");
8
+ const memory_nonce_cache_js_1 = require("../memory-nonce-cache.js");
9
+ // Mock environment variables
10
+ const originalEnv = process.env;
11
+ (0, vitest_1.describe)("Nonce Cache Factory", () => {
12
+ (0, vitest_1.beforeEach)(() => {
13
+ vitest_1.vi.clearAllMocks();
14
+ // Reset environment
15
+ process.env = { ...originalEnv };
16
+ });
17
+ (0, vitest_1.afterEach)(() => {
18
+ process.env = originalEnv;
19
+ });
20
+ (0, vitest_1.describe)("detectCacheType", () => {
21
+ (0, vitest_1.it)("should detect explicit cache type from environment", () => {
22
+ process.env.mcpi_NONCE_CACHE_TYPE = "redis";
23
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
24
+ process.env.mcpi_NONCE_CACHE_TYPE = "dynamodb";
25
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
26
+ process.env.mcpi_NONCE_CACHE_TYPE = "cloudflare-kv";
27
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("cloudflare-kv");
28
+ process.env.mcpi_NONCE_CACHE_TYPE = "memory";
29
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
30
+ });
31
+ (0, vitest_1.it)("should ignore invalid explicit cache types", () => {
32
+ process.env.mcpi_NONCE_CACHE_TYPE = "invalid-type";
33
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
34
+ });
35
+ (0, vitest_1.it)("should detect Redis from environment variables", () => {
36
+ process.env.REDIS_URL = "redis://localhost:6379";
37
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
38
+ delete process.env.REDIS_URL;
39
+ process.env.mcpi_REDIS_URL = "redis://localhost:6379";
40
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("redis");
41
+ });
42
+ (0, vitest_1.it)("should detect DynamoDB from environment variables", () => {
43
+ process.env.AWS_REGION = "us-east-1";
44
+ process.env.mcpi_DYNAMODB_TABLE = "nonce-cache";
45
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
46
+ delete process.env.AWS_REGION;
47
+ process.env.AWS_DEFAULT_REGION = "us-west-2";
48
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("dynamodb");
49
+ });
50
+ (0, vitest_1.it)("should detect Cloudflare Workers environment", () => {
51
+ // Mock Cloudflare Workers globals
52
+ const originalGlobalThis = globalThis;
53
+ Object.defineProperty(globalThis, "caches", {
54
+ value: {},
55
+ configurable: true,
56
+ });
57
+ Object.defineProperty(globalThis, "fetch", {
58
+ value: () => { },
59
+ configurable: true,
60
+ });
61
+ Object.defineProperty(globalThis, "addEventListener", {
62
+ value: () => { },
63
+ configurable: true,
64
+ });
65
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("cloudflare-kv");
66
+ // Cleanup
67
+ delete globalThis.caches;
68
+ delete globalThis.addEventListener;
69
+ });
70
+ (0, vitest_1.it)("should default to memory cache", () => {
71
+ (0, vitest_1.expect)((0, nonce_cache_factory_js_1.detectCacheType)()).toBe("memory");
72
+ });
73
+ (0, vitest_1.it)("should warn about memory cache in production", () => {
74
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
75
+ process.env.NODE_ENV = "production";
76
+ (0, nonce_cache_factory_js_1.detectCacheType)();
77
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Using memory cache in production"));
78
+ consoleSpy.mockRestore();
79
+ });
80
+ });
81
+ (0, vitest_1.describe)("createNonceCache", () => {
82
+ (0, vitest_1.it)("should create memory cache by default", async () => {
83
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)();
84
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
85
+ // Cleanup
86
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
87
+ cache.destroy();
88
+ }
89
+ });
90
+ (0, vitest_1.it)("should create memory cache when explicitly configured", async () => {
91
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "memory" });
92
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
93
+ // Cleanup
94
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
95
+ cache.destroy();
96
+ }
97
+ });
98
+ (0, vitest_1.it)("should fall back to memory cache when Redis URL is missing", async () => {
99
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
100
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "redis" });
101
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
102
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("Redis URL not found, falling back to memory cache");
103
+ consoleSpy.mockRestore();
104
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
105
+ cache.destroy();
106
+ }
107
+ });
108
+ (0, vitest_1.it)("should fall back to memory cache when DynamoDB table is missing", async () => {
109
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
110
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "dynamodb" });
111
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
112
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("DynamoDB table name not found, falling back to memory cache");
113
+ consoleSpy.mockRestore();
114
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
115
+ cache.destroy();
116
+ }
117
+ });
118
+ (0, vitest_1.it)("should fall back to memory cache when KV namespace is missing", async () => {
119
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
120
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "cloudflare-kv" });
121
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
122
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("Cloudflare KV namespace not found, falling back to memory cache");
123
+ consoleSpy.mockRestore();
124
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
125
+ cache.destroy();
126
+ }
127
+ });
128
+ (0, vitest_1.it)("should handle Redis connection failures gracefully", async () => {
129
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
130
+ // Mock Redis import to throw error
131
+ vitest_1.vi.doMock("redis", () => {
132
+ throw new Error("Redis not available");
133
+ });
134
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({
135
+ type: "redis",
136
+ redis: { url: "redis://localhost:6379", keyPrefix: "test:" },
137
+ });
138
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
139
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Failed to connect to Redis"), vitest_1.expect.any(Error));
140
+ consoleSpy.mockRestore();
141
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
142
+ cache.destroy();
143
+ }
144
+ });
145
+ (0, vitest_1.it)("should handle DynamoDB initialization failures gracefully", async () => {
146
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
147
+ // Mock AWS SDK import to throw error
148
+ vitest_1.vi.doMock("@aws-sdk/client-dynamodb", () => {
149
+ throw new Error("AWS SDK not available");
150
+ });
151
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({
152
+ type: "dynamodb",
153
+ dynamodb: {
154
+ tableName: "test-table",
155
+ keyAttribute: "nonce",
156
+ ttlAttribute: "ttl",
157
+ },
158
+ });
159
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
160
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Failed to initialize DynamoDB"), vitest_1.expect.any(Error));
161
+ consoleSpy.mockRestore();
162
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
163
+ cache.destroy();
164
+ }
165
+ });
166
+ (0, vitest_1.it)("should handle Cloudflare KV namespace not found", async () => {
167
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
168
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({
169
+ type: "cloudflare-kv",
170
+ cloudflareKv: {
171
+ namespace: "NONEXISTENT_KV",
172
+ keyPrefix: "test:",
173
+ },
174
+ });
175
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
176
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Failed to initialize Cloudflare KV"), vitest_1.expect.any(Error));
177
+ consoleSpy.mockRestore();
178
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
179
+ cache.destroy();
180
+ }
181
+ });
182
+ });
183
+ (0, vitest_1.describe)("createNonceCacheWithConfig", () => {
184
+ (0, vitest_1.it)("should create cache with default options", async () => {
185
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCacheWithConfig)();
186
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
187
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
188
+ cache.destroy();
189
+ }
190
+ });
191
+ (0, vitest_1.it)("should fall back to memory cache on errors by default", async () => {
192
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
193
+ // Mock to throw error
194
+ vitest_1.vi.doMock("redis", () => {
195
+ throw new Error("Connection failed");
196
+ });
197
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCacheWithConfig)({
198
+ config: {
199
+ type: "redis",
200
+ redis: { url: "redis://localhost:6379", keyPrefix: "test:" },
201
+ },
202
+ });
203
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
204
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalled();
205
+ consoleSpy.mockRestore();
206
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
207
+ cache.destroy();
208
+ }
209
+ });
210
+ (0, vitest_1.it)("should throw error when fallbackToMemory is false", async () => {
211
+ // Mock to throw error
212
+ vitest_1.vi.doMock("redis", () => {
213
+ throw new Error("Connection failed");
214
+ });
215
+ await (0, vitest_1.expect)((0, nonce_cache_factory_js_1.createNonceCacheWithConfig)({
216
+ config: {
217
+ type: "redis",
218
+ redis: { url: "redis://localhost:6379", keyPrefix: "test:" },
219
+ },
220
+ fallbackToMemory: false,
221
+ })).rejects.toThrow();
222
+ });
223
+ });
224
+ (0, vitest_1.describe)("Environment Variable Priority", () => {
225
+ (0, vitest_1.it)("should prioritize config over environment variables", async () => {
226
+ process.env.REDIS_URL = "redis://env-redis:6379";
227
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
228
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({
229
+ type: "redis",
230
+ redis: { url: "redis://config-redis:6379", keyPrefix: "test:" },
231
+ });
232
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
233
+ // Should have tried to use config URL, not env URL
234
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Failed to connect to Redis"), vitest_1.expect.any(Error));
235
+ consoleSpy.mockRestore();
236
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
237
+ cache.destroy();
238
+ }
239
+ });
240
+ (0, vitest_1.it)("should use environment variables when config is not provided", async () => {
241
+ process.env.mcpi_REDIS_URL = "redis://env-redis:6379";
242
+ const consoleSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
243
+ const cache = await (0, nonce_cache_factory_js_1.createNonceCache)({ type: "redis" });
244
+ (0, vitest_1.expect)(cache).toBeInstanceOf(memory_nonce_cache_js_1.MemoryNonceCache);
245
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("Failed to connect to Redis"), vitest_1.expect.any(Error));
246
+ consoleSpy.mockRestore();
247
+ if (cache instanceof memory_nonce_cache_js_1.MemoryNonceCache) {
248
+ cache.destroy();
249
+ }
250
+ });
251
+ });
252
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Tests for Redis Nonce Cache
3
+ */
4
+ export {};
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for Redis Nonce Cache
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const redis_nonce_cache_js_1 = require("../redis-nonce-cache.js");
8
+ // Mock Redis client
9
+ const mockRedis = {
10
+ exists: vitest_1.vi.fn(),
11
+ set: vitest_1.vi.fn(),
12
+ };
13
+ (0, vitest_1.describe)("RedisNonceCache", () => {
14
+ let cache;
15
+ (0, vitest_1.beforeEach)(() => {
16
+ vitest_1.vi.clearAllMocks();
17
+ cache = new redis_nonce_cache_js_1.RedisNonceCache(mockRedis, "test:nonce:");
18
+ });
19
+ (0, vitest_1.describe)("Basic Operations", () => {
20
+ (0, vitest_1.it)("should add and check nonce existence", async () => {
21
+ const nonce = "test-nonce-123";
22
+ // Mock Redis responses
23
+ mockRedis.exists.mockResolvedValue(0); // doesn't exist
24
+ mockRedis.set.mockResolvedValue("OK"); // successful set
25
+ // Initially should not exist
26
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
27
+ (0, vitest_1.expect)(mockRedis.exists).toHaveBeenCalledWith("test:nonce:test-nonce-123");
28
+ // Add nonce
29
+ await cache.add(nonce, 60);
30
+ (0, vitest_1.expect)(mockRedis.set).toHaveBeenCalledWith("test:nonce:test-nonce-123", "1", "EX", 60, "NX");
31
+ // Mock that it now exists
32
+ mockRedis.exists.mockResolvedValue(1);
33
+ (0, vitest_1.expect)(await cache.has(nonce)).toBe(true);
34
+ });
35
+ (0, vitest_1.it)("should prevent duplicate nonce addition", async () => {
36
+ const nonce = "duplicate-nonce";
37
+ // Mock Redis SET NX returning null (key already exists)
38
+ mockRedis.set.mockResolvedValue(null);
39
+ // Adding duplicate nonce should throw
40
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Nonce duplicate-nonce already exists - potential replay attack");
41
+ });
42
+ (0, vitest_1.it)("should handle Redis connection errors gracefully", async () => {
43
+ const nonce = "error-nonce";
44
+ // Mock Redis throwing connection error
45
+ mockRedis.exists.mockRejectedValue(new Error("Connection failed"));
46
+ mockRedis.set.mockRejectedValue(new Error("Connection failed"));
47
+ // Should propagate errors with context
48
+ await (0, vitest_1.expect)(cache.has(nonce)).rejects.toThrow("Failed to check nonce existence");
49
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Failed to add nonce to cache");
50
+ });
51
+ });
52
+ (0, vitest_1.describe)("Atomic Operations", () => {
53
+ (0, vitest_1.it)("should use atomic SET NX EX command", async () => {
54
+ const nonce = "atomic-test-nonce";
55
+ const ttl = 300;
56
+ mockRedis.set.mockResolvedValue("OK");
57
+ await cache.add(nonce, ttl);
58
+ // Verify atomic command was used
59
+ (0, vitest_1.expect)(mockRedis.set).toHaveBeenCalledWith("test:nonce:atomic-test-nonce", "1", "EX", ttl, "NX");
60
+ });
61
+ (0, vitest_1.it)("should handle concurrent add attempts", async () => {
62
+ const nonce = "concurrent-nonce";
63
+ // First call succeeds
64
+ mockRedis.set.mockResolvedValueOnce("OK");
65
+ // Second call fails (key exists)
66
+ mockRedis.set.mockResolvedValueOnce(null);
67
+ // First add should succeed
68
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).resolves.not.toThrow();
69
+ // Second add should fail
70
+ await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("potential replay attack");
71
+ });
72
+ });
73
+ (0, vitest_1.describe)("Cleanup", () => {
74
+ (0, vitest_1.it)("should be a no-op since Redis handles expiry", async () => {
75
+ // cleanup() should not call any Redis methods
76
+ await cache.cleanup();
77
+ (0, vitest_1.expect)(mockRedis.exists).not.toHaveBeenCalled();
78
+ (0, vitest_1.expect)(mockRedis.set).not.toHaveBeenCalled();
79
+ });
80
+ });
81
+ (0, vitest_1.describe)("Key Prefix", () => {
82
+ (0, vitest_1.it)("should use custom key prefix", () => {
83
+ const customCache = new redis_nonce_cache_js_1.RedisNonceCache(mockRedis, "custom:prefix:");
84
+ mockRedis.exists.mockResolvedValue(0);
85
+ customCache.has("test-nonce");
86
+ (0, vitest_1.expect)(mockRedis.exists).toHaveBeenCalledWith("custom:prefix:test-nonce");
87
+ });
88
+ (0, vitest_1.it)("should use default key prefix", () => {
89
+ const defaultCache = new redis_nonce_cache_js_1.RedisNonceCache(mockRedis);
90
+ mockRedis.exists.mockResolvedValue(0);
91
+ defaultCache.has("test-nonce");
92
+ (0, vitest_1.expect)(mockRedis.exists).toHaveBeenCalledWith("mcpi:nonce:test-nonce");
93
+ });
94
+ });
95
+ });
@@ -0,0 +1,14 @@
1
+ import { NonceCache } from "@kya-os/contracts/handshake";
2
+ /**
3
+ * Cloudflare KV-based nonce cache implementation
4
+ * Suitable for Cloudflare Workers deployments
5
+ */
6
+ export declare class CloudflareKVNonceCache implements NonceCache {
7
+ private kv;
8
+ private keyPrefix;
9
+ constructor(kv: any, keyPrefix?: string);
10
+ private getKey;
11
+ has(nonce: string): Promise<boolean>;
12
+ add(nonce: string, ttl: number): Promise<void>;
13
+ cleanup(): Promise<void>;
14
+ }