@memberjunction/global 3.4.0 → 4.1.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.
Files changed (51) hide show
  1. package/README.md +634 -0
  2. package/dist/BaseSingleton.d.ts +2 -2
  3. package/dist/BaseSingleton.d.ts.map +1 -1
  4. package/dist/BaseSingleton.js +9 -13
  5. package/dist/BaseSingleton.js.map +1 -1
  6. package/dist/ClassFactory.d.ts +6 -6
  7. package/dist/ClassFactory.d.ts.map +1 -1
  8. package/dist/ClassFactory.js +31 -21
  9. package/dist/ClassFactory.js.map +1 -1
  10. package/dist/ClassUtils.js +9 -21
  11. package/dist/ClassUtils.js.map +1 -1
  12. package/dist/DeepDiff.js +4 -31
  13. package/dist/DeepDiff.js.map +1 -1
  14. package/dist/EncryptionUtils.js +6 -11
  15. package/dist/EncryptionUtils.js.map +1 -1
  16. package/dist/Global.d.ts +4 -4
  17. package/dist/Global.js +11 -15
  18. package/dist/Global.js.map +1 -1
  19. package/dist/JSONValidator.d.ts +1 -1
  20. package/dist/JSONValidator.d.ts.map +1 -1
  21. package/dist/JSONValidator.js +12 -15
  22. package/dist/JSONValidator.js.map +1 -1
  23. package/dist/ObjectCache.js +2 -7
  24. package/dist/ObjectCache.js.map +1 -1
  25. package/dist/RegisterClass.d.ts +1 -1
  26. package/dist/RegisterClass.d.ts.map +1 -1
  27. package/dist/RegisterClass.js +3 -7
  28. package/dist/RegisterClass.js.map +1 -1
  29. package/dist/SQLExpressionValidator.js +9 -13
  30. package/dist/SQLExpressionValidator.js.map +1 -1
  31. package/dist/SafeExpressionEvaluator.js +60 -64
  32. package/dist/SafeExpressionEvaluator.js.map +1 -1
  33. package/dist/ValidationTypes.js +4 -9
  34. package/dist/ValidationTypes.js.map +1 -1
  35. package/dist/index.d.ts +16 -16
  36. package/dist/index.js +16 -35
  37. package/dist/index.js.map +1 -1
  38. package/dist/interface.d.ts +2 -2
  39. package/dist/interface.d.ts.map +1 -1
  40. package/dist/interface.js +3 -8
  41. package/dist/interface.js.map +1 -1
  42. package/dist/util/PatternUtils.js +6 -15
  43. package/dist/util/PatternUtils.js.map +1 -1
  44. package/dist/util.d.ts +13 -5
  45. package/dist/util.d.ts.map +1 -1
  46. package/dist/util.js +36 -75
  47. package/dist/util.js.map +1 -1
  48. package/dist/warningManager.js +2 -6
  49. package/dist/warningManager.js.map +1 -1
  50. package/package.json +7 -6
  51. package/readme.md +0 -1168
package/README.md ADDED
@@ -0,0 +1,634 @@
1
+ # @memberjunction/global
2
+
3
+ The foundational package for the entire MemberJunction ecosystem. `@memberjunction/global` provides the core infrastructure that every other MJ package depends on: a singleton coordination hub, a dynamic class factory with decorator-based registration, cross-environment global state management, and a collection of essential utilities for validation, diffing, caching, pattern matching, and more.
4
+
5
+ This package has **zero MJ dependencies** and sits at the very bottom of the dependency graph, making it safe to import from anywhere in the stack without circular dependency concerns.
6
+
7
+ ## Architecture Overview
8
+
9
+ ```mermaid
10
+ graph TD
11
+ subgraph MJGlobal["@memberjunction/global"]
12
+ direction TB
13
+ MJG["MJGlobal (Singleton Hub)"]
14
+ CF["ClassFactory"]
15
+ RC["@RegisterClass Decorator"]
16
+ OC["ObjectCache"]
17
+ BS["BaseSingleton<T>"]
18
+ EV["Event System (RxJS)"]
19
+
20
+ MJG --> CF
21
+ MJG --> OC
22
+ MJG --> EV
23
+ RC --> CF
24
+ MJG -.->|extends| BS
25
+ end
26
+
27
+ subgraph Utilities["Utility Modules"]
28
+ direction TB
29
+ DD["DeepDiffer"]
30
+ JV["JSONValidator"]
31
+ SE["SafeExpressionEvaluator"]
32
+ SQ["SQLExpressionValidator"]
33
+ CU["ClassUtils"]
34
+ PU["PatternUtils"]
35
+ WM["WarningManager"]
36
+ EU["EncryptionUtils"]
37
+ UT["String / JSON Utilities"]
38
+ end
39
+
40
+ Core["@memberjunction/core"] --> MJGlobal
41
+ Entities["@memberjunction/core-entities"] --> MJGlobal
42
+ Server["@memberjunction/server"] --> MJGlobal
43
+ Angular["Angular packages"] --> MJGlobal
44
+
45
+ style MJGlobal fill:#2d6a9f,stroke:#1a4971,color:#fff
46
+ style Utilities fill:#7c5295,stroke:#563a6b,color:#fff
47
+ style Core fill:#2d8659,stroke:#1a5c3a,color:#fff
48
+ style Entities fill:#2d8659,stroke:#1a5c3a,color:#fff
49
+ style Server fill:#2d8659,stroke:#1a5c3a,color:#fff
50
+ style Angular fill:#2d8659,stroke:#1a5c3a,color:#fff
51
+ ```
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ npm install @memberjunction/global
57
+ ```
58
+
59
+ ## Core Concepts
60
+
61
+ ### MJGlobal -- The Singleton Hub
62
+
63
+ `MJGlobal` is the central coordination point for the MemberJunction runtime. It is a singleton (via `BaseSingleton<T>`) that provides access to the class factory, a global event bus, a property bag, and an in-memory object cache.
64
+
65
+ ```mermaid
66
+ classDiagram
67
+ class MJGlobal {
68
+ +Instance : MJGlobal$
69
+ +ClassFactory : ClassFactory
70
+ +ObjectCache : ObjectCache
71
+ +Properties : MJGlobalProperty[]
72
+ +RegisterComponent(component)
73
+ +RaiseEvent(event)
74
+ +GetEventListener(withReplay?) : Observable~MJEvent~
75
+ +Reset()
76
+ }
77
+ class ClassFactory {
78
+ +Register(baseClass, subClass, key?, priority?)
79
+ +CreateInstance~T~(baseClass, key?, ...params) : T
80
+ +GetRegistration(baseClass, key?) : ClassRegistration
81
+ +GetAllRegistrations(baseClass, key?) : ClassRegistration[]
82
+ +GetRegistrationsByRootClass(rootClass, key?) : ClassRegistration[]
83
+ }
84
+ class ObjectCache {
85
+ +Add~T~(key, object)
86
+ +Find~T~(key) : T
87
+ +Replace~T~(key, object)
88
+ +Remove(key)
89
+ +Clear()
90
+ }
91
+ MJGlobal --> ClassFactory
92
+ MJGlobal --> ObjectCache
93
+
94
+ style MJGlobal fill:#2d6a9f,stroke:#1a4971,color:#fff
95
+ style ClassFactory fill:#2d8659,stroke:#1a5c3a,color:#fff
96
+ style ObjectCache fill:#b8762f,stroke:#8a5722,color:#fff
97
+ ```
98
+
99
+ ```typescript
100
+ import { MJGlobal } from '@memberjunction/global';
101
+
102
+ // Access the singleton
103
+ const g = MJGlobal.Instance;
104
+
105
+ // Use the class factory
106
+ const instance = g.ClassFactory.CreateInstance<MyBase>(MyBase, 'some-key');
107
+
108
+ // Use the object cache
109
+ g.ObjectCache.Add('config', { debug: true });
110
+ const config = g.ObjectCache.Find<{ debug: boolean }>('config');
111
+
112
+ // Use the global property bag
113
+ g.Properties.push({ key: 'appName', value: 'MyApp' });
114
+ ```
115
+
116
+ ### Class Factory and @RegisterClass
117
+
118
+ The class factory is MemberJunction's dependency injection system. It allows any module to register a subclass for a given base class and key, so that later code can request an instance by base class and key and automatically receive the most specific (highest-priority) subclass.
119
+
120
+ ```mermaid
121
+ flowchart LR
122
+ A["@RegisterClass(BaseEntity, 'Users')"] -->|registers| CF["ClassFactory"]
123
+ B["@RegisterClass(BaseEntity, 'Users', 10)"] -->|higher priority| CF
124
+ CF -->|"CreateInstance(BaseEntity, 'Users')"| B
125
+ CF -->|returns instance of| SUB["UserEntity (priority 10)"]
126
+
127
+ style A fill:#64748b,stroke:#475569,color:#fff
128
+ style B fill:#2d8659,stroke:#1a5c3a,color:#fff
129
+ style CF fill:#2d6a9f,stroke:#1a4971,color:#fff
130
+ style SUB fill:#b8762f,stroke:#8a5722,color:#fff
131
+ ```
132
+
133
+ **Decorator usage:**
134
+
135
+ ```typescript
136
+ import { RegisterClass } from '@memberjunction/global';
137
+
138
+ // Register a subclass for a base class with a key
139
+ @RegisterClass(BaseFormComponent, 'Users')
140
+ export class UserFormComponent extends BaseFormComponent {
141
+ // ...
142
+ }
143
+
144
+ // Priority controls which registration wins
145
+ @RegisterClass(BaseFormComponent, 'Users', 10)
146
+ export class CustomUserFormComponent extends UserFormComponent {
147
+ // Wins over UserFormComponent because priority 10 > auto-assigned
148
+ }
149
+ ```
150
+
151
+ **Programmatic registration:**
152
+
153
+ ```typescript
154
+ MJGlobal.Instance.ClassFactory.Register(
155
+ BaseEntity, // base class
156
+ UserEntity, // subclass
157
+ 'Users', // key
158
+ 5 // priority (optional)
159
+ );
160
+ ```
161
+
162
+ **Instance creation:**
163
+
164
+ ```typescript
165
+ const entity = MJGlobal.Instance.ClassFactory.CreateInstance<BaseEntity>(
166
+ BaseEntity,
167
+ 'Users'
168
+ );
169
+ // Returns an instance of the highest-priority registered subclass for 'Users'
170
+ ```
171
+
172
+ ### Event System
173
+
174
+ MJGlobal provides a publish/subscribe event bus built on RxJS. Events can be observed in real-time or with replay (a `ReplaySubject` buffering up to 100 events for 30 seconds).
175
+
176
+ ```typescript
177
+ import { MJGlobal, MJEventType } from '@memberjunction/global';
178
+
179
+ // Subscribe to events (with replay for late subscribers)
180
+ MJGlobal.Instance.GetEventListener(true).subscribe(event => {
181
+ if (event.event === MJEventType.LoggedIn) {
182
+ console.log('User logged in:', event.args);
183
+ }
184
+ });
185
+
186
+ // Raise an event
187
+ MJGlobal.Instance.RaiseEvent({
188
+ event: MJEventType.ComponentEvent,
189
+ eventCode: 'data-loaded',
190
+ args: { recordCount: 42 },
191
+ component: myComponent
192
+ });
193
+ ```
194
+
195
+ **Built-in event types:**
196
+
197
+ | Event Type | Description |
198
+ |---|---|
199
+ | `ComponentRegistered` | A component was registered with MJGlobal |
200
+ | `ComponentUnregistered` | A component was unregistered |
201
+ | `ComponentEvent` | Generic component-level event |
202
+ | `LoggedIn` | User authentication succeeded |
203
+ | `LoggedOut` | User logged out |
204
+ | `LoginFailed` | Authentication attempt failed |
205
+ | `LogoutFailed` | Logout attempt failed |
206
+ | `ManualResizeRequest` | Request for UI components to recalculate layout |
207
+ | `DisplaySimpleNotificationRequest` | Request to show a notification to the user |
208
+
209
+ ### BaseSingleton\<T\>
210
+
211
+ A generic abstract base class for implementing the singleton pattern. It uses the global object store (`window` in browsers, `global` in Node.js) to guarantee a single instance even when module code is duplicated across multiple bundle paths.
212
+
213
+ ```typescript
214
+ import { BaseSingleton } from '@memberjunction/global';
215
+
216
+ export class MyService extends BaseSingleton<MyService> {
217
+ public static get Instance(): MyService {
218
+ return super.getInstance<MyService>();
219
+ }
220
+
221
+ public DoWork(): void {
222
+ // service logic
223
+ }
224
+ }
225
+
226
+ // Usage
227
+ MyService.Instance.DoWork();
228
+ ```
229
+
230
+ ## Utility Modules
231
+
232
+ ### DeepDiffer -- Object Comparison
233
+
234
+ Recursively compares two objects and produces a detailed, human-readable diff with change tracking.
235
+
236
+ ```typescript
237
+ import { DeepDiffer, DiffChangeType } from '@memberjunction/global';
238
+
239
+ const differ = new DeepDiffer({
240
+ maxDepth: 10,
241
+ treatNullAsUndefined: true,
242
+ includeUnchanged: false
243
+ });
244
+
245
+ const result = differ.diff(
246
+ { name: 'Alice', age: 30, tags: ['dev'] },
247
+ { name: 'Alice', age: 31, tags: ['dev', 'lead'] }
248
+ );
249
+
250
+ console.log(result.summary);
251
+ // { added: 1, removed: 0, modified: 2, unchanged: 0, totalPaths: 3 }
252
+
253
+ console.log(result.formatted);
254
+ // === Deep Diff Summary ===
255
+ // Total changes: 3
256
+ // Added: 1
257
+ // Modified: 2
258
+ // ...
259
+ ```
260
+
261
+ ### JSONValidator -- Template-Based Validation
262
+
263
+ A lightweight validator that checks objects against example templates using special field-name syntax for validation rules.
264
+
265
+ ```typescript
266
+ import { JSONValidator } from '@memberjunction/global';
267
+
268
+ const validator = new JSONValidator();
269
+
270
+ const template = {
271
+ "name": "example", // required
272
+ "email?": "user@example.com", // optional (? suffix)
273
+ "config*": {}, // required, any content (* suffix)
274
+ "tags:[1+]": ["tag1"], // array with 1+ items
275
+ "count:number": 0, // must be a number
276
+ "title:string:!empty": "" // must be a non-empty string
277
+ };
278
+
279
+ const result = validator.validate(myData, template);
280
+ if (!result.Success) {
281
+ console.log(result.Errors);
282
+ }
283
+ ```
284
+
285
+ **Supported validation rules:**
286
+
287
+ | Syntax | Meaning |
288
+ |---|---|
289
+ | `field?` | Field is optional |
290
+ | `field*` | Required, accepts any content |
291
+ | `field:string` | Must be a string |
292
+ | `field:number` | Must be a number |
293
+ | `field:boolean` | Must be a boolean |
294
+ | `field:object` | Must be a plain object |
295
+ | `field:array` | Must be an array |
296
+ | `field:!empty` | Must not be empty |
297
+ | `field:[N+]` | Array with at least N elements |
298
+ | `field:[N-M]` | Array with N to M elements |
299
+ | `field:[=N]` | Array with exactly N elements |
300
+
301
+ ### SafeExpressionEvaluator
302
+
303
+ Evaluates boolean expressions against context objects securely, blocking injection patterns like `eval()`, `require()`, `process.`, template literals, and more.
304
+
305
+ ```typescript
306
+ import { SafeExpressionEvaluator } from '@memberjunction/global';
307
+
308
+ const evaluator = new SafeExpressionEvaluator();
309
+
310
+ const result = evaluator.evaluate(
311
+ "customer.tier == 'premium' && order.total > 1000",
312
+ {
313
+ customer: { tier: 'premium' },
314
+ order: { total: 1500 }
315
+ }
316
+ );
317
+
318
+ if (result.success) {
319
+ console.log(result.value); // true
320
+ }
321
+ ```
322
+
323
+ Supports comparisons (`==`, `!=`, `<`, `>`, `<=`, `>=`), logical operators (`&&`, `||`, `!`), dot-notation property access, bracket-notation array access, and safe string/array methods (`.includes()`, `.startsWith()`, `.some()`, `.every()`, etc.).
324
+
325
+ ### SQLExpressionValidator
326
+
327
+ Validates user-provided SQL expressions against injection attacks. Provides context-aware validation (WHERE clauses, ORDER BY, aggregates, field references) with an allowlist of safe SQL functions.
328
+
329
+ ```typescript
330
+ import { SQLExpressionValidator } from '@memberjunction/global';
331
+
332
+ const validator = SQLExpressionValidator.Instance;
333
+
334
+ // Validate a WHERE clause
335
+ const result = validator.validate("Status = 'Active' AND Total > 100", {
336
+ context: 'where_clause'
337
+ });
338
+ // result.valid === true
339
+
340
+ // Unsafe input is rejected
341
+ const bad = validator.validate("Name = 'test'; 1=1", {
342
+ context: 'where_clause'
343
+ });
344
+ // bad.valid === false
345
+ // bad.error === "Semicolons are not allowed in SQL expressions"
346
+ ```
347
+
348
+ ### ClassUtils -- Reflection Helpers
349
+
350
+ Functions for introspecting class hierarchies at runtime.
351
+
352
+ ```typescript
353
+ import {
354
+ GetSuperclass,
355
+ GetRootClass,
356
+ IsSubclassOf,
357
+ IsRootClass,
358
+ GetClassInheritance,
359
+ GetFullClassHierarchy,
360
+ GetClassName,
361
+ IsClassConstructor
362
+ } from '@memberjunction/global';
363
+
364
+ const chain = GetClassInheritance(MyDerivedClass);
365
+ // [{ name: 'MyBaseClass', reference: ... }, { name: 'MyRootClass', reference: ... }]
366
+
367
+ const isChild = IsSubclassOf(ChildClass, ParentClass); // true
368
+ const root = GetRootClass(ChildClass); // returns the top-most user-defined class
369
+ ```
370
+
371
+ ### PatternUtils -- Wildcard and Regex Matching
372
+
373
+ Converts wildcard patterns and regex strings to `RegExp` objects for flexible text matching.
374
+
375
+ ```typescript
376
+ import { parsePattern, matchesAnyPattern } from '@memberjunction/global';
377
+
378
+ const regex = parsePattern('*AIPrompt*'); // matches strings containing "AIPrompt"
379
+ const exact = parsePattern('Users'); // matches exactly "Users" (case-insensitive)
380
+ const re = parsePattern('/^sp_Create/i'); // parsed as a regex literal
381
+
382
+ const matches = matchesAnyPattern('AIPromptRuns', ['*Prompt*', '*Agent*']); // true
383
+ ```
384
+
385
+ ### ObjectCache
386
+
387
+ A simple in-memory key-value cache with type-safe generic accessors. Keys are case-insensitive.
388
+
389
+ ```typescript
390
+ import { MJGlobal } from '@memberjunction/global';
391
+
392
+ const cache = MJGlobal.Instance.ObjectCache;
393
+
394
+ cache.Add('user-prefs', { theme: 'dark' });
395
+ const prefs = cache.Find<{ theme: string }>('User-Prefs'); // case-insensitive lookup
396
+ cache.Replace('user-prefs', { theme: 'light' });
397
+ cache.Remove('user-prefs');
398
+ cache.Clear();
399
+ ```
400
+
401
+ ### WarningManager
402
+
403
+ A singleton warning system with session-level deduplication, debounced output, and tree-structured formatting. Tracks deprecation warnings, field-not-found warnings, and redundant load warnings.
404
+
405
+ ```typescript
406
+ import { WarningManager } from '@memberjunction/global';
407
+
408
+ const wm = WarningManager.Instance;
409
+
410
+ // Configure
411
+ wm.UpdateConfig({ DebounceMs: 5000, GroupWarnings: true });
412
+
413
+ // Record warnings (deduplicated and batched automatically)
414
+ wm.RecordEntityDeprecationWarning('User Preferences', 'BaseEntity::constructor');
415
+ wm.RecordFieldNotFoundWarning('Users', 'DeletedColumn', 'BaseEntity::SetMany');
416
+ wm.RecordRedundantLoadWarning('AI Models', ['DashboardEngine', 'AIEngine']);
417
+
418
+ // Force immediate output if needed
419
+ wm.FlushWarnings();
420
+ ```
421
+
422
+ ### EncryptionUtils
423
+
424
+ Constants and utility functions for working with encrypted field values. Located in this foundational package so any package can detect encrypted values without depending on the full Encryption package.
425
+
426
+ ```typescript
427
+ import {
428
+ IsValueEncrypted,
429
+ IsEncryptedSentinel,
430
+ ENCRYPTION_MARKER,
431
+ ENCRYPTED_SENTINEL
432
+ } from '@memberjunction/global';
433
+
434
+ IsValueEncrypted('$ENC$keyId$AES-256-GCM$iv$ciphertext$authTag'); // true
435
+ IsValueEncrypted('[!ENCRYPTED$]'); // true (sentinel)
436
+ IsValueEncrypted('plain text'); // false
437
+ IsEncryptedSentinel('[!ENCRYPTED$]'); // true
438
+ ```
439
+
440
+ ### String and JSON Utilities
441
+
442
+ A collection of utility functions for common string and JSON operations.
443
+
444
+ | Function | Description |
445
+ |---|---|
446
+ | `CleanJSON(input)` | Extracts and formats JSON from various formats (double-escaped, markdown blocks, mixed content) |
447
+ | `SafeJSONParse<T>(json, logErrors?)` | Parses JSON returning `T` or `null` without throwing |
448
+ | `CleanAndParseJSON<T>(input, logErrors?)` | Combines `CleanJSON` and `SafeJSONParse` in one call |
449
+ | `ParseJSONRecursive(obj, options?)` | Recursively parses nested JSON strings within objects |
450
+ | `CleanJavaScript(code)` | Extracts JavaScript from markdown code blocks |
451
+ | `CopyScalarsAndArrays<T>(input, resolveCircular?)` | Deep-copies scalar and array properties, optionally handling circular references |
452
+ | `convertCamelCaseToHaveSpaces(s)` | `"AIAgentRun"` becomes `"AI Agent Run"` |
453
+ | `stripWhitespace(s)` | Removes all whitespace from a string |
454
+ | `generatePluralName(singular, options?)` | Handles irregular and regular English pluralization |
455
+ | `getIrregularPlural(word)` | Looks up irregular plural forms |
456
+ | `adjustCasing(word, options?)` | Capitalizes first letter, entire word, or leaves as-is |
457
+ | `stripTrailingChars(s, chars, skipIfExact?)` | Removes trailing substring |
458
+ | `replaceAllSpaces(s)` | Removes all space characters |
459
+ | `compareStringsByLine(str1, str2, log?)` | Line-by-line diff with character-level detail |
460
+ | `IsOnlyTimezoneShift(date1, date2)` | Detects if two dates differ only by a whole-hour timezone offset |
461
+ | `InvokeManualResize(delay?, component?)` | Broadcasts a `ManualResizeRequest` event |
462
+ | `uuidv4()` | Generates a v4 UUID |
463
+ | `GetGlobalObjectStore()` | Returns `window` (browser) or `global` (Node.js) for cross-environment state |
464
+
465
+ ### ValidationTypes
466
+
467
+ Standard validation result types used across the framework.
468
+
469
+ ```typescript
470
+ import { ValidationResult, ValidationErrorInfo, ValidationErrorType } from '@memberjunction/global';
471
+
472
+ const result = new ValidationResult();
473
+ result.Success = false;
474
+ result.Errors.push(
475
+ new ValidationErrorInfo('fieldName', 'Value is required', null, ValidationErrorType.Failure)
476
+ );
477
+ ```
478
+
479
+ ## Module Dependency Flow
480
+
481
+ ```mermaid
482
+ flowchart TB
483
+ subgraph MJGlobal["@memberjunction/global (this package)"]
484
+ direction LR
485
+ G["MJGlobal"]
486
+ CF["ClassFactory"]
487
+ RC["RegisterClass"]
488
+ BS["BaseSingleton"]
489
+ OC["ObjectCache"]
490
+ U["Utilities"]
491
+ end
492
+
493
+ subgraph External["External Dependencies"]
494
+ RX["rxjs"]
495
+ LO["lodash"]
496
+ UUID["uuid"]
497
+ end
498
+
499
+ G --> RX
500
+ U --> LO
501
+ U --> UUID
502
+
503
+ subgraph Consumers["Consuming Packages (examples)"]
504
+ direction LR
505
+ MJC["@memberjunction/core"]
506
+ MCE["@memberjunction/core-entities"]
507
+ GQL["@memberjunction/graphql-dataprovider"]
508
+ ENC["@memberjunction/encryption"]
509
+ end
510
+
511
+ Consumers --> MJGlobal
512
+
513
+ style MJGlobal fill:#2d6a9f,stroke:#1a4971,color:#fff
514
+ style External fill:#b8762f,stroke:#8a5722,color:#fff
515
+ style Consumers fill:#2d8659,stroke:#1a5c3a,color:#fff
516
+ ```
517
+
518
+ ## API Reference
519
+
520
+ ### MJGlobal
521
+
522
+ | Member | Type | Description |
523
+ |---|---|---|
524
+ | `Instance` | `MJGlobal` (static) | Returns the singleton instance |
525
+ | `ClassFactory` | `ClassFactory` | Access the class registration and instantiation system |
526
+ | `ObjectCache` | `ObjectCache` | In-memory key-value cache |
527
+ | `Properties` | `MJGlobalProperty[]` | Global property bag for arbitrary key-value storage |
528
+ | `RegisterComponent(component)` | `void` | Register an `IMJComponent` |
529
+ | `RaiseEvent(event)` | `void` | Publish an `MJEvent` to all listeners |
530
+ | `GetEventListener(withReplay?)` | `Observable<MJEvent>` | Subscribe to the event stream |
531
+ | `Reset()` | `void` | Reset all internal state (use with extreme caution) |
532
+
533
+ ### ClassFactory
534
+
535
+ | Method | Returns | Description |
536
+ |---|---|---|
537
+ | `Register(baseClass, subClass, key?, priority?, skipNullKeyWarning?, autoRegisterWithRootClass?)` | `void` | Register a subclass for a base class and optional key |
538
+ | `CreateInstance<T>(baseClass, key?, ...params)` | `T \| null` | Create an instance of the highest-priority registered subclass |
539
+ | `GetRegistration(baseClass, key?)` | `ClassRegistration \| null` | Get the highest-priority registration |
540
+ | `GetAllRegistrations(baseClass, key?)` | `ClassRegistration[]` | Get all registrations for a base class and optional key |
541
+ | `GetRegistrationsByRootClass(rootClass, key?)` | `ClassRegistration[]` | Get registrations by root class in the hierarchy |
542
+
543
+ ### RegisterClass Decorator
544
+
545
+ ```typescript
546
+ function RegisterClass(
547
+ baseClass: unknown,
548
+ key?: string | null,
549
+ priority?: number,
550
+ skipNullKeyWarning?: boolean,
551
+ autoRegisterWithRootClass?: boolean
552
+ ): (constructor: Function) => void;
553
+ ```
554
+
555
+ ### ObjectCache
556
+
557
+ | Method | Returns | Description |
558
+ |---|---|---|
559
+ | `Add<T>(key, object)` | `void` | Add entry; throws if key exists |
560
+ | `Find<T>(key)` | `T \| null` | Case-insensitive key lookup |
561
+ | `Replace<T>(key, object)` | `void` | Replace or add entry |
562
+ | `Remove(key)` | `void` | Remove entry by key |
563
+ | `Clear()` | `void` | Remove all entries |
564
+
565
+ ### DeepDiffer
566
+
567
+ | Method | Returns | Description |
568
+ |---|---|---|
569
+ | `diff<T>(oldValue, newValue)` | `DeepDiffResult` | Generate a full diff between two values |
570
+ | `updateConfig(config)` | `void` | Update configuration options |
571
+
572
+ ### JSONValidator
573
+
574
+ | Method | Returns | Description |
575
+ |---|---|---|
576
+ | `validate(data, template, path?)` | `ValidationResult` | Validate data against a template |
577
+ | `validateAgainstSchema(data, schemaJson)` | `ValidationResult` | Validate against a JSON string schema |
578
+ | `cleanValidationSyntax<T>(data)` | `T` | Strip validation markers from keys |
579
+
580
+ ### SafeExpressionEvaluator
581
+
582
+ | Method | Returns | Description |
583
+ |---|---|---|
584
+ | `evaluate(expression, context, enableDiagnostics?)` | `ExpressionEvaluationResult` | Evaluate a single boolean expression |
585
+ | `evaluateMultiple(expressions, context)` | `Record<string, ExpressionEvaluationResult>` | Evaluate multiple expressions |
586
+
587
+ ### SQLExpressionValidator
588
+
589
+ | Method | Returns | Description |
590
+ |---|---|---|
591
+ | `Instance` (static) | `SQLExpressionValidator` | Singleton accessor |
592
+ | `validate(expression, options)` | `SQLValidationResult` | Validate a SQL expression |
593
+
594
+ ### WarningManager
595
+
596
+ | Method | Returns | Description |
597
+ |---|---|---|
598
+ | `Instance` (static) | `WarningManager` | Singleton accessor |
599
+ | `UpdateConfig(config)` | `void` | Update warning configuration |
600
+ | `GetConfig()` | `Readonly<WarningConfig>` | Get current configuration |
601
+ | `RecordEntityDeprecationWarning(entityName, callerName)` | `boolean` | Record an entity deprecation warning |
602
+ | `RecordFieldDeprecationWarning(entityName, fieldName, callerName)` | `boolean` | Record a field deprecation warning |
603
+ | `RecordFieldNotFoundWarning(entityName, fieldName, context)` | `boolean` | Record a field-not-found warning |
604
+ | `RecordRedundantLoadWarning(entityName, engines)` | `boolean` | Record a redundant data loading warning |
605
+ | `FlushWarnings()` | `void` | Force immediate output of all pending warnings |
606
+ | `Reset()` | `void` | Clear all tracking state |
607
+
608
+ ## Dependencies
609
+
610
+ | Package | Purpose |
611
+ |---|---|
612
+ | `rxjs` | Observable-based event system (`Subject`, `ReplaySubject`) |
613
+ | `lodash` | Deep comparison, type checking, object utilities |
614
+ | `uuid` | UUID v4 generation |
615
+
616
+ ## Related Packages
617
+
618
+ | Package | Relationship |
619
+ |---|---|
620
+ | `@memberjunction/core` | Builds on MJGlobal; adds Metadata, RunView, BaseEntity, and more |
621
+ | `@memberjunction/core-entities` | Generated entity subclasses registered via `@RegisterClass` |
622
+ | `@memberjunction/encryption` | Full encryption implementation; uses `EncryptionUtils` constants from this package |
623
+ | `@memberjunction/server` | Server-side runtime that depends on MJGlobal for class factory and events |
624
+ | `@memberjunction/graphql-dataprovider` | Client-side data provider registered through the class factory |
625
+
626
+ ## Build
627
+
628
+ ```bash
629
+ # From the package directory
630
+ cd packages/MJGlobal
631
+ npm run build
632
+ ```
633
+
634
+ The build step runs `tsc` followed by `tsc-alias` for path alias resolution.
@@ -17,12 +17,12 @@ export declare abstract class BaseSingleton<T> {
17
17
  * @param className
18
18
  * @returns
19
19
  */
20
- protected static getInstance<T extends BaseSingleton<any>>(this: new () => T, className?: string): T;
20
+ protected static getInstance<T extends BaseSingleton<unknown>>(this: new () => T, className?: string): T;
21
21
  /**
22
22
  * The Global Object Store is a place to store global objects that need to be shared across the application. Depending on the execution environment, this could be the window object in a browser, or the global object in a node environment, or something else in other contexts. The key here is that in some cases static variables are not truly shared
23
23
  * because it is possible that a given class might have copies of its code in multiple paths in a deployed application. This approach ensures that no matter how many code copies might exist, there is only one instance of the object in question by using the Global Object Store.
24
24
  * @returns
25
25
  */
26
- GetGlobalObjectStore(): typeof globalThis;
26
+ GetGlobalObjectStore(): import("./util.js").GlobalObjectStore | null;
27
27
  }
28
28
  //# sourceMappingURL=BaseSingleton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BaseSingleton.d.ts","sourceRoot":"","sources":["../src/BaseSingleton.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,8BAAsB,aAAa,CAAC,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAA4B;IAC3D,OAAO,CAAC,UAAU,CAAS;IAC3B,IAAW,SAAS,IAAI,MAAM,CAE7B;IACD,SAAS;IAcT;;;;;;;;OAQG;IACH,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC;IASpG;;;;OAIG;IACI,oBAAoB;CAG9B"}
1
+ {"version":3,"file":"BaseSingleton.d.ts","sourceRoot":"","sources":["../src/BaseSingleton.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,8BAAsB,aAAa,CAAC,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAA4B;IAC3D,OAAO,CAAC,UAAU,CAAS;IAC3B,IAAW,SAAS,IAAI,MAAM,CAE7B;IACD,SAAS;IAcT;;;;;;;;OAQG;IACH,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC;IASxG;;;;OAIG;IACI,oBAAoB;CAG9B"}