@vigneshreddy/cms-sdk 1.0.15 → 1.0.16
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/package.json +1 -1
- package/dist/src/circuit-breaker.d.ts +0 -97
- package/dist/src/circuit-breaker.js +0 -162
- package/dist/src/constants.d.ts +0 -128
- package/dist/src/constants.js +0 -182
- package/dist/src/generated/api.d.ts +0 -192
- package/dist/src/generated/api.js +0 -276
- package/dist/src/generated/base.d.ts +0 -46
- package/dist/src/generated/base.js +0 -39
- package/dist/src/generated/common.d.ts +0 -20
- package/dist/src/generated/common.js +0 -103
- package/dist/src/generated/configuration.d.ts +0 -87
- package/dist/src/generated/configuration.js +0 -37
- package/dist/src/generated/index.d.ts +0 -4
- package/dist/src/generated/index.js +0 -20
- package/dist/src/rate-limiter.d.ts +0 -74
- package/dist/src/rate-limiter.js +0 -109
- package/dist/src/validation.d.ts +0 -119
- package/dist/src/validation.js +0 -196
package/package.json
CHANGED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Circuit breaker to prevent cascading failures
|
|
3
|
-
* Fails fast when backend is unhealthy
|
|
4
|
-
*/
|
|
5
|
-
export declare enum CircuitBreakerState {
|
|
6
|
-
CLOSED = "CLOSED",// Normal operation
|
|
7
|
-
OPEN = "OPEN",// Failing fast
|
|
8
|
-
HALF_OPEN = "HALF_OPEN"
|
|
9
|
-
}
|
|
10
|
-
export interface CircuitBreakerOptions {
|
|
11
|
-
/** Number of failures before opening circuit */
|
|
12
|
-
failureThreshold: number;
|
|
13
|
-
/** Time window to count failures (milliseconds) */
|
|
14
|
-
failureWindowMs: number;
|
|
15
|
-
/** Time to wait before attempting to recover (milliseconds) */
|
|
16
|
-
resetTimeoutMs: number;
|
|
17
|
-
/** Callback when state changes */
|
|
18
|
-
onStateChange?: (newState: CircuitBreakerState, reason?: string) => void;
|
|
19
|
-
}
|
|
20
|
-
export declare class CircuitBreaker {
|
|
21
|
-
private state;
|
|
22
|
-
private failureCount;
|
|
23
|
-
private failureTimestamps;
|
|
24
|
-
private lastFailureTime;
|
|
25
|
-
private nextAttemptTime;
|
|
26
|
-
private failureThreshold;
|
|
27
|
-
private failureWindowMs;
|
|
28
|
-
private resetTimeoutMs;
|
|
29
|
-
private onStateChange?;
|
|
30
|
-
constructor(options: CircuitBreakerOptions);
|
|
31
|
-
/**
|
|
32
|
-
* Check if a request should be allowed
|
|
33
|
-
*/
|
|
34
|
-
canAttempt(): boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Record a successful request
|
|
37
|
-
*/
|
|
38
|
-
recordSuccess(): void;
|
|
39
|
-
/**
|
|
40
|
-
* Record a failed request
|
|
41
|
-
*/
|
|
42
|
-
recordFailure(): void;
|
|
43
|
-
/**
|
|
44
|
-
* Get current state
|
|
45
|
-
*/
|
|
46
|
-
getState(): CircuitBreakerState;
|
|
47
|
-
/**
|
|
48
|
-
* Get number of recent failures
|
|
49
|
-
*/
|
|
50
|
-
getFailureCount(): number;
|
|
51
|
-
/**
|
|
52
|
-
* Get milliseconds until circuit attempts to recover
|
|
53
|
-
*/
|
|
54
|
-
getRecoveryTime(): number;
|
|
55
|
-
/**
|
|
56
|
-
* Manually reset the circuit breaker
|
|
57
|
-
*/
|
|
58
|
-
reset(): void;
|
|
59
|
-
private setState;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Pre-configured circuit breaker settings for common scenarios
|
|
63
|
-
*/
|
|
64
|
-
export declare const CIRCUIT_BREAKER_PRESETS: {
|
|
65
|
-
/**
|
|
66
|
-
* Strict: Open after 2 failures in 10 seconds, wait 30 seconds before retry
|
|
67
|
-
*/
|
|
68
|
-
readonly STRICT: {
|
|
69
|
-
readonly failureThreshold: 2;
|
|
70
|
-
readonly failureWindowMs: 10000;
|
|
71
|
-
readonly resetTimeoutMs: 30000;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Standard: Open after 5 failures in 30 seconds, wait 60 seconds before retry
|
|
75
|
-
*/
|
|
76
|
-
readonly STANDARD: {
|
|
77
|
-
readonly failureThreshold: 5;
|
|
78
|
-
readonly failureWindowMs: 30000;
|
|
79
|
-
readonly resetTimeoutMs: 60000;
|
|
80
|
-
};
|
|
81
|
-
/**
|
|
82
|
-
* Lenient: Open after 10 failures in 60 seconds, wait 120 seconds before retry
|
|
83
|
-
*/
|
|
84
|
-
readonly LENIENT: {
|
|
85
|
-
readonly failureThreshold: 10;
|
|
86
|
-
readonly failureWindowMs: 60000;
|
|
87
|
-
readonly resetTimeoutMs: 120000;
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Disabled: Circuit breaker always allows attempts
|
|
91
|
-
*/
|
|
92
|
-
readonly DISABLED: {
|
|
93
|
-
readonly failureThreshold: number;
|
|
94
|
-
readonly failureWindowMs: number;
|
|
95
|
-
readonly resetTimeoutMs: 0;
|
|
96
|
-
};
|
|
97
|
-
};
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Circuit breaker to prevent cascading failures
|
|
4
|
-
* Fails fast when backend is unhealthy
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.CIRCUIT_BREAKER_PRESETS = exports.CircuitBreaker = exports.CircuitBreakerState = void 0;
|
|
8
|
-
var CircuitBreakerState;
|
|
9
|
-
(function (CircuitBreakerState) {
|
|
10
|
-
CircuitBreakerState["CLOSED"] = "CLOSED";
|
|
11
|
-
CircuitBreakerState["OPEN"] = "OPEN";
|
|
12
|
-
CircuitBreakerState["HALF_OPEN"] = "HALF_OPEN";
|
|
13
|
-
})(CircuitBreakerState || (exports.CircuitBreakerState = CircuitBreakerState = {}));
|
|
14
|
-
class CircuitBreaker {
|
|
15
|
-
constructor(options) {
|
|
16
|
-
this.state = CircuitBreakerState.CLOSED;
|
|
17
|
-
this.failureCount = 0;
|
|
18
|
-
this.failureTimestamps = [];
|
|
19
|
-
this.lastFailureTime = 0;
|
|
20
|
-
this.nextAttemptTime = 0;
|
|
21
|
-
this.failureThreshold = options.failureThreshold;
|
|
22
|
-
this.failureWindowMs = options.failureWindowMs;
|
|
23
|
-
this.resetTimeoutMs = options.resetTimeoutMs;
|
|
24
|
-
this.onStateChange = options.onStateChange;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Check if a request should be allowed
|
|
28
|
-
*/
|
|
29
|
-
canAttempt() {
|
|
30
|
-
if (this.state === CircuitBreakerState.CLOSED) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
if (this.state === CircuitBreakerState.OPEN) {
|
|
34
|
-
const now = Date.now();
|
|
35
|
-
if (now >= this.nextAttemptTime) {
|
|
36
|
-
// Try to recover
|
|
37
|
-
this.setState(CircuitBreakerState.HALF_OPEN, "Attempting recovery");
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
// HALF_OPEN - allow attempt
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Record a successful request
|
|
47
|
-
*/
|
|
48
|
-
recordSuccess() {
|
|
49
|
-
if (this.state === CircuitBreakerState.HALF_OPEN) {
|
|
50
|
-
this.setState(CircuitBreakerState.CLOSED, "Recovered successfully");
|
|
51
|
-
}
|
|
52
|
-
// Clear failure history on success
|
|
53
|
-
if (this.state === CircuitBreakerState.CLOSED) {
|
|
54
|
-
this.failureCount = 0;
|
|
55
|
-
this.failureTimestamps = [];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Record a failed request
|
|
60
|
-
*/
|
|
61
|
-
recordFailure() {
|
|
62
|
-
const now = Date.now();
|
|
63
|
-
this.lastFailureTime = now;
|
|
64
|
-
// Remove old failures outside the window
|
|
65
|
-
this.failureTimestamps = this.failureTimestamps.filter((timestamp) => now - timestamp < this.failureWindowMs);
|
|
66
|
-
// Add new failure
|
|
67
|
-
this.failureTimestamps.push(now);
|
|
68
|
-
this.failureCount = this.failureTimestamps.length;
|
|
69
|
-
if (this.state === CircuitBreakerState.HALF_OPEN) {
|
|
70
|
-
// Failed during recovery attempt
|
|
71
|
-
this.setState(CircuitBreakerState.OPEN, "Recovery attempt failed");
|
|
72
|
-
this.nextAttemptTime = now + this.resetTimeoutMs;
|
|
73
|
-
}
|
|
74
|
-
else if (this.state === CircuitBreakerState.CLOSED) {
|
|
75
|
-
// Check if threshold exceeded
|
|
76
|
-
if (this.failureCount >= this.failureThreshold) {
|
|
77
|
-
this.setState(CircuitBreakerState.OPEN, `${this.failureCount} failures in ${this.failureWindowMs}ms`);
|
|
78
|
-
this.nextAttemptTime = now + this.resetTimeoutMs;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Get current state
|
|
84
|
-
*/
|
|
85
|
-
getState() {
|
|
86
|
-
return this.state;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Get number of recent failures
|
|
90
|
-
*/
|
|
91
|
-
getFailureCount() {
|
|
92
|
-
// Clean up old failures
|
|
93
|
-
const now = Date.now();
|
|
94
|
-
this.failureTimestamps = this.failureTimestamps.filter((timestamp) => now - timestamp < this.failureWindowMs);
|
|
95
|
-
return this.failureTimestamps.length;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Get milliseconds until circuit attempts to recover
|
|
99
|
-
*/
|
|
100
|
-
getRecoveryTime() {
|
|
101
|
-
if (this.state !== CircuitBreakerState.OPEN) {
|
|
102
|
-
return 0;
|
|
103
|
-
}
|
|
104
|
-
return Math.max(0, this.nextAttemptTime - Date.now());
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Manually reset the circuit breaker
|
|
108
|
-
*/
|
|
109
|
-
reset() {
|
|
110
|
-
this.setState(CircuitBreakerState.CLOSED, "Manual reset");
|
|
111
|
-
this.failureCount = 0;
|
|
112
|
-
this.failureTimestamps = [];
|
|
113
|
-
this.lastFailureTime = 0;
|
|
114
|
-
this.nextAttemptTime = 0;
|
|
115
|
-
}
|
|
116
|
-
setState(newState, reason) {
|
|
117
|
-
if (this.state !== newState) {
|
|
118
|
-
this.state = newState;
|
|
119
|
-
if (this.onStateChange) {
|
|
120
|
-
this.onStateChange(newState, reason);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
exports.CircuitBreaker = CircuitBreaker;
|
|
126
|
-
/**
|
|
127
|
-
* Pre-configured circuit breaker settings for common scenarios
|
|
128
|
-
*/
|
|
129
|
-
exports.CIRCUIT_BREAKER_PRESETS = {
|
|
130
|
-
/**
|
|
131
|
-
* Strict: Open after 2 failures in 10 seconds, wait 30 seconds before retry
|
|
132
|
-
*/
|
|
133
|
-
STRICT: {
|
|
134
|
-
failureThreshold: 2,
|
|
135
|
-
failureWindowMs: 10000,
|
|
136
|
-
resetTimeoutMs: 30000,
|
|
137
|
-
},
|
|
138
|
-
/**
|
|
139
|
-
* Standard: Open after 5 failures in 30 seconds, wait 60 seconds before retry
|
|
140
|
-
*/
|
|
141
|
-
STANDARD: {
|
|
142
|
-
failureThreshold: 5,
|
|
143
|
-
failureWindowMs: 30000,
|
|
144
|
-
resetTimeoutMs: 60000,
|
|
145
|
-
},
|
|
146
|
-
/**
|
|
147
|
-
* Lenient: Open after 10 failures in 60 seconds, wait 120 seconds before retry
|
|
148
|
-
*/
|
|
149
|
-
LENIENT: {
|
|
150
|
-
failureThreshold: 10,
|
|
151
|
-
failureWindowMs: 60000,
|
|
152
|
-
resetTimeoutMs: 120000,
|
|
153
|
-
},
|
|
154
|
-
/**
|
|
155
|
-
* Disabled: Circuit breaker always allows attempts
|
|
156
|
-
*/
|
|
157
|
-
DISABLED: {
|
|
158
|
-
failureThreshold: Infinity,
|
|
159
|
-
failureWindowMs: Infinity,
|
|
160
|
-
resetTimeoutMs: 0,
|
|
161
|
-
},
|
|
162
|
-
};
|
package/dist/src/constants.d.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Centralized constants for the CMS SDK
|
|
3
|
-
* This single source of truth makes it easy to adjust configuration without updating multiple files
|
|
4
|
-
*/
|
|
5
|
-
export declare const SDK_VERSION = "1.0.14";
|
|
6
|
-
export declare const API_CONFIG: {
|
|
7
|
-
/** Default base URL for the CMS API */
|
|
8
|
-
readonly BASE_URL: "https://www.cutmeshort.com";
|
|
9
|
-
/** Default timeout in milliseconds for HTTP requests */
|
|
10
|
-
readonly TIMEOUT_MS: 10000;
|
|
11
|
-
};
|
|
12
|
-
export declare const RETRY_CONFIG: {
|
|
13
|
-
/** Default maximum number of retry attempts for transient failures */
|
|
14
|
-
readonly MAX_RETRIES: 2;
|
|
15
|
-
/** Default base delay (in ms) between retries for transient failures */
|
|
16
|
-
readonly DELAY_MS: 500;
|
|
17
|
-
/** Default maximum delay cap (in ms) for retry backoff */
|
|
18
|
-
readonly MAX_DELAY_MS: 10000;
|
|
19
|
-
/** HTTP status codes that should be retried by default */
|
|
20
|
-
readonly ON_STATUSES: readonly [429, 500, 502, 503, 504];
|
|
21
|
-
/** Whether to retry on network errors (no response / timeout) by default */
|
|
22
|
-
readonly ON_NETWORK_ERROR: true;
|
|
23
|
-
};
|
|
24
|
-
export declare const VALIDATION_CONSTRAINTS: {
|
|
25
|
-
readonly API_KEY: {
|
|
26
|
-
/** Regex pattern for valid API keys: must be 20+ alphanumeric chars */
|
|
27
|
-
readonly PATTERN: RegExp;
|
|
28
|
-
};
|
|
29
|
-
readonly TIMEOUT: {
|
|
30
|
-
readonly MIN_MS: 1000;
|
|
31
|
-
readonly MAX_MS: 60000;
|
|
32
|
-
};
|
|
33
|
-
readonly MAX_RETRIES: {
|
|
34
|
-
readonly MIN: 0;
|
|
35
|
-
readonly MAX: 10;
|
|
36
|
-
};
|
|
37
|
-
readonly RETRY_DELAY: {
|
|
38
|
-
readonly MIN_MS: 100;
|
|
39
|
-
readonly MAX_MS: 30000;
|
|
40
|
-
};
|
|
41
|
-
readonly RETRY_MAX_DELAY: {
|
|
42
|
-
readonly MIN_MS: 1000;
|
|
43
|
-
readonly MAX_MS: 120000;
|
|
44
|
-
};
|
|
45
|
-
readonly STRING_FIELDS: {
|
|
46
|
-
readonly CLICK_ID: {
|
|
47
|
-
readonly MIN: 1;
|
|
48
|
-
readonly MAX: 255;
|
|
49
|
-
};
|
|
50
|
-
readonly CUSTOMER_ID: {
|
|
51
|
-
readonly MIN: 1;
|
|
52
|
-
readonly MAX: 255;
|
|
53
|
-
};
|
|
54
|
-
readonly CUSTOMER_EXTERNAL_ID: {
|
|
55
|
-
readonly MIN: 1;
|
|
56
|
-
readonly MAX: 255;
|
|
57
|
-
};
|
|
58
|
-
readonly CUSTOMER_NAME: {
|
|
59
|
-
readonly MAX: 255;
|
|
60
|
-
};
|
|
61
|
-
readonly CUSTOMER_EMAIL: {
|
|
62
|
-
readonly MAX: 255;
|
|
63
|
-
};
|
|
64
|
-
readonly EVENT_NAME: {
|
|
65
|
-
readonly MIN: 1;
|
|
66
|
-
readonly MAX: 255;
|
|
67
|
-
};
|
|
68
|
-
readonly INVOICE_ID: {
|
|
69
|
-
readonly MIN: 1;
|
|
70
|
-
readonly MAX: 255;
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
readonly CURRENCY: {
|
|
74
|
-
readonly LENGTH: 3;
|
|
75
|
-
readonly PATTERN: RegExp;
|
|
76
|
-
};
|
|
77
|
-
readonly AMOUNT: {
|
|
78
|
-
readonly MIN: 0;
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
export declare const ERROR_MESSAGES: {
|
|
82
|
-
readonly API_KEY_REQUIRED: "apiKey is required";
|
|
83
|
-
readonly API_KEY_INVALID_FORMAT: "apiKey must be a valid API key format";
|
|
84
|
-
readonly BASE_URL_INVALID: "baseUrl must be a valid absolute URL";
|
|
85
|
-
readonly TIMEOUT_TOO_LOW: "timeout must be at least 1000ms";
|
|
86
|
-
readonly TIMEOUT_TOO_HIGH: "timeout must not exceed 60000ms";
|
|
87
|
-
readonly MAX_RETRIES_NEGATIVE: "maxRetries must be non-negative";
|
|
88
|
-
readonly MAX_RETRIES_TOO_HIGH: "maxRetries must not exceed 10";
|
|
89
|
-
readonly RETRY_DELAY_TOO_LOW: "retryDelayMs must be at least 100ms";
|
|
90
|
-
readonly RETRY_DELAY_TOO_HIGH: "retryDelayMs must not exceed 30000ms";
|
|
91
|
-
readonly RETRY_MAX_DELAY_TOO_LOW: "retryMaxDelayMs must be at least 1000ms";
|
|
92
|
-
readonly RETRY_MAX_DELAY_TOO_HIGH: "retryMaxDelayMs must not exceed 120000ms";
|
|
93
|
-
readonly EVENT_NAME_REQUIRED: "eventName is required";
|
|
94
|
-
readonly EVENT_NAME_TOO_LONG: "eventName must not exceed 255 characters";
|
|
95
|
-
readonly CUSTOMER_ID_REQUIRED: "customerId is required";
|
|
96
|
-
readonly CUSTOMER_ID_TOO_LONG: "customerId must not exceed 255 characters";
|
|
97
|
-
readonly CUSTOMER_EXTERNAL_ID_REQUIRED: "customerExternalId is required";
|
|
98
|
-
readonly CUSTOMER_EXTERNAL_ID_TOO_LONG: "customerExternalId must not exceed 255 characters";
|
|
99
|
-
readonly CUSTOMER_EMAIL_INVALID: "customerEmail must be a valid email";
|
|
100
|
-
readonly CUSTOMER_EMAIL_TOO_LONG: "customerEmail must not exceed 255 characters";
|
|
101
|
-
readonly CUSTOMER_AVATAR_INVALID: "customerAvatar must be a valid URL";
|
|
102
|
-
readonly INVOICE_ID_REQUIRED: "invoiceId is required";
|
|
103
|
-
readonly INVOICE_ID_TOO_LONG: "invoiceId must not exceed 255 characters";
|
|
104
|
-
readonly AMOUNT_NEGATIVE: "amount must be non-negative";
|
|
105
|
-
readonly CURRENCY_INVALID_LENGTH: "currency must be 3-letter code (e.g., USD)";
|
|
106
|
-
readonly CURRENCY_INVALID_FORMAT: "currency must be uppercase ISO 4217 code";
|
|
107
|
-
readonly CURRENCY_OPTIONAL_IN_SALE: "currency is optional in sale tracking";
|
|
108
|
-
};
|
|
109
|
-
export declare const HTTP_HEADERS: {
|
|
110
|
-
/** Content type for all API requests */
|
|
111
|
-
readonly CONTENT_TYPE: "application/json";
|
|
112
|
-
/** SDK version header key */
|
|
113
|
-
readonly SDK_VERSION_HEADER: "X-CMS-SDK-Version";
|
|
114
|
-
/** SDK runtime detection header key */
|
|
115
|
-
readonly SDK_RUNTIME_HEADER: "X-CMS-SDK-Runtime";
|
|
116
|
-
/** SDK runtime value for Node.js */
|
|
117
|
-
readonly RUNTIME_NODEJS: "nodejs";
|
|
118
|
-
/** SDK runtime value for browser */
|
|
119
|
-
readonly RUNTIME_BROWSER: "browser";
|
|
120
|
-
};
|
|
121
|
-
export declare const SENSITIVE_FIELDS: {
|
|
122
|
-
/** List of field names that should be redacted in logs */
|
|
123
|
-
readonly PATTERNS: readonly ["apiKey", "accessToken", "token", "password", "secret", "authorization", "x-api-key"];
|
|
124
|
-
/** Redaction placeholder */
|
|
125
|
-
readonly REDACTION_PLACEHOLDER: "[REDACTED]";
|
|
126
|
-
/** API key redaction placeholder */
|
|
127
|
-
readonly API_KEY_REDACTION: "[REDACTED_API_KEY]";
|
|
128
|
-
};
|
package/dist/src/constants.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Centralized constants for the CMS SDK
|
|
4
|
-
* This single source of truth makes it easy to adjust configuration without updating multiple files
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.SENSITIVE_FIELDS = exports.HTTP_HEADERS = exports.ERROR_MESSAGES = exports.VALIDATION_CONSTRAINTS = exports.RETRY_CONFIG = exports.API_CONFIG = exports.SDK_VERSION = void 0;
|
|
8
|
-
// ============================================================================
|
|
9
|
-
// SDK VERSION
|
|
10
|
-
// ============================================================================
|
|
11
|
-
exports.SDK_VERSION = "1.0.14";
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// API CONFIGURATION
|
|
14
|
-
// ============================================================================
|
|
15
|
-
exports.API_CONFIG = {
|
|
16
|
-
/** Default base URL for the CMS API */
|
|
17
|
-
BASE_URL: "https://www.cutmeshort.com",
|
|
18
|
-
/** Default timeout in milliseconds for HTTP requests */
|
|
19
|
-
TIMEOUT_MS: 10000,
|
|
20
|
-
};
|
|
21
|
-
// ============================================================================
|
|
22
|
-
// RETRY CONFIGURATION
|
|
23
|
-
// ============================================================================
|
|
24
|
-
exports.RETRY_CONFIG = {
|
|
25
|
-
/** Default maximum number of retry attempts for transient failures */
|
|
26
|
-
MAX_RETRIES: 2,
|
|
27
|
-
/** Default base delay (in ms) between retries for transient failures */
|
|
28
|
-
DELAY_MS: 500,
|
|
29
|
-
/** Default maximum delay cap (in ms) for retry backoff */
|
|
30
|
-
MAX_DELAY_MS: 10000,
|
|
31
|
-
/** HTTP status codes that should be retried by default */
|
|
32
|
-
ON_STATUSES: [429, 500, 502, 503, 504],
|
|
33
|
-
/** Whether to retry on network errors (no response / timeout) by default */
|
|
34
|
-
ON_NETWORK_ERROR: true,
|
|
35
|
-
};
|
|
36
|
-
// ============================================================================
|
|
37
|
-
// VALIDATION CONSTRAINTS
|
|
38
|
-
// ============================================================================
|
|
39
|
-
exports.VALIDATION_CONSTRAINTS = {
|
|
40
|
-
// API Key validation
|
|
41
|
-
API_KEY: {
|
|
42
|
-
/** Regex pattern for valid API keys: must be 20+ alphanumeric chars */
|
|
43
|
-
PATTERN: /^[a-zA-Z0-9_]{20,}$/,
|
|
44
|
-
},
|
|
45
|
-
// Timeout constraints
|
|
46
|
-
TIMEOUT: {
|
|
47
|
-
MIN_MS: 1000,
|
|
48
|
-
MAX_MS: 60000,
|
|
49
|
-
},
|
|
50
|
-
// Max retries constraints
|
|
51
|
-
MAX_RETRIES: {
|
|
52
|
-
MIN: 0,
|
|
53
|
-
MAX: 10,
|
|
54
|
-
},
|
|
55
|
-
// Retry delay constraints
|
|
56
|
-
RETRY_DELAY: {
|
|
57
|
-
MIN_MS: 100,
|
|
58
|
-
MAX_MS: 30000,
|
|
59
|
-
},
|
|
60
|
-
// Retry max delay constraints
|
|
61
|
-
RETRY_MAX_DELAY: {
|
|
62
|
-
MIN_MS: 1000,
|
|
63
|
-
MAX_MS: 120000,
|
|
64
|
-
},
|
|
65
|
-
// String field constraints
|
|
66
|
-
STRING_FIELDS: {
|
|
67
|
-
CLICK_ID: {
|
|
68
|
-
MIN: 1,
|
|
69
|
-
MAX: 255,
|
|
70
|
-
},
|
|
71
|
-
CUSTOMER_ID: {
|
|
72
|
-
MIN: 1,
|
|
73
|
-
MAX: 255,
|
|
74
|
-
},
|
|
75
|
-
CUSTOMER_EXTERNAL_ID: {
|
|
76
|
-
MIN: 1,
|
|
77
|
-
MAX: 255,
|
|
78
|
-
},
|
|
79
|
-
CUSTOMER_NAME: {
|
|
80
|
-
MAX: 255,
|
|
81
|
-
},
|
|
82
|
-
CUSTOMER_EMAIL: {
|
|
83
|
-
MAX: 255,
|
|
84
|
-
},
|
|
85
|
-
EVENT_NAME: {
|
|
86
|
-
MIN: 1,
|
|
87
|
-
MAX: 255,
|
|
88
|
-
},
|
|
89
|
-
INVOICE_ID: {
|
|
90
|
-
MIN: 1,
|
|
91
|
-
MAX: 255,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
// Currency code constraints (ISO 4217)
|
|
95
|
-
CURRENCY: {
|
|
96
|
-
LENGTH: 3,
|
|
97
|
-
PATTERN: /^[A-Z]{3}$/,
|
|
98
|
-
},
|
|
99
|
-
// Amount constraints
|
|
100
|
-
AMOUNT: {
|
|
101
|
-
MIN: 0,
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
// ============================================================================
|
|
105
|
-
// ERROR HANDLING
|
|
106
|
-
// ============================================================================
|
|
107
|
-
exports.ERROR_MESSAGES = {
|
|
108
|
-
// API Key errors
|
|
109
|
-
API_KEY_REQUIRED: "apiKey is required",
|
|
110
|
-
API_KEY_INVALID_FORMAT: "apiKey must be a valid API key format",
|
|
111
|
-
// Base URL errors
|
|
112
|
-
BASE_URL_INVALID: "baseUrl must be a valid absolute URL",
|
|
113
|
-
// Timeout errors
|
|
114
|
-
TIMEOUT_TOO_LOW: `timeout must be at least ${exports.VALIDATION_CONSTRAINTS.TIMEOUT.MIN_MS}ms`,
|
|
115
|
-
TIMEOUT_TOO_HIGH: `timeout must not exceed ${exports.VALIDATION_CONSTRAINTS.TIMEOUT.MAX_MS}ms`,
|
|
116
|
-
// Max retries errors
|
|
117
|
-
MAX_RETRIES_NEGATIVE: "maxRetries must be non-negative",
|
|
118
|
-
MAX_RETRIES_TOO_HIGH: `maxRetries must not exceed ${exports.VALIDATION_CONSTRAINTS.MAX_RETRIES.MAX}`,
|
|
119
|
-
// Retry delay errors
|
|
120
|
-
RETRY_DELAY_TOO_LOW: `retryDelayMs must be at least ${exports.VALIDATION_CONSTRAINTS.RETRY_DELAY.MIN_MS}ms`,
|
|
121
|
-
RETRY_DELAY_TOO_HIGH: `retryDelayMs must not exceed ${exports.VALIDATION_CONSTRAINTS.RETRY_DELAY.MAX_MS}ms`,
|
|
122
|
-
// Retry max delay errors
|
|
123
|
-
RETRY_MAX_DELAY_TOO_LOW: `retryMaxDelayMs must be at least ${exports.VALIDATION_CONSTRAINTS.RETRY_MAX_DELAY.MIN_MS}ms`,
|
|
124
|
-
RETRY_MAX_DELAY_TOO_HIGH: `retryMaxDelayMs must not exceed ${exports.VALIDATION_CONSTRAINTS.RETRY_MAX_DELAY.MAX_MS}ms`,
|
|
125
|
-
// Event name errors
|
|
126
|
-
EVENT_NAME_REQUIRED: "eventName is required",
|
|
127
|
-
EVENT_NAME_TOO_LONG: `eventName must not exceed ${exports.VALIDATION_CONSTRAINTS.STRING_FIELDS.EVENT_NAME.MAX} characters`,
|
|
128
|
-
// Customer ID errors
|
|
129
|
-
CUSTOMER_ID_REQUIRED: "customerId is required",
|
|
130
|
-
CUSTOMER_ID_TOO_LONG: `customerId must not exceed ${exports.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_ID.MAX} characters`,
|
|
131
|
-
// Customer external ID errors
|
|
132
|
-
CUSTOMER_EXTERNAL_ID_REQUIRED: "customerExternalId is required",
|
|
133
|
-
CUSTOMER_EXTERNAL_ID_TOO_LONG: `customerExternalId must not exceed ${exports.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EXTERNAL_ID.MAX} characters`,
|
|
134
|
-
// Email errors
|
|
135
|
-
CUSTOMER_EMAIL_INVALID: "customerEmail must be a valid email",
|
|
136
|
-
CUSTOMER_EMAIL_TOO_LONG: `customerEmail must not exceed ${exports.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EMAIL.MAX} characters`,
|
|
137
|
-
// Avatar errors
|
|
138
|
-
CUSTOMER_AVATAR_INVALID: "customerAvatar must be a valid URL",
|
|
139
|
-
// Invoice ID errors
|
|
140
|
-
INVOICE_ID_REQUIRED: "invoiceId is required",
|
|
141
|
-
INVOICE_ID_TOO_LONG: `invoiceId must not exceed ${exports.VALIDATION_CONSTRAINTS.STRING_FIELDS.INVOICE_ID.MAX} characters`,
|
|
142
|
-
// Amount errors
|
|
143
|
-
AMOUNT_NEGATIVE: "amount must be non-negative",
|
|
144
|
-
// Currency errors
|
|
145
|
-
CURRENCY_INVALID_LENGTH: `currency must be ${exports.VALIDATION_CONSTRAINTS.CURRENCY.LENGTH}-letter code (e.g., USD)`,
|
|
146
|
-
CURRENCY_INVALID_FORMAT: "currency must be uppercase ISO 4217 code",
|
|
147
|
-
CURRENCY_OPTIONAL_IN_SALE: "currency is optional in sale tracking",
|
|
148
|
-
};
|
|
149
|
-
// ============================================================================
|
|
150
|
-
// HTTP HEADERS
|
|
151
|
-
// ============================================================================
|
|
152
|
-
exports.HTTP_HEADERS = {
|
|
153
|
-
/** Content type for all API requests */
|
|
154
|
-
CONTENT_TYPE: "application/json",
|
|
155
|
-
/** SDK version header key */
|
|
156
|
-
SDK_VERSION_HEADER: "X-CMS-SDK-Version",
|
|
157
|
-
/** SDK runtime detection header key */
|
|
158
|
-
SDK_RUNTIME_HEADER: "X-CMS-SDK-Runtime",
|
|
159
|
-
/** SDK runtime value for Node.js */
|
|
160
|
-
RUNTIME_NODEJS: "nodejs",
|
|
161
|
-
/** SDK runtime value for browser */
|
|
162
|
-
RUNTIME_BROWSER: "browser",
|
|
163
|
-
};
|
|
164
|
-
// ============================================================================
|
|
165
|
-
// SENSITIVE FIELD PATTERNS
|
|
166
|
-
// ============================================================================
|
|
167
|
-
exports.SENSITIVE_FIELDS = {
|
|
168
|
-
/** List of field names that should be redacted in logs */
|
|
169
|
-
PATTERNS: [
|
|
170
|
-
"apiKey",
|
|
171
|
-
"accessToken",
|
|
172
|
-
"token",
|
|
173
|
-
"password",
|
|
174
|
-
"secret",
|
|
175
|
-
"authorization",
|
|
176
|
-
"x-api-key",
|
|
177
|
-
],
|
|
178
|
-
/** Redaction placeholder */
|
|
179
|
-
REDACTION_PLACEHOLDER: "[REDACTED]",
|
|
180
|
-
/** API key redaction placeholder */
|
|
181
|
-
API_KEY_REDACTION: "[REDACTED_API_KEY]",
|
|
182
|
-
};
|