@vigneshreddy/cms-sdk 1.0.14 → 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/README.md +122 -37
- package/dist/src/client.d.ts +3 -3
- package/dist/src/client.js +37 -12
- package/dist/src/constants/constants.d.ts +128 -0
- package/dist/src/constants/constants.js +182 -0
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.js +20 -4
- package/dist/src/{generated → funcs}/base.js +2 -1
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +28 -1
- package/dist/src/validations/validation.d.ts +119 -0
- package/dist/src/validations/validation.js +196 -0
- package/package.json +7 -2
- /package/dist/src/{generated → funcs}/api.d.ts +0 -0
- /package/dist/src/{generated → funcs}/api.js +0 -0
- /package/dist/src/{generated → funcs}/base.d.ts +0 -0
- /package/dist/src/{generated → funcs}/common.d.ts +0 -0
- /package/dist/src/{generated → funcs}/common.js +0 -0
- /package/dist/src/{generated → funcs}/configuration.d.ts +0 -0
- /package/dist/src/{generated → funcs}/configuration.js +0 -0
- /package/dist/src/{generated → funcs}/index.d.ts +0 -0
- /package/dist/src/{generated → funcs}/index.js +0 -0
package/README.md
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
# @vigneshreddy/cms-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@vigneshreddy/cms-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
Official TypeScript/JavaScript SDK for the CutMeShort CMS API. Track leads and sales with reliable retry logic, comprehensive validation, and security best practices.
|
|
8
|
+
|
|
9
|
+
**Key Features:**
|
|
10
|
+
- 🚀 Full TypeScript support with strict types
|
|
11
|
+
- ✅ Input validation with Zod
|
|
12
|
+
- 🔄 Automatic retry with exponential backoff
|
|
13
|
+
- 🛡️ Security hardened (API key validation, sensitive data redaction)
|
|
14
|
+
- ⚡ Sub-second tracking events
|
|
15
|
+
- 📊 Comprehensive error handling with specific error types
|
|
16
|
+
|
|
17
|
+
---
|
|
8
18
|
|
|
9
19
|
## Install
|
|
10
20
|
|
|
@@ -41,7 +51,7 @@ const cms = new CMS({
|
|
|
41
51
|
const response = await cms.trackLead({
|
|
42
52
|
clickId: "id_123",
|
|
43
53
|
eventName: "signup_started",
|
|
44
|
-
|
|
54
|
+
customerExternalId: "user_42",
|
|
45
55
|
});
|
|
46
56
|
|
|
47
57
|
console.log(response);
|
|
@@ -59,16 +69,15 @@ const cms = new CMS({ apiKey: "sk_live_xxx" });
|
|
|
59
69
|
await cms.trackLead({
|
|
60
70
|
clickId: "id_123",
|
|
61
71
|
eventName: "signup_started",
|
|
62
|
-
|
|
72
|
+
customerExternalId: "user_42",
|
|
63
73
|
});
|
|
64
74
|
```
|
|
65
75
|
|
|
66
76
|
Lead payload fields:
|
|
67
77
|
- `clickId: string` (optional in **deferred** follow-up calls)
|
|
68
78
|
- `eventName: string`
|
|
69
|
-
- `
|
|
79
|
+
- `customerExternalId: string`
|
|
70
80
|
- `timestamp?: string` (ISO 8601, e.g. `new Date().toISOString()`)
|
|
71
|
-
- `customerExternalId?: string`
|
|
72
81
|
- `customerName?: string`
|
|
73
82
|
- `customerEmail?: string`
|
|
74
83
|
- `customerAvatar?: string`
|
|
@@ -82,18 +91,18 @@ import { CMS } from "@vigneshreddy/cms-sdk";
|
|
|
82
91
|
|
|
83
92
|
const cms = new CMS({ apiKey: "sk_live_xxx" });
|
|
84
93
|
|
|
85
|
-
// Step 1: store the clickId <->
|
|
94
|
+
// Step 1: store the clickId <-> customerExternalId association
|
|
86
95
|
await cms.trackLead({
|
|
87
96
|
clickId: "id_123",
|
|
88
97
|
eventName: "signup_started",
|
|
89
|
-
|
|
98
|
+
customerExternalId: "user_42",
|
|
90
99
|
mode: "deferred",
|
|
91
100
|
});
|
|
92
101
|
|
|
93
|
-
// Step 2: later, track using just
|
|
102
|
+
// Step 2: later, track using just customerExternalId (no clickId)
|
|
94
103
|
await cms.trackLead({
|
|
95
104
|
eventName: "email_verified",
|
|
96
|
-
|
|
105
|
+
customerExternalId: "user_42",
|
|
97
106
|
mode: "deferred",
|
|
98
107
|
});
|
|
99
108
|
```
|
|
@@ -103,10 +112,11 @@ await cms.trackLead({
|
|
|
103
112
|
```ts
|
|
104
113
|
import { CMS } from "@vigneshreddy/cms-sdk";
|
|
105
114
|
|
|
106
|
-
const cms = new CMS({ apiKey: "
|
|
115
|
+
const cms = new CMS({ apiKey: "xxx" });
|
|
107
116
|
|
|
108
117
|
await cms.trackSale({
|
|
109
118
|
clickId: "id_123",
|
|
119
|
+
customerExternalId: "user_123",
|
|
110
120
|
eventName: "purchase_completed",
|
|
111
121
|
invoiceId: "inv_987",
|
|
112
122
|
amount: 4999,
|
|
@@ -118,7 +128,7 @@ Sale payload fields:
|
|
|
118
128
|
- `clickId: string`
|
|
119
129
|
- `eventName: string`
|
|
120
130
|
- `timestamp?: string` (ISO 8601, e.g. `new Date().toISOString()`)
|
|
121
|
-
- `customerExternalId
|
|
131
|
+
- `customerExternalId: string`
|
|
122
132
|
- `customerName?: string`
|
|
123
133
|
- `customerEmail?: string`
|
|
124
134
|
- `customerAvatar?: string`
|
|
@@ -144,7 +154,7 @@ type CMSConfig = {
|
|
|
144
154
|
```
|
|
145
155
|
|
|
146
156
|
Defaults:
|
|
147
|
-
- `baseUrl`: `https://www.cutmeshort.com
|
|
157
|
+
- `baseUrl`: `https://www.cutmeshort.com`
|
|
148
158
|
- `timeout`: `10000`
|
|
149
159
|
- `maxRetries`: `2`
|
|
150
160
|
- `retryDelayMs`: `500`
|
|
@@ -165,7 +175,7 @@ await cms.trackLead(
|
|
|
165
175
|
{
|
|
166
176
|
clickId: "id_123",
|
|
167
177
|
eventName: "signup_started",
|
|
168
|
-
|
|
178
|
+
customerExternalId: "user_42",
|
|
169
179
|
},
|
|
170
180
|
{
|
|
171
181
|
timeout: 5000,
|
|
@@ -177,42 +187,117 @@ await cms.trackLead(
|
|
|
177
187
|
|
|
178
188
|
## Error Handling
|
|
179
189
|
|
|
180
|
-
|
|
190
|
+
The SDK provides specific error classes for different failure scenarios. Catch and handle them appropriately:
|
|
181
191
|
|
|
182
192
|
```ts
|
|
183
|
-
import {
|
|
193
|
+
import {
|
|
194
|
+
CMS,
|
|
195
|
+
CMSAPIError,
|
|
196
|
+
UnauthorizedError,
|
|
197
|
+
RateLimitError,
|
|
198
|
+
ValidationError
|
|
199
|
+
} from "@vigneshreddy/cms-sdk";
|
|
184
200
|
|
|
185
|
-
const cms = new CMS({ apiKey:
|
|
201
|
+
const cms = new CMS({ apiKey: process.env.CMS_API_KEY });
|
|
186
202
|
|
|
187
203
|
try {
|
|
188
|
-
await cms.
|
|
204
|
+
await cms.trackLead({
|
|
189
205
|
clickId: "id_123",
|
|
190
|
-
eventName: "
|
|
191
|
-
|
|
192
|
-
amount: 4999,
|
|
193
|
-
currency: "USD",
|
|
206
|
+
eventName: "signup_started",
|
|
207
|
+
customerExternalId: "user_42",
|
|
194
208
|
});
|
|
195
209
|
} catch (error) {
|
|
196
|
-
if (error instanceof
|
|
197
|
-
console.error("
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
});
|
|
210
|
+
if (error instanceof UnauthorizedError) {
|
|
211
|
+
console.error("Invalid API key - check your credentials");
|
|
212
|
+
} else if (error instanceof RateLimitError) {
|
|
213
|
+
console.error("Rate limited - wait before retrying");
|
|
214
|
+
} else if (error instanceof CMSAPIError) {
|
|
215
|
+
console.error(`CMS API error [${error.statusCode}]:`, error.message);
|
|
216
|
+
console.debug("Type:", error.type);
|
|
202
217
|
} else {
|
|
203
|
-
console.error("Unexpected error", error);
|
|
218
|
+
console.error("Unexpected error:", error);
|
|
204
219
|
}
|
|
205
220
|
}
|
|
206
221
|
```
|
|
207
222
|
|
|
223
|
+
### Available Error Types
|
|
224
|
+
|
|
225
|
+
| Error Type | HTTP Code | When It Happens |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| `BadRequestError` | 400 | Invalid payload format |
|
|
228
|
+
| `UnauthorizedError` | 401 | Invalid/missing API key |
|
|
229
|
+
| `ForbiddenError` | 403 | Insufficient permissions |
|
|
230
|
+
| `NotFoundError` | 404 | Resource not found |
|
|
231
|
+
| `ConflictError` | 409 | Resource already exists |
|
|
232
|
+
| `UnprocessableEntityError` | 422 | Validation failed |
|
|
233
|
+
| `RateLimitError` | 429 | Too many requests |
|
|
234
|
+
| `InternalServerError` | 500 | Server error |
|
|
235
|
+
| `BadGatewayError` | 502 | Gateway error (retried) |
|
|
236
|
+
| `ServiceUnavailableError` | 503 | Service down (retried) |
|
|
237
|
+
| `GatewayTimeoutError` | 504 | Timeout (retried) |
|
|
238
|
+
|
|
239
|
+
**Note:** Errors with HTTP codes 429, 500, 502, 503, 504 are automatically retried (configurable).
|
|
240
|
+
|
|
241
|
+
### Retry Behavior
|
|
242
|
+
|
|
243
|
+
The SDK automatically retries transient failures with exponential backoff:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
const cms = new CMS({
|
|
247
|
+
apiKey: process.env.CMS_API_KEY,
|
|
248
|
+
maxRetries: 2, // default: 2
|
|
249
|
+
retryDelayMs: 500, // initial delay: 500ms
|
|
250
|
+
retryMaxDelayMs: 10000, // max delay cap: 10s
|
|
251
|
+
retryOnNetworkError: true,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Override for a specific request
|
|
255
|
+
await cms.trackLead(
|
|
256
|
+
{ clickId: "id_123", eventName: "event", customerExternalId: "user_1" },
|
|
257
|
+
{ maxRetries: 5, retryDelayMs: 1000 }
|
|
258
|
+
);
|
|
259
|
+
```
|
|
260
|
+
## TypeScript Usage
|
|
261
|
+
|
|
262
|
+
The SDK is fully typed. Utilize TypeScript for better DX:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import {
|
|
266
|
+
CMS,
|
|
267
|
+
type CMSConfig,
|
|
268
|
+
type LeadPayload,
|
|
269
|
+
type SalePayload,
|
|
270
|
+
type RequestOptions
|
|
271
|
+
} from "@vigneshreddy/cms-sdk";
|
|
272
|
+
|
|
273
|
+
// Config is validated at initialization
|
|
274
|
+
const config: CMSConfig = {
|
|
275
|
+
apiKey: process.env.CMS_API_KEY!,
|
|
276
|
+
timeout: 5000,
|
|
277
|
+
maxRetries: 3,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const cms = new CMS(config);
|
|
281
|
+
|
|
282
|
+
// Payloads have full type hints
|
|
283
|
+
const leadPayload: LeadPayload = {
|
|
284
|
+
clickId: "id_123",
|
|
285
|
+
eventName: "signup_started",
|
|
286
|
+
customerExteranlId: "user_42",
|
|
287
|
+
customerEmail: "user@example.com",
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// RequestOptions for per-call configuration
|
|
291
|
+
const options: RequestOptions = {
|
|
292
|
+
timeout: 3000,
|
|
293
|
+
maxRetries: 1,
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
await cms.trackLead(leadPayload, options);
|
|
297
|
+
```
|
|
298
|
+
|
|
208
299
|
## Public API
|
|
209
300
|
|
|
210
301
|
This package intentionally exposes only:
|
|
211
302
|
- `CMS` (use `cms.trackLead` and `cms.trackSale`)
|
|
212
303
|
- `CMSAPIError` (for `instanceof` checks)
|
|
213
|
-
|
|
214
|
-
Deep imports (example: `@vigneshreddy/cms-sdk/client`) are intentionally blocked.
|
|
215
|
-
|
|
216
|
-
## Security Best Practice
|
|
217
|
-
|
|
218
|
-
Do not expose private API keys in public frontend code. Use this SDK from a trusted backend/server environment when using secret keys.
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventsApi, TrackLeadRequest, TrackSaleRequest } from "./
|
|
1
|
+
import { EventsApi, TrackLeadRequest, TrackSaleRequest } from "./funcs";
|
|
2
2
|
export type LeadPayload = TrackLeadRequest;
|
|
3
3
|
export type SalePayload = TrackSaleRequest;
|
|
4
4
|
export interface CMSConfig {
|
|
@@ -57,6 +57,6 @@ export declare class CMS {
|
|
|
57
57
|
private toGeneratedRequestOptions;
|
|
58
58
|
private withRetry;
|
|
59
59
|
private isRetryableErrorWithOptions;
|
|
60
|
-
trackLead(leadData: LeadPayload, options?: RequestOptions): Promise<import("./
|
|
61
|
-
trackSale(saleData: SalePayload, options?: RequestOptions): Promise<import("./
|
|
60
|
+
trackLead(leadData: LeadPayload, options?: RequestOptions): Promise<import("./funcs").TrackResponse>;
|
|
61
|
+
trackSale(saleData: SalePayload, options?: RequestOptions): Promise<import("./funcs").TrackResponse>;
|
|
62
62
|
}
|
package/dist/src/client.js
CHANGED
|
@@ -2,19 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CMS = void 0;
|
|
4
4
|
// src/client.ts
|
|
5
|
-
const
|
|
5
|
+
const funcs_1 = require("./funcs");
|
|
6
6
|
const errors_1 = require("./errors");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
7
|
+
const validation_1 = require("./validations/validation");
|
|
8
|
+
const constants_1 = require("./constants/constants");
|
|
9
|
+
const DEFAULT_BASE_URL = constants_1.API_CONFIG.BASE_URL;
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = constants_1.API_CONFIG.TIMEOUT_MS;
|
|
11
|
+
const DEFAULT_MAX_RETRIES = constants_1.RETRY_CONFIG.MAX_RETRIES;
|
|
12
|
+
const DEFAULT_RETRY_DELAY_MS = constants_1.RETRY_CONFIG.DELAY_MS;
|
|
13
|
+
const DEFAULT_RETRY_MAX_DELAY_MS = constants_1.RETRY_CONFIG.MAX_DELAY_MS;
|
|
14
|
+
const DEFAULT_RETRY_STATUSES = [...constants_1.RETRY_CONFIG.ON_STATUSES];
|
|
13
15
|
class CMS {
|
|
14
16
|
constructor(config) {
|
|
15
17
|
var _a, _b, _c, _d;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
// Validate configuration with strict schema
|
|
19
|
+
try {
|
|
20
|
+
(0, validation_1.validateCMSConfig)(config);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
+
throw new Error(`CMS SDK: Invalid configuration - ${message}`);
|
|
18
25
|
}
|
|
19
26
|
const basePath = this.normalizeBaseUrl((_a = config.baseUrl) !== null && _a !== void 0 ? _a : DEFAULT_BASE_URL);
|
|
20
27
|
// Retry configuration with sensible defaults
|
|
@@ -24,20 +31,22 @@ class CMS {
|
|
|
24
31
|
this.retryOnStatuses = this.resolveRetryStatuses((_b = config.retryOnStatuses) !== null && _b !== void 0 ? _b : DEFAULT_RETRY_STATUSES);
|
|
25
32
|
this.retryOnNetworkError = (_c = config.retryOnNetworkError) !== null && _c !== void 0 ? _c : true;
|
|
26
33
|
// Create the Configuration object
|
|
27
|
-
const apiConfig = new
|
|
34
|
+
const apiConfig = new funcs_1.Configuration({
|
|
28
35
|
basePath,
|
|
29
36
|
accessToken: config.apiKey,
|
|
30
37
|
baseOptions: {
|
|
31
38
|
// Ensure generated client uses the same timeout & headers
|
|
32
39
|
timeout: (_d = config.timeout) !== null && _d !== void 0 ? _d : DEFAULT_TIMEOUT_MS,
|
|
33
40
|
headers: {
|
|
34
|
-
'Content-Type': 'application/json'
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
'X-CMS-SDK-Version': constants_1.SDK_VERSION,
|
|
43
|
+
'X-CMS-SDK-Runtime': typeof globalThis !== 'undefined' ? constants_1.HTTP_HEADERS.RUNTIME_NODEJS : constants_1.HTTP_HEADERS.RUNTIME_BROWSER,
|
|
35
44
|
},
|
|
36
45
|
},
|
|
37
46
|
});
|
|
38
47
|
// Instantiate the EventsApi using configuration and basePath.
|
|
39
48
|
// The underlying implementation uses the global `fetch` API.
|
|
40
|
-
this.events = new
|
|
49
|
+
this.events = new funcs_1.EventsApi(apiConfig, basePath);
|
|
41
50
|
}
|
|
42
51
|
async sleep(ms) {
|
|
43
52
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -182,12 +191,28 @@ class CMS {
|
|
|
182
191
|
return false;
|
|
183
192
|
}
|
|
184
193
|
async trackLead(leadData, options) {
|
|
194
|
+
// Validate lead data
|
|
195
|
+
try {
|
|
196
|
+
(0, validation_1.validateLeadPayload)(leadData);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
200
|
+
throw new Error(`CMS SDK: Invalid lead data - ${message}`);
|
|
201
|
+
}
|
|
185
202
|
const requestOptions = this.toGeneratedRequestOptions(options);
|
|
186
203
|
return this.withRetry(async () => {
|
|
187
204
|
return this.events.trackLead(leadData, requestOptions);
|
|
188
205
|
}, options);
|
|
189
206
|
}
|
|
190
207
|
async trackSale(saleData, options) {
|
|
208
|
+
// Validate sale data
|
|
209
|
+
try {
|
|
210
|
+
(0, validation_1.validateSalePayload)(saleData);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
214
|
+
throw new Error(`CMS SDK: Invalid sale data - ${message}`);
|
|
215
|
+
}
|
|
191
216
|
const requestOptions = this.toGeneratedRequestOptions(options);
|
|
192
217
|
return this.withRetry(async () => {
|
|
193
218
|
return this.events.trackSale(saleData, requestOptions);
|
|
@@ -0,0 +1,128 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
};
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export { BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, Conf
|
|
|
4
4
|
/**
|
|
5
5
|
* Parses fetch/network errors into a clean CMSAPIError (or specific subclass)
|
|
6
6
|
* Uses specific error types when possible for better type safety
|
|
7
|
+
* Sanitizes sensitive information before storing
|
|
7
8
|
*/
|
|
8
9
|
export declare function handleApiError(error: unknown, request?: unknown, response?: unknown): never;
|
package/dist/src/errors.js
CHANGED
|
@@ -23,6 +23,7 @@ Object.defineProperty(exports, "createSpecificError", { enumerable: true, get: f
|
|
|
23
23
|
/**
|
|
24
24
|
* Parses fetch/network errors into a clean CMSAPIError (or specific subclass)
|
|
25
25
|
* Uses specific error types when possible for better type safety
|
|
26
|
+
* Sanitizes sensitive information before storing
|
|
26
27
|
*/
|
|
27
28
|
function handleApiError(error, request, response) {
|
|
28
29
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -71,14 +72,29 @@ function handleApiError(error, request, response) {
|
|
|
71
72
|
if (!req || typeof req !== "object")
|
|
72
73
|
return undefined;
|
|
73
74
|
const r = req;
|
|
74
|
-
|
|
75
|
+
const sanitized = {
|
|
75
76
|
url: typeof r.url === "string" ? r.url : undefined,
|
|
76
77
|
method: typeof r.method === "string" ? r.method : undefined,
|
|
77
78
|
timeout: typeof r.timeout === "number" ? r.timeout : undefined,
|
|
78
|
-
headers: typeof r.headers === "object" && r.headers !== null
|
|
79
|
-
? r.headers
|
|
80
|
-
: undefined,
|
|
81
79
|
};
|
|
80
|
+
// Only include headers if they don't contain sensitive data
|
|
81
|
+
if (typeof r.headers === "object" && r.headers !== null) {
|
|
82
|
+
const headersObj = r.headers;
|
|
83
|
+
const safeHeaders = {};
|
|
84
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
85
|
+
const lowerKey = key.toLowerCase();
|
|
86
|
+
// Exclude authorization and api-key headers
|
|
87
|
+
if (!lowerKey.includes("authorization") &&
|
|
88
|
+
!lowerKey.includes("api-key") &&
|
|
89
|
+
!lowerKey.includes("token")) {
|
|
90
|
+
safeHeaders[key] = value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (Object.keys(safeHeaders).length > 0) {
|
|
94
|
+
sanitized.headers = safeHeaders;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return sanitized;
|
|
82
98
|
};
|
|
83
99
|
// Error with response from server
|
|
84
100
|
const errorWithResponse = (_a = error === null || error === void 0 ? void 0 : error.response) !== null && _a !== void 0 ? _a : response;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.operationServerMap = exports.RequiredError = exports.BaseAPI = exports.COLLECTION_FORMATS = exports.BASE_PATH = void 0;
|
|
4
|
-
|
|
4
|
+
const constants_1 = require("../constants/constants");
|
|
5
|
+
exports.BASE_PATH = constants_1.API_CONFIG.BASE_URL.replace(/\/+$/, "");
|
|
5
6
|
exports.COLLECTION_FORMATS = {
|
|
6
7
|
csv: ",",
|
|
7
8
|
ssv: " ",
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export { CMS } from "./client";
|
|
2
|
+
export type { CMSConfig, RequestOptions, LeadPayload, SalePayload } from "./client";
|
|
2
3
|
export { CMSAPIError } from "./errors";
|
|
4
|
+
export { BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, BadGatewayError, ServiceUnavailableError, GatewayTimeoutError, createSpecificError, } from "./errors/specific";
|
|
5
|
+
export { validateLeadPayload, validateSalePayload, validateCMSConfig, sanitizeForLogging } from "./validations/validation";
|
|
6
|
+
export type { LeadPayloadInput, SalePayloadInput, CMSConfigInput } from "./validations/validation";
|
|
7
|
+
export { SDK_VERSION, API_CONFIG, RETRY_CONFIG, VALIDATION_CONSTRAINTS, ERROR_MESSAGES, HTTP_HEADERS, SENSITIVE_FIELDS, } from "./constants/constants";
|
package/dist/src/index.js
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CMSAPIError = exports.CMS = void 0;
|
|
3
|
+
exports.SENSITIVE_FIELDS = exports.HTTP_HEADERS = exports.ERROR_MESSAGES = exports.VALIDATION_CONSTRAINTS = exports.RETRY_CONFIG = exports.API_CONFIG = exports.SDK_VERSION = exports.sanitizeForLogging = exports.validateCMSConfig = exports.validateSalePayload = exports.validateLeadPayload = exports.createSpecificError = exports.GatewayTimeoutError = exports.ServiceUnavailableError = exports.BadGatewayError = exports.InternalServerError = exports.RateLimitError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.CMSAPIError = exports.CMS = void 0;
|
|
4
4
|
var client_1 = require("./client");
|
|
5
5
|
Object.defineProperty(exports, "CMS", { enumerable: true, get: function () { return client_1.CMS; } });
|
|
6
6
|
var errors_1 = require("./errors");
|
|
7
7
|
Object.defineProperty(exports, "CMSAPIError", { enumerable: true, get: function () { return errors_1.CMSAPIError; } });
|
|
8
|
+
var specific_1 = require("./errors/specific");
|
|
9
|
+
Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return specific_1.BadRequestError; } });
|
|
10
|
+
Object.defineProperty(exports, "UnauthorizedError", { enumerable: true, get: function () { return specific_1.UnauthorizedError; } });
|
|
11
|
+
Object.defineProperty(exports, "ForbiddenError", { enumerable: true, get: function () { return specific_1.ForbiddenError; } });
|
|
12
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return specific_1.NotFoundError; } });
|
|
13
|
+
Object.defineProperty(exports, "ConflictError", { enumerable: true, get: function () { return specific_1.ConflictError; } });
|
|
14
|
+
Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, get: function () { return specific_1.UnprocessableEntityError; } });
|
|
15
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return specific_1.RateLimitError; } });
|
|
16
|
+
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return specific_1.InternalServerError; } });
|
|
17
|
+
Object.defineProperty(exports, "BadGatewayError", { enumerable: true, get: function () { return specific_1.BadGatewayError; } });
|
|
18
|
+
Object.defineProperty(exports, "ServiceUnavailableError", { enumerable: true, get: function () { return specific_1.ServiceUnavailableError; } });
|
|
19
|
+
Object.defineProperty(exports, "GatewayTimeoutError", { enumerable: true, get: function () { return specific_1.GatewayTimeoutError; } });
|
|
20
|
+
Object.defineProperty(exports, "createSpecificError", { enumerable: true, get: function () { return specific_1.createSpecificError; } });
|
|
21
|
+
var validation_1 = require("./validations/validation");
|
|
22
|
+
Object.defineProperty(exports, "validateLeadPayload", { enumerable: true, get: function () { return validation_1.validateLeadPayload; } });
|
|
23
|
+
Object.defineProperty(exports, "validateSalePayload", { enumerable: true, get: function () { return validation_1.validateSalePayload; } });
|
|
24
|
+
Object.defineProperty(exports, "validateCMSConfig", { enumerable: true, get: function () { return validation_1.validateCMSConfig; } });
|
|
25
|
+
Object.defineProperty(exports, "sanitizeForLogging", { enumerable: true, get: function () { return validation_1.sanitizeForLogging; } });
|
|
26
|
+
// Export constants for advanced configuration
|
|
27
|
+
var constants_1 = require("./constants/constants");
|
|
28
|
+
Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return constants_1.SDK_VERSION; } });
|
|
29
|
+
Object.defineProperty(exports, "API_CONFIG", { enumerable: true, get: function () { return constants_1.API_CONFIG; } });
|
|
30
|
+
Object.defineProperty(exports, "RETRY_CONFIG", { enumerable: true, get: function () { return constants_1.RETRY_CONFIG; } });
|
|
31
|
+
Object.defineProperty(exports, "VALIDATION_CONSTRAINTS", { enumerable: true, get: function () { return constants_1.VALIDATION_CONSTRAINTS; } });
|
|
32
|
+
Object.defineProperty(exports, "ERROR_MESSAGES", { enumerable: true, get: function () { return constants_1.ERROR_MESSAGES; } });
|
|
33
|
+
Object.defineProperty(exports, "HTTP_HEADERS", { enumerable: true, get: function () { return constants_1.HTTP_HEADERS; } });
|
|
34
|
+
Object.defineProperty(exports, "SENSITIVE_FIELDS", { enumerable: true, get: function () { return constants_1.SENSITIVE_FIELDS; } });
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation schemas using Zod
|
|
3
|
+
* Ensures all incoming data is sanitized and valid
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
export declare const CMSConfigSchema: z.ZodObject<{
|
|
7
|
+
apiKey: z.ZodEffects<z.ZodString, string, string>;
|
|
8
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
9
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
maxRetries: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
retryDelayMs: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
retryMaxDelayMs: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
retryOnStatuses: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
|
|
14
|
+
retryOnNetworkError: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
apiKey: string;
|
|
17
|
+
timeout?: number | undefined;
|
|
18
|
+
baseUrl?: string | undefined;
|
|
19
|
+
maxRetries?: number | undefined;
|
|
20
|
+
retryDelayMs?: number | undefined;
|
|
21
|
+
retryMaxDelayMs?: number | undefined;
|
|
22
|
+
retryOnStatuses?: number[] | undefined;
|
|
23
|
+
retryOnNetworkError?: boolean | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
apiKey: string;
|
|
26
|
+
timeout?: number | undefined;
|
|
27
|
+
baseUrl?: string | undefined;
|
|
28
|
+
maxRetries?: number | undefined;
|
|
29
|
+
retryDelayMs?: number | undefined;
|
|
30
|
+
retryMaxDelayMs?: number | undefined;
|
|
31
|
+
retryOnStatuses?: number[] | undefined;
|
|
32
|
+
retryOnNetworkError?: boolean | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export type CMSConfigInput = z.infer<typeof CMSConfigSchema>;
|
|
35
|
+
export declare const LeadPayloadSchema: z.ZodObject<{
|
|
36
|
+
clickId: z.ZodOptional<z.ZodString>;
|
|
37
|
+
eventName: z.ZodString;
|
|
38
|
+
customerExternalId: z.ZodString;
|
|
39
|
+
timestamp: z.ZodOptional<z.ZodString>;
|
|
40
|
+
customerId: z.ZodOptional<z.ZodString>;
|
|
41
|
+
customerName: z.ZodOptional<z.ZodString>;
|
|
42
|
+
customerEmail: z.ZodOptional<z.ZodString>;
|
|
43
|
+
customerAvatar: z.ZodOptional<z.ZodString>;
|
|
44
|
+
mode: z.ZodOptional<z.ZodEnum<["deferred"]>>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
eventName: string;
|
|
47
|
+
customerExternalId: string;
|
|
48
|
+
clickId?: string | undefined;
|
|
49
|
+
timestamp?: string | undefined;
|
|
50
|
+
customerId?: string | undefined;
|
|
51
|
+
customerName?: string | undefined;
|
|
52
|
+
customerEmail?: string | undefined;
|
|
53
|
+
customerAvatar?: string | undefined;
|
|
54
|
+
mode?: "deferred" | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
eventName: string;
|
|
57
|
+
customerExternalId: string;
|
|
58
|
+
clickId?: string | undefined;
|
|
59
|
+
timestamp?: string | undefined;
|
|
60
|
+
customerId?: string | undefined;
|
|
61
|
+
customerName?: string | undefined;
|
|
62
|
+
customerEmail?: string | undefined;
|
|
63
|
+
customerAvatar?: string | undefined;
|
|
64
|
+
mode?: "deferred" | undefined;
|
|
65
|
+
}>;
|
|
66
|
+
export type LeadPayloadInput = z.infer<typeof LeadPayloadSchema>;
|
|
67
|
+
export declare const SalePayloadSchema: z.ZodObject<{
|
|
68
|
+
clickId: z.ZodOptional<z.ZodString>;
|
|
69
|
+
eventName: z.ZodOptional<z.ZodString>;
|
|
70
|
+
invoiceId: z.ZodString;
|
|
71
|
+
amount: z.ZodNumber;
|
|
72
|
+
currency: z.ZodOptional<z.ZodString>;
|
|
73
|
+
timestamp: z.ZodOptional<z.ZodString>;
|
|
74
|
+
customerId: z.ZodOptional<z.ZodString>;
|
|
75
|
+
customerExternalId: z.ZodOptional<z.ZodString>;
|
|
76
|
+
customerName: z.ZodOptional<z.ZodString>;
|
|
77
|
+
customerEmail: z.ZodOptional<z.ZodString>;
|
|
78
|
+
mode: z.ZodOptional<z.ZodEnum<["deferred"]>>;
|
|
79
|
+
}, "strip", z.ZodTypeAny, {
|
|
80
|
+
invoiceId: string;
|
|
81
|
+
amount: number;
|
|
82
|
+
clickId?: string | undefined;
|
|
83
|
+
eventName?: string | undefined;
|
|
84
|
+
customerExternalId?: string | undefined;
|
|
85
|
+
timestamp?: string | undefined;
|
|
86
|
+
customerId?: string | undefined;
|
|
87
|
+
customerName?: string | undefined;
|
|
88
|
+
customerEmail?: string | undefined;
|
|
89
|
+
mode?: "deferred" | undefined;
|
|
90
|
+
currency?: string | undefined;
|
|
91
|
+
}, {
|
|
92
|
+
invoiceId: string;
|
|
93
|
+
amount: number;
|
|
94
|
+
clickId?: string | undefined;
|
|
95
|
+
eventName?: string | undefined;
|
|
96
|
+
customerExternalId?: string | undefined;
|
|
97
|
+
timestamp?: string | undefined;
|
|
98
|
+
customerId?: string | undefined;
|
|
99
|
+
customerName?: string | undefined;
|
|
100
|
+
customerEmail?: string | undefined;
|
|
101
|
+
mode?: "deferred" | undefined;
|
|
102
|
+
currency?: string | undefined;
|
|
103
|
+
}>;
|
|
104
|
+
export type SalePayloadInput = z.infer<typeof SalePayloadSchema>;
|
|
105
|
+
/**
|
|
106
|
+
* Validates input data and throws detailed error if invalid
|
|
107
|
+
*/
|
|
108
|
+
export declare function validateLeadPayload(data: unknown): LeadPayloadInput;
|
|
109
|
+
export declare function validateSalePayload(data: unknown): SalePayloadInput;
|
|
110
|
+
export declare function validateCMSConfig(data: unknown): CMSConfigInput;
|
|
111
|
+
/**
|
|
112
|
+
* Sanitizes sensitive data for logging/errors
|
|
113
|
+
* Removes API keys, tokens, and other credentials
|
|
114
|
+
*/
|
|
115
|
+
export declare function sanitizeForLogging(obj: any): any;
|
|
116
|
+
/**
|
|
117
|
+
* Redacts API key from error messages
|
|
118
|
+
*/
|
|
119
|
+
export declare function redactApiKey(message: string, apiKey?: string): string;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalePayloadSchema = exports.LeadPayloadSchema = exports.CMSConfigSchema = void 0;
|
|
4
|
+
exports.validateLeadPayload = validateLeadPayload;
|
|
5
|
+
exports.validateSalePayload = validateSalePayload;
|
|
6
|
+
exports.validateCMSConfig = validateCMSConfig;
|
|
7
|
+
exports.sanitizeForLogging = sanitizeForLogging;
|
|
8
|
+
exports.redactApiKey = redactApiKey;
|
|
9
|
+
/**
|
|
10
|
+
* Input validation schemas using Zod
|
|
11
|
+
* Ensures all incoming data is sanitized and valid
|
|
12
|
+
*/
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
const constants_1 = require("../constants/constants");
|
|
15
|
+
exports.CMSConfigSchema = zod_1.z.object({
|
|
16
|
+
apiKey: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.min(1, constants_1.ERROR_MESSAGES.API_KEY_REQUIRED)
|
|
19
|
+
.refine((key) => constants_1.VALIDATION_CONSTRAINTS.API_KEY.PATTERN.test(key), constants_1.ERROR_MESSAGES.API_KEY_INVALID_FORMAT),
|
|
20
|
+
baseUrl: zod_1.z
|
|
21
|
+
.string()
|
|
22
|
+
.url(constants_1.ERROR_MESSAGES.BASE_URL_INVALID)
|
|
23
|
+
.optional(),
|
|
24
|
+
timeout: zod_1.z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.TIMEOUT.MIN_MS, constants_1.ERROR_MESSAGES.TIMEOUT_TOO_LOW)
|
|
28
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.TIMEOUT.MAX_MS, constants_1.ERROR_MESSAGES.TIMEOUT_TOO_HIGH)
|
|
29
|
+
.optional(),
|
|
30
|
+
maxRetries: zod_1.z
|
|
31
|
+
.number()
|
|
32
|
+
.int()
|
|
33
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.MAX_RETRIES.MIN, constants_1.ERROR_MESSAGES.MAX_RETRIES_NEGATIVE)
|
|
34
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.MAX_RETRIES.MAX, constants_1.ERROR_MESSAGES.MAX_RETRIES_TOO_HIGH)
|
|
35
|
+
.optional(),
|
|
36
|
+
retryDelayMs: zod_1.z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.RETRY_DELAY.MIN_MS, constants_1.ERROR_MESSAGES.RETRY_DELAY_TOO_LOW)
|
|
40
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.RETRY_DELAY.MAX_MS, constants_1.ERROR_MESSAGES.RETRY_DELAY_TOO_HIGH)
|
|
41
|
+
.optional(),
|
|
42
|
+
retryMaxDelayMs: zod_1.z
|
|
43
|
+
.number()
|
|
44
|
+
.int()
|
|
45
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.RETRY_MAX_DELAY.MIN_MS, constants_1.ERROR_MESSAGES.RETRY_MAX_DELAY_TOO_LOW)
|
|
46
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.RETRY_MAX_DELAY.MAX_MS, constants_1.ERROR_MESSAGES.RETRY_MAX_DELAY_TOO_HIGH)
|
|
47
|
+
.optional(),
|
|
48
|
+
retryOnStatuses: zod_1.z
|
|
49
|
+
.array(zod_1.z.number().int().min(100).max(599))
|
|
50
|
+
.optional(),
|
|
51
|
+
retryOnNetworkError: zod_1.z.boolean().optional(),
|
|
52
|
+
});
|
|
53
|
+
// Lead payload validation
|
|
54
|
+
exports.LeadPayloadSchema = zod_1.z.object({
|
|
55
|
+
clickId: zod_1.z
|
|
56
|
+
.string()
|
|
57
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CLICK_ID.MIN)
|
|
58
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CLICK_ID.MAX)
|
|
59
|
+
.optional(),
|
|
60
|
+
eventName: zod_1.z
|
|
61
|
+
.string()
|
|
62
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.EVENT_NAME.MIN, constants_1.ERROR_MESSAGES.EVENT_NAME_REQUIRED)
|
|
63
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.EVENT_NAME.MAX, constants_1.ERROR_MESSAGES.EVENT_NAME_TOO_LONG),
|
|
64
|
+
customerExternalId: zod_1.z
|
|
65
|
+
.string()
|
|
66
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EXTERNAL_ID.MIN, constants_1.ERROR_MESSAGES.CUSTOMER_EXTERNAL_ID_REQUIRED)
|
|
67
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EXTERNAL_ID.MAX, constants_1.ERROR_MESSAGES.CUSTOMER_EXTERNAL_ID_TOO_LONG),
|
|
68
|
+
timestamp: zod_1.z
|
|
69
|
+
.string()
|
|
70
|
+
.datetime()
|
|
71
|
+
.optional(),
|
|
72
|
+
customerId: zod_1.z
|
|
73
|
+
.string()
|
|
74
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_ID.MAX)
|
|
75
|
+
.optional(),
|
|
76
|
+
customerName: zod_1.z
|
|
77
|
+
.string()
|
|
78
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_NAME.MAX)
|
|
79
|
+
.optional(),
|
|
80
|
+
customerEmail: zod_1.z
|
|
81
|
+
.string()
|
|
82
|
+
.email(constants_1.ERROR_MESSAGES.CUSTOMER_EMAIL_INVALID)
|
|
83
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EMAIL.MAX, constants_1.ERROR_MESSAGES.CUSTOMER_EMAIL_TOO_LONG)
|
|
84
|
+
.optional(),
|
|
85
|
+
customerAvatar: zod_1.z
|
|
86
|
+
.string()
|
|
87
|
+
.url(constants_1.ERROR_MESSAGES.CUSTOMER_AVATAR_INVALID)
|
|
88
|
+
.optional(),
|
|
89
|
+
mode: zod_1.z
|
|
90
|
+
.enum(["deferred"])
|
|
91
|
+
.optional(),
|
|
92
|
+
});
|
|
93
|
+
// Sale payload validation
|
|
94
|
+
exports.SalePayloadSchema = zod_1.z.object({
|
|
95
|
+
clickId: zod_1.z
|
|
96
|
+
.string()
|
|
97
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CLICK_ID.MIN)
|
|
98
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CLICK_ID.MAX)
|
|
99
|
+
.optional(),
|
|
100
|
+
eventName: zod_1.z
|
|
101
|
+
.string()
|
|
102
|
+
.optional(),
|
|
103
|
+
invoiceId: zod_1.z
|
|
104
|
+
.string()
|
|
105
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.INVOICE_ID.MIN, constants_1.ERROR_MESSAGES.INVOICE_ID_REQUIRED)
|
|
106
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.INVOICE_ID.MAX, constants_1.ERROR_MESSAGES.INVOICE_ID_TOO_LONG),
|
|
107
|
+
amount: zod_1.z
|
|
108
|
+
.number()
|
|
109
|
+
.int()
|
|
110
|
+
.min(constants_1.VALIDATION_CONSTRAINTS.AMOUNT.MIN, constants_1.ERROR_MESSAGES.AMOUNT_NEGATIVE),
|
|
111
|
+
currency: zod_1.z
|
|
112
|
+
.string()
|
|
113
|
+
.length(constants_1.VALIDATION_CONSTRAINTS.CURRENCY.LENGTH, constants_1.ERROR_MESSAGES.CURRENCY_INVALID_LENGTH)
|
|
114
|
+
.regex(constants_1.VALIDATION_CONSTRAINTS.CURRENCY.PATTERN, constants_1.ERROR_MESSAGES.CURRENCY_INVALID_FORMAT)
|
|
115
|
+
.optional(),
|
|
116
|
+
timestamp: zod_1.z
|
|
117
|
+
.string()
|
|
118
|
+
.datetime()
|
|
119
|
+
.optional(),
|
|
120
|
+
customerId: zod_1.z
|
|
121
|
+
.string()
|
|
122
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_ID.MAX)
|
|
123
|
+
.optional(),
|
|
124
|
+
customerExternalId: zod_1.z
|
|
125
|
+
.string()
|
|
126
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EXTERNAL_ID.MAX)
|
|
127
|
+
.optional(),
|
|
128
|
+
customerName: zod_1.z
|
|
129
|
+
.string()
|
|
130
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_NAME.MAX)
|
|
131
|
+
.optional(),
|
|
132
|
+
customerEmail: zod_1.z
|
|
133
|
+
.string()
|
|
134
|
+
.email(constants_1.ERROR_MESSAGES.CUSTOMER_EMAIL_INVALID)
|
|
135
|
+
.max(constants_1.VALIDATION_CONSTRAINTS.STRING_FIELDS.CUSTOMER_EMAIL.MAX, constants_1.ERROR_MESSAGES.CUSTOMER_EMAIL_TOO_LONG)
|
|
136
|
+
.optional(),
|
|
137
|
+
mode: zod_1.z
|
|
138
|
+
.enum(["deferred"])
|
|
139
|
+
.optional(),
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* Validates input data and throws detailed error if invalid
|
|
143
|
+
*/
|
|
144
|
+
function validateLeadPayload(data) {
|
|
145
|
+
return exports.LeadPayloadSchema.parse(data);
|
|
146
|
+
}
|
|
147
|
+
function validateSalePayload(data) {
|
|
148
|
+
return exports.SalePayloadSchema.parse(data);
|
|
149
|
+
}
|
|
150
|
+
function validateCMSConfig(data) {
|
|
151
|
+
return exports.CMSConfigSchema.parse(data);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Sanitizes sensitive data for logging/errors
|
|
155
|
+
* Removes API keys, tokens, and other credentials
|
|
156
|
+
*/
|
|
157
|
+
function sanitizeForLogging(obj) {
|
|
158
|
+
if (!obj || typeof obj !== "object") {
|
|
159
|
+
return obj;
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(obj)) {
|
|
162
|
+
return obj.map((item) => sanitizeForLogging(item));
|
|
163
|
+
}
|
|
164
|
+
const sanitized = {};
|
|
165
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
166
|
+
const lowerKey = key.toLowerCase();
|
|
167
|
+
// Mask sensitive field names
|
|
168
|
+
if (constants_1.SENSITIVE_FIELDS.PATTERNS.some((field) => lowerKey.includes(field))) {
|
|
169
|
+
sanitized[key] = typeof value === "string" ? constants_1.SENSITIVE_FIELDS.REDACTION_PLACEHOLDER : value;
|
|
170
|
+
}
|
|
171
|
+
else if (typeof value === "object" && value !== null) {
|
|
172
|
+
sanitized[key] = sanitizeForLogging(value);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
sanitized[key] = value;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return sanitized;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Redacts API key from error messages
|
|
182
|
+
*/
|
|
183
|
+
function redactApiKey(message, apiKey) {
|
|
184
|
+
if (!apiKey)
|
|
185
|
+
return message;
|
|
186
|
+
// Replace the full key and common patterns
|
|
187
|
+
const patterns = [
|
|
188
|
+
apiKey,
|
|
189
|
+
apiKey.substring(0, 3) + "***" + apiKey.substring(apiKey.length - 3),
|
|
190
|
+
];
|
|
191
|
+
let result = message;
|
|
192
|
+
for (const pattern of patterns) {
|
|
193
|
+
result = result.replace(new RegExp(pattern, "g"), constants_1.SENSITIVE_FIELDS.API_KEY_REDACTION);
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vigneshreddy/cms-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Official TypeScript SDK for CutMeShort CMS API",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsc -p tsconfig.json",
|
|
20
|
-
"test": "vitest"
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"audit": "npm audit --audit-level=moderate",
|
|
22
|
+
"security-check": "npm audit && npm ls"
|
|
21
23
|
},
|
|
22
24
|
"keywords": [
|
|
23
25
|
"cutmeshort",
|
|
@@ -42,6 +44,9 @@
|
|
|
42
44
|
},
|
|
43
45
|
"author": "Vignesh Reddy",
|
|
44
46
|
"license": "MIT",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"zod": "^3.22.0"
|
|
49
|
+
},
|
|
45
50
|
"devDependencies": {
|
|
46
51
|
"typescript": "^5.7.0",
|
|
47
52
|
"vitest": "^4.0.18"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|