@kya-os/mcp-i 1.2.1 → 1.2.3

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 (53) hide show
  1. package/dist/149.js +1 -1
  2. package/dist/261.js +1 -1
  3. package/dist/742.js +1 -1
  4. package/dist/904.js +1 -1
  5. package/dist/cli-adapter/index.d.ts +54 -0
  6. package/dist/cli-adapter/index.js +84 -0
  7. package/dist/cli-adapter/kta-registration.d.ts +39 -0
  8. package/dist/cli-adapter/kta-registration.js +92 -0
  9. package/dist/compiler/get-webpack-config/get-externals.js +2 -2
  10. package/dist/compiler/get-webpack-config/plugins.js +1 -13
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +2 -0
  13. package/dist/index.js.LICENSE.txt +14 -0
  14. package/dist/runtime/session.js +4 -2
  15. package/dist/storage/encryption.d.ts +61 -0
  16. package/dist/storage/encryption.js +151 -0
  17. package/dist/storage/index.d.ts +11 -0
  18. package/dist/storage/index.js +26 -0
  19. package/package.json +2 -2
  20. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.d.ts +0 -4
  21. package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.js +0 -176
  22. package/dist/cache/__tests__/concurrency.test.d.ts +0 -5
  23. package/dist/cache/__tests__/concurrency.test.js +0 -300
  24. package/dist/cache/__tests__/dynamodb-nonce-cache.test.d.ts +0 -4
  25. package/dist/cache/__tests__/dynamodb-nonce-cache.test.js +0 -176
  26. package/dist/cache/__tests__/memory-nonce-cache.test.d.ts +0 -4
  27. package/dist/cache/__tests__/memory-nonce-cache.test.js +0 -132
  28. package/dist/cache/__tests__/nonce-cache-factory-simple.test.d.ts +0 -4
  29. package/dist/cache/__tests__/nonce-cache-factory-simple.test.js +0 -133
  30. package/dist/cache/__tests__/nonce-cache-factory.test.d.ts +0 -4
  31. package/dist/cache/__tests__/nonce-cache-factory.test.js +0 -252
  32. package/dist/cache/__tests__/redis-nonce-cache.test.d.ts +0 -4
  33. package/dist/cache/__tests__/redis-nonce-cache.test.js +0 -95
  34. package/dist/runtime/__tests__/audit.test.d.ts +0 -4
  35. package/dist/runtime/__tests__/audit.test.js +0 -328
  36. package/dist/runtime/__tests__/identity.test.d.ts +0 -4
  37. package/dist/runtime/__tests__/identity.test.js +0 -164
  38. package/dist/runtime/__tests__/mcpi-runtime.test.d.ts +0 -4
  39. package/dist/runtime/__tests__/mcpi-runtime.test.js +0 -372
  40. package/dist/runtime/__tests__/proof.test.d.ts +0 -4
  41. package/dist/runtime/__tests__/proof.test.js +0 -302
  42. package/dist/runtime/__tests__/session.test.d.ts +0 -4
  43. package/dist/runtime/__tests__/session.test.js +0 -254
  44. package/dist/runtime/__tests__/well-known.test.d.ts +0 -4
  45. package/dist/runtime/__tests__/well-known.test.js +0 -312
  46. package/dist/test/__tests__/nonce-cache-integration.test.d.ts +0 -1
  47. package/dist/test/__tests__/nonce-cache-integration.test.js +0 -116
  48. package/dist/test/__tests__/nonce-cache.test.d.ts +0 -1
  49. package/dist/test/__tests__/nonce-cache.test.js +0 -122
  50. package/dist/test/__tests__/runtime-integration.test.d.ts +0 -4
  51. package/dist/test/__tests__/runtime-integration.test.js +0 -192
  52. package/dist/test/__tests__/test-infrastructure.test.d.ts +0 -4
  53. package/dist/test/__tests__/test-infrastructure.test.js +0 -178
@@ -1,300 +0,0 @@
1
- "use strict";
2
- /**
3
- * Concurrency tests for nonce cache implementations
4
- * Tests multi-instance replay prevention and atomic operations
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const vitest_1 = require("vitest");
8
- const memory_nonce_cache_js_1 = require("../memory-nonce-cache.js");
9
- const redis_nonce_cache_js_1 = require("../redis-nonce-cache.js");
10
- const dynamodb_nonce_cache_js_1 = require("../dynamodb-nonce-cache.js");
11
- const cloudflare_kv_nonce_cache_js_1 = require("../cloudflare-kv-nonce-cache.js");
12
- // Mock implementations for external services
13
- const mockRedis = {
14
- exists: vitest_1.vi.fn(),
15
- set: vitest_1.vi.fn(),
16
- };
17
- const mockDynamoDB = {
18
- getItem: vitest_1.vi.fn(),
19
- putItem: vitest_1.vi.fn(),
20
- };
21
- const mockKV = {
22
- get: vitest_1.vi.fn(),
23
- getWithMetadata: vitest_1.vi.fn(),
24
- put: vitest_1.vi.fn(),
25
- delete: vitest_1.vi.fn(),
26
- };
27
- (0, vitest_1.describe)("Nonce Cache Concurrency Tests", () => {
28
- let memoryCache;
29
- let redisCache;
30
- let dynamoCache;
31
- let kvCache;
32
- (0, vitest_1.beforeEach)(() => {
33
- vitest_1.vi.clearAllMocks();
34
- memoryCache = new memory_nonce_cache_js_1.MemoryNonceCache(100);
35
- redisCache = new redis_nonce_cache_js_1.RedisNonceCache(mockRedis, "test:");
36
- dynamoCache = new dynamodb_nonce_cache_js_1.DynamoNonceCache(mockDynamoDB, "test-table");
37
- kvCache = new cloudflare_kv_nonce_cache_js_1.CloudflareKVNonceCache(mockKV, "test:");
38
- });
39
- (0, vitest_1.afterEach)(() => {
40
- memoryCache.destroy();
41
- });
42
- (0, vitest_1.describe)("Memory Cache Concurrency", () => {
43
- (0, vitest_1.it)("should prevent concurrent duplicate nonce addition", async () => {
44
- const nonce = "concurrent-memory-nonce";
45
- const ttl = 60;
46
- // Simulate concurrent add operations
47
- const promises = [
48
- memoryCache.add(nonce, ttl),
49
- memoryCache.add(nonce, ttl),
50
- memoryCache.add(nonce, ttl),
51
- ];
52
- const results = await Promise.allSettled(promises);
53
- // Exactly one should succeed, others should fail
54
- const successful = results.filter((r) => r.status === "fulfilled");
55
- const failed = results.filter((r) => r.status === "rejected");
56
- (0, vitest_1.expect)(successful).toHaveLength(1);
57
- (0, vitest_1.expect)(failed).toHaveLength(2);
58
- // All failures should be due to duplicate nonce
59
- failed.forEach((result) => {
60
- if (result.status === "rejected") {
61
- (0, vitest_1.expect)(result.reason.message).toContain("already exists");
62
- }
63
- });
64
- // Nonce should exist after successful addition
65
- (0, vitest_1.expect)(await memoryCache.has(nonce)).toBe(true);
66
- });
67
- (0, vitest_1.it)("should handle rapid sequential operations", async () => {
68
- const baseNonce = "rapid-memory-nonce";
69
- const operations = [];
70
- // Create 100 rapid sequential operations
71
- for (let i = 0; i < 100; i++) {
72
- operations.push(memoryCache.add(`${baseNonce}-${i}`, 60));
73
- }
74
- // All should succeed since they're different nonces
75
- const results = await Promise.allSettled(operations);
76
- const successful = results.filter((r) => r.status === "fulfilled");
77
- (0, vitest_1.expect)(successful).toHaveLength(100);
78
- // All nonces should exist
79
- for (let i = 0; i < 100; i++) {
80
- (0, vitest_1.expect)(await memoryCache.has(`${baseNonce}-${i}`)).toBe(true);
81
- }
82
- });
83
- });
84
- (0, vitest_1.describe)("Redis Cache Atomicity", () => {
85
- (0, vitest_1.it)("should use atomic SET NX EX for add operations", async () => {
86
- const nonce = "atomic-redis-nonce";
87
- const ttl = 300;
88
- // Mock successful atomic operation
89
- mockRedis.set.mockResolvedValue("OK");
90
- await redisCache.add(nonce, ttl);
91
- // Verify atomic command was used
92
- (0, vitest_1.expect)(mockRedis.set).toHaveBeenCalledWith("test:atomic-redis-nonce", "1", "EX", ttl, "NX");
93
- });
94
- (0, vitest_1.it)("should handle concurrent add attempts atomically", async () => {
95
- const nonce = "concurrent-redis-nonce";
96
- // First call succeeds, subsequent calls fail
97
- mockRedis.set.mockResolvedValueOnce("OK").mockResolvedValue(null);
98
- const promises = [
99
- redisCache.add(nonce, 60),
100
- redisCache.add(nonce, 60),
101
- redisCache.add(nonce, 60),
102
- ];
103
- const results = await Promise.allSettled(promises);
104
- // First should succeed, others should fail
105
- (0, vitest_1.expect)(results[0].status).toBe("fulfilled");
106
- (0, vitest_1.expect)(results[1].status).toBe("rejected");
107
- (0, vitest_1.expect)(results[2].status).toBe("rejected");
108
- // Verify all calls used atomic operation
109
- (0, vitest_1.expect)(mockRedis.set).toHaveBeenCalledTimes(3);
110
- mockRedis.set.mock.calls.forEach((call) => {
111
- (0, vitest_1.expect)(call).toEqual([
112
- vitest_1.expect.stringContaining(nonce),
113
- "1",
114
- "EX",
115
- 60,
116
- "NX",
117
- ]);
118
- });
119
- });
120
- });
121
- (0, vitest_1.describe)("DynamoDB Cache Atomicity", () => {
122
- (0, vitest_1.it)("should use conditional writes for atomicity", async () => {
123
- const nonce = "atomic-dynamo-nonce";
124
- const ttl = 300;
125
- // Mock successful conditional write
126
- mockDynamoDB.putItem.mockReturnValue({
127
- promise: () => Promise.resolve({}),
128
- });
129
- await dynamoCache.add(nonce, ttl);
130
- // Verify conditional expression was used
131
- (0, vitest_1.expect)(mockDynamoDB.putItem).toHaveBeenCalledWith({
132
- TableName: "test-table",
133
- Item: {
134
- nonce: { S: nonce },
135
- expiresAt: { N: vitest_1.expect.any(String) },
136
- createdAt: { N: vitest_1.expect.any(String) },
137
- },
138
- ConditionExpression: "attribute_not_exists(nonce)",
139
- });
140
- });
141
- (0, vitest_1.it)("should handle concurrent add attempts with conditional writes", async () => {
142
- const nonce = "concurrent-dynamo-nonce";
143
- // First call succeeds
144
- mockDynamoDB.putItem.mockReturnValueOnce({
145
- promise: () => Promise.resolve({}),
146
- });
147
- // Subsequent calls fail with conditional check exception
148
- const conditionalError = new Error("ConditionalCheckFailedException");
149
- conditionalError.code = "ConditionalCheckFailedException";
150
- mockDynamoDB.putItem.mockReturnValue({
151
- promise: () => Promise.reject(conditionalError),
152
- });
153
- const promises = [
154
- dynamoCache.add(nonce, 60),
155
- dynamoCache.add(nonce, 60),
156
- dynamoCache.add(nonce, 60),
157
- ];
158
- const results = await Promise.allSettled(promises);
159
- // First should succeed, others should fail
160
- (0, vitest_1.expect)(results[0].status).toBe("fulfilled");
161
- (0, vitest_1.expect)(results[1].status).toBe("rejected");
162
- (0, vitest_1.expect)(results[2].status).toBe("rejected");
163
- // All failures should be due to conditional check
164
- results.slice(1).forEach((result) => {
165
- if (result.status === "rejected") {
166
- (0, vitest_1.expect)(result.reason.message).toContain("already exists");
167
- }
168
- });
169
- });
170
- });
171
- (0, vitest_1.describe)("Cloudflare KV Cache Best-Effort Atomicity", () => {
172
- (0, vitest_1.it)("should attempt atomicity with getWithMetadata", async () => {
173
- const nonce = "atomic-kv-nonce";
174
- // Mock no existing value
175
- mockKV.getWithMetadata.mockResolvedValue({ value: null, metadata: null });
176
- mockKV.put.mockResolvedValue(undefined);
177
- await kvCache.add(nonce, 60);
178
- (0, vitest_1.expect)(mockKV.getWithMetadata).toHaveBeenCalledWith("test:atomic-kv-nonce");
179
- (0, vitest_1.expect)(mockKV.put).toHaveBeenCalled();
180
- });
181
- (0, vitest_1.it)("should detect existing nonces with getWithMetadata", async () => {
182
- const nonce = "existing-kv-nonce";
183
- // Mock existing valid nonce
184
- const futureTime = Date.now() + 50000;
185
- mockKV.getWithMetadata.mockResolvedValue({
186
- value: JSON.stringify({
187
- nonce,
188
- expiresAt: futureTime,
189
- createdAt: Date.now(),
190
- }),
191
- metadata: null,
192
- });
193
- await (0, vitest_1.expect)(kvCache.add(nonce, 60)).rejects.toThrow("already exists - potential replay attack");
194
- });
195
- (0, vitest_1.it)("should fall back to basic operations when getWithMetadata unavailable", async () => {
196
- const nonce = "fallback-kv-nonce";
197
- // Mock getWithMetadata failure
198
- mockKV.getWithMetadata.mockRejectedValue(new Error("getWithMetadata is not available"));
199
- // Mock basic operations
200
- mockKV.get.mockResolvedValue(null);
201
- mockKV.put.mockResolvedValue(undefined);
202
- await kvCache.add(nonce, 60);
203
- // Should fall back to basic has() check
204
- (0, vitest_1.expect)(mockKV.get).toHaveBeenCalledWith("test:fallback-kv-nonce");
205
- (0, vitest_1.expect)(mockKV.put).toHaveBeenCalled();
206
- });
207
- });
208
- (0, vitest_1.describe)("Cross-Implementation Consistency", () => {
209
- const testCases = [
210
- { name: "Memory", cache: () => memoryCache },
211
- {
212
- name: "Redis",
213
- cache: () => redisCache,
214
- setup: () => {
215
- mockRedis.exists.mockResolvedValue(0);
216
- mockRedis.set.mockResolvedValue("OK");
217
- },
218
- },
219
- {
220
- name: "DynamoDB",
221
- cache: () => dynamoCache,
222
- setup: () => {
223
- mockDynamoDB.getItem.mockReturnValue({
224
- promise: () => Promise.resolve({}),
225
- });
226
- mockDynamoDB.putItem.mockReturnValue({
227
- promise: () => Promise.resolve({}),
228
- });
229
- },
230
- },
231
- {
232
- name: "Cloudflare KV",
233
- cache: () => kvCache,
234
- setup: () => {
235
- mockKV.get.mockResolvedValue(null);
236
- mockKV.getWithMetadata.mockResolvedValue({
237
- value: null,
238
- metadata: null,
239
- });
240
- mockKV.put.mockResolvedValue(undefined);
241
- },
242
- },
243
- ];
244
- testCases.forEach(({ name, cache, setup }) => {
245
- (0, vitest_1.it)(`${name} should implement consistent interface`, async () => {
246
- if (setup)
247
- setup();
248
- const cacheInstance = cache();
249
- const nonce = `interface-test-${name.toLowerCase()}-nonce`;
250
- // Test interface methods exist and work
251
- (0, vitest_1.expect)(typeof cacheInstance.has).toBe("function");
252
- (0, vitest_1.expect)(typeof cacheInstance.add).toBe("function");
253
- (0, vitest_1.expect)(typeof cacheInstance.cleanup).toBe("function");
254
- // Test basic flow
255
- if (name === "Memory") {
256
- // Only test actual functionality for memory cache
257
- (0, vitest_1.expect)(await cacheInstance.has(nonce)).toBe(false);
258
- await cacheInstance.add(nonce, 60);
259
- (0, vitest_1.expect)(await cacheInstance.has(nonce)).toBe(true);
260
- }
261
- // cleanup should not throw
262
- await (0, vitest_1.expect)(cacheInstance.cleanup()).resolves.not.toThrow();
263
- });
264
- });
265
- });
266
- (0, vitest_1.describe)("Performance and Stress Testing", () => {
267
- (0, vitest_1.it)("should handle high-frequency operations on memory cache", async () => {
268
- const startTime = Date.now();
269
- const operations = [];
270
- // Create 1000 rapid operations
271
- for (let i = 0; i < 1000; i++) {
272
- operations.push(memoryCache.add(`stress-nonce-${i}`, 60));
273
- }
274
- await Promise.all(operations);
275
- const endTime = Date.now();
276
- // Should complete within reasonable time (adjust threshold as needed)
277
- (0, vitest_1.expect)(endTime - startTime).toBeLessThan(1000); // 1 second
278
- // All nonces should exist
279
- for (let i = 0; i < 1000; i++) {
280
- (0, vitest_1.expect)(await memoryCache.has(`stress-nonce-${i}`)).toBe(true);
281
- }
282
- });
283
- (0, vitest_1.it)("should handle mixed read/write operations on memory cache", async () => {
284
- const nonce = "mixed-ops-nonce";
285
- // Add initial nonce
286
- await memoryCache.add(nonce, 60);
287
- // Create mixed operations
288
- const operations = [];
289
- for (let i = 0; i < 100; i++) {
290
- operations.push(memoryCache.has(nonce));
291
- operations.push(memoryCache.add(`mixed-${i}`, 60));
292
- }
293
- const results = await Promise.allSettled(operations);
294
- // All has() operations should succeed
295
- // All add() operations should succeed (different nonces)
296
- const successful = results.filter((r) => r.status === "fulfilled");
297
- (0, vitest_1.expect)(successful.length).toBeGreaterThan(150); // Most should succeed
298
- });
299
- });
300
- });
@@ -1,4 +0,0 @@
1
- /**
2
- * Tests for DynamoDB Nonce Cache
3
- */
4
- export {};
@@ -1,176 +0,0 @@
1
- "use strict";
2
- /**
3
- * Tests for DynamoDB Nonce Cache
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const vitest_1 = require("vitest");
7
- const dynamodb_nonce_cache_js_1 = require("../dynamodb-nonce-cache.js");
8
- // Mock DynamoDB client
9
- const mockDynamoDB = {
10
- getItem: vitest_1.vi.fn(),
11
- putItem: vitest_1.vi.fn(),
12
- };
13
- // Helper to create mock DynamoDB responses
14
- const createMockGetItemResponse = (exists, expired = false) => {
15
- if (!exists) {
16
- return { promise: () => Promise.resolve({}) };
17
- }
18
- const expiresAt = expired
19
- ? Math.floor(Date.now() / 1000) - 100 // Expired 100 seconds ago
20
- : Math.floor(Date.now() / 1000) + 300; // Expires in 300 seconds
21
- return {
22
- promise: () => Promise.resolve({
23
- Item: {
24
- nonce: { S: "test-nonce" },
25
- expiresAt: { N: expiresAt.toString() },
26
- },
27
- }),
28
- };
29
- };
30
- const createMockPutItemResponse = (success = true) => {
31
- if (success) {
32
- return { promise: () => Promise.resolve({}) };
33
- }
34
- else {
35
- const error = new Error("ConditionalCheckFailedException");
36
- error.code = "ConditionalCheckFailedException";
37
- return { promise: () => Promise.reject(error) };
38
- }
39
- };
40
- (0, vitest_1.describe)("DynamoNonceCache", () => {
41
- let cache;
42
- (0, vitest_1.beforeEach)(() => {
43
- vitest_1.vi.clearAllMocks();
44
- cache = new dynamodb_nonce_cache_js_1.DynamoNonceCache(mockDynamoDB, "test-nonce-table");
45
- });
46
- (0, vitest_1.describe)("Basic Operations", () => {
47
- (0, vitest_1.it)("should add and check nonce existence", async () => {
48
- const nonce = "test-nonce-123";
49
- // Mock DynamoDB responses
50
- mockDynamoDB.getItem.mockReturnValue(createMockGetItemResponse(false));
51
- mockDynamoDB.putItem.mockReturnValue(createMockPutItemResponse(true));
52
- // Initially should not exist
53
- (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
54
- (0, vitest_1.expect)(mockDynamoDB.getItem).toHaveBeenCalledWith({
55
- TableName: "test-nonce-table",
56
- Key: { nonce: { S: nonce } },
57
- ConsistentRead: true,
58
- });
59
- // Add nonce
60
- await cache.add(nonce, 60);
61
- (0, vitest_1.expect)(mockDynamoDB.putItem).toHaveBeenCalledWith({
62
- TableName: "test-nonce-table",
63
- Item: {
64
- nonce: { S: nonce },
65
- expiresAt: { N: vitest_1.expect.any(String) },
66
- createdAt: { N: vitest_1.expect.any(String) },
67
- },
68
- ConditionExpression: "attribute_not_exists(nonce)",
69
- });
70
- // Mock that it now exists
71
- mockDynamoDB.getItem.mockReturnValue(createMockGetItemResponse(true));
72
- (0, vitest_1.expect)(await cache.has(nonce)).toBe(true);
73
- });
74
- (0, vitest_1.it)("should prevent duplicate nonce addition", async () => {
75
- const nonce = "duplicate-nonce";
76
- // Mock DynamoDB conditional check failure
77
- mockDynamoDB.putItem.mockReturnValue(createMockPutItemResponse(false));
78
- // Adding duplicate nonce should throw
79
- await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Nonce duplicate-nonce already exists - potential replay attack");
80
- });
81
- (0, vitest_1.it)("should handle expired nonces correctly", async () => {
82
- const nonce = "expired-nonce";
83
- // Mock expired nonce
84
- mockDynamoDB.getItem.mockReturnValue(createMockGetItemResponse(true, true));
85
- // Should return false for expired nonce
86
- (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
87
- });
88
- });
89
- (0, vitest_1.describe)("Error Handling", () => {
90
- (0, vitest_1.it)("should handle ResourceNotFoundException", async () => {
91
- const nonce = "missing-table-nonce";
92
- const error = new Error("Table not found");
93
- error.code = "ResourceNotFoundException";
94
- mockDynamoDB.getItem.mockReturnValue({
95
- promise: () => Promise.reject(error),
96
- });
97
- // Should return false for missing table
98
- (0, vitest_1.expect)(await cache.has(nonce)).toBe(false);
99
- });
100
- (0, vitest_1.it)("should handle ValidationException on add", async () => {
101
- const nonce = "validation-error-nonce";
102
- const error = new Error("Invalid request");
103
- error.code = "ValidationException";
104
- mockDynamoDB.putItem.mockReturnValue({
105
- promise: () => Promise.reject(error),
106
- });
107
- await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("Invalid DynamoDB operation");
108
- });
109
- (0, vitest_1.it)("should handle ProvisionedThroughputExceededException", async () => {
110
- const nonce = "throughput-error-nonce";
111
- const error = new Error("Throughput exceeded");
112
- error.code = "ProvisionedThroughputExceededException";
113
- mockDynamoDB.putItem.mockReturnValue({
114
- promise: () => Promise.reject(error),
115
- });
116
- await (0, vitest_1.expect)(cache.add(nonce, 60)).rejects.toThrow("DynamoDB throughput exceeded");
117
- });
118
- (0, vitest_1.it)("should propagate unknown errors with context", async () => {
119
- const nonce = "unknown-error-nonce";
120
- const error = new Error("Unknown error");
121
- error.code = "UnknownException";
122
- mockDynamoDB.getItem.mockReturnValue({
123
- promise: () => Promise.reject(error),
124
- });
125
- await (0, vitest_1.expect)(cache.has(nonce)).rejects.toThrow("Failed to check nonce existence");
126
- });
127
- });
128
- (0, vitest_1.describe)("Atomic Operations", () => {
129
- (0, vitest_1.it)("should use conditional write for atomicity", async () => {
130
- const nonce = "atomic-test-nonce";
131
- const ttl = 300;
132
- mockDynamoDB.putItem.mockReturnValue(createMockPutItemResponse(true));
133
- await cache.add(nonce, ttl);
134
- // Verify conditional expression was used
135
- (0, vitest_1.expect)(mockDynamoDB.putItem).toHaveBeenCalledWith({
136
- TableName: "test-nonce-table",
137
- Item: {
138
- nonce: { S: nonce },
139
- expiresAt: { N: vitest_1.expect.any(String) },
140
- createdAt: { N: vitest_1.expect.any(String) },
141
- },
142
- ConditionExpression: "attribute_not_exists(nonce)",
143
- });
144
- });
145
- (0, vitest_1.it)("should use consistent reads for has() operations", async () => {
146
- const nonce = "consistent-read-nonce";
147
- mockDynamoDB.getItem.mockReturnValue(createMockGetItemResponse(false));
148
- await cache.has(nonce);
149
- (0, vitest_1.expect)(mockDynamoDB.getItem).toHaveBeenCalledWith({
150
- TableName: "test-nonce-table",
151
- Key: { nonce: { S: nonce } },
152
- ConsistentRead: true,
153
- });
154
- });
155
- });
156
- (0, vitest_1.describe)("Cleanup", () => {
157
- (0, vitest_1.it)("should be a no-op since DynamoDB handles TTL", async () => {
158
- // cleanup() should not call any DynamoDB methods
159
- await cache.cleanup();
160
- (0, vitest_1.expect)(mockDynamoDB.getItem).not.toHaveBeenCalled();
161
- (0, vitest_1.expect)(mockDynamoDB.putItem).not.toHaveBeenCalled();
162
- });
163
- });
164
- (0, vitest_1.describe)("Custom Configuration", () => {
165
- (0, vitest_1.it)("should use custom attribute names", () => {
166
- const customCache = new dynamodb_nonce_cache_js_1.DynamoNonceCache(mockDynamoDB, "custom-table", "customKey", "customTTL");
167
- mockDynamoDB.getItem.mockReturnValue(createMockGetItemResponse(false));
168
- customCache.has("test-nonce");
169
- (0, vitest_1.expect)(mockDynamoDB.getItem).toHaveBeenCalledWith({
170
- TableName: "custom-table",
171
- Key: { customKey: { S: "test-nonce" } },
172
- ConsistentRead: true,
173
- });
174
- });
175
- });
176
- });
@@ -1,4 +0,0 @@
1
- /**
2
- * Tests for Memory Nonce Cache
3
- */
4
- export {};
@@ -1,132 +0,0 @@
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
- });
@@ -1,4 +0,0 @@
1
- /**
2
- * Simplified tests for Nonce Cache Factory
3
- */
4
- export {};