observability-toolkit 1.6.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +221 -91
  2. package/dist/backends/index.d.ts +146 -0
  3. package/dist/backends/index.d.ts.map +1 -1
  4. package/dist/backends/index.js +65 -1
  5. package/dist/backends/index.js.map +1 -1
  6. package/dist/backends/local-jsonl-boolean-search.test.js +1 -23
  7. package/dist/backends/local-jsonl-boolean-search.test.js.map +1 -1
  8. package/dist/backends/local-jsonl.d.ts +4 -1
  9. package/dist/backends/local-jsonl.d.ts.map +1 -1
  10. package/dist/backends/local-jsonl.js +216 -6
  11. package/dist/backends/local-jsonl.js.map +1 -1
  12. package/dist/backends/local-jsonl.test.js +715 -26
  13. package/dist/backends/local-jsonl.test.js.map +1 -1
  14. package/dist/backends/signoz-api.d.ts +32 -0
  15. package/dist/backends/signoz-api.d.ts.map +1 -1
  16. package/dist/backends/signoz-api.js +237 -33
  17. package/dist/backends/signoz-api.js.map +1 -1
  18. package/dist/backends/signoz-api.test.js +410 -63
  19. package/dist/backends/signoz-api.test.js.map +1 -1
  20. package/dist/lib/constants.d.ts +16 -0
  21. package/dist/lib/constants.d.ts.map +1 -1
  22. package/dist/lib/constants.js +121 -5
  23. package/dist/lib/constants.js.map +1 -1
  24. package/dist/lib/constants.test.js +202 -15
  25. package/dist/lib/constants.test.js.map +1 -1
  26. package/dist/lib/error-sanitizer.d.ts +57 -0
  27. package/dist/lib/error-sanitizer.d.ts.map +1 -0
  28. package/dist/lib/error-sanitizer.js +197 -0
  29. package/dist/lib/error-sanitizer.js.map +1 -0
  30. package/dist/lib/error-sanitizer.test.d.ts +8 -0
  31. package/dist/lib/error-sanitizer.test.d.ts.map +1 -0
  32. package/dist/lib/error-sanitizer.test.js +342 -0
  33. package/dist/lib/error-sanitizer.test.js.map +1 -0
  34. package/dist/lib/file-utils.d.ts +210 -0
  35. package/dist/lib/file-utils.d.ts.map +1 -1
  36. package/dist/lib/file-utils.js +529 -14
  37. package/dist/lib/file-utils.js.map +1 -1
  38. package/dist/lib/file-utils.test.js +657 -3
  39. package/dist/lib/file-utils.test.js.map +1 -1
  40. package/dist/lib/indexer.d.ts +19 -1
  41. package/dist/lib/indexer.d.ts.map +1 -1
  42. package/dist/lib/indexer.js +84 -8
  43. package/dist/lib/indexer.js.map +1 -1
  44. package/dist/lib/indexer.test.js +187 -16
  45. package/dist/lib/indexer.test.js.map +1 -1
  46. package/dist/lib/input-validator.d.ts +98 -0
  47. package/dist/lib/input-validator.d.ts.map +1 -0
  48. package/dist/lib/input-validator.js +245 -0
  49. package/dist/lib/input-validator.js.map +1 -0
  50. package/dist/lib/input-validator.test.d.ts +2 -0
  51. package/dist/lib/input-validator.test.d.ts.map +1 -0
  52. package/dist/lib/input-validator.test.js +287 -0
  53. package/dist/lib/input-validator.test.js.map +1 -0
  54. package/dist/lib/query-sanitizer.d.ts +95 -0
  55. package/dist/lib/query-sanitizer.d.ts.map +1 -0
  56. package/dist/lib/query-sanitizer.js +187 -0
  57. package/dist/lib/query-sanitizer.js.map +1 -0
  58. package/dist/lib/query-sanitizer.test.d.ts +5 -0
  59. package/dist/lib/query-sanitizer.test.d.ts.map +1 -0
  60. package/dist/lib/query-sanitizer.test.js +299 -0
  61. package/dist/lib/query-sanitizer.test.js.map +1 -0
  62. package/dist/server.d.ts +49 -1
  63. package/dist/server.d.ts.map +1 -1
  64. package/dist/server.js +97 -13
  65. package/dist/server.js.map +1 -1
  66. package/dist/server.test.js +202 -0
  67. package/dist/server.test.js.map +1 -1
  68. package/dist/test-helpers/file-utils.d.ts +26 -0
  69. package/dist/test-helpers/file-utils.d.ts.map +1 -0
  70. package/dist/test-helpers/file-utils.js +43 -0
  71. package/dist/test-helpers/file-utils.js.map +1 -0
  72. package/dist/test-helpers/mock-backends.d.ts +28 -0
  73. package/dist/test-helpers/mock-backends.d.ts.map +1 -0
  74. package/dist/test-helpers/mock-backends.js +31 -0
  75. package/dist/test-helpers/mock-backends.js.map +1 -0
  76. package/dist/tools/health-check.js +1 -1
  77. package/dist/tools/health-check.js.map +1 -1
  78. package/dist/tools/index.d.ts +1 -0
  79. package/dist/tools/index.d.ts.map +1 -1
  80. package/dist/tools/index.js +1 -0
  81. package/dist/tools/index.js.map +1 -1
  82. package/dist/tools/query-evaluations.d.ts +183 -0
  83. package/dist/tools/query-evaluations.d.ts.map +1 -0
  84. package/dist/tools/query-evaluations.js +351 -0
  85. package/dist/tools/query-evaluations.js.map +1 -0
  86. package/dist/tools/query-evaluations.test.d.ts +5 -0
  87. package/dist/tools/query-evaluations.test.d.ts.map +1 -0
  88. package/dist/tools/query-evaluations.test.js +743 -0
  89. package/dist/tools/query-evaluations.test.js.map +1 -0
  90. package/dist/tools/query-llm-events.d.ts +62 -11
  91. package/dist/tools/query-llm-events.d.ts.map +1 -1
  92. package/dist/tools/query-llm-events.js +97 -37
  93. package/dist/tools/query-llm-events.js.map +1 -1
  94. package/dist/tools/query-llm-events.test.js +253 -0
  95. package/dist/tools/query-llm-events.test.js.map +1 -1
  96. package/dist/tools/query-logs.d.ts +32 -18
  97. package/dist/tools/query-logs.d.ts.map +1 -1
  98. package/dist/tools/query-logs.js +77 -44
  99. package/dist/tools/query-logs.js.map +1 -1
  100. package/dist/tools/query-logs.test.js +226 -64
  101. package/dist/tools/query-logs.test.js.map +1 -1
  102. package/dist/tools/query-metrics.d.ts +24 -24
  103. package/dist/tools/query-metrics.d.ts.map +1 -1
  104. package/dist/tools/query-metrics.js +102 -54
  105. package/dist/tools/query-metrics.js.map +1 -1
  106. package/dist/tools/query-metrics.test.js +35 -36
  107. package/dist/tools/query-metrics.test.js.map +1 -1
  108. package/dist/tools/query-traces.d.ts +66 -22
  109. package/dist/tools/query-traces.d.ts.map +1 -1
  110. package/dist/tools/query-traces.js +86 -42
  111. package/dist/tools/query-traces.js.map +1 -1
  112. package/dist/tools/query-traces.test.js +458 -36
  113. package/dist/tools/query-traces.test.js.map +1 -1
  114. package/package.json +1 -3
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Input validation utilities for observability-toolkit MCP server
3
+ *
4
+ * Enforces strict limits on user inputs to prevent:
5
+ * - Resource exhaustion (unbounded queries)
6
+ * - Regex denial of service (ReDoS)
7
+ * - Invalid date ranges
8
+ */
9
+ // Validation constants
10
+ export const MAX_LIMIT = 1000;
11
+ export const MAX_DATE_RANGE_DAYS = 365;
12
+ export const MAX_REGEX_LENGTH = 200;
13
+ export const MAX_REGEX_GROUPS = 10;
14
+ export const DEFAULT_LIMIT = 50;
15
+ export const MAX_DURATION_MS = 86400000; // 24 hours
16
+ /**
17
+ * Custom error class for input validation failures.
18
+ * Provides structured error information for user-friendly error responses.
19
+ */
20
+ export class InputValidationError extends Error {
21
+ /** Field that failed validation */
22
+ field;
23
+ /** Constraint that was violated */
24
+ constraint;
25
+ constructor(message, field, constraint) {
26
+ super(message);
27
+ this.name = 'InputValidationError';
28
+ this.field = field;
29
+ this.constraint = constraint;
30
+ // Maintain proper stack trace in V8 environments
31
+ if (Error.captureStackTrace) {
32
+ Error.captureStackTrace(this, InputValidationError);
33
+ }
34
+ }
35
+ }
36
+ /**
37
+ * Validate and clamp the limit parameter.
38
+ *
39
+ * @param limit - User-provided limit (undefined uses default)
40
+ * @returns Clamped limit between 1 and MAX_LIMIT
41
+ *
42
+ * @example
43
+ * validateLimit(undefined) // returns 50 (default)
44
+ * validateLimit(5000) // returns 1000 (clamped to max)
45
+ * validateLimit(0) // returns 1 (minimum)
46
+ * validateLimit(-10) // returns 1 (minimum)
47
+ */
48
+ export function validateLimit(limit) {
49
+ if (limit === undefined || limit === null) {
50
+ return DEFAULT_LIMIT;
51
+ }
52
+ // Clamp to valid range [1, MAX_LIMIT]
53
+ return Math.max(1, Math.min(limit, MAX_LIMIT));
54
+ }
55
+ /**
56
+ * Validate and clamp duration parameters.
57
+ *
58
+ * @param duration - User-provided duration in milliseconds (undefined passes through)
59
+ * @param field - Field name for error messages ('minDurationMs' or 'maxDurationMs')
60
+ * @returns Clamped duration between 0 and MAX_DURATION_MS, or undefined if not provided
61
+ * @throws InputValidationError if duration is negative
62
+ *
63
+ * @example
64
+ * validateDuration(undefined, 'minDurationMs') // returns undefined
65
+ * validateDuration(5000, 'minDurationMs') // returns 5000
66
+ * validateDuration(100000000, 'maxDurationMs') // returns 86400000 (clamped to max)
67
+ * validateDuration(-10, 'minDurationMs') // throws: negative duration
68
+ */
69
+ export function validateDuration(duration, field) {
70
+ if (duration === undefined || duration === null) {
71
+ return undefined;
72
+ }
73
+ // Reject negative values
74
+ if (duration < 0) {
75
+ throw new InputValidationError(`${field} cannot be negative: ${duration}`, field, 'range');
76
+ }
77
+ // Clamp to MAX_DURATION_MS
78
+ return Math.min(duration, MAX_DURATION_MS);
79
+ }
80
+ /**
81
+ * Parse a date string in YYYY-MM-DD format.
82
+ * Returns null if the format is invalid.
83
+ */
84
+ function parseDateString(dateStr) {
85
+ const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})$/);
86
+ if (!match) {
87
+ return null;
88
+ }
89
+ const year = parseInt(match[1], 10);
90
+ const month = parseInt(match[2], 10) - 1; // JS months are 0-indexed
91
+ const day = parseInt(match[3], 10);
92
+ // Validate date components
93
+ if (month < 0 || month > 11 || day < 1 || day > 31) {
94
+ return null;
95
+ }
96
+ const date = new Date(year, month, day);
97
+ // Check for date overflow (e.g., Feb 30 becomes Mar 2)
98
+ if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {
99
+ return null;
100
+ }
101
+ return date;
102
+ }
103
+ /**
104
+ * Validate date range parameters.
105
+ *
106
+ * Validates:
107
+ * - Date format (YYYY-MM-DD)
108
+ * - startDate is not after endDate
109
+ * - Range does not exceed MAX_DATE_RANGE_DAYS
110
+ *
111
+ * @param startDate - Optional start date string (YYYY-MM-DD)
112
+ * @param endDate - Optional end date string (YYYY-MM-DD)
113
+ * @returns Parsed Date objects for start and end
114
+ * @throws InputValidationError if validation fails
115
+ *
116
+ * @example
117
+ * validateDateRange('2024-01-01', '2024-01-31') // valid
118
+ * validateDateRange(undefined, undefined) // defaults to today
119
+ * validateDateRange('2024-01-15', '2024-01-01') // throws: start after end
120
+ */
121
+ export function validateDateRange(startDate, endDate) {
122
+ const now = new Date();
123
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
124
+ // Parse end date first (used for default start calculation)
125
+ let end;
126
+ if (endDate) {
127
+ const parsed = parseDateString(endDate);
128
+ if (!parsed) {
129
+ throw new InputValidationError(`Invalid endDate format: "${endDate}". Expected YYYY-MM-DD.`, 'endDate', 'format');
130
+ }
131
+ end = parsed;
132
+ }
133
+ else {
134
+ // Default to today
135
+ end = today;
136
+ }
137
+ // Parse start date
138
+ let start;
139
+ if (startDate) {
140
+ const parsed = parseDateString(startDate);
141
+ if (!parsed) {
142
+ throw new InputValidationError(`Invalid startDate format: "${startDate}". Expected YYYY-MM-DD.`, 'startDate', 'format');
143
+ }
144
+ start = parsed;
145
+ }
146
+ else {
147
+ // Default to MAX_DATE_RANGE_DAYS before end date (to ensure valid range)
148
+ start = new Date(end.getTime() - MAX_DATE_RANGE_DAYS * 24 * 60 * 60 * 1000);
149
+ }
150
+ // Validate start is not after end
151
+ if (start > end) {
152
+ throw new InputValidationError(`startDate (${startDate || start.toISOString().split('T')[0]}) cannot be after endDate (${endDate || end.toISOString().split('T')[0]}).`, 'startDate', 'range');
153
+ }
154
+ // Validate range does not exceed maximum (only when both are explicitly provided)
155
+ if (startDate && endDate) {
156
+ const rangeDays = Math.ceil((end.getTime() - start.getTime()) / (24 * 60 * 60 * 1000));
157
+ if (rangeDays > MAX_DATE_RANGE_DAYS) {
158
+ throw new InputValidationError(`Date range of ${rangeDays} days exceeds maximum of ${MAX_DATE_RANGE_DAYS} days.`, 'dateRange', 'maxRange');
159
+ }
160
+ }
161
+ return { start, end };
162
+ }
163
+ /**
164
+ * Count the number of capture groups in a regex pattern.
165
+ * Handles escaped parentheses and non-capturing groups.
166
+ */
167
+ function countRegexGroups(pattern) {
168
+ let count = 0;
169
+ let escaped = false;
170
+ let inCharClass = false;
171
+ for (let i = 0; i < pattern.length; i++) {
172
+ const char = pattern[i];
173
+ if (escaped) {
174
+ escaped = false;
175
+ continue;
176
+ }
177
+ if (char === '\\') {
178
+ escaped = true;
179
+ continue;
180
+ }
181
+ if (char === '[') {
182
+ inCharClass = true;
183
+ continue;
184
+ }
185
+ if (char === ']' && inCharClass) {
186
+ inCharClass = false;
187
+ continue;
188
+ }
189
+ if (inCharClass) {
190
+ continue;
191
+ }
192
+ // Check for opening parenthesis that starts a capturing group
193
+ if (char === '(') {
194
+ // Look ahead to check for non-capturing group (?:, (?=, (?!, (?<= etc.
195
+ const next = pattern[i + 1];
196
+ if (next !== '?') {
197
+ count++;
198
+ }
199
+ }
200
+ }
201
+ return count;
202
+ }
203
+ /**
204
+ * Validate a regex pattern for safety and correctness.
205
+ *
206
+ * Validates:
207
+ * - Pattern length does not exceed MAX_REGEX_LENGTH
208
+ * - Number of capture groups does not exceed MAX_REGEX_GROUPS
209
+ * - Pattern compiles successfully
210
+ *
211
+ * @param pattern - Regex pattern string to validate
212
+ * @throws InputValidationError if validation fails
213
+ *
214
+ * @example
215
+ * validateRegexPattern('error.*timeout') // valid
216
+ * validateRegexPattern('(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)') // throws: too many groups
217
+ * validateRegexPattern('[invalid') // throws: invalid syntax
218
+ */
219
+ export function validateRegexPattern(pattern) {
220
+ // Validate length
221
+ if (pattern.length > MAX_REGEX_LENGTH) {
222
+ throw new InputValidationError(`Pattern length of ${pattern.length} exceeds maximum of ${MAX_REGEX_LENGTH} characters.`, 'pattern', 'maxLength');
223
+ }
224
+ // Count capture groups before attempting compilation
225
+ const groupCount = countRegexGroups(pattern);
226
+ if (groupCount > MAX_REGEX_GROUPS) {
227
+ throw new InputValidationError(`Pattern has ${groupCount} capture groups, exceeding maximum of ${MAX_REGEX_GROUPS}.`, 'pattern', 'maxGroups');
228
+ }
229
+ // Attempt compilation to check syntax
230
+ try {
231
+ new RegExp(pattern);
232
+ }
233
+ catch (error) {
234
+ const message = error instanceof Error ? error.message : String(error);
235
+ throw new InputValidationError(`Invalid regex pattern: ${message}`, 'pattern', 'syntax');
236
+ }
237
+ }
238
+ /**
239
+ * Helper to check if an error is an InputValidationError.
240
+ * Useful for catch blocks.
241
+ */
242
+ export function isInputValidationError(error) {
243
+ return error instanceof InputValidationError;
244
+ }
245
+ //# sourceMappingURL=input-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/lib/input-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=input-validator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.test.d.ts","sourceRoot":"","sources":["../../src/lib/input-validator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,287 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { validateLimit, validateDuration, validateDateRange, validateRegexPattern, InputValidationError, isInputValidationError, MAX_LIMIT, MAX_DATE_RANGE_DAYS, MAX_REGEX_LENGTH, MAX_REGEX_GROUPS, DEFAULT_LIMIT, MAX_DURATION_MS, } from './input-validator.js';
4
+ describe('input-validator', () => {
5
+ describe('validateLimit', () => {
6
+ it('should return default limit when undefined', () => {
7
+ const result = validateLimit(undefined);
8
+ assert.strictEqual(result, DEFAULT_LIMIT);
9
+ });
10
+ it('should return default limit when null', () => {
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const result = validateLimit(null);
13
+ assert.strictEqual(result, DEFAULT_LIMIT);
14
+ });
15
+ it('should return value when within valid range', () => {
16
+ assert.strictEqual(validateLimit(100), 100);
17
+ assert.strictEqual(validateLimit(500), 500);
18
+ assert.strictEqual(validateLimit(1), 1);
19
+ });
20
+ it('should clamp to MAX_LIMIT when value exceeds maximum', () => {
21
+ assert.strictEqual(validateLimit(5000), MAX_LIMIT);
22
+ assert.strictEqual(validateLimit(1001), MAX_LIMIT);
23
+ assert.strictEqual(validateLimit(Number.MAX_SAFE_INTEGER), MAX_LIMIT);
24
+ });
25
+ it('should clamp to 1 when value is zero or negative', () => {
26
+ assert.strictEqual(validateLimit(0), 1);
27
+ assert.strictEqual(validateLimit(-1), 1);
28
+ assert.strictEqual(validateLimit(-100), 1);
29
+ });
30
+ it('should handle edge cases', () => {
31
+ assert.strictEqual(validateLimit(MAX_LIMIT), MAX_LIMIT);
32
+ assert.strictEqual(validateLimit(1), 1);
33
+ });
34
+ });
35
+ describe('validateDuration', () => {
36
+ it('should return undefined when undefined', () => {
37
+ const result = validateDuration(undefined, 'minDurationMs');
38
+ assert.strictEqual(result, undefined);
39
+ });
40
+ it('should return undefined when null', () => {
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ const result = validateDuration(null, 'minDurationMs');
43
+ assert.strictEqual(result, undefined);
44
+ });
45
+ it('should return value when within valid range', () => {
46
+ assert.strictEqual(validateDuration(0, 'minDurationMs'), 0);
47
+ assert.strictEqual(validateDuration(1000, 'minDurationMs'), 1000);
48
+ assert.strictEqual(validateDuration(5000, 'maxDurationMs'), 5000);
49
+ assert.strictEqual(validateDuration(MAX_DURATION_MS, 'maxDurationMs'), MAX_DURATION_MS);
50
+ });
51
+ it('should clamp to MAX_DURATION_MS when value exceeds maximum', () => {
52
+ assert.strictEqual(validateDuration(MAX_DURATION_MS + 1, 'minDurationMs'), MAX_DURATION_MS);
53
+ assert.strictEqual(validateDuration(100000000, 'maxDurationMs'), MAX_DURATION_MS);
54
+ assert.strictEqual(validateDuration(Number.MAX_SAFE_INTEGER, 'minDurationMs'), MAX_DURATION_MS);
55
+ });
56
+ it('should throw when value is negative', () => {
57
+ assert.throws(() => validateDuration(-1, 'minDurationMs'), (err) => {
58
+ assert.strictEqual(err.field, 'minDurationMs');
59
+ assert.strictEqual(err.constraint, 'range');
60
+ assert.ok(err.message.includes('cannot be negative'));
61
+ return true;
62
+ });
63
+ assert.throws(() => validateDuration(-100, 'maxDurationMs'), (err) => {
64
+ assert.strictEqual(err.field, 'maxDurationMs');
65
+ assert.strictEqual(err.constraint, 'range');
66
+ return true;
67
+ });
68
+ });
69
+ it('should handle edge cases', () => {
70
+ assert.strictEqual(validateDuration(0, 'minDurationMs'), 0);
71
+ assert.strictEqual(validateDuration(MAX_DURATION_MS, 'maxDurationMs'), MAX_DURATION_MS);
72
+ });
73
+ });
74
+ describe('validateDateRange', () => {
75
+ it('should parse valid date strings', () => {
76
+ const result = validateDateRange('2024-01-01', '2024-01-31');
77
+ assert.strictEqual(result.start.getFullYear(), 2024);
78
+ assert.strictEqual(result.start.getMonth(), 0); // January
79
+ assert.strictEqual(result.start.getDate(), 1);
80
+ assert.strictEqual(result.end.getFullYear(), 2024);
81
+ assert.strictEqual(result.end.getMonth(), 0);
82
+ assert.strictEqual(result.end.getDate(), 31);
83
+ });
84
+ it('should return defaults when both dates undefined', () => {
85
+ const result = validateDateRange(undefined, undefined);
86
+ const today = new Date();
87
+ // End should be today
88
+ assert.strictEqual(result.end.getFullYear(), today.getFullYear());
89
+ assert.strictEqual(result.end.getMonth(), today.getMonth());
90
+ assert.strictEqual(result.end.getDate(), today.getDate());
91
+ // Start should be MAX_DATE_RANGE_DAYS ago
92
+ const expectedStart = new Date(today.getTime() - MAX_DATE_RANGE_DAYS * 24 * 60 * 60 * 1000);
93
+ assert.strictEqual(result.start.getFullYear(), expectedStart.getFullYear());
94
+ assert.strictEqual(result.start.getMonth(), expectedStart.getMonth());
95
+ assert.strictEqual(result.start.getDate(), expectedStart.getDate());
96
+ });
97
+ it('should throw on invalid startDate format', () => {
98
+ assert.throws(() => validateDateRange('invalid', '2024-01-31'), (err) => {
99
+ assert.strictEqual(err.field, 'startDate');
100
+ assert.strictEqual(err.constraint, 'format');
101
+ assert.ok(err.message.includes('Invalid startDate format'));
102
+ return true;
103
+ });
104
+ });
105
+ it('should throw on invalid endDate format', () => {
106
+ assert.throws(() => validateDateRange('2024-01-01', 'not-a-date'), (err) => {
107
+ assert.strictEqual(err.field, 'endDate');
108
+ assert.strictEqual(err.constraint, 'format');
109
+ assert.ok(err.message.includes('Invalid endDate format'));
110
+ return true;
111
+ });
112
+ });
113
+ it('should throw on partial date format', () => {
114
+ assert.throws(() => validateDateRange('2024-01', '2024-01-31'), (err) => {
115
+ assert.strictEqual(err.field, 'startDate');
116
+ assert.strictEqual(err.constraint, 'format');
117
+ return true;
118
+ });
119
+ });
120
+ it('should throw on invalid date like Feb 30', () => {
121
+ assert.throws(() => validateDateRange('2024-02-30', '2024-03-01'), (err) => {
122
+ assert.strictEqual(err.field, 'startDate');
123
+ assert.strictEqual(err.constraint, 'format');
124
+ return true;
125
+ });
126
+ });
127
+ it('should throw on invalid month', () => {
128
+ assert.throws(() => validateDateRange('2024-13-01', '2024-12-31'), (err) => {
129
+ assert.strictEqual(err.field, 'startDate');
130
+ assert.strictEqual(err.constraint, 'format');
131
+ return true;
132
+ });
133
+ });
134
+ it('should throw when startDate is after endDate', () => {
135
+ assert.throws(() => validateDateRange('2024-12-31', '2024-01-01'), (err) => {
136
+ assert.strictEqual(err.field, 'startDate');
137
+ assert.strictEqual(err.constraint, 'range');
138
+ assert.ok(err.message.includes('cannot be after'));
139
+ return true;
140
+ });
141
+ });
142
+ it('should throw when date range exceeds maximum', () => {
143
+ // Calculate dates that exceed MAX_DATE_RANGE_DAYS
144
+ const start = '2022-01-01';
145
+ const end = '2024-01-01'; // ~730 days
146
+ assert.throws(() => validateDateRange(start, end), (err) => {
147
+ assert.strictEqual(err.field, 'dateRange');
148
+ assert.strictEqual(err.constraint, 'maxRange');
149
+ assert.ok(err.message.includes(`exceeds maximum of ${MAX_DATE_RANGE_DAYS}`));
150
+ return true;
151
+ });
152
+ });
153
+ it('should allow range exactly at maximum', () => {
154
+ const start = new Date();
155
+ start.setDate(start.getDate() - MAX_DATE_RANGE_DAYS);
156
+ const startStr = start.toISOString().split('T')[0];
157
+ const endStr = new Date().toISOString().split('T')[0];
158
+ // Should not throw
159
+ const result = validateDateRange(startStr, endStr);
160
+ assert.ok(result.start);
161
+ assert.ok(result.end);
162
+ });
163
+ it('should handle same start and end date', () => {
164
+ const result = validateDateRange('2024-06-15', '2024-06-15');
165
+ assert.strictEqual(result.start.getTime(), result.end.getTime());
166
+ });
167
+ });
168
+ describe('validateRegexPattern', () => {
169
+ it('should accept valid simple patterns', () => {
170
+ assert.doesNotThrow(() => validateRegexPattern('error'));
171
+ assert.doesNotThrow(() => validateRegexPattern('error.*timeout'));
172
+ assert.doesNotThrow(() => validateRegexPattern('^start'));
173
+ assert.doesNotThrow(() => validateRegexPattern('end$'));
174
+ });
175
+ it('should accept patterns with allowed capture groups', () => {
176
+ assert.doesNotThrow(() => validateRegexPattern('(foo)'));
177
+ assert.doesNotThrow(() => validateRegexPattern('(a)(b)(c)'));
178
+ // 10 groups is the max
179
+ assert.doesNotThrow(() => validateRegexPattern('(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)'));
180
+ });
181
+ it('should accept non-capturing groups without counting', () => {
182
+ // Non-capturing groups don't count toward limit
183
+ assert.doesNotThrow(() => validateRegexPattern('(?:foo)'));
184
+ assert.doesNotThrow(() => validateRegexPattern('(?:a)(?:b)(?:c)(?:d)(?:e)(?:f)(?:g)(?:h)(?:i)(?:j)(?:k)'));
185
+ });
186
+ it('should accept lookahead/lookbehind without counting', () => {
187
+ assert.doesNotThrow(() => validateRegexPattern('(?=foo)'));
188
+ assert.doesNotThrow(() => validateRegexPattern('(?!foo)'));
189
+ assert.doesNotThrow(() => validateRegexPattern('(?<=foo)'));
190
+ assert.doesNotThrow(() => validateRegexPattern('(?<!foo)'));
191
+ });
192
+ it('should throw when pattern exceeds max length', () => {
193
+ const longPattern = 'a'.repeat(MAX_REGEX_LENGTH + 1);
194
+ assert.throws(() => validateRegexPattern(longPattern), (err) => {
195
+ assert.strictEqual(err.field, 'pattern');
196
+ assert.strictEqual(err.constraint, 'maxLength');
197
+ assert.ok(err.message.includes(`exceeds maximum of ${MAX_REGEX_LENGTH}`));
198
+ return true;
199
+ });
200
+ });
201
+ it('should throw when pattern has too many capture groups', () => {
202
+ // 11 groups exceeds the limit of 10
203
+ const manyGroups = '(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)';
204
+ assert.throws(() => validateRegexPattern(manyGroups), (err) => {
205
+ assert.strictEqual(err.field, 'pattern');
206
+ assert.strictEqual(err.constraint, 'maxGroups');
207
+ assert.ok(err.message.includes(`exceeding maximum of ${MAX_REGEX_GROUPS}`));
208
+ return true;
209
+ });
210
+ });
211
+ it('should throw on invalid regex syntax', () => {
212
+ assert.throws(() => validateRegexPattern('[invalid'), (err) => {
213
+ assert.strictEqual(err.field, 'pattern');
214
+ assert.strictEqual(err.constraint, 'syntax');
215
+ assert.ok(err.message.includes('Invalid regex pattern'));
216
+ return true;
217
+ });
218
+ });
219
+ it('should throw on unclosed parenthesis', () => {
220
+ assert.throws(() => validateRegexPattern('(unclosed'), (err) => {
221
+ assert.strictEqual(err.field, 'pattern');
222
+ assert.strictEqual(err.constraint, 'syntax');
223
+ return true;
224
+ });
225
+ });
226
+ it('should handle escaped parentheses', () => {
227
+ // Escaped parens don't count as groups
228
+ assert.doesNotThrow(() => validateRegexPattern('\\(not a group\\)'));
229
+ assert.doesNotThrow(() => validateRegexPattern('\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)\\(\\)'));
230
+ });
231
+ it('should handle parentheses inside character classes', () => {
232
+ // Parens inside [] don't count as groups
233
+ assert.doesNotThrow(() => validateRegexPattern('[(]'));
234
+ assert.doesNotThrow(() => validateRegexPattern('[()]'));
235
+ });
236
+ it('should handle complex patterns', () => {
237
+ // Mix of real groups, non-capturing, and escaped
238
+ assert.doesNotThrow(() => validateRegexPattern('(a)(?:b)\\(c\\)[d]'));
239
+ });
240
+ });
241
+ describe('InputValidationError', () => {
242
+ it('should have correct properties', () => {
243
+ const error = new InputValidationError('Test message', 'testField', 'testConstraint');
244
+ assert.strictEqual(error.message, 'Test message');
245
+ assert.strictEqual(error.field, 'testField');
246
+ assert.strictEqual(error.constraint, 'testConstraint');
247
+ assert.strictEqual(error.name, 'InputValidationError');
248
+ });
249
+ it('should be instanceof Error', () => {
250
+ const error = new InputValidationError('Test', 'field', 'constraint');
251
+ assert.ok(error instanceof Error);
252
+ assert.ok(error instanceof InputValidationError);
253
+ });
254
+ it('should have stack trace', () => {
255
+ const error = new InputValidationError('Test', 'field', 'constraint');
256
+ assert.ok(error.stack);
257
+ assert.ok(error.stack.includes('InputValidationError'));
258
+ });
259
+ });
260
+ describe('isInputValidationError', () => {
261
+ it('should return true for InputValidationError', () => {
262
+ const error = new InputValidationError('Test', 'field', 'constraint');
263
+ assert.strictEqual(isInputValidationError(error), true);
264
+ });
265
+ it('should return false for regular Error', () => {
266
+ const error = new Error('Test');
267
+ assert.strictEqual(isInputValidationError(error), false);
268
+ });
269
+ it('should return false for non-error objects', () => {
270
+ assert.strictEqual(isInputValidationError({ message: 'fake' }), false);
271
+ assert.strictEqual(isInputValidationError(null), false);
272
+ assert.strictEqual(isInputValidationError(undefined), false);
273
+ assert.strictEqual(isInputValidationError('string'), false);
274
+ });
275
+ });
276
+ describe('constants', () => {
277
+ it('should export expected constant values', () => {
278
+ assert.strictEqual(MAX_LIMIT, 1000);
279
+ assert.strictEqual(MAX_DATE_RANGE_DAYS, 365);
280
+ assert.strictEqual(MAX_REGEX_LENGTH, 200);
281
+ assert.strictEqual(MAX_REGEX_GROUPS, 10);
282
+ assert.strictEqual(DEFAULT_LIMIT, 50);
283
+ assert.strictEqual(MAX_DURATION_MS, 86400000); // 24 hours
284
+ });
285
+ });
286
+ });
287
+ //# sourceMappingURL=input-validator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.test.js","sourceRoot":"","sources":["../../src/lib/input-validator.test.ts"],"names":[],"mappings":"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"}