@jarenjs/core 0.72.0 → 0.72.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.
package/ARCHITECTURE.md CHANGED
@@ -445,6 +445,7 @@ flowchart TB
445
445
  RegExpUtils --> IsRegExp["isRegExpType()"]
446
446
  RegExpUtils --> IsStringRegExp["isStringRegExp()<br/>(tests if valid pattern)"]
447
447
  RegExpUtils --> CreateRegExp["createRegExp()<br/>(handles /pattern/flags syntax)"]
448
+ RegExpUtils --> TestRegExp["createRegExpTester()<br/>(repeatable, isolated global/sticky state)"]
448
449
 
449
450
  Unicode["Unicode Support"]
450
451
  Unicode --> Ascii["isAsciiString()"]
package/README.md CHANGED
@@ -11,7 +11,7 @@ None of it depends on JSON Schema: every module can be used standalone in any Ja
11
11
  | `@jarenjs/core` | type guards and getters (`isStringType`, `isObjectClass`, `getIntegerType`, ...) |
12
12
  | `@jarenjs/core/array` | array helpers (`isUniqueArray`, `getUniqueArray`, `includesAll`, ...) |
13
13
  | `@jarenjs/core/object` | deep equality (`equalsDeep`, JSON-only `equalsJson`), the `isJsonObject` and deep `isJsonValue` predicates, `__proto__`-safe `setObjectMember`, `deepFreeze`, map/set merging |
14
- | `@jarenjs/core/string` | Unicode string helpers (`countCodePoints`, `compareCodePoints`, ...), cached regex compilation, the suite's one content hash (`fnv1a` and the `hashContent` fingerprint over it) and `kebabCase` |
14
+ | `@jarenjs/core/string` | Unicode string helpers (`countCodePoints`, `compareCodePoints`, ...), regex compilation and repeatable `createRegExpTester` predicates, the suite's one content hash (`fnv1a` and the `hashContent` fingerprint over it) and `kebabCase` |
15
15
  | `@jarenjs/core/cache` | the bounded LRU (`createBoundedCache`), the reference-keyed `createWeakCache`, and `createSemanticCache` — keyed by what a value IS, for caches whose entries decide a result |
16
16
  | `@jarenjs/core/random` | the suite's one seeded generator (`mulberry32`, pinned sequence, ToUint32 seed) and the draws built on it: `randomInt` over a half-open range, in-place Fisher–Yates `shuffle`, and `drawDistinct` — `k` distinct indices from one stream |
17
17
  | `@jarenjs/core/runtime` | the runtime record — `createRuntime({ now, uuid, random, zoneProvider })`, frozen, defaulting member for member to the platform's own (`Date.now`, `crypto.randomUUID`, `Math.random`, no zone provider) — that the store (its query deadlines included), the jobs engine, the migration runner, every contract binding and the contract memory ledger take as `runtime`, so a deterministic run is configured once; a subsystem's own explicit option wins over the record, and the record reaches hosts, never query compilation |
@@ -41,14 +41,16 @@ Deep imports work too (`@jarenjs/core/text/email`, `@jarenjs/core/math/vec2f64`,
41
41
  `@jarenjs/core/string` counts string length the way JSON Schema expects — by grapheme cluster, not UTF-16 code units — without paying for `Intl.Segmenter` unless the string actually needs it:
42
42
 
43
43
  ```javascript
44
- import { getStringLength, isAsciiString, createRegExp } from '@jarenjs/core/string';
44
+ import { getStringLength, isAsciiString, createRegExp, createRegExpTester } from '@jarenjs/core/string';
45
45
 
46
46
  getStringLength('hello', true); // 5 (ASCII fast path: str.length)
47
47
  getStringLength('héllo', true); // 5 (surrogate-aware code point count)
48
48
  getStringLength('👨‍👩‍👧‍👦', true); // 1 (grapheme segmentation, only when clusters can form)
49
49
  getStringLength('👨‍👩‍👧‍👦'); // 11 (default: plain UTF-16 length)
50
50
 
51
- createRegExp('^\\p{L}+$'); // cached, unicode-flagged RegExp
51
+ createRegExp('^\\p{L}+$'); // unicode-flagged RegExp
52
+ const matches = createRegExpTester('/^x/gi');
53
+ matches('X'); matches('X'); // true both times; global/sticky state is isolated
52
54
  ```
53
55
 
54
56
  ## Text validation
@@ -88,7 +90,7 @@ orient2d(0, 0, 1, 0, 0, 1); // > 0 — counter-clockwise, exa
88
90
  haversineDistance(4.9041, 52.3676, 2.3522, 48.8566); // 429_862 m (Amsterdam–Paris)
89
91
  ringWinding([[0,0],[1,0],[1,1],[0,1],[0,0]]); // 1 — an RFC 7946 exterior ring
90
92
  bboxOf({ type: 'Polygon', coordinates: [[[4,52],[5,52],[5,53],[4,52]]] }); // [4, 52, 5, 53]
91
- geohashEncode(4.9041, 52.3676, 5); // 'u173z' — a string, so a prefix test is proximity
93
+ geohashEncode(4.9041, 52.3676, 5); // 'u173z' — a string identifying a cell; use distances for proximity
92
94
 
93
95
  wktToGeoJson('POINT (4.9041 52.3676)'); // { type: 'Point', coordinates: [4.9041, 52.3676] }
94
96
  geoJsonToWkt({ type: 'Point', coordinates: [4.9041, 52.3676] }); // 'POINT (4.9041 52.3676)'
@@ -33,6 +33,13 @@ export declare function isStringRegExp(data: string | RegExp | null | undefined)
33
33
  * @returns {RegExp | undefined}
34
34
  */
35
35
  export declare function createRegExp(pattern: string | RegExp | null | undefined): RegExp | undefined;
36
+ /**
37
+ * Compile a pattern into a repeatable predicate. Global and sticky patterns
38
+ * start at index zero on every call and never change a caller's RegExp state.
39
+ * @param {string | RegExp | null | undefined} pattern - The regular expression
40
+ * @returns {((value: string) => boolean) | undefined} The tester, or undefined when no pattern was supplied
41
+ */
42
+ export declare function createRegExpTester(pattern: string | RegExp | null | undefined): ((value: string) => boolean) | undefined;
36
43
  export declare function getSegmenter(): Intl.Segmenter;
37
44
  /**
38
45
  * @param {string} str
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/core",
3
3
  "private": false,
4
- "version": "0.72.0",
4
+ "version": "0.72.2",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./dist/types/index.d.ts",
package/src/string.js CHANGED
@@ -88,6 +88,24 @@ export function createRegExp(pattern) {
88
88
  throw new Error(`Unknown Regular Expression Pattern Type: ${pattern}`);
89
89
  }
90
90
 
91
+ /**
92
+ * Compile a pattern into a repeatable predicate. Global and sticky patterns
93
+ * start at index zero on every call and never change a caller's RegExp state.
94
+ * @param {string | RegExp | null | undefined} pattern - The regular expression
95
+ * @returns {((value: string) => boolean) | undefined} The tester, or undefined when no pattern was supplied
96
+ */
97
+ export function createRegExpTester(pattern) {
98
+ const parsed = createRegExp(pattern);
99
+ if (parsed === undefined) return undefined;
100
+ if (!parsed.global && !parsed.sticky)
101
+ return (value) => parsed.test(value);
102
+ const owned = new RegExp(parsed.source, parsed.flags);
103
+ return (value) => {
104
+ owned.lastIndex = 0;
105
+ return owned.test(value);
106
+ };
107
+ }
108
+
91
109
  /**
92
110
  * @type {Intl.Segmenter | null}
93
111
  */