opticedge-cloud-utils 1.1.3 → 1.1.4

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/dist/regex.d.ts CHANGED
@@ -1 +1,12 @@
1
- export declare function escapeForRegex(input: string): string;
1
+ /**
2
+ * Escape user input so it can be safely used as a regex pattern string.
3
+ *
4
+ * - Escapes regex metacharacters.
5
+ * - Replaces any run of whitespace with the token `\s+` so searches tolerate variable whitespace.
6
+ * - Caps input length to avoid pathological long-input ReDoS vectors (default cap = 100).
7
+ *
8
+ * @param input - user-provided string to escape
9
+ * @param maxLength - maximum number of characters to consider from input (default 100)
10
+ * @returns a safe regex pattern string (do NOT wrap with // when passing to Mongo $regex)
11
+ */
12
+ export declare function escapeForRegex(input: string, maxLength?: number): string;
package/dist/regex.js CHANGED
@@ -1,6 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.escapeForRegex = escapeForRegex;
4
- function escapeForRegex(input) {
5
- return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
4
+ /**
5
+ * Escape user input so it can be safely used as a regex pattern string.
6
+ *
7
+ * - Escapes regex metacharacters.
8
+ * - Replaces any run of whitespace with the token `\s+` so searches tolerate variable whitespace.
9
+ * - Caps input length to avoid pathological long-input ReDoS vectors (default cap = 100).
10
+ *
11
+ * @param input - user-provided string to escape
12
+ * @param maxLength - maximum number of characters to consider from input (default 100)
13
+ * @returns a safe regex pattern string (do NOT wrap with // when passing to Mongo $regex)
14
+ */
15
+ function escapeForRegex(input, maxLength = 100) {
16
+ const safeStr = String(input ?? '');
17
+ const capped = safeStr.length > maxLength ? safeStr.slice(0, maxLength) : safeStr;
18
+ // escape regex metacharacters: . * + ? ^ $ { } ( ) | [ ] \ /
19
+ const escaped = capped.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
20
+ // convert any whitespace run to the regex token \s+ (as a string)
21
+ return escaped.replace(/\s+/g, '\\s+');
6
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opticedge-cloud-utils",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Common utilities for cloud functions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/regex.ts CHANGED
@@ -1,3 +1,19 @@
1
- export function escapeForRegex(input: string): string {
2
- return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
1
+ /**
2
+ * Escape user input so it can be safely used as a regex pattern string.
3
+ *
4
+ * - Escapes regex metacharacters.
5
+ * - Replaces any run of whitespace with the token `\s+` so searches tolerate variable whitespace.
6
+ * - Caps input length to avoid pathological long-input ReDoS vectors (default cap = 100).
7
+ *
8
+ * @param input - user-provided string to escape
9
+ * @param maxLength - maximum number of characters to consider from input (default 100)
10
+ * @returns a safe regex pattern string (do NOT wrap with // when passing to Mongo $regex)
11
+ */
12
+ export function escapeForRegex(input: string, maxLength = 100): string {
13
+ const safeStr = String(input ?? '')
14
+ const capped = safeStr.length > maxLength ? safeStr.slice(0, maxLength) : safeStr
15
+ // escape regex metacharacters: . * + ? ^ $ { } ( ) | [ ] \ /
16
+ const escaped = capped.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
17
+ // convert any whitespace run to the regex token \s+ (as a string)
18
+ return escaped.replace(/\s+/g, '\\s+')
3
19
  }
@@ -1,24 +1,69 @@
1
+ // tests/regex.test.ts
1
2
  import { escapeForRegex } from '../src/regex'
2
3
 
3
- describe('escapeRegex', () => {
4
- it('escapes regex special characters', () => {
4
+ describe('escapeForRegex', () => {
5
+ it('escapes regex special characters (including backslash)', () => {
5
6
  const input = 'Pikachu.$^*+?()[]{}|\\'
6
7
  const expected = 'Pikachu\\.\\$\\^\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\'
7
8
  expect(escapeForRegex(input)).toBe(expected)
8
9
  })
9
10
 
10
- it('returns same string if no special characters', () => {
11
+ it('replaces whitespace runs with \\s+ and escapes other metachars', () => {
12
+ const input = 'Charizard (Holo Rare)' // multiple spaces inside
13
+ const expected = 'Charizard\\s+\\(Holo\\s+Rare\\)'
14
+ expect(escapeForRegex(input)).toBe(expected)
15
+ })
16
+
17
+ it('leaves plain alphanumerics unchanged', () => {
11
18
  const input = 'Charmander123'
12
19
  expect(escapeForRegex(input)).toBe('Charmander123')
13
20
  })
14
21
 
15
- it('works with empty string', () => {
22
+ it('converts tabs and single spaces to \\s+ and escapes dots', () => {
23
+ const input = 'Lt. Surge\tPikachu'
24
+ const expected = 'Lt\\.\\s+Surge\\s+Pikachu'
25
+ expect(escapeForRegex(input)).toBe(expected)
26
+ })
27
+
28
+ it('truncates input when maxLength is passed', () => {
29
+ const long = 'a'.repeat(200)
30
+ // override maxLength to 50 for this test
31
+ expect(escapeForRegex(long, 50)).toBe('a'.repeat(50))
32
+ })
33
+
34
+ it('applies default cap of 100 characters when input is longer and contains no metachars', () => {
35
+ const long = 'b'.repeat(150)
36
+ const out = escapeForRegex(long) // default cap = 100
37
+ expect(out).toBe('b'.repeat(100))
38
+ expect(out.length).toBe(100)
39
+ })
40
+
41
+ it('handles empty string', () => {
16
42
  expect(escapeForRegex('')).toBe('')
17
43
  })
18
44
 
19
- it('does not escape regular alphanumerics or spaces', () => {
20
- const input = 'Lt. Surge Pikachu'
21
- const expected = 'Lt\\. Surge Pikachu'
22
- expect(escapeForRegex(input)).toBe(expected)
45
+ // -----------------------------
46
+ // NEW: coverage for safeStr branch
47
+ // -----------------------------
48
+ it('handles undefined input (covers input ?? "")', () => {
49
+ // call with undefined; TypeScript may complain so cast to any in test
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ expect(escapeForRegex(undefined as any)).toBe('')
52
+ })
53
+
54
+ it('handles null input (covers input ?? "")', () => {
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ expect(escapeForRegex(null as any)).toBe('')
57
+ })
58
+
59
+ it('coerces non-string input to string and escapes metachars if present', () => {
60
+ // number becomes "42"
61
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+ expect(escapeForRegex(42 as any)).toBe('42')
63
+
64
+ // object coerces to "[object Object]" and special chars will be escaped if present
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ const objInput = { toString: () => 'X(1) Y' } as any
67
+ expect(escapeForRegex(objInput)).toBe('X\\(1\\)\\s+Y')
23
68
  })
24
69
  })