@memberjunction/global 2.63.0 → 2.63.1
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/ClassFactory.d.ts +13 -2
- package/dist/ClassFactory.d.ts.map +1 -1
- package/dist/ClassFactory.js +35 -7
- package/dist/ClassFactory.js.map +1 -1
- package/dist/ClassUtils.d.ts +72 -0
- package/dist/ClassUtils.d.ts.map +1 -0
- package/dist/ClassUtils.js +202 -0
- package/dist/ClassUtils.js.map +1 -0
- package/dist/Global.d.ts +51 -0
- package/dist/Global.d.ts.map +1 -0
- package/dist/Global.js +81 -0
- package/dist/Global.js.map +1 -0
- package/dist/RegisterClass.d.ts +11 -0
- package/dist/RegisterClass.d.ts.map +1 -0
- package/dist/RegisterClass.js +21 -0
- package/dist/RegisterClass.js.map +1 -0
- package/dist/__tests__/ClassUtils.test.d.ts +2 -0
- package/dist/__tests__/ClassUtils.test.d.ts.map +1 -0
- package/dist/__tests__/ClassUtils.test.js +173 -0
- package/dist/__tests__/ClassUtils.test.js.map +1 -0
- package/dist/index.d.ts +3 -59
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -96
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +190 -6
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ClassUtils_1 = require("../ClassUtils");
|
|
4
|
+
// Test class hierarchy
|
|
5
|
+
class Animal {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.name = '';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
class Mammal extends Animal {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.furColor = '';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class Dog extends Mammal {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.breed = '';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
class GoldenRetriever extends Dog {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
this.temperament = 'friendly';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Test cases
|
|
29
|
+
describe('ClassUtils', () => {
|
|
30
|
+
describe('GetSuperclass', () => {
|
|
31
|
+
it('should return immediate superclass', () => {
|
|
32
|
+
expect((0, ClassUtils_1.GetSuperclass)(GoldenRetriever)).toBe(Dog);
|
|
33
|
+
expect((0, ClassUtils_1.GetSuperclass)(Dog)).toBe(Mammal);
|
|
34
|
+
expect((0, ClassUtils_1.GetSuperclass)(Mammal)).toBe(Animal);
|
|
35
|
+
expect((0, ClassUtils_1.GetSuperclass)(Animal)).toBe(null);
|
|
36
|
+
});
|
|
37
|
+
it('should handle invalid inputs', () => {
|
|
38
|
+
expect((0, ClassUtils_1.GetSuperclass)(null)).toBe(null);
|
|
39
|
+
expect((0, ClassUtils_1.GetSuperclass)(undefined)).toBe(null);
|
|
40
|
+
expect((0, ClassUtils_1.GetSuperclass)({})).toBe(null);
|
|
41
|
+
expect((0, ClassUtils_1.GetSuperclass)('not a class')).toBe(null);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('GetRootClass', () => {
|
|
45
|
+
it('should return the root class', () => {
|
|
46
|
+
expect((0, ClassUtils_1.GetRootClass)(GoldenRetriever)).toBe(Animal);
|
|
47
|
+
expect((0, ClassUtils_1.GetRootClass)(Dog)).toBe(Animal);
|
|
48
|
+
expect((0, ClassUtils_1.GetRootClass)(Animal)).toBe(Animal);
|
|
49
|
+
});
|
|
50
|
+
it('should handle classes without inheritance', () => {
|
|
51
|
+
class Standalone {
|
|
52
|
+
}
|
|
53
|
+
expect((0, ClassUtils_1.GetRootClass)(Standalone)).toBe(Standalone);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('IsSubclassOf', () => {
|
|
57
|
+
it('should correctly identify subclass relationships', () => {
|
|
58
|
+
expect((0, ClassUtils_1.IsSubclassOf)(GoldenRetriever, Dog)).toBe(true);
|
|
59
|
+
expect((0, ClassUtils_1.IsSubclassOf)(GoldenRetriever, Mammal)).toBe(true);
|
|
60
|
+
expect((0, ClassUtils_1.IsSubclassOf)(GoldenRetriever, Animal)).toBe(true);
|
|
61
|
+
expect((0, ClassUtils_1.IsSubclassOf)(Dog, Animal)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('should return false for non-subclass relationships', () => {
|
|
64
|
+
expect((0, ClassUtils_1.IsSubclassOf)(Animal, Dog)).toBe(false);
|
|
65
|
+
expect((0, ClassUtils_1.IsSubclassOf)(Dog, GoldenRetriever)).toBe(false);
|
|
66
|
+
expect((0, ClassUtils_1.IsSubclassOf)(Dog, Dog)).toBe(false); // Not a subclass of itself
|
|
67
|
+
});
|
|
68
|
+
it('should handle invalid inputs', () => {
|
|
69
|
+
expect((0, ClassUtils_1.IsSubclassOf)(null, Animal)).toBe(false);
|
|
70
|
+
expect((0, ClassUtils_1.IsSubclassOf)(Dog, null)).toBe(false);
|
|
71
|
+
expect((0, ClassUtils_1.IsSubclassOf)('not a class', Animal)).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('IsRootClass', () => {
|
|
75
|
+
it('should identify root classes', () => {
|
|
76
|
+
expect((0, ClassUtils_1.IsRootClass)(Animal)).toBe(true);
|
|
77
|
+
class StandaloneClass {
|
|
78
|
+
}
|
|
79
|
+
expect((0, ClassUtils_1.IsRootClass)(StandaloneClass)).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('should return false for classes with superclasses', () => {
|
|
82
|
+
expect((0, ClassUtils_1.IsRootClass)(GoldenRetriever)).toBe(false);
|
|
83
|
+
expect((0, ClassUtils_1.IsRootClass)(Dog)).toBe(false);
|
|
84
|
+
expect((0, ClassUtils_1.IsRootClass)(Mammal)).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
it('should handle invalid inputs', () => {
|
|
87
|
+
expect((0, ClassUtils_1.IsRootClass)(null)).toBe(false);
|
|
88
|
+
expect((0, ClassUtils_1.IsRootClass)(undefined)).toBe(false);
|
|
89
|
+
expect((0, ClassUtils_1.IsRootClass)(42)).toBe(false);
|
|
90
|
+
expect((0, ClassUtils_1.IsRootClass)('string')).toBe(false);
|
|
91
|
+
expect((0, ClassUtils_1.IsRootClass)({})).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('IsDescendantClassOf', () => {
|
|
95
|
+
it('should work identically to IsSubclassOf', () => {
|
|
96
|
+
// Test direct parent
|
|
97
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(GoldenRetriever, Dog)).toBe(true);
|
|
98
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(Dog, Mammal)).toBe(true);
|
|
99
|
+
// Test grandparent and beyond
|
|
100
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(GoldenRetriever, Mammal)).toBe(true);
|
|
101
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(GoldenRetriever, Animal)).toBe(true);
|
|
102
|
+
// Test non-relationships
|
|
103
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(Animal, GoldenRetriever)).toBe(false);
|
|
104
|
+
expect((0, ClassUtils_1.IsDescendantClassOf)(Dog, Dog)).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('GetClassInheritance', () => {
|
|
108
|
+
it('should return inheritance chain', () => {
|
|
109
|
+
const chain = (0, ClassUtils_1.GetClassInheritance)(GoldenRetriever);
|
|
110
|
+
expect(chain.length).toBe(3);
|
|
111
|
+
expect(chain[0].name).toBe('Dog');
|
|
112
|
+
expect(chain[0].reference).toBe(Dog);
|
|
113
|
+
expect(chain[1].name).toBe('Mammal');
|
|
114
|
+
expect(chain[1].reference).toBe(Mammal);
|
|
115
|
+
expect(chain[2].name).toBe('Animal');
|
|
116
|
+
expect(chain[2].reference).toBe(Animal);
|
|
117
|
+
});
|
|
118
|
+
it('should return empty array for base classes', () => {
|
|
119
|
+
const chain = (0, ClassUtils_1.GetClassInheritance)(Animal);
|
|
120
|
+
expect(chain.length).toBe(0);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('GetFullClassHierarchy', () => {
|
|
124
|
+
it('should include the class itself', () => {
|
|
125
|
+
const hierarchy = (0, ClassUtils_1.GetFullClassHierarchy)(GoldenRetriever);
|
|
126
|
+
expect(hierarchy.length).toBe(4);
|
|
127
|
+
expect(hierarchy[0].name).toBe('GoldenRetriever');
|
|
128
|
+
expect(hierarchy[0].reference).toBe(GoldenRetriever);
|
|
129
|
+
expect(hierarchy[1].name).toBe('Dog');
|
|
130
|
+
expect(hierarchy[2].name).toBe('Mammal');
|
|
131
|
+
expect(hierarchy[3].name).toBe('Animal');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe('IsClassConstructor', () => {
|
|
135
|
+
it('should identify class constructors', () => {
|
|
136
|
+
expect((0, ClassUtils_1.IsClassConstructor)(Animal)).toBe(true);
|
|
137
|
+
expect((0, ClassUtils_1.IsClassConstructor)(GoldenRetriever)).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
it('should reject non-constructors', () => {
|
|
140
|
+
expect((0, ClassUtils_1.IsClassConstructor)(() => { })).toBe(false);
|
|
141
|
+
expect((0, ClassUtils_1.IsClassConstructor)(function regularFunction() { })).toBe(false);
|
|
142
|
+
expect((0, ClassUtils_1.IsClassConstructor)(42)).toBe(false);
|
|
143
|
+
expect((0, ClassUtils_1.IsClassConstructor)('string')).toBe(false);
|
|
144
|
+
expect((0, ClassUtils_1.IsClassConstructor)({})).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
it('should handle constructor functions', () => {
|
|
147
|
+
function OldStyleClass() {
|
|
148
|
+
this.property = 'value';
|
|
149
|
+
}
|
|
150
|
+
OldStyleClass.prototype.method = function () { };
|
|
151
|
+
expect((0, ClassUtils_1.IsClassConstructor)(OldStyleClass)).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('GetClassName', () => {
|
|
155
|
+
it('should get class names', () => {
|
|
156
|
+
expect((0, ClassUtils_1.GetClassName)(Animal)).toBe('Animal');
|
|
157
|
+
expect((0, ClassUtils_1.GetClassName)(GoldenRetriever)).toBe('GoldenRetriever');
|
|
158
|
+
});
|
|
159
|
+
it('should handle anonymous classes', () => {
|
|
160
|
+
const AnonClass = class {
|
|
161
|
+
};
|
|
162
|
+
// Note: This might return 'AnonClass' or 'Anonymous' depending on environment
|
|
163
|
+
const name = (0, ClassUtils_1.GetClassName)(AnonClass);
|
|
164
|
+
expect(['AnonClass', 'Anonymous'].includes(name)).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
it('should handle invalid inputs', () => {
|
|
167
|
+
expect((0, ClassUtils_1.GetClassName)(null)).toBe('Unknown');
|
|
168
|
+
expect((0, ClassUtils_1.GetClassName)(undefined)).toBe('Unknown');
|
|
169
|
+
expect((0, ClassUtils_1.GetClassName)(42)).toBe('Unknown');
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=ClassUtils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClassUtils.test.js","sourceRoot":"","sources":["../../src/__tests__/ClassUtils.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,66 +1,10 @@
|
|
|
1
|
-
import * as MJ from './interface';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
import { ClassFactory } from './ClassFactory';
|
|
4
|
-
import { ObjectCache } from './ObjectCache';
|
|
5
|
-
import { BaseSingleton } from './BaseSingleton';
|
|
6
1
|
export { ClassFactory, ClassRegistration } from './ClassFactory';
|
|
7
2
|
export * from './interface';
|
|
8
3
|
export * from './util';
|
|
9
4
|
export * from './ObjectCache';
|
|
10
5
|
export * from './BaseSingleton';
|
|
11
6
|
export * from './DeepDiff';
|
|
12
|
-
|
|
13
|
-
* Global
|
|
14
|
-
|
|
15
|
-
export declare class MJGlobal extends BaseSingleton<MJGlobal> {
|
|
16
|
-
private _eventsSubject;
|
|
17
|
-
private _eventsReplaySubject;
|
|
18
|
-
private _events$;
|
|
19
|
-
private _eventsReplay$;
|
|
20
|
-
private _components;
|
|
21
|
-
private _classFactory;
|
|
22
|
-
private _properties;
|
|
23
|
-
/**
|
|
24
|
-
* Returns the global instance of the MJGlobal class. This is a singleton class, so there is only one instance of it in the application. Do not directly create new instances of MJGlobal, always use this method to get the instance.
|
|
25
|
-
*/
|
|
26
|
-
static get Instance(): MJGlobal;
|
|
27
|
-
RegisterComponent(component: MJ.IMJComponent): void;
|
|
28
|
-
/**
|
|
29
|
-
* Resets the class to its initial state. Use very carefully and sparingly.
|
|
30
|
-
*/
|
|
31
|
-
Reset(): void;
|
|
32
|
-
/**
|
|
33
|
-
* Use this method to raise an event to all component who are listening for the event.
|
|
34
|
-
* @param event
|
|
35
|
-
*/
|
|
36
|
-
RaiseEvent(event: MJ.MJEvent): void;
|
|
37
|
-
/**
|
|
38
|
-
* Use this method to get an observable that will fire when an event is raised.
|
|
39
|
-
* @param withReplay
|
|
40
|
-
* @returns
|
|
41
|
-
*/
|
|
42
|
-
GetEventListener(withReplay?: boolean): Observable<MJ.MJEvent>;
|
|
43
|
-
/**
|
|
44
|
-
* Returns the instance of ClassFactory you should use in your application. Access this via the MJGlobal.Instance.ClassFactory property.
|
|
45
|
-
*/
|
|
46
|
-
get ClassFactory(): ClassFactory;
|
|
47
|
-
/**
|
|
48
|
-
* Global property bag
|
|
49
|
-
*/
|
|
50
|
-
get Properties(): MJ.MJGlobalProperty[];
|
|
51
|
-
private _objectCache;
|
|
52
|
-
/**
|
|
53
|
-
* ObjectCache can be used to cache objects as needed by any application in memory. These objects are NOT persisted to disk or any other storage medium, so they are only good for the lifetime of the application
|
|
54
|
-
*/
|
|
55
|
-
get ObjectCache(): ObjectCache;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Decorate your class with this to register it with the MJGlobal class factory.
|
|
59
|
-
* @param baseClass
|
|
60
|
-
* @param key a string that is later used to retrieve a given registration - this should be unique for each baseClass/key combination, if multiple registrations exist for a given baseClass/key combination, the highest priority registration will be used to create class instances
|
|
61
|
-
* @param priority Higher priority registrations will be used over lower priority registrations. If there are multiple registrations for a given base class/sub-class/key combination, the one with the highest priority will be used. If there are multiple registrations with the same priority, the last one registered will be used. Finally, if you do NOT provide this setting, the order of registrations will increment the priority automatically so dependency injection will typically care care of this. That is, in order for Class B, a subclass of Class A, to be registered properly, Class A code has to already have been loaded and therefore Class A's RegisterClass decorator was run. In that scenario, if neither Class A or B has a priority setting, Class A would be 1 and Class B would be 2 automatically. For this reason, you only need to explicitly set priority if you want to do something atypical as this mechanism normally will solve for setting the priority correctly based on the furthest descendant class that is registered.
|
|
62
|
-
* @param skipNullKeyWarning If true, will not print a warning if the key is null or undefined. This is useful for cases where you know that the key is not needed and you don't want to see the warning in the console.
|
|
63
|
-
* @returns an instance of the class that was registered for the combination of baseClass/key (with highest priority if more than one)
|
|
64
|
-
*/
|
|
65
|
-
export declare function RegisterClass(baseClass: any, key?: string, priority?: number, skipNullKeyWarning?: boolean): (constructor: Function) => void;
|
|
7
|
+
export * from './ClassUtils';
|
|
8
|
+
export * from './Global';
|
|
9
|
+
export * from './RegisterClass';
|
|
66
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
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;AAG5B,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -14,105 +14,18 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
var ClassFactory_2 = require("./ClassFactory");
|
|
23
|
-
Object.defineProperty(exports, "ClassFactory", { enumerable: true, get: function () { return ClassFactory_2.ClassFactory; } });
|
|
24
|
-
Object.defineProperty(exports, "ClassRegistration", { enumerable: true, get: function () { return ClassFactory_2.ClassRegistration; } });
|
|
17
|
+
exports.ClassRegistration = exports.ClassFactory = void 0;
|
|
18
|
+
// Export all types and utilities
|
|
19
|
+
var ClassFactory_1 = require("./ClassFactory");
|
|
20
|
+
Object.defineProperty(exports, "ClassFactory", { enumerable: true, get: function () { return ClassFactory_1.ClassFactory; } });
|
|
21
|
+
Object.defineProperty(exports, "ClassRegistration", { enumerable: true, get: function () { return ClassFactory_1.ClassRegistration; } });
|
|
25
22
|
__exportStar(require("./interface"), exports);
|
|
26
23
|
__exportStar(require("./util"), exports);
|
|
27
24
|
__exportStar(require("./ObjectCache"), exports);
|
|
28
25
|
__exportStar(require("./BaseSingleton"), exports);
|
|
29
26
|
__exportStar(require("./DeepDiff"), exports);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
constructor() {
|
|
35
|
-
super(...arguments);
|
|
36
|
-
// subjects for observables to handle eventing
|
|
37
|
-
this._eventsSubject = new rxjs_1.Subject();
|
|
38
|
-
this._eventsReplaySubject = new rxjs_1.ReplaySubject();
|
|
39
|
-
// Convert the Subjects to Observables for public use.
|
|
40
|
-
this._events$ = this._eventsSubject.asObservable();
|
|
41
|
-
this._eventsReplay$ = this._eventsReplaySubject.asObservable();
|
|
42
|
-
this._components = [];
|
|
43
|
-
this._classFactory = new ClassFactory_1.ClassFactory();
|
|
44
|
-
this._properties = [];
|
|
45
|
-
this._objectCache = new ObjectCache_1.ObjectCache();
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Returns the global instance of the MJGlobal class. This is a singleton class, so there is only one instance of it in the application. Do not directly create new instances of MJGlobal, always use this method to get the instance.
|
|
49
|
-
*/
|
|
50
|
-
static get Instance() {
|
|
51
|
-
return super.getInstance();
|
|
52
|
-
}
|
|
53
|
-
RegisterComponent(component) {
|
|
54
|
-
this._components.push(component);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Resets the class to its initial state. Use very carefully and sparingly.
|
|
58
|
-
*/
|
|
59
|
-
Reset() {
|
|
60
|
-
this._components = [];
|
|
61
|
-
this._eventsSubject = new rxjs_1.Subject();
|
|
62
|
-
this._eventsReplaySubject = new rxjs_1.ReplaySubject();
|
|
63
|
-
// Convert the Subjects to Observables for public use.
|
|
64
|
-
this._events$ = this._eventsSubject.asObservable();
|
|
65
|
-
this._eventsReplay$ = this._eventsReplaySubject.asObservable();
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Use this method to raise an event to all component who are listening for the event.
|
|
69
|
-
* @param event
|
|
70
|
-
*/
|
|
71
|
-
RaiseEvent(event) {
|
|
72
|
-
this._eventsSubject.next(event);
|
|
73
|
-
this._eventsReplaySubject.next(event);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Use this method to get an observable that will fire when an event is raised.
|
|
77
|
-
* @param withReplay
|
|
78
|
-
* @returns
|
|
79
|
-
*/
|
|
80
|
-
GetEventListener(withReplay = false) {
|
|
81
|
-
return withReplay ? this._eventsReplay$ : this._events$;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Returns the instance of ClassFactory you should use in your application. Access this via the MJGlobal.Instance.ClassFactory property.
|
|
85
|
-
*/
|
|
86
|
-
get ClassFactory() {
|
|
87
|
-
return this._classFactory;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Global property bag
|
|
91
|
-
*/
|
|
92
|
-
get Properties() {
|
|
93
|
-
return this._properties;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* ObjectCache can be used to cache objects as needed by any application in memory. These objects are NOT persisted to disk or any other storage medium, so they are only good for the lifetime of the application
|
|
97
|
-
*/
|
|
98
|
-
get ObjectCache() {
|
|
99
|
-
return this._objectCache;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.MJGlobal = MJGlobal;
|
|
103
|
-
/**
|
|
104
|
-
* Decorate your class with this to register it with the MJGlobal class factory.
|
|
105
|
-
* @param baseClass
|
|
106
|
-
* @param key a string that is later used to retrieve a given registration - this should be unique for each baseClass/key combination, if multiple registrations exist for a given baseClass/key combination, the highest priority registration will be used to create class instances
|
|
107
|
-
* @param priority Higher priority registrations will be used over lower priority registrations. If there are multiple registrations for a given base class/sub-class/key combination, the one with the highest priority will be used. If there are multiple registrations with the same priority, the last one registered will be used. Finally, if you do NOT provide this setting, the order of registrations will increment the priority automatically so dependency injection will typically care care of this. That is, in order for Class B, a subclass of Class A, to be registered properly, Class A code has to already have been loaded and therefore Class A's RegisterClass decorator was run. In that scenario, if neither Class A or B has a priority setting, Class A would be 1 and Class B would be 2 automatically. For this reason, you only need to explicitly set priority if you want to do something atypical as this mechanism normally will solve for setting the priority correctly based on the furthest descendant class that is registered.
|
|
108
|
-
* @param skipNullKeyWarning If true, will not print a warning if the key is null or undefined. This is useful for cases where you know that the key is not needed and you don't want to see the warning in the console.
|
|
109
|
-
* @returns an instance of the class that was registered for the combination of baseClass/key (with highest priority if more than one)
|
|
110
|
-
*/
|
|
111
|
-
function RegisterClass(baseClass, key = null, priority = 0, skipNullKeyWarning = false) {
|
|
112
|
-
return function (constructor) {
|
|
113
|
-
// Invoke the registration method
|
|
114
|
-
MJGlobal.Instance.ClassFactory.Register(baseClass, constructor, key, priority, skipNullKeyWarning);
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
exports.RegisterClass = RegisterClass;
|
|
27
|
+
__exportStar(require("./ClassUtils"), exports);
|
|
28
|
+
// Export the main classes
|
|
29
|
+
__exportStar(require("./Global"), exports);
|
|
30
|
+
__exportStar(require("./RegisterClass"), exports);
|
|
118
31
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iCAAiC;AACjC,+CAAgE;AAAvD,4GAAA,YAAY,OAAA;AAAE,iHAAA,iBAAiB,OAAA;AACxC,8CAA2B;AAC3B,yCAAsB;AACtB,gDAA6B;AAC7B,kDAA+B;AAC/B,6CAA0B;AAC1B,+CAA4B;AAE5B,0BAA0B;AAC1B,2CAAwB;AACxB,kDAA+B"}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -13,9 +13,11 @@ npm install @memberjunction/global
|
|
|
13
13
|
The `@memberjunction/global` library serves as the foundation for cross-component communication and coordination in MemberJunction applications. It provides:
|
|
14
14
|
|
|
15
15
|
- **Global Singleton Management** - Ensures true singleton instances across module boundaries
|
|
16
|
-
- **Class Factory System** - Dynamic class registration and instantiation with
|
|
16
|
+
- **Class Factory System** - Dynamic class registration and instantiation with automatic root class detection
|
|
17
17
|
- **Event System** - RxJS-based event bus for component communication
|
|
18
18
|
- **Object Caching** - In-memory object cache for application lifetime
|
|
19
|
+
- **Class Reflection Utilities** - Runtime class hierarchy inspection and analysis
|
|
20
|
+
- **Deep Diff Engine** - Comprehensive object comparison and change tracking
|
|
19
21
|
- **Utility Functions** - Common string manipulation, JSON parsing (including recursive nested JSON parsing), and formatting utilities
|
|
20
22
|
|
|
21
23
|
## Core Components
|
|
@@ -54,21 +56,27 @@ const replaySubscription = mjGlobal.GetEventListener(true).subscribe(event => {
|
|
|
54
56
|
|
|
55
57
|
### Class Factory System
|
|
56
58
|
|
|
57
|
-
Register and instantiate classes dynamically with
|
|
59
|
+
Register and instantiate classes dynamically with automatic root class detection and inheritance chain support.
|
|
58
60
|
|
|
59
61
|
```typescript
|
|
60
62
|
import { RegisterClass, MJGlobal } from '@memberjunction/global';
|
|
61
63
|
|
|
62
|
-
// Define a base class
|
|
64
|
+
// Define a base class hierarchy
|
|
63
65
|
class BaseProcessor {
|
|
64
66
|
process(data: any): void {
|
|
65
67
|
console.log('Base processing');
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
class SpecialProcessor extends BaseProcessor {
|
|
72
|
+
process(data: any): void {
|
|
73
|
+
console.log('Special processing');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Register a subclass - automatically registers with root class (BaseProcessor)
|
|
78
|
+
@RegisterClass(SpecialProcessor, 'custom')
|
|
79
|
+
class CustomProcessor extends SpecialProcessor {
|
|
72
80
|
process(data: any): void {
|
|
73
81
|
console.log('Custom processing');
|
|
74
82
|
}
|
|
@@ -78,6 +86,15 @@ class CustomProcessor extends BaseProcessor {
|
|
|
78
86
|
const factory = MJGlobal.Instance.ClassFactory;
|
|
79
87
|
const processor = factory.CreateInstance<BaseProcessor>(BaseProcessor, 'custom');
|
|
80
88
|
processor.process(data); // Uses CustomProcessor
|
|
89
|
+
|
|
90
|
+
// Key Features:
|
|
91
|
+
// 1. Auto-registers with root class by default (BaseProcessor in this case)
|
|
92
|
+
// 2. Ensures proper priority ordering in inheritance chains
|
|
93
|
+
// 3. Can opt-out with autoRegisterWithRootClass: false
|
|
94
|
+
@RegisterClass(SpecialProcessor, 'special', 0, false, false) // Last param disables auto-root registration
|
|
95
|
+
class DirectRegistration extends SpecialProcessor {
|
|
96
|
+
// This registers directly to SpecialProcessor, not BaseProcessor
|
|
97
|
+
}
|
|
81
98
|
```
|
|
82
99
|
|
|
83
100
|
### Object Cache
|
|
@@ -127,6 +144,117 @@ const service = MyService.Instance;
|
|
|
127
144
|
service.addData('example');
|
|
128
145
|
```
|
|
129
146
|
|
|
147
|
+
### Class Reflection Utilities
|
|
148
|
+
|
|
149
|
+
Runtime utilities for inspecting and analyzing class hierarchies.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import {
|
|
153
|
+
GetSuperclass,
|
|
154
|
+
GetRootClass,
|
|
155
|
+
IsSubclassOf,
|
|
156
|
+
IsRootClass,
|
|
157
|
+
IsDescendantClassOf,
|
|
158
|
+
GetClassInheritance,
|
|
159
|
+
GetFullClassHierarchy,
|
|
160
|
+
IsClassConstructor,
|
|
161
|
+
GetClassName
|
|
162
|
+
} from '@memberjunction/global';
|
|
163
|
+
|
|
164
|
+
// Example class hierarchy
|
|
165
|
+
class Animal {}
|
|
166
|
+
class Mammal extends Animal {}
|
|
167
|
+
class Dog extends Mammal {}
|
|
168
|
+
class GoldenRetriever extends Dog {}
|
|
169
|
+
|
|
170
|
+
// Get immediate superclass
|
|
171
|
+
const parent = GetSuperclass(GoldenRetriever); // Returns: Dog
|
|
172
|
+
|
|
173
|
+
// Get root class of hierarchy
|
|
174
|
+
const root = GetRootClass(GoldenRetriever); // Returns: Animal
|
|
175
|
+
|
|
176
|
+
// Check inheritance relationships
|
|
177
|
+
IsSubclassOf(GoldenRetriever, Animal); // true (checks entire chain)
|
|
178
|
+
IsDescendantClassOf(GoldenRetriever, Animal); // true (alias for IsSubclassOf)
|
|
179
|
+
IsRootClass(Animal); // true
|
|
180
|
+
IsRootClass(Dog); // false
|
|
181
|
+
|
|
182
|
+
// Get inheritance chain
|
|
183
|
+
const chain = GetClassInheritance(GoldenRetriever);
|
|
184
|
+
// Returns: [
|
|
185
|
+
// { name: 'Dog', reference: Dog },
|
|
186
|
+
// { name: 'Mammal', reference: Mammal },
|
|
187
|
+
// { name: 'Animal', reference: Animal }
|
|
188
|
+
// ]
|
|
189
|
+
|
|
190
|
+
// Get full hierarchy including the class itself
|
|
191
|
+
const fullChain = GetFullClassHierarchy(GoldenRetriever);
|
|
192
|
+
// Returns: [
|
|
193
|
+
// { name: 'GoldenRetriever', reference: GoldenRetriever },
|
|
194
|
+
// { name: 'Dog', reference: Dog },
|
|
195
|
+
// { name: 'Mammal', reference: Mammal },
|
|
196
|
+
// { name: 'Animal', reference: Animal }
|
|
197
|
+
// ]
|
|
198
|
+
|
|
199
|
+
// Utility functions
|
|
200
|
+
IsClassConstructor(Dog); // true
|
|
201
|
+
IsClassConstructor(() => {}); // false
|
|
202
|
+
GetClassName(GoldenRetriever); // "GoldenRetriever"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Deep Diff Engine
|
|
206
|
+
|
|
207
|
+
Comprehensive object comparison and change tracking with hierarchical diff visualization.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { DeepDiffer, DiffChangeType } from '@memberjunction/global';
|
|
211
|
+
|
|
212
|
+
// Create a differ instance
|
|
213
|
+
const differ = new DeepDiffer({
|
|
214
|
+
includeUnchanged: false, // Don't track unchanged values
|
|
215
|
+
maxDepth: 10, // Maximum recursion depth
|
|
216
|
+
maxStringLength: 100 // Truncate long strings
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Compare two objects
|
|
220
|
+
const oldData = {
|
|
221
|
+
user: { name: 'John', age: 30, role: 'admin' },
|
|
222
|
+
settings: { theme: 'dark', notifications: true },
|
|
223
|
+
tags: ['important', 'active']
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const newData = {
|
|
227
|
+
user: { name: 'John', age: 31, role: 'superadmin' },
|
|
228
|
+
settings: { theme: 'light', notifications: true, language: 'en' },
|
|
229
|
+
tags: ['important', 'active', 'premium']
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Get the diff
|
|
233
|
+
const result = differ.diff(oldData, newData);
|
|
234
|
+
|
|
235
|
+
// Access summary
|
|
236
|
+
console.log(result.summary);
|
|
237
|
+
// { added: 2, removed: 0, modified: 3, unchanged: 3, total: 8 }
|
|
238
|
+
|
|
239
|
+
// Iterate through changes
|
|
240
|
+
result.changes.forEach(change => {
|
|
241
|
+
console.log(`${change.path}: ${change.type} - ${change.description}`);
|
|
242
|
+
});
|
|
243
|
+
// Output:
|
|
244
|
+
// user.age: Modified - Changed from 30 to 31
|
|
245
|
+
// user.role: Modified - Changed from "admin" to "superadmin"
|
|
246
|
+
// settings.theme: Modified - Changed from "dark" to "light"
|
|
247
|
+
// settings.language: Added - Value: "en"
|
|
248
|
+
// tags[2]: Added - Value: "premium"
|
|
249
|
+
|
|
250
|
+
// Filter changes by type
|
|
251
|
+
const additions = result.changes.filter(c => c.type === DiffChangeType.Added);
|
|
252
|
+
const modifications = result.changes.filter(c => c.type === DiffChangeType.Modified);
|
|
253
|
+
|
|
254
|
+
// Update configuration on the fly
|
|
255
|
+
differ.updateConfig({ includeUnchanged: true });
|
|
256
|
+
```
|
|
257
|
+
|
|
130
258
|
## Event Types
|
|
131
259
|
|
|
132
260
|
The library provides predefined event types for common scenarios:
|
|
@@ -255,6 +383,45 @@ InvokeManualResize(50, myComponent);
|
|
|
255
383
|
|
|
256
384
|
## Advanced Usage
|
|
257
385
|
|
|
386
|
+
### Class Factory with Root Class Detection
|
|
387
|
+
|
|
388
|
+
The Class Factory automatically detects and uses root classes for registration, ensuring proper priority ordering in inheritance hierarchies:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
class BaseEntity {} // Root class
|
|
392
|
+
|
|
393
|
+
class UserEntity extends BaseEntity {}
|
|
394
|
+
|
|
395
|
+
// This automatically registers with BaseEntity (the root)
|
|
396
|
+
@RegisterClass(UserEntity, 'Admin')
|
|
397
|
+
class AdminUserEntity extends UserEntity {}
|
|
398
|
+
|
|
399
|
+
// Also registers with BaseEntity, gets higher priority
|
|
400
|
+
@RegisterClass(AdminUserEntity, 'SuperAdmin')
|
|
401
|
+
class SuperAdminEntity extends AdminUserEntity {}
|
|
402
|
+
|
|
403
|
+
// All of these create SuperAdminEntity (highest priority)
|
|
404
|
+
factory.CreateInstance(BaseEntity, 'SuperAdmin'); // ✓ Works
|
|
405
|
+
factory.CreateInstance(UserEntity, 'SuperAdmin'); // ✓ Works
|
|
406
|
+
factory.CreateInstance(AdminUserEntity, 'SuperAdmin'); // ✓ Works
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Disabling Auto-Root Registration
|
|
410
|
+
|
|
411
|
+
Sometimes you want to register at a specific level in the hierarchy:
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
// Register directly to UserEntity, not BaseEntity
|
|
415
|
+
@RegisterClass(UserEntity, 'Special', 0, false, false) // Last param = false
|
|
416
|
+
class SpecialUserEntity extends UserEntity {
|
|
417
|
+
// This only matches when creating from UserEntity, not BaseEntity
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Direct registration queries
|
|
421
|
+
factory.CreateInstance(UserEntity, 'Special'); // ✓ Returns SpecialUserEntity
|
|
422
|
+
factory.CreateInstance(BaseEntity, 'Special'); // ✗ Returns BaseEntity instance
|
|
423
|
+
```
|
|
424
|
+
|
|
258
425
|
### Class Factory with Parameters
|
|
259
426
|
|
|
260
427
|
```typescript
|
|
@@ -289,6 +456,23 @@ class AdvancedDataHandler extends BaseHandler {}
|
|
|
289
456
|
const handler = factory.CreateInstance<BaseHandler>(BaseHandler, 'data');
|
|
290
457
|
```
|
|
291
458
|
|
|
459
|
+
### Inspecting Registrations
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// Get all registrations for a base class
|
|
463
|
+
const registrations = factory.GetAllRegistrations(BaseEntity, 'Users');
|
|
464
|
+
|
|
465
|
+
// Get registrations by root class
|
|
466
|
+
const rootRegistrations = factory.GetRegistrationsByRootClass(BaseEntity);
|
|
467
|
+
|
|
468
|
+
// Each registration contains:
|
|
469
|
+
// - BaseClass: The class it's registered to (usually root)
|
|
470
|
+
// - SubClass: The actual implementation class
|
|
471
|
+
// - RootClass: The detected root of the hierarchy
|
|
472
|
+
// - Key: The registration key
|
|
473
|
+
// - Priority: The priority number
|
|
474
|
+
```
|
|
475
|
+
|
|
292
476
|
### Global Properties
|
|
293
477
|
|
|
294
478
|
Store and retrieve global properties:
|