@teneo-protocol/sdk 1.0.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.
- package/.dockerignore +14 -0
- package/.env.test.example +14 -0
- package/.eslintrc.json +26 -0
- package/.github/workflows/claude-code-review.yml +78 -0
- package/.github/workflows/claude-reviewer.yml +64 -0
- package/.github/workflows/publish-npm.yml +38 -0
- package/.github/workflows/push-to-main.yml +23 -0
- package/.node-version +1 -0
- package/.prettierrc +11 -0
- package/Dockerfile +25 -0
- package/LICENCE +661 -0
- package/README.md +709 -0
- package/dist/constants.d.ts +42 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +45 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/websocket-client.d.ts +261 -0
- package/dist/core/websocket-client.d.ts.map +1 -0
- package/dist/core/websocket-client.js +875 -0
- package/dist/core/websocket-client.js.map +1 -0
- package/dist/formatters/response-formatter.d.ts +354 -0
- package/dist/formatters/response-formatter.d.ts.map +1 -0
- package/dist/formatters/response-formatter.js +575 -0
- package/dist/formatters/response-formatter.js.map +1 -0
- package/dist/handlers/message-handler-registry.d.ts +155 -0
- package/dist/handlers/message-handler-registry.d.ts.map +1 -0
- package/dist/handlers/message-handler-registry.js +216 -0
- package/dist/handlers/message-handler-registry.js.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts +112 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.js +40 -0
- package/dist/handlers/message-handlers/agent-selected-handler.js.map +1 -0
- package/dist/handlers/message-handlers/agents-list-handler.d.ts +14 -0
- package/dist/handlers/message-handlers/agents-list-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agents-list-handler.js +25 -0
- package/dist/handlers/message-handlers/agents-list-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts +71 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.js +30 -0
- package/dist/handlers/message-handlers/auth-error-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-message-handler.d.ts +18 -0
- package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-message-handler.js +60 -0
- package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-required-handler.d.ts +76 -0
- package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-required-handler.js +23 -0
- package/dist/handlers/message-handlers/auth-required-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-success-handler.d.ts +18 -0
- package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/auth-success-handler.js +51 -0
- package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -0
- package/dist/handlers/message-handlers/base-handler.d.ts +55 -0
- package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/base-handler.js +83 -0
- package/dist/handlers/message-handlers/base-handler.js.map +1 -0
- package/dist/handlers/message-handlers/challenge-handler.d.ts +73 -0
- package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/challenge-handler.js +47 -0
- package/dist/handlers/message-handlers/challenge-handler.js.map +1 -0
- package/dist/handlers/message-handlers/error-message-handler.d.ts +76 -0
- package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/error-message-handler.js +29 -0
- package/dist/handlers/message-handlers/error-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/index.d.ts +28 -0
- package/dist/handlers/message-handlers/index.d.ts.map +1 -0
- package/dist/handlers/message-handlers/index.js +100 -0
- package/dist/handlers/message-handlers/index.js.map +1 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +122 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.js +30 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts +104 -0
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/ping-pong-handler.js +36 -0
- package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts +56 -0
- package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/regular-message-handler.js +59 -0
- package/dist/handlers/message-handlers/regular-message-handler.js.map +1 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +81 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.js +48 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/task-response-handler.d.ts +14 -0
- package/dist/handlers/message-handlers/task-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/task-response-handler.js +44 -0
- package/dist/handlers/message-handlers/task-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/types.d.ts +51 -0
- package/dist/handlers/message-handlers/types.d.ts.map +1 -0
- package/dist/handlers/message-handlers/types.js +7 -0
- package/dist/handlers/message-handlers/types.js.map +1 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +81 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js +48 -0
- package/dist/handlers/message-handlers/unsubscribe-response-handler.js.map +1 -0
- package/dist/handlers/webhook-handler.d.ts +202 -0
- package/dist/handlers/webhook-handler.d.ts.map +1 -0
- package/dist/handlers/webhook-handler.js +511 -0
- package/dist/handlers/webhook-handler.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +217 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/agent-registry.d.ts +173 -0
- package/dist/managers/agent-registry.d.ts.map +1 -0
- package/dist/managers/agent-registry.js +310 -0
- package/dist/managers/agent-registry.js.map +1 -0
- package/dist/managers/connection-manager.d.ts +134 -0
- package/dist/managers/connection-manager.d.ts.map +1 -0
- package/dist/managers/connection-manager.js +176 -0
- package/dist/managers/connection-manager.js.map +1 -0
- package/dist/managers/index.d.ts +9 -0
- package/dist/managers/index.d.ts.map +1 -0
- package/dist/managers/index.js +16 -0
- package/dist/managers/index.js.map +1 -0
- package/dist/managers/message-router.d.ts +112 -0
- package/dist/managers/message-router.d.ts.map +1 -0
- package/dist/managers/message-router.js +260 -0
- package/dist/managers/message-router.js.map +1 -0
- package/dist/managers/room-manager.d.ts +165 -0
- package/dist/managers/room-manager.d.ts.map +1 -0
- package/dist/managers/room-manager.js +227 -0
- package/dist/managers/room-manager.js.map +1 -0
- package/dist/teneo-sdk.d.ts +703 -0
- package/dist/teneo-sdk.d.ts.map +1 -0
- package/dist/teneo-sdk.js +907 -0
- package/dist/teneo-sdk.js.map +1 -0
- package/dist/types/config.d.ts +1047 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +720 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/error-codes.d.ts +29 -0
- package/dist/types/error-codes.d.ts.map +1 -0
- package/dist/types/error-codes.js +41 -0
- package/dist/types/error-codes.js.map +1 -0
- package/dist/types/events.d.ts +616 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +261 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/health.d.ts +40 -0
- package/dist/types/health.d.ts.map +1 -0
- package/dist/types/health.js +6 -0
- package/dist/types/health.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +123 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/messages.d.ts +3734 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +482 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/validation.d.ts +81 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +115 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/utils/bounded-queue.d.ts +127 -0
- package/dist/utils/bounded-queue.d.ts.map +1 -0
- package/dist/utils/bounded-queue.js +181 -0
- package/dist/utils/bounded-queue.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +141 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +215 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/deduplication-cache.d.ts +110 -0
- package/dist/utils/deduplication-cache.d.ts.map +1 -0
- package/dist/utils/deduplication-cache.js +177 -0
- package/dist/utils/deduplication-cache.js.map +1 -0
- package/dist/utils/event-waiter.d.ts +101 -0
- package/dist/utils/event-waiter.d.ts.map +1 -0
- package/dist/utils/event-waiter.js +118 -0
- package/dist/utils/event-waiter.js.map +1 -0
- package/dist/utils/index.d.ts +51 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +72 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +22 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +91 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +122 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +190 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry-policy.d.ts +191 -0
- package/dist/utils/retry-policy.d.ts.map +1 -0
- package/dist/utils/retry-policy.js +225 -0
- package/dist/utils/retry-policy.js.map +1 -0
- package/dist/utils/secure-private-key.d.ts +113 -0
- package/dist/utils/secure-private-key.d.ts.map +1 -0
- package/dist/utils/secure-private-key.js +188 -0
- package/dist/utils/secure-private-key.js.map +1 -0
- package/dist/utils/signature-verifier.d.ts +143 -0
- package/dist/utils/signature-verifier.d.ts.map +1 -0
- package/dist/utils/signature-verifier.js +238 -0
- package/dist/utils/signature-verifier.js.map +1 -0
- package/dist/utils/ssrf-validator.d.ts +36 -0
- package/dist/utils/ssrf-validator.d.ts.map +1 -0
- package/dist/utils/ssrf-validator.js +195 -0
- package/dist/utils/ssrf-validator.js.map +1 -0
- package/examples/.env.example +17 -0
- package/examples/basic-usage.ts +211 -0
- package/examples/production-dashboard/.env.example +153 -0
- package/examples/production-dashboard/package.json +39 -0
- package/examples/production-dashboard/public/dashboard.html +642 -0
- package/examples/production-dashboard/server.ts +753 -0
- package/examples/webhook-integration.ts +239 -0
- package/examples/x-influencer-battle-redesign.html +1065 -0
- package/examples/x-influencer-battle-server.ts +217 -0
- package/examples/x-influencer-battle.html +787 -0
- package/package.json +65 -0
- package/src/constants.ts +43 -0
- package/src/core/websocket-client.test.ts +512 -0
- package/src/core/websocket-client.ts +1056 -0
- package/src/formatters/response-formatter.test.ts +571 -0
- package/src/formatters/response-formatter.ts +677 -0
- package/src/handlers/message-handler-registry.ts +239 -0
- package/src/handlers/message-handlers/agent-selected-handler.ts +40 -0
- package/src/handlers/message-handlers/agents-list-handler.ts +26 -0
- package/src/handlers/message-handlers/auth-error-handler.ts +31 -0
- package/src/handlers/message-handlers/auth-message-handler.ts +66 -0
- package/src/handlers/message-handlers/auth-required-handler.ts +23 -0
- package/src/handlers/message-handlers/auth-success-handler.ts +57 -0
- package/src/handlers/message-handlers/base-handler.ts +101 -0
- package/src/handlers/message-handlers/challenge-handler.ts +57 -0
- package/src/handlers/message-handlers/error-message-handler.ts +27 -0
- package/src/handlers/message-handlers/index.ts +77 -0
- package/src/handlers/message-handlers/list-rooms-response-handler.ts +28 -0
- package/src/handlers/message-handlers/ping-pong-handler.ts +30 -0
- package/src/handlers/message-handlers/regular-message-handler.ts +65 -0
- package/src/handlers/message-handlers/subscribe-response-handler.ts +47 -0
- package/src/handlers/message-handlers/task-response-handler.ts +45 -0
- package/src/handlers/message-handlers/types.ts +77 -0
- package/src/handlers/message-handlers/unsubscribe-response-handler.ts +47 -0
- package/src/handlers/webhook-handler.test.ts +789 -0
- package/src/handlers/webhook-handler.ts +576 -0
- package/src/index.ts +269 -0
- package/src/managers/agent-registry.test.ts +466 -0
- package/src/managers/agent-registry.ts +347 -0
- package/src/managers/connection-manager.ts +195 -0
- package/src/managers/index.ts +9 -0
- package/src/managers/message-router.ts +349 -0
- package/src/managers/room-manager.ts +248 -0
- package/src/teneo-sdk.ts +1022 -0
- package/src/types/config.test.ts +325 -0
- package/src/types/config.ts +799 -0
- package/src/types/error-codes.ts +44 -0
- package/src/types/events.test.ts +302 -0
- package/src/types/events.ts +382 -0
- package/src/types/health.ts +46 -0
- package/src/types/index.ts +199 -0
- package/src/types/messages.test.ts +660 -0
- package/src/types/messages.ts +570 -0
- package/src/types/validation.ts +123 -0
- package/src/utils/bounded-queue.test.ts +356 -0
- package/src/utils/bounded-queue.ts +205 -0
- package/src/utils/circuit-breaker.test.ts +394 -0
- package/src/utils/circuit-breaker.ts +262 -0
- package/src/utils/deduplication-cache.test.ts +380 -0
- package/src/utils/deduplication-cache.ts +198 -0
- package/src/utils/event-waiter.test.ts +381 -0
- package/src/utils/event-waiter.ts +172 -0
- package/src/utils/index.ts +74 -0
- package/src/utils/logger.ts +87 -0
- package/src/utils/rate-limiter.test.ts +341 -0
- package/src/utils/rate-limiter.ts +211 -0
- package/src/utils/retry-policy.test.ts +558 -0
- package/src/utils/retry-policy.ts +272 -0
- package/src/utils/secure-private-key.test.ts +356 -0
- package/src/utils/secure-private-key.ts +205 -0
- package/src/utils/signature-verifier.test.ts +464 -0
- package/src/utils/signature-verifier.ts +298 -0
- package/src/utils/ssrf-validator.test.ts +372 -0
- package/src/utils/ssrf-validator.ts +224 -0
- package/tests/integration/real-server.test.ts +740 -0
- package/tests/integration/websocket.test.ts +381 -0
- package/tests/integration-setup.ts +16 -0
- package/tests/setup.ts +34 -0
- package/tsconfig.json +32 -0
- package/vitest.config.ts +42 -0
- package/vitest.integration.config.ts +23 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validation schemas for user inputs
|
|
4
|
+
* Provides strict validation with length limits, character restrictions, and format requirements
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SearchQuerySchema = exports.AgentCommandContentSchema = exports.MessageContentSchema = exports.AgentIdSchema = exports.RoomIdSchema = void 0;
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
/**
|
|
10
|
+
* Validates room IDs with strict constraints.
|
|
11
|
+
* - Must not be empty
|
|
12
|
+
* - Maximum 100 characters
|
|
13
|
+
* - Only alphanumeric characters, spaces, dashes, and underscores allowed
|
|
14
|
+
* - Automatically trims whitespace
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const roomId = RoomIdSchema.parse('general-chat'); // OK
|
|
19
|
+
* const roomId = RoomIdSchema.parse('room_123'); // OK
|
|
20
|
+
* const roomId = RoomIdSchema.parse('Crawler Room'); // OK
|
|
21
|
+
* const roomId = RoomIdSchema.parse('invalid room!'); // Error: invalid characters
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
exports.RoomIdSchema = zod_1.z
|
|
25
|
+
.string()
|
|
26
|
+
.min(1, "Room ID cannot be empty")
|
|
27
|
+
.max(100, "Room ID must be 100 characters or less")
|
|
28
|
+
.regex(/^[a-zA-Z0-9_\- ]+$/, "Room ID can only contain letters, numbers, spaces, dashes, and underscores")
|
|
29
|
+
.trim();
|
|
30
|
+
/**
|
|
31
|
+
* Validates agent IDs with strict constraints.
|
|
32
|
+
* - Must not be empty
|
|
33
|
+
* - Maximum 100 characters
|
|
34
|
+
* - Only alphanumeric characters, dashes, and underscores allowed
|
|
35
|
+
* - Automatically trims whitespace
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const agentId = AgentIdSchema.parse('agent-123'); // OK
|
|
40
|
+
* const agentId = AgentIdSchema.parse('my_agent'); // OK
|
|
41
|
+
* const agentId = AgentIdSchema.parse('invalid agent!'); // Error: invalid characters
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
exports.AgentIdSchema = zod_1.z
|
|
45
|
+
.string()
|
|
46
|
+
.min(1, "Agent ID cannot be empty")
|
|
47
|
+
.max(100, "Agent ID must be 100 characters or less")
|
|
48
|
+
.regex(/^[a-zA-Z0-9_-]+$/, "Agent ID can only contain letters, numbers, dashes, and underscores")
|
|
49
|
+
.trim();
|
|
50
|
+
/**
|
|
51
|
+
* Validates message content with strict constraints.
|
|
52
|
+
* - Must not be empty
|
|
53
|
+
* - Maximum 10,000 characters to prevent abuse
|
|
54
|
+
* - No control characters (except newline, tab, carriage return)
|
|
55
|
+
* - Automatically trims whitespace
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const content = MessageContentSchema.parse('Hello, world!'); // OK
|
|
60
|
+
* const content = MessageContentSchema.parse('Multi\nline\nmessage'); // OK
|
|
61
|
+
* const content = MessageContentSchema.parse('\x00Bad content'); // Error: control characters
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
exports.MessageContentSchema = zod_1.z
|
|
65
|
+
.string()
|
|
66
|
+
.trim()
|
|
67
|
+
.min(1, "Message content cannot be empty")
|
|
68
|
+
.max(10000, "Message content must be 10,000 characters or less")
|
|
69
|
+
.refine(
|
|
70
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
71
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str), "Message content cannot contain control characters");
|
|
72
|
+
/**
|
|
73
|
+
* Validates agent command content (string) with strict constraints.
|
|
74
|
+
* - Must not be empty
|
|
75
|
+
* - Maximum 5,000 characters
|
|
76
|
+
* - No control characters (except newline, tab, carriage return)
|
|
77
|
+
* - Automatically trims whitespace
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const command = AgentCommandContentSchema.parse('execute task'); // OK
|
|
82
|
+
* const command = AgentCommandContentSchema.parse('multi\nline\ncommand'); // OK
|
|
83
|
+
* const command = AgentCommandContentSchema.parse('\x00Bad'); // Error: control characters
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
exports.AgentCommandContentSchema = zod_1.z
|
|
87
|
+
.string()
|
|
88
|
+
.trim()
|
|
89
|
+
.min(1, "Agent command cannot be empty")
|
|
90
|
+
.max(5000, "Agent command must be 5,000 characters or less")
|
|
91
|
+
.refine(
|
|
92
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
93
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str), "Agent command cannot contain control characters");
|
|
94
|
+
/**
|
|
95
|
+
* Validates search queries with strict constraints.
|
|
96
|
+
* - Must not be empty
|
|
97
|
+
* - Maximum 200 characters (reasonable for search)
|
|
98
|
+
* - No control characters
|
|
99
|
+
* - Automatically trims whitespace
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const query = SearchQuerySchema.parse('find agents'); // OK
|
|
104
|
+
* const query = SearchQuerySchema.parse('\x00Bad query'); // Error: control characters
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
exports.SearchQuerySchema = zod_1.z
|
|
108
|
+
.string()
|
|
109
|
+
.trim()
|
|
110
|
+
.min(1, "Search query cannot be empty")
|
|
111
|
+
.max(200, "Search query must be 200 characters or less")
|
|
112
|
+
.refine(
|
|
113
|
+
// eslint-disable-next-line no-control-regex -- Intentionally checking for control characters to prevent injection
|
|
114
|
+
(str) => !/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str), "Search query cannot contain control characters");
|
|
115
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/types/validation.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6BAAwB;AAExB;;;;;;;;;;;;;;GAcG;AACU,QAAA,YAAY,GAAG,OAAC;KAC1B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,yBAAyB,CAAC;KACjC,GAAG,CAAC,GAAG,EAAE,wCAAwC,CAAC;KAClD,KAAK,CAAC,oBAAoB,EAAE,4EAA4E,CAAC;KACzG,IAAI,EAAE,CAAC;AAEV;;;;;;;;;;;;;GAaG;AACU,QAAA,aAAa,GAAG,OAAC;KAC3B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,0BAA0B,CAAC;KAClC,GAAG,CAAC,GAAG,EAAE,yCAAyC,CAAC;KACnD,KAAK,CAAC,kBAAkB,EAAE,qEAAqE,CAAC;KAChG,IAAI,EAAE,CAAC;AAEV;;;;;;;;;;;;;GAaG;AACU,QAAA,oBAAoB,GAAG,OAAC;KAClC,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC;KACzC,GAAG,CAAC,KAAK,EAAE,mDAAmD,CAAC;KAC/D,MAAM;AACL,kHAAkH;AAClH,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC,EACtD,mDAAmD,CACpD,CAAC;AAEJ;;;;;;;;;;;;;GAaG;AACU,QAAA,yBAAyB,GAAG,OAAC;KACvC,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,EAAE,+BAA+B,CAAC;KACvC,GAAG,CAAC,IAAI,EAAE,gDAAgD,CAAC;KAC3D,MAAM;AACL,kHAAkH;AAClH,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC,EACtD,iDAAiD,CAClD,CAAC;AAEJ;;;;;;;;;;;;GAYG;AACU,QAAA,iBAAiB,GAAG,OAAC;KAC/B,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,EAAE,8BAA8B,CAAC;KACtC,GAAG,CAAC,GAAG,EAAE,6CAA6C,CAAC;KACvD,MAAM;AACL,kHAAkH;AAClH,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC,EACtD,gDAAgD,CACjD,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded Queue with Overflow Strategies
|
|
3
|
+
* Prevents unbounded memory growth by enforcing a maximum size
|
|
4
|
+
*
|
|
5
|
+
* This queue prevents the OOM (Out of Memory) issues that can occur
|
|
6
|
+
* with unbounded queues when producers outpace consumers (e.g., webhook
|
|
7
|
+
* delivery failures causing queue buildup).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Strategy for handling queue overflow when at max capacity
|
|
11
|
+
*/
|
|
12
|
+
export type OverflowStrategy = 'drop-oldest' | 'drop-newest' | 'reject';
|
|
13
|
+
/**
|
|
14
|
+
* A queue with a maximum size limit and configurable overflow behavior
|
|
15
|
+
*
|
|
16
|
+
* @template T The type of items stored in the queue
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Create queue that drops oldest items when full
|
|
21
|
+
* const queue = new BoundedQueue<Message>(1000, 'drop-oldest');
|
|
22
|
+
*
|
|
23
|
+
* queue.push(message1); // returns true
|
|
24
|
+
* queue.push(message2); // returns true
|
|
25
|
+
*
|
|
26
|
+
* const msg = queue.shift(); // Remove from front
|
|
27
|
+
* const peek = queue.peek(); // Look at front without removing
|
|
28
|
+
*
|
|
29
|
+
* if (queue.isFull()) {
|
|
30
|
+
* console.log('Queue at capacity');
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class BoundedQueue<T> {
|
|
35
|
+
private readonly maxSize;
|
|
36
|
+
private readonly strategy;
|
|
37
|
+
private queue;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new bounded queue
|
|
40
|
+
*
|
|
41
|
+
* @param maxSize Maximum number of items the queue can hold
|
|
42
|
+
* @param strategy How to handle overflow when queue is full
|
|
43
|
+
* @throws {Error} If maxSize is less than 1
|
|
44
|
+
*/
|
|
45
|
+
constructor(maxSize: number, strategy?: OverflowStrategy);
|
|
46
|
+
/**
|
|
47
|
+
* Add an item to the end of the queue
|
|
48
|
+
*
|
|
49
|
+
* Behavior when queue is full depends on strategy:
|
|
50
|
+
* - 'drop-oldest': Removes oldest item, adds new item, returns true
|
|
51
|
+
* - 'drop-newest': Rejects new item, returns false
|
|
52
|
+
* - 'reject': Throws QueueOverflowError
|
|
53
|
+
*
|
|
54
|
+
* @param item Item to add to the queue
|
|
55
|
+
* @returns true if item was added, false if rejected (drop-newest strategy only)
|
|
56
|
+
* @throws {QueueOverflowError} If strategy is 'reject' and queue is full
|
|
57
|
+
*/
|
|
58
|
+
push(item: T): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Remove and return the item at the front of the queue
|
|
61
|
+
*
|
|
62
|
+
* @returns The item at the front, or undefined if queue is empty
|
|
63
|
+
*/
|
|
64
|
+
shift(): T | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Look at the item at the front of the queue without removing it
|
|
67
|
+
*
|
|
68
|
+
* @returns The item at the front, or undefined if queue is empty
|
|
69
|
+
*/
|
|
70
|
+
peek(): T | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Remove all items from the queue
|
|
73
|
+
*/
|
|
74
|
+
clear(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Get the current number of items in the queue
|
|
77
|
+
*
|
|
78
|
+
* @returns Number of items currently in the queue
|
|
79
|
+
*/
|
|
80
|
+
size(): number;
|
|
81
|
+
/**
|
|
82
|
+
* Check if the queue is at maximum capacity
|
|
83
|
+
*
|
|
84
|
+
* @returns true if queue is full, false otherwise
|
|
85
|
+
*/
|
|
86
|
+
isFull(): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Check if the queue is empty
|
|
89
|
+
*
|
|
90
|
+
* @returns true if queue has no items, false otherwise
|
|
91
|
+
*/
|
|
92
|
+
isEmpty(): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Get the maximum capacity of the queue
|
|
95
|
+
*
|
|
96
|
+
* @returns The maximum number of items the queue can hold
|
|
97
|
+
*/
|
|
98
|
+
getMaxSize(): number;
|
|
99
|
+
/**
|
|
100
|
+
* Get the current overflow strategy
|
|
101
|
+
*
|
|
102
|
+
* @returns The configured overflow strategy
|
|
103
|
+
*/
|
|
104
|
+
getStrategy(): OverflowStrategy;
|
|
105
|
+
/**
|
|
106
|
+
* Get all items in the queue (for inspection/debugging)
|
|
107
|
+
* Returns a copy to prevent external modification
|
|
108
|
+
*
|
|
109
|
+
* @returns Array of all items in the queue (oldest to newest)
|
|
110
|
+
*/
|
|
111
|
+
toArray(): T[];
|
|
112
|
+
/**
|
|
113
|
+
* Handle queue overflow based on configured strategy
|
|
114
|
+
*
|
|
115
|
+
* @param item The item attempting to be added
|
|
116
|
+
* @returns true if item was added, false if rejected
|
|
117
|
+
* @throws {QueueOverflowError} If strategy is 'reject'
|
|
118
|
+
*/
|
|
119
|
+
private handleOverflow;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Error thrown when attempting to add to a full queue with 'reject' strategy
|
|
123
|
+
*/
|
|
124
|
+
export declare class QueueOverflowError extends Error {
|
|
125
|
+
constructor(message: string);
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=bounded-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-queue.d.ts","sourceRoot":"","sources":["../../src/utils/bounded-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,aAAa,GACb,QAAQ,CAAC;AAEb;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,YAAY,CAAC,CAAC;IAWvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,OAAO,CAAC,KAAK,CAAW;IAExB;;;;;;OAMG;gBAEgB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,gBAAgC;IAO7D;;;;;;;;;;;OAWG;IACI,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAS7B;;;;OAIG;IACI,KAAK,IAAI,CAAC,GAAG,SAAS;IAI7B;;;;OAIG;IACI,IAAI,IAAI,CAAC,GAAG,SAAS;IAI5B;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;;;OAIG;IACI,IAAI,IAAI,MAAM;IAIrB;;;;OAIG;IACI,MAAM,IAAI,OAAO;IAIxB;;;;OAIG;IACI,OAAO,IAAI,OAAO;IAIzB;;;;OAIG;IACI,UAAU,IAAI,MAAM;IAI3B;;;;OAIG;IACI,WAAW,IAAI,gBAAgB;IAItC;;;;;OAKG;IACI,OAAO,IAAI,CAAC,EAAE;IAIrB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAwBvB;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAS5B"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bounded Queue with Overflow Strategies
|
|
4
|
+
* Prevents unbounded memory growth by enforcing a maximum size
|
|
5
|
+
*
|
|
6
|
+
* This queue prevents the OOM (Out of Memory) issues that can occur
|
|
7
|
+
* with unbounded queues when producers outpace consumers (e.g., webhook
|
|
8
|
+
* delivery failures causing queue buildup).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.QueueOverflowError = exports.BoundedQueue = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* A queue with a maximum size limit and configurable overflow behavior
|
|
14
|
+
*
|
|
15
|
+
* @template T The type of items stored in the queue
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Create queue that drops oldest items when full
|
|
20
|
+
* const queue = new BoundedQueue<Message>(1000, 'drop-oldest');
|
|
21
|
+
*
|
|
22
|
+
* queue.push(message1); // returns true
|
|
23
|
+
* queue.push(message2); // returns true
|
|
24
|
+
*
|
|
25
|
+
* const msg = queue.shift(); // Remove from front
|
|
26
|
+
* const peek = queue.peek(); // Look at front without removing
|
|
27
|
+
*
|
|
28
|
+
* if (queue.isFull()) {
|
|
29
|
+
* console.log('Queue at capacity');
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
class BoundedQueue {
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new bounded queue
|
|
36
|
+
*
|
|
37
|
+
* @param maxSize Maximum number of items the queue can hold
|
|
38
|
+
* @param strategy How to handle overflow when queue is full
|
|
39
|
+
* @throws {Error} If maxSize is less than 1
|
|
40
|
+
*/
|
|
41
|
+
constructor(maxSize, strategy = 'drop-oldest') {
|
|
42
|
+
this.maxSize = maxSize;
|
|
43
|
+
this.strategy = strategy;
|
|
44
|
+
this.queue = [];
|
|
45
|
+
if (maxSize < 1) {
|
|
46
|
+
throw new Error('BoundedQueue maxSize must be at least 1');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Add an item to the end of the queue
|
|
51
|
+
*
|
|
52
|
+
* Behavior when queue is full depends on strategy:
|
|
53
|
+
* - 'drop-oldest': Removes oldest item, adds new item, returns true
|
|
54
|
+
* - 'drop-newest': Rejects new item, returns false
|
|
55
|
+
* - 'reject': Throws QueueOverflowError
|
|
56
|
+
*
|
|
57
|
+
* @param item Item to add to the queue
|
|
58
|
+
* @returns true if item was added, false if rejected (drop-newest strategy only)
|
|
59
|
+
* @throws {QueueOverflowError} If strategy is 'reject' and queue is full
|
|
60
|
+
*/
|
|
61
|
+
push(item) {
|
|
62
|
+
if (this.queue.length >= this.maxSize) {
|
|
63
|
+
return this.handleOverflow(item);
|
|
64
|
+
}
|
|
65
|
+
this.queue.push(item);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Remove and return the item at the front of the queue
|
|
70
|
+
*
|
|
71
|
+
* @returns The item at the front, or undefined if queue is empty
|
|
72
|
+
*/
|
|
73
|
+
shift() {
|
|
74
|
+
return this.queue.shift();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Look at the item at the front of the queue without removing it
|
|
78
|
+
*
|
|
79
|
+
* @returns The item at the front, or undefined if queue is empty
|
|
80
|
+
*/
|
|
81
|
+
peek() {
|
|
82
|
+
return this.queue[0];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Remove all items from the queue
|
|
86
|
+
*/
|
|
87
|
+
clear() {
|
|
88
|
+
this.queue = [];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the current number of items in the queue
|
|
92
|
+
*
|
|
93
|
+
* @returns Number of items currently in the queue
|
|
94
|
+
*/
|
|
95
|
+
size() {
|
|
96
|
+
return this.queue.length;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if the queue is at maximum capacity
|
|
100
|
+
*
|
|
101
|
+
* @returns true if queue is full, false otherwise
|
|
102
|
+
*/
|
|
103
|
+
isFull() {
|
|
104
|
+
return this.queue.length >= this.maxSize;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if the queue is empty
|
|
108
|
+
*
|
|
109
|
+
* @returns true if queue has no items, false otherwise
|
|
110
|
+
*/
|
|
111
|
+
isEmpty() {
|
|
112
|
+
return this.queue.length === 0;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get the maximum capacity of the queue
|
|
116
|
+
*
|
|
117
|
+
* @returns The maximum number of items the queue can hold
|
|
118
|
+
*/
|
|
119
|
+
getMaxSize() {
|
|
120
|
+
return this.maxSize;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the current overflow strategy
|
|
124
|
+
*
|
|
125
|
+
* @returns The configured overflow strategy
|
|
126
|
+
*/
|
|
127
|
+
getStrategy() {
|
|
128
|
+
return this.strategy;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get all items in the queue (for inspection/debugging)
|
|
132
|
+
* Returns a copy to prevent external modification
|
|
133
|
+
*
|
|
134
|
+
* @returns Array of all items in the queue (oldest to newest)
|
|
135
|
+
*/
|
|
136
|
+
toArray() {
|
|
137
|
+
return [...this.queue];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Handle queue overflow based on configured strategy
|
|
141
|
+
*
|
|
142
|
+
* @param item The item attempting to be added
|
|
143
|
+
* @returns true if item was added, false if rejected
|
|
144
|
+
* @throws {QueueOverflowError} If strategy is 'reject'
|
|
145
|
+
*/
|
|
146
|
+
handleOverflow(item) {
|
|
147
|
+
switch (this.strategy) {
|
|
148
|
+
case 'drop-oldest':
|
|
149
|
+
// Remove oldest item and add new one
|
|
150
|
+
this.queue.shift();
|
|
151
|
+
this.queue.push(item);
|
|
152
|
+
return true;
|
|
153
|
+
case 'drop-newest':
|
|
154
|
+
// Reject the new item
|
|
155
|
+
return false;
|
|
156
|
+
case 'reject':
|
|
157
|
+
// Throw error - let caller handle
|
|
158
|
+
throw new QueueOverflowError(`Queue is full (max size: ${this.maxSize}). Cannot add more items.`);
|
|
159
|
+
default:
|
|
160
|
+
// TypeScript exhaustiveness check
|
|
161
|
+
const _exhaustive = this.strategy;
|
|
162
|
+
throw new Error(`Unknown overflow strategy: ${_exhaustive}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.BoundedQueue = BoundedQueue;
|
|
167
|
+
/**
|
|
168
|
+
* Error thrown when attempting to add to a full queue with 'reject' strategy
|
|
169
|
+
*/
|
|
170
|
+
class QueueOverflowError extends Error {
|
|
171
|
+
constructor(message) {
|
|
172
|
+
super(message);
|
|
173
|
+
this.name = 'QueueOverflowError';
|
|
174
|
+
// Maintains proper stack trace for where error was thrown (V8 only)
|
|
175
|
+
if (Error.captureStackTrace) {
|
|
176
|
+
Error.captureStackTrace(this, QueueOverflowError);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.QueueOverflowError = QueueOverflowError;
|
|
181
|
+
//# sourceMappingURL=bounded-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-queue.js","sourceRoot":"","sources":["../../src/utils/bounded-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Pattern Implementation
|
|
3
|
+
* Provides fault tolerance by preventing cascading failures
|
|
4
|
+
*
|
|
5
|
+
* States:
|
|
6
|
+
* - CLOSED: Normal operation, requests pass through
|
|
7
|
+
* - OPEN: Failure threshold exceeded, requests fail fast
|
|
8
|
+
* - HALF_OPEN: Testing if service recovered, limited requests allowed
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Circuit breaker states
|
|
12
|
+
*/
|
|
13
|
+
export type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
|
|
14
|
+
/**
|
|
15
|
+
* Circuit breaker configuration options
|
|
16
|
+
*/
|
|
17
|
+
export interface CircuitBreakerOptions {
|
|
18
|
+
/** Number of failures before opening circuit (default: 5) */
|
|
19
|
+
failureThreshold?: number;
|
|
20
|
+
/** Success count needed to close from half-open (default: 2) */
|
|
21
|
+
successThreshold?: number;
|
|
22
|
+
/** Time in ms to wait before trying half-open (default: 60000) */
|
|
23
|
+
timeout?: number;
|
|
24
|
+
/** Window size in ms for tracking failures (default: 60000) */
|
|
25
|
+
windowSize?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Error thrown when circuit is open
|
|
29
|
+
*/
|
|
30
|
+
export declare class CircuitBreakerError extends Error {
|
|
31
|
+
readonly state: CircuitState;
|
|
32
|
+
constructor(message: string, state: CircuitState);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Circuit breaker for fault tolerance
|
|
36
|
+
* Prevents cascading failures by failing fast when errors are detected
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const breaker = new CircuitBreaker({
|
|
41
|
+
* failureThreshold: 5,
|
|
42
|
+
* timeout: 60000
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* try {
|
|
46
|
+
* await breaker.execute(async () => {
|
|
47
|
+
* return await fetch('https://api.example.com/data');
|
|
48
|
+
* });
|
|
49
|
+
* } catch (error) {
|
|
50
|
+
* if (error instanceof CircuitBreakerError) {
|
|
51
|
+
* console.log('Circuit is open, failing fast');
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare class CircuitBreaker {
|
|
57
|
+
private state;
|
|
58
|
+
private failureCount;
|
|
59
|
+
private successCount;
|
|
60
|
+
private lastFailureTime?;
|
|
61
|
+
private nextAttemptTime?;
|
|
62
|
+
private readonly failures;
|
|
63
|
+
private readonly failureThreshold;
|
|
64
|
+
private readonly successThreshold;
|
|
65
|
+
private readonly timeout;
|
|
66
|
+
private readonly windowSize;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new circuit breaker
|
|
69
|
+
*
|
|
70
|
+
* @param options - Configuration options
|
|
71
|
+
* @throws {Error} If thresholds are less than 1
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const breaker = new CircuitBreaker({
|
|
76
|
+
* failureThreshold: 5, // Open after 5 failures
|
|
77
|
+
* successThreshold: 2, // Close after 2 successes
|
|
78
|
+
* timeout: 60000, // Wait 60s before trying again
|
|
79
|
+
* windowSize: 60000 // Track failures in 60s window
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
constructor(options?: CircuitBreakerOptions);
|
|
84
|
+
/**
|
|
85
|
+
* Execute an operation through the circuit breaker
|
|
86
|
+
*
|
|
87
|
+
* @template T - Return type of the operation
|
|
88
|
+
* @param operation - Async operation to execute
|
|
89
|
+
* @returns Promise resolving to operation result
|
|
90
|
+
* @throws {CircuitBreakerError} If circuit is open
|
|
91
|
+
* @throws Operation error if operation fails
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const result = await breaker.execute(async () => {
|
|
96
|
+
* const response = await fetch(url);
|
|
97
|
+
* return await response.json();
|
|
98
|
+
* });
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
execute<T>(operation: () => Promise<T>): Promise<T>;
|
|
102
|
+
/**
|
|
103
|
+
* Get current circuit breaker state and metrics
|
|
104
|
+
*
|
|
105
|
+
* @returns State object with status and counters
|
|
106
|
+
*/
|
|
107
|
+
getState(): {
|
|
108
|
+
state: CircuitState;
|
|
109
|
+
failureCount: number;
|
|
110
|
+
successCount: number;
|
|
111
|
+
lastFailureTime?: number;
|
|
112
|
+
nextAttemptTime?: number;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Get circuit breaker configuration
|
|
116
|
+
*/
|
|
117
|
+
getConfig(): {
|
|
118
|
+
failureThreshold: number;
|
|
119
|
+
successThreshold: number;
|
|
120
|
+
timeout: number;
|
|
121
|
+
windowSize: number;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Manually reset the circuit breaker to CLOSED state
|
|
125
|
+
* Useful for recovery scenarios or testing
|
|
126
|
+
*/
|
|
127
|
+
reset(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Try to transition from OPEN to HALF_OPEN if timeout has passed
|
|
130
|
+
*/
|
|
131
|
+
private tryTransitionToHalfOpen;
|
|
132
|
+
/**
|
|
133
|
+
* Handle successful operation
|
|
134
|
+
*/
|
|
135
|
+
private onSuccess;
|
|
136
|
+
/**
|
|
137
|
+
* Handle failed operation
|
|
138
|
+
*/
|
|
139
|
+
private onFailure;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/utils/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aACC,KAAK,EAAE,YAAY;gBAApD,OAAO,EAAE,MAAM,EAAkB,KAAK,EAAE,YAAY;CAQjE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IAEzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC;;;;;;;;;;;;;;;OAeG;gBACS,OAAO,GAAE,qBAA0B;IAc/C;;;;;;;;;;;;;;;;OAgBG;IACU,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBhE;;;;OAIG;IACI,QAAQ,IAAI;QACjB,KAAK,EAAE,YAAY,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAUD;;OAEG;IACI,SAAS,IAAI;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB;IASD;;;OAGG;IACI,KAAK,IAAI,IAAI;IASpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAS/B;;OAEG;IACH,OAAO,CAAC,SAAS;IAkBjB;;OAEG;IACH,OAAO,CAAC,SAAS;CA8BlB"}
|