@memberjunction/global 5.4.0 → 5.5.0

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=UUIDCompliance.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDCompliance.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/UUIDCompliance.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * UUID Compliance Tests
3
+ *
4
+ * These tests scan the MemberJunction source tree for direct UUID comparison
5
+ * patterns (=== / !==) that should use UUIDsEqual() or NormalizeUUID() instead.
6
+ *
7
+ * PostgreSQL returns UUIDs in lowercase while SQL Server returns uppercase.
8
+ * Direct string comparisons break cross-database compatibility.
9
+ *
10
+ * If this test fails, it means new code introduced a direct UUID comparison.
11
+ * Fix by replacing `x.ID === y` with `UUIDsEqual(x.ID, y)`.
12
+ */
13
+ import { describe, it, expect } from 'vitest';
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ /** Directories that should never contain UUID comparison anti-patterns */
17
+ const SCAN_ROOT = path.resolve(__dirname, '..', '..', '..'); // packages/
18
+ /** Patterns that indicate direct UUID comparison (anti-patterns) */
19
+ const ANTI_PATTERNS = [
20
+ /\.ID\s*===\s*(?!['"]|true|false|null|undefined|0\b)/, // .ID === someVar (not string literals or primitives)
21
+ /===\s*\w+\.ID\b/, // something === x.ID
22
+ /\.ID\s*!==\s*(?!['"]|true|false|null|undefined|0\b)/, // .ID !== someVar
23
+ /!==\s*\w+\.ID\b/, // something !== x.ID
24
+ /\.includes\(\w+\.ID\b\)/, // array.includes(x.ID) — uses === internally
25
+ ];
26
+ /** Files/directories to exclude from scanning */
27
+ const EXCLUDE_PATTERNS = [
28
+ /node_modules/,
29
+ /\/dist\//,
30
+ /\/generated\//,
31
+ /\.test\.ts$/,
32
+ /\.spec\.ts$/,
33
+ /__tests__/,
34
+ /UUIDUtils\.ts$/, // The utility itself
35
+ /\.js$/, // Only scan TypeScript source
36
+ /\.d\.ts$/, // Skip declaration files
37
+ /\.map$/, // Skip source maps
38
+ /package-lock\.json$/,
39
+ ];
40
+ /** Known exceptions — files where .ID === is comparing non-UUID values (e.g., numeric IDs, string enum values) */
41
+ const KNOWN_EXCEPTIONS = {
42
+ // Add file paths (relative to packages/) and the reason they're excepted
43
+ // Example: 'SomePackage/src/file.ts': ['Uses numeric IDs, not UUIDs'],
44
+ };
45
+ function shouldScanFile(filePath) {
46
+ if (!filePath.endsWith('.ts'))
47
+ return false;
48
+ return !EXCLUDE_PATTERNS.some(pattern => pattern.test(filePath));
49
+ }
50
+ function findTsFiles(dir) {
51
+ const results = [];
52
+ if (!fs.existsSync(dir))
53
+ return results;
54
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
55
+ for (const entry of entries) {
56
+ const fullPath = path.join(dir, entry.name);
57
+ if (entry.isDirectory()) {
58
+ if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git') {
59
+ continue; // Skip these directories entirely for performance
60
+ }
61
+ results.push(...findTsFiles(fullPath));
62
+ }
63
+ else if (shouldScanFile(fullPath)) {
64
+ results.push(fullPath);
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ function scanFileForViolations(filePath) {
70
+ const violations = [];
71
+ const content = fs.readFileSync(filePath, 'utf-8');
72
+ const lines = content.split('\n');
73
+ // Check if file is in known exceptions
74
+ const relativePath = path.relative(SCAN_ROOT, filePath);
75
+ if (KNOWN_EXCEPTIONS[relativePath]) {
76
+ return [];
77
+ }
78
+ for (let i = 0; i < lines.length; i++) {
79
+ const line = lines[i];
80
+ const trimmed = line.trim();
81
+ // Skip comments
82
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) {
83
+ continue;
84
+ }
85
+ // Skip import lines
86
+ if (trimmed.startsWith('import ')) {
87
+ continue;
88
+ }
89
+ for (const pattern of ANTI_PATTERNS) {
90
+ if (pattern.test(line)) {
91
+ // Additional filter: skip comparisons with empty string '', string literals, null, undefined, or type checks
92
+ if (/\.ID\s*[!=]==?\s*''/.test(line) || /[!=]==?\s*''/.test(line))
93
+ continue; // Comparing to empty string
94
+ if (/\.ID\s*[!=]==?\s*['"]/.test(line))
95
+ continue; // Comparing to any string literal
96
+ if (/[!=]==?\s*['"]/.test(line) && /\.ID\b/.test(line))
97
+ continue; // String literal comparison involving .ID
98
+ if (/typeof\s+\w+\.ID\s*===/.test(line))
99
+ continue; // typeof check
100
+ if (/\.ID\s*===\s*null\b/.test(line) || /\.ID\s*===\s*undefined\b/.test(line))
101
+ continue; // null/undefined check
102
+ if (/\.ID\s*!==\s*null\b/.test(line) || /\.ID\s*!==\s*undefined\b/.test(line))
103
+ continue; // negated null/undefined check
104
+ violations.push({
105
+ file: relativePath,
106
+ line: i + 1,
107
+ content: trimmed.substring(0, 120),
108
+ pattern: pattern.source,
109
+ });
110
+ break; // One violation per line is enough
111
+ }
112
+ }
113
+ }
114
+ return violations;
115
+ }
116
+ describe('UUID Comparison Compliance', () => {
117
+ it('should not have direct UUID comparisons (=== / !==) in source files', () => {
118
+ const tsFiles = findTsFiles(SCAN_ROOT);
119
+ const allViolations = [];
120
+ for (const file of tsFiles) {
121
+ allViolations.push(...scanFileForViolations(file));
122
+ }
123
+ if (allViolations.length > 0) {
124
+ const report = allViolations
125
+ .map(v => ` ${v.file}:${v.line}: ${v.content}`)
126
+ .join('\n');
127
+ expect.fail(`Found ${allViolations.length} direct UUID comparison(s) that should use UUIDsEqual():\n${report}\n\n` +
128
+ `Fix by replacing:\n` +
129
+ ` - 'x.ID === y' with 'UUIDsEqual(x.ID, y)'\n` +
130
+ ` - 'x.ID !== y' with '!UUIDsEqual(x.ID, y)'\n` +
131
+ ` - 'arr.includes(x.ID)' with 'arr.some(id => UUIDsEqual(id, x.ID))'\n` +
132
+ `Import UUIDsEqual from '@memberjunction/global'.\n` +
133
+ `If a comparison is NOT a UUID (e.g., numeric ID), add it to KNOWN_EXCEPTIONS in this test file.`);
134
+ }
135
+ });
136
+ });
137
+ //# sourceMappingURL=UUIDCompliance.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDCompliance.test.js","sourceRoot":"","sources":["../../src/__tests__/UUIDCompliance.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=UUIDUtils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDUtils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/UUIDUtils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { NormalizeUUID, UUIDsEqual } from '../util/UUIDUtils.js';
3
+ describe('NormalizeUUID', () => {
4
+ it('should lowercase an uppercase UUID (SQL Server format)', () => {
5
+ expect(NormalizeUUID('A1B2C3D4-E5F6-7890-ABCD-EF1234567890'))
6
+ .toBe('a1b2c3d4-e5f6-7890-abcd-ef1234567890');
7
+ });
8
+ it('should pass through a lowercase UUID unchanged (PostgreSQL format)', () => {
9
+ expect(NormalizeUUID('a1b2c3d4-e5f6-7890-abcd-ef1234567890'))
10
+ .toBe('a1b2c3d4-e5f6-7890-abcd-ef1234567890');
11
+ });
12
+ it('should handle mixed-case UUIDs', () => {
13
+ expect(NormalizeUUID('A1b2C3d4-E5f6-7890-AbCd-Ef1234567890'))
14
+ .toBe('a1b2c3d4-e5f6-7890-abcd-ef1234567890');
15
+ });
16
+ it('should trim whitespace', () => {
17
+ expect(NormalizeUUID(' A1B2C3D4 ')).toBe('a1b2c3d4');
18
+ });
19
+ it('should return empty string for null', () => {
20
+ expect(NormalizeUUID(null)).toBe('');
21
+ });
22
+ it('should return empty string for undefined', () => {
23
+ expect(NormalizeUUID(undefined)).toBe('');
24
+ });
25
+ it('should return empty string for whitespace-only input', () => {
26
+ expect(NormalizeUUID(' ')).toBe('');
27
+ });
28
+ it('should handle empty string', () => {
29
+ expect(NormalizeUUID('')).toBe('');
30
+ });
31
+ });
32
+ describe('UUIDsEqual', () => {
33
+ const upperUUID = 'A1B2C3D4-E5F6-7890-ABCD-EF1234567890';
34
+ const lowerUUID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
35
+ it('should consider SQL Server (uppercase) and PostgreSQL (lowercase) UUIDs equal', () => {
36
+ expect(UUIDsEqual(upperUUID, lowerUUID)).toBe(true);
37
+ });
38
+ it('should consider identical uppercase UUIDs equal', () => {
39
+ expect(UUIDsEqual(upperUUID, upperUUID)).toBe(true);
40
+ });
41
+ it('should consider identical lowercase UUIDs equal', () => {
42
+ expect(UUIDsEqual(lowerUUID, lowerUUID)).toBe(true);
43
+ });
44
+ it('should return false for different UUIDs', () => {
45
+ expect(UUIDsEqual('A1B2C3D4-0000-0000-0000-000000000000', 'A1B2C3D4-0000-0000-0000-000000000001')).toBe(false);
46
+ });
47
+ it('should consider two nulls equal', () => {
48
+ expect(UUIDsEqual(null, null)).toBe(true);
49
+ });
50
+ it('should consider two undefineds equal', () => {
51
+ expect(UUIDsEqual(undefined, undefined)).toBe(true);
52
+ });
53
+ it('should consider null and undefined equal', () => {
54
+ expect(UUIDsEqual(null, undefined)).toBe(true);
55
+ });
56
+ it('should return false for null vs non-null', () => {
57
+ expect(UUIDsEqual(null, lowerUUID)).toBe(false);
58
+ });
59
+ it('should return false for non-null vs null', () => {
60
+ expect(UUIDsEqual(upperUUID, null)).toBe(false);
61
+ });
62
+ it('should return false for undefined vs non-undefined', () => {
63
+ expect(UUIDsEqual(undefined, lowerUUID)).toBe(false);
64
+ });
65
+ it('should handle UUIDs with surrounding whitespace', () => {
66
+ expect(UUIDsEqual(' ' + upperUUID + ' ', lowerUUID)).toBe(true);
67
+ });
68
+ it('should handle mixed-case comparison', () => {
69
+ expect(UUIDsEqual('AbCd1234', 'aBcD1234')).toBe(true);
70
+ });
71
+ it('should handle empty strings as equal', () => {
72
+ expect(UUIDsEqual('', '')).toBe(true);
73
+ });
74
+ });
75
+ //# sourceMappingURL=UUIDUtils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDUtils.test.js","sourceRoot":"","sources":["../../src/__tests__/UUIDUtils.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './BaseSingleton.js';
6
6
  export * from './DeepDiff.js';
7
7
  export * from './ClassUtils.js';
8
8
  export * from './util/PatternUtils.js';
9
+ export * from './util/UUIDUtils.js';
9
10
  export * from './ValidationTypes.js';
10
11
  export * from './JSONValidator.js';
11
12
  export * from './SafeExpressionEvaluator.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAChE,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AAMjC,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAChE,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AAMjC,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA"}
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ export * from './BaseSingleton.js';
7
7
  export * from './DeepDiff.js';
8
8
  export * from './ClassUtils.js';
9
9
  export * from './util/PatternUtils.js';
10
+ export * from './util/UUIDUtils.js';
10
11
  export * from './ValidationTypes.js';
11
12
  export * from './JSONValidator.js';
12
13
  export * from './SafeExpressionEvaluator.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAChE,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AAEjC,2DAA2D;AAC3D,oCAAoC;AAEpC,0BAA0B;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AAEtC,6DAA6D;AAC7D,oCAAoC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAChE,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AAEjC,2DAA2D;AAC3D,oCAAoC;AAEpC,0BAA0B;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AAEtC,6DAA6D;AAC7D,oCAAoC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @fileoverview UUID comparison utility functions for MemberJunction
3
+ *
4
+ * Provides case-insensitive UUID comparison to handle the difference between
5
+ * SQL Server (returns UUIDs in UPPERCASE) and PostgreSQL (returns UUIDs in lowercase).
6
+ * These utilities ensure consistent UUID handling across all database platforms.
7
+ *
8
+ * @module @memberjunction/global/UUIDUtils
9
+ */
10
+ /**
11
+ * Normalizes a UUID string for consistent comparison by trimming whitespace
12
+ * and converting to lowercase. Returns an empty string for null/undefined input.
13
+ *
14
+ * @param uuid - The UUID string to normalize
15
+ * @returns The normalized (lowercased, trimmed) UUID string, or empty string if input is nullish
16
+ *
17
+ * @example
18
+ * NormalizeUUID('A1B2C3D4-E5F6-7890-ABCD-EF1234567890')
19
+ * // Returns: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
20
+ *
21
+ * NormalizeUUID(null) // Returns: ''
22
+ * NormalizeUUID(' A1B2C3D4 ') // Returns: 'a1b2c3d4'
23
+ */
24
+ export declare function NormalizeUUID(uuid: string | null | undefined): string;
25
+ /**
26
+ * Performs a case-insensitive comparison of two UUID strings.
27
+ * Handles null/undefined gracefully — two nullish values are considered equal,
28
+ * but a nullish value is never equal to a non-nullish value.
29
+ *
30
+ * @param uuid1 - First UUID to compare
31
+ * @param uuid2 - Second UUID to compare
32
+ * @returns true if the UUIDs are equal (case-insensitive), false otherwise
33
+ *
34
+ * @example
35
+ * // Cross-platform comparison (SQL Server uppercase vs PostgreSQL lowercase)
36
+ * UUIDsEqual('A1B2C3D4-E5F6-7890-ABCD-EF1234567890',
37
+ * 'a1b2c3d4-e5f6-7890-abcd-ef1234567890') // true
38
+ *
39
+ * UUIDsEqual(null, null) // true
40
+ * UUIDsEqual(null, 'some-id') // false
41
+ * UUIDsEqual('abc', 'ABC') // true
42
+ */
43
+ export declare function UUIDsEqual(uuid1: string | null | undefined, uuid2: string | null | undefined): boolean;
44
+ //# sourceMappingURL=UUIDUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDUtils.d.ts","sourceRoot":"","sources":["../../src/util/UUIDUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGrE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAItG"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @fileoverview UUID comparison utility functions for MemberJunction
3
+ *
4
+ * Provides case-insensitive UUID comparison to handle the difference between
5
+ * SQL Server (returns UUIDs in UPPERCASE) and PostgreSQL (returns UUIDs in lowercase).
6
+ * These utilities ensure consistent UUID handling across all database platforms.
7
+ *
8
+ * @module @memberjunction/global/UUIDUtils
9
+ */
10
+ /**
11
+ * Normalizes a UUID string for consistent comparison by trimming whitespace
12
+ * and converting to lowercase. Returns an empty string for null/undefined input.
13
+ *
14
+ * @param uuid - The UUID string to normalize
15
+ * @returns The normalized (lowercased, trimmed) UUID string, or empty string if input is nullish
16
+ *
17
+ * @example
18
+ * NormalizeUUID('A1B2C3D4-E5F6-7890-ABCD-EF1234567890')
19
+ * // Returns: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
20
+ *
21
+ * NormalizeUUID(null) // Returns: ''
22
+ * NormalizeUUID(' A1B2C3D4 ') // Returns: 'a1b2c3d4'
23
+ */
24
+ export function NormalizeUUID(uuid) {
25
+ if (uuid == null)
26
+ return '';
27
+ return uuid.trim().toLowerCase();
28
+ }
29
+ /**
30
+ * Performs a case-insensitive comparison of two UUID strings.
31
+ * Handles null/undefined gracefully — two nullish values are considered equal,
32
+ * but a nullish value is never equal to a non-nullish value.
33
+ *
34
+ * @param uuid1 - First UUID to compare
35
+ * @param uuid2 - Second UUID to compare
36
+ * @returns true if the UUIDs are equal (case-insensitive), false otherwise
37
+ *
38
+ * @example
39
+ * // Cross-platform comparison (SQL Server uppercase vs PostgreSQL lowercase)
40
+ * UUIDsEqual('A1B2C3D4-E5F6-7890-ABCD-EF1234567890',
41
+ * 'a1b2c3d4-e5f6-7890-abcd-ef1234567890') // true
42
+ *
43
+ * UUIDsEqual(null, null) // true
44
+ * UUIDsEqual(null, 'some-id') // false
45
+ * UUIDsEqual('abc', 'ABC') // true
46
+ */
47
+ export function UUIDsEqual(uuid1, uuid2) {
48
+ if (uuid1 == null && uuid2 == null)
49
+ return true;
50
+ if (uuid1 == null || uuid2 == null)
51
+ return false;
52
+ return uuid1.trim().toLowerCase() === uuid2.trim().toLowerCase();
53
+ }
54
+ //# sourceMappingURL=UUIDUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDUtils.js","sourceRoot":"","sources":["../../src/util/UUIDUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,IAA+B;IACzD,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAgC,EAAE,KAAgC;IACzF,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACjD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACrE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/global",
3
3
  "type": "module",
4
- "version": "5.4.0",
4
+ "version": "5.5.0",
5
5
  "description": "MemberJunction: Global Object - Needed for ALL other MJ components",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",