@memberjunction/global 2.62.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/DeepDiff.d.ts +191 -0
- package/dist/DeepDiff.d.ts.map +1 -0
- package/dist/DeepDiff.js +342 -0
- package/dist/DeepDiff.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 +4 -59
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -96
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +190 -6
package/dist/ClassFactory.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
export declare class ClassRegistration {
|
|
12
12
|
BaseClass: any;
|
|
13
13
|
SubClass: any;
|
|
14
|
+
RootClass: any;
|
|
14
15
|
Key: string;
|
|
15
16
|
Priority: number;
|
|
16
17
|
}
|
|
@@ -27,10 +28,12 @@ export declare class ClassFactory {
|
|
|
27
28
|
* @param key A key can be used to differentiate registrations for the same base class/sub-class combination. For example, in the case of BaseEntity and Entity object subclasses we'll have a LOT of entries and we want to get the highest priority registered sub-class for a specific key. In that case, the key is the entity name, but the key can be any value you want to use to differentiate registrations.
|
|
28
29
|
* @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.
|
|
29
30
|
* @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.
|
|
31
|
+
* @param autoRegisterWithRootClass If true (default), will automatically register the subclass with the root class of the baseClass hierarchy. This ensures proper priority ordering when multiple subclasses are registered in a hierarchy.
|
|
30
32
|
*/
|
|
31
|
-
Register(baseClass: any, subClass: any, key?: string, priority?: number, skipNullKeyWarning?: boolean): void;
|
|
33
|
+
Register(baseClass: any, subClass: any, key?: string, priority?: number, skipNullKeyWarning?: boolean, autoRegisterWithRootClass?: boolean): void;
|
|
32
34
|
/**
|
|
33
|
-
* Creates an instance of the class registered for the given base class and key.
|
|
35
|
+
* Creates an instance of the class registered for the given base class and key.
|
|
36
|
+
* If no registration is found, will return an instance of the base class.
|
|
34
37
|
*/
|
|
35
38
|
CreateInstance<T>(baseClass: any, key?: string, ...params: any[]): T | null;
|
|
36
39
|
/**
|
|
@@ -44,5 +47,13 @@ export declare class ClassFactory {
|
|
|
44
47
|
* Returns the registration with the highest priority for a given base class and key. If key is not provided, will return the registration with the highest priority for the base class.
|
|
45
48
|
*/
|
|
46
49
|
GetRegistration(baseClass: any, key?: string): ClassRegistration;
|
|
50
|
+
/**
|
|
51
|
+
* Returns all registrations that have the specified root class, regardless of what base class was used in the registration.
|
|
52
|
+
* This is useful for finding all registrations in a class hierarchy.
|
|
53
|
+
* @param rootClass The root class to search for
|
|
54
|
+
* @param key Optional key to filter results
|
|
55
|
+
* @returns Array of matching registrations
|
|
56
|
+
*/
|
|
57
|
+
GetRegistrationsByRootClass(rootClass: any, key?: string): ClassRegistration[];
|
|
47
58
|
}
|
|
48
59
|
//# sourceMappingURL=ClassFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassFactory.d.ts","sourceRoot":"","sources":["../src/ClassFactory.ts"],"names":[],"mappings":"AAAA;;;;;;wGAMwG;
|
|
1
|
+
{"version":3,"file":"ClassFactory.d.ts","sourceRoot":"","sources":["../src/ClassFactory.ts"],"names":[],"mappings":"AAAA;;;;;;wGAMwG;AAIxG;;GAEG;AACH,qBAAa,iBAAiB;IAC1B,SAAS,EAAE,GAAG,CAAA;IACd,QAAQ,EAAE,GAAG,CAAA;IACb,SAAS,EAAE,GAAG,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IAEX,QAAQ,EAAE,MAAM,CAAA;CACnB;AAGD;;;GAGG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,cAAc,CAA2B;IAEjD;;;;;;;;OAQG;IACI,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAE,MAAa,EAAE,QAAQ,GAAE,MAAU,EAAE,kBAAkB,GAAE,OAAe,EAAE,yBAAyB,GAAE,OAAc,GAAG,IAAI;IAmD9K;;;OAGG;IACI,cAAc,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,GAAE,MAAa,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI;IAqBxF;;;;;OAKG;IACI,mBAAmB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAE,MAAkB,GAAG,iBAAiB,EAAE;IAWxF;;OAEG;IACI,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAE,MAAkB,GAAG,iBAAiB;IAoBlF;;;;;;OAMG;IACI,2BAA2B,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAE,MAAkB,GAAG,iBAAiB,EAAE;CASnG"}
|
package/dist/ClassFactory.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
******************************************************************************************************/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.ClassFactory = exports.ClassRegistration = void 0;
|
|
11
|
+
const ClassUtils_1 = require("./ClassUtils");
|
|
11
12
|
/**
|
|
12
13
|
* Data structure to track the class registrations
|
|
13
14
|
*/
|
|
@@ -29,19 +30,28 @@ class ClassFactory {
|
|
|
29
30
|
* @param key A key can be used to differentiate registrations for the same base class/sub-class combination. For example, in the case of BaseEntity and Entity object subclasses we'll have a LOT of entries and we want to get the highest priority registered sub-class for a specific key. In that case, the key is the entity name, but the key can be any value you want to use to differentiate registrations.
|
|
30
31
|
* @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.
|
|
31
32
|
* @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.
|
|
33
|
+
* @param autoRegisterWithRootClass If true (default), will automatically register the subclass with the root class of the baseClass hierarchy. This ensures proper priority ordering when multiple subclasses are registered in a hierarchy.
|
|
32
34
|
*/
|
|
33
|
-
Register(baseClass, subClass, key = null, priority = 0, skipNullKeyWarning = false) {
|
|
35
|
+
Register(baseClass, subClass, key = null, priority = 0, skipNullKeyWarning = false, autoRegisterWithRootClass = true) {
|
|
34
36
|
if (baseClass && subClass) {
|
|
35
37
|
if (key === undefined || key === null && !skipNullKeyWarning) {
|
|
36
38
|
console.warn(`ClassFactory.GetAllRegistrations: Registration for base class ${baseClass.name} has no key set. This is not recommended and may lead to unintended behavior when trying to match registrations. Please set a key for this registration.`);
|
|
37
39
|
}
|
|
38
|
-
//
|
|
39
|
-
const
|
|
40
|
+
// Get the root class for this registration
|
|
41
|
+
const rootClass = (0, ClassUtils_1.GetRootClass)(baseClass);
|
|
42
|
+
// Determine which class to actually register against
|
|
43
|
+
const effectiveBaseClass = autoRegisterWithRootClass ? rootClass : baseClass;
|
|
44
|
+
// Log if we're auto-registering with root class
|
|
45
|
+
if (autoRegisterWithRootClass && effectiveBaseClass !== baseClass) {
|
|
46
|
+
console.info(`ClassFactory.Register: Auto-registering ${subClass.name} with root class ${rootClass.name} instead of ${baseClass.name}`);
|
|
47
|
+
}
|
|
48
|
+
// get all of the existing registrations for the effective base class and key
|
|
49
|
+
const registrations = this.GetAllRegistrations(effectiveBaseClass, key);
|
|
40
50
|
if (priority > 0) {
|
|
41
|
-
// validate to make sure that the
|
|
51
|
+
// validate to make sure that the combination of base class and key for the provided priority # is not already registered, if it is, then print a warning
|
|
42
52
|
const existing = registrations.filter(r => r.Priority === priority);
|
|
43
53
|
if (existing && existing.length > 0) {
|
|
44
|
-
console.warn(`*** ClassFactory.Register: Registering class ${subClass.name} for base class ${
|
|
54
|
+
console.warn(`*** ClassFactory.Register: Registering class ${subClass.name} for base class ${effectiveBaseClass.name} and key/priority ${key}/${priority}. ${existing.length} registrations already exist for that combination. While this is allowed it is not desired and when matching class requests occur, we will simply use the LAST registration we happen to have which can lead to unintended behavior. ***`);
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
else if (priority === 0 || priority === null || priority === undefined) {
|
|
@@ -57,15 +67,17 @@ class ClassFactory {
|
|
|
57
67
|
}
|
|
58
68
|
// this combination of baseclass/key/priority is NOT already registered.
|
|
59
69
|
let reg = new ClassRegistration();
|
|
60
|
-
reg.BaseClass =
|
|
70
|
+
reg.BaseClass = effectiveBaseClass;
|
|
61
71
|
reg.SubClass = subClass;
|
|
72
|
+
reg.RootClass = rootClass;
|
|
62
73
|
reg.Key = key;
|
|
63
74
|
reg.Priority = priority;
|
|
64
75
|
this._registrations.push(reg);
|
|
65
76
|
}
|
|
66
77
|
}
|
|
67
78
|
/**
|
|
68
|
-
* Creates an instance of the class registered for the given base class and key.
|
|
79
|
+
* Creates an instance of the class registered for the given base class and key.
|
|
80
|
+
* If no registration is found, will return an instance of the base class.
|
|
69
81
|
*/
|
|
70
82
|
CreateInstance(baseClass, key = null, ...params) {
|
|
71
83
|
if (baseClass) {
|
|
@@ -120,6 +132,22 @@ class ClassFactory {
|
|
|
120
132
|
}
|
|
121
133
|
return null;
|
|
122
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns all registrations that have the specified root class, regardless of what base class was used in the registration.
|
|
137
|
+
* This is useful for finding all registrations in a class hierarchy.
|
|
138
|
+
* @param rootClass The root class to search for
|
|
139
|
+
* @param key Optional key to filter results
|
|
140
|
+
* @returns Array of matching registrations
|
|
141
|
+
*/
|
|
142
|
+
GetRegistrationsByRootClass(rootClass, key = undefined) {
|
|
143
|
+
if (rootClass) {
|
|
144
|
+
return this._registrations.filter(r => {
|
|
145
|
+
return r.RootClass?.name === rootClass.name &&
|
|
146
|
+
(key === undefined || key === null ? true : r.Key?.trim().toLowerCase() === key.trim().toLowerCase());
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
123
151
|
}
|
|
124
152
|
exports.ClassFactory = ClassFactory;
|
|
125
153
|
//# sourceMappingURL=ClassFactory.js.map
|
package/dist/ClassFactory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassFactory.js","sourceRoot":"","sources":["../src/ClassFactory.ts"],"names":[],"mappings":";AAAA;;;;;;wGAMwG;;;AAExG;;GAEG;AACH,MAAa,iBAAiB;
|
|
1
|
+
{"version":3,"file":"ClassFactory.js","sourceRoot":"","sources":["../src/ClassFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for working with class hierarchies and reflection
|
|
3
|
+
*/
|
|
4
|
+
export interface ClassInfo {
|
|
5
|
+
/**
|
|
6
|
+
* The name of the class
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Reference to the class constructor
|
|
11
|
+
*/
|
|
12
|
+
reference: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Gets the immediate superclass of the given class
|
|
16
|
+
* @param ClassRef The class constructor reference
|
|
17
|
+
* @returns The superclass constructor or null if no superclass
|
|
18
|
+
*/
|
|
19
|
+
export declare function GetSuperclass(ClassRef: any): any | null;
|
|
20
|
+
/**
|
|
21
|
+
* Gets the root class in the inheritance chain (the topmost user-defined class)
|
|
22
|
+
* @param ClassRef The class constructor reference
|
|
23
|
+
* @returns The root class constructor
|
|
24
|
+
*/
|
|
25
|
+
export declare function GetRootClass(ClassRef: any): any;
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a class is a subclass of another class (at any level in the inheritance hierarchy)
|
|
28
|
+
* Note: This checks the entire inheritance chain, not just the immediate parent
|
|
29
|
+
* @param PotentialSubclass The potential subclass constructor
|
|
30
|
+
* @param PotentialAncestor The potential ancestor class constructor
|
|
31
|
+
* @returns True if PotentialSubclass inherits from PotentialAncestor at any level
|
|
32
|
+
*/
|
|
33
|
+
export declare function IsSubclassOf(PotentialSubclass: any, PotentialAncestor: any): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Checks if a class is a root class (has no user-defined superclass)
|
|
36
|
+
* @param ClassRef The class constructor reference
|
|
37
|
+
* @returns True if the class has no superclass
|
|
38
|
+
*/
|
|
39
|
+
export declare function IsRootClass(ClassRef: any): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Checks if a class is a descendant of another class (at any level in the hierarchy)
|
|
42
|
+
* This is an alias for IsSubclassOf with a more descriptive name
|
|
43
|
+
* @param PotentialDescendant The potential descendant class constructor
|
|
44
|
+
* @param PotentialAncestor The potential ancestor class constructor
|
|
45
|
+
* @returns True if PotentialDescendant inherits from PotentialAncestor at any level
|
|
46
|
+
*/
|
|
47
|
+
export declare function IsDescendantClassOf(PotentialDescendant: any, PotentialAncestor: any): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Gets the complete inheritance chain for a class
|
|
50
|
+
* @param ClassRef The class constructor reference
|
|
51
|
+
* @returns Array of ClassInfo objects, ordered from immediate superclass to root
|
|
52
|
+
*/
|
|
53
|
+
export declare function GetClassInheritance(ClassRef: any): ClassInfo[];
|
|
54
|
+
/**
|
|
55
|
+
* Gets the complete class hierarchy including the class itself
|
|
56
|
+
* @param ClassRef The class constructor reference
|
|
57
|
+
* @returns Array of ClassInfo objects, ordered from the class itself up to root
|
|
58
|
+
*/
|
|
59
|
+
export declare function GetFullClassHierarchy(ClassRef: any): ClassInfo[];
|
|
60
|
+
/**
|
|
61
|
+
* Checks if a value is a class constructor (not an instance)
|
|
62
|
+
* @param value The value to check
|
|
63
|
+
* @returns True if the value is a class constructor
|
|
64
|
+
*/
|
|
65
|
+
export declare function IsClassConstructor(value: any): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Gets the class name safely, handling minification and anonymous classes
|
|
68
|
+
* @param ClassRef The class constructor reference
|
|
69
|
+
* @returns The class name or a fallback string
|
|
70
|
+
*/
|
|
71
|
+
export declare function GetClassName(ClassRef: any): string;
|
|
72
|
+
//# sourceMappingURL=ClassUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClassUtils.d.ts","sourceRoot":"","sources":["../src/ClassUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAavD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAqB/C;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,GAAG,OAAO,CA6BpF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAWlD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,mBAAmB,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,GAAG,OAAO,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE,CAwB9D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,EAAE,CAwBhE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAqBtD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,CAkBlD"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for working with class hierarchies and reflection
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GetClassName = exports.IsClassConstructor = exports.GetFullClassHierarchy = exports.GetClassInheritance = exports.IsDescendantClassOf = exports.IsRootClass = exports.IsSubclassOf = exports.GetRootClass = exports.GetSuperclass = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the immediate superclass of the given class
|
|
9
|
+
* @param ClassRef The class constructor reference
|
|
10
|
+
* @returns The superclass constructor or null if no superclass
|
|
11
|
+
*/
|
|
12
|
+
function GetSuperclass(ClassRef) {
|
|
13
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const superclass = Object.getPrototypeOf(ClassRef);
|
|
17
|
+
// Check if we've reached the top of the chain
|
|
18
|
+
if (!superclass || superclass === Function.prototype || superclass.constructor === Function) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return superclass;
|
|
22
|
+
}
|
|
23
|
+
exports.GetSuperclass = GetSuperclass;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the root class in the inheritance chain (the topmost user-defined class)
|
|
26
|
+
* @param ClassRef The class constructor reference
|
|
27
|
+
* @returns The root class constructor
|
|
28
|
+
*/
|
|
29
|
+
function GetRootClass(ClassRef) {
|
|
30
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
31
|
+
return ClassRef;
|
|
32
|
+
}
|
|
33
|
+
let current = ClassRef;
|
|
34
|
+
let previous = ClassRef;
|
|
35
|
+
while (current) {
|
|
36
|
+
const superclass = Object.getPrototypeOf(current);
|
|
37
|
+
// Stop when we reach built-in prototypes
|
|
38
|
+
if (!superclass || superclass === Function.prototype || superclass.constructor === Function) {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
previous = current;
|
|
42
|
+
current = superclass;
|
|
43
|
+
}
|
|
44
|
+
return previous;
|
|
45
|
+
}
|
|
46
|
+
exports.GetRootClass = GetRootClass;
|
|
47
|
+
/**
|
|
48
|
+
* Checks if a class is a subclass of another class (at any level in the inheritance hierarchy)
|
|
49
|
+
* Note: This checks the entire inheritance chain, not just the immediate parent
|
|
50
|
+
* @param PotentialSubclass The potential subclass constructor
|
|
51
|
+
* @param PotentialAncestor The potential ancestor class constructor
|
|
52
|
+
* @returns True if PotentialSubclass inherits from PotentialAncestor at any level
|
|
53
|
+
*/
|
|
54
|
+
function IsSubclassOf(PotentialSubclass, PotentialAncestor) {
|
|
55
|
+
if (!PotentialSubclass || !PotentialAncestor ||
|
|
56
|
+
typeof PotentialSubclass !== 'function' ||
|
|
57
|
+
typeof PotentialAncestor !== 'function') {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// Check if they're the same class
|
|
61
|
+
if (PotentialSubclass === PotentialAncestor) {
|
|
62
|
+
return false; // A class is not a subclass of itself
|
|
63
|
+
}
|
|
64
|
+
// Walk up the prototype chain
|
|
65
|
+
let current = PotentialSubclass;
|
|
66
|
+
while (current) {
|
|
67
|
+
current = Object.getPrototypeOf(current);
|
|
68
|
+
if (current === PotentialAncestor) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
// Stop when we reach built-in prototypes
|
|
72
|
+
if (!current || current === Function.prototype || current.constructor === Function) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
exports.IsSubclassOf = IsSubclassOf;
|
|
79
|
+
/**
|
|
80
|
+
* Checks if a class is a root class (has no user-defined superclass)
|
|
81
|
+
* @param ClassRef The class constructor reference
|
|
82
|
+
* @returns True if the class has no superclass
|
|
83
|
+
*/
|
|
84
|
+
function IsRootClass(ClassRef) {
|
|
85
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const superclass = Object.getPrototypeOf(ClassRef);
|
|
89
|
+
// It's a root class if it has no superclass or only inherits from built-in prototypes
|
|
90
|
+
return !superclass ||
|
|
91
|
+
superclass === Function.prototype ||
|
|
92
|
+
superclass.constructor === Function;
|
|
93
|
+
}
|
|
94
|
+
exports.IsRootClass = IsRootClass;
|
|
95
|
+
/**
|
|
96
|
+
* Checks if a class is a descendant of another class (at any level in the hierarchy)
|
|
97
|
+
* This is an alias for IsSubclassOf with a more descriptive name
|
|
98
|
+
* @param PotentialDescendant The potential descendant class constructor
|
|
99
|
+
* @param PotentialAncestor The potential ancestor class constructor
|
|
100
|
+
* @returns True if PotentialDescendant inherits from PotentialAncestor at any level
|
|
101
|
+
*/
|
|
102
|
+
function IsDescendantClassOf(PotentialDescendant, PotentialAncestor) {
|
|
103
|
+
return IsSubclassOf(PotentialDescendant, PotentialAncestor);
|
|
104
|
+
}
|
|
105
|
+
exports.IsDescendantClassOf = IsDescendantClassOf;
|
|
106
|
+
/**
|
|
107
|
+
* Gets the complete inheritance chain for a class
|
|
108
|
+
* @param ClassRef The class constructor reference
|
|
109
|
+
* @returns Array of ClassInfo objects, ordered from immediate superclass to root
|
|
110
|
+
*/
|
|
111
|
+
function GetClassInheritance(ClassRef) {
|
|
112
|
+
const chain = [];
|
|
113
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
114
|
+
return chain;
|
|
115
|
+
}
|
|
116
|
+
let current = Object.getPrototypeOf(ClassRef);
|
|
117
|
+
while (current) {
|
|
118
|
+
// Stop when we reach built-in prototypes
|
|
119
|
+
if (current === Function.prototype || current.constructor === Function) {
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
chain.push({
|
|
123
|
+
name: current.name || 'Anonymous',
|
|
124
|
+
reference: current
|
|
125
|
+
});
|
|
126
|
+
current = Object.getPrototypeOf(current);
|
|
127
|
+
}
|
|
128
|
+
return chain;
|
|
129
|
+
}
|
|
130
|
+
exports.GetClassInheritance = GetClassInheritance;
|
|
131
|
+
/**
|
|
132
|
+
* Gets the complete class hierarchy including the class itself
|
|
133
|
+
* @param ClassRef The class constructor reference
|
|
134
|
+
* @returns Array of ClassInfo objects, ordered from the class itself up to root
|
|
135
|
+
*/
|
|
136
|
+
function GetFullClassHierarchy(ClassRef) {
|
|
137
|
+
const chain = [];
|
|
138
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
139
|
+
return chain;
|
|
140
|
+
}
|
|
141
|
+
let current = ClassRef;
|
|
142
|
+
while (current) {
|
|
143
|
+
// Stop when we reach built-in prototypes
|
|
144
|
+
if (current === Function.prototype || current.constructor === Function) {
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
chain.push({
|
|
148
|
+
name: current.name || 'Anonymous',
|
|
149
|
+
reference: current
|
|
150
|
+
});
|
|
151
|
+
current = Object.getPrototypeOf(current);
|
|
152
|
+
}
|
|
153
|
+
return chain;
|
|
154
|
+
}
|
|
155
|
+
exports.GetFullClassHierarchy = GetFullClassHierarchy;
|
|
156
|
+
/**
|
|
157
|
+
* Checks if a value is a class constructor (not an instance)
|
|
158
|
+
* @param value The value to check
|
|
159
|
+
* @returns True if the value is a class constructor
|
|
160
|
+
*/
|
|
161
|
+
function IsClassConstructor(value) {
|
|
162
|
+
if (typeof value !== 'function') {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
// Check if it's a class by looking at its string representation
|
|
166
|
+
const fnString = value.toString();
|
|
167
|
+
// ES6 classes start with "class"
|
|
168
|
+
if (fnString.startsWith('class ')) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
// Check for constructor functions that might be transpiled classes
|
|
172
|
+
// They typically have a prototype with a constructor property
|
|
173
|
+
if (value.prototype && value.prototype.constructor === value) {
|
|
174
|
+
// Additional check: does it look like it's meant to be instantiated?
|
|
175
|
+
return fnString.includes('this.') || Object.getOwnPropertyNames(value.prototype).length > 1;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
exports.IsClassConstructor = IsClassConstructor;
|
|
180
|
+
/**
|
|
181
|
+
* Gets the class name safely, handling minification and anonymous classes
|
|
182
|
+
* @param ClassRef The class constructor reference
|
|
183
|
+
* @returns The class name or a fallback string
|
|
184
|
+
*/
|
|
185
|
+
function GetClassName(ClassRef) {
|
|
186
|
+
if (!ClassRef || typeof ClassRef !== 'function') {
|
|
187
|
+
return 'Unknown';
|
|
188
|
+
}
|
|
189
|
+
// Try to get the name property
|
|
190
|
+
if (ClassRef.name) {
|
|
191
|
+
return ClassRef.name;
|
|
192
|
+
}
|
|
193
|
+
// Try to extract from toString() as fallback
|
|
194
|
+
const fnString = ClassRef.toString();
|
|
195
|
+
const match = fnString.match(/^class\s+(\w+)/);
|
|
196
|
+
if (match && match[1]) {
|
|
197
|
+
return match[1];
|
|
198
|
+
}
|
|
199
|
+
return 'Anonymous';
|
|
200
|
+
}
|
|
201
|
+
exports.GetClassName = GetClassName;
|
|
202
|
+
//# sourceMappingURL=ClassUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClassUtils.js","sourceRoot":"","sources":["../src/ClassUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Deep difference comparison utility for JavaScript objects
|
|
3
|
+
*
|
|
4
|
+
* This module provides comprehensive utilities to generate detailed diffs between
|
|
5
|
+
* any two JavaScript objects, arrays, or primitive values. It recursively traverses
|
|
6
|
+
* nested structures and produces both machine-readable change objects and human-readable
|
|
7
|
+
* formatted output.
|
|
8
|
+
*
|
|
9
|
+
* Key features:
|
|
10
|
+
* - Deep recursive comparison of objects and arrays
|
|
11
|
+
* - Configurable depth limits and output formatting
|
|
12
|
+
* - Path tracking for nested changes
|
|
13
|
+
* - Summary statistics for change types
|
|
14
|
+
* - Human-readable formatted output
|
|
15
|
+
* - Type-safe change tracking
|
|
16
|
+
*
|
|
17
|
+
* @module @memberjunction/global
|
|
18
|
+
* @author MemberJunction.com
|
|
19
|
+
* @since 2.63.0
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const differ = new DeepDiffer();
|
|
24
|
+
* const diff = differ.diff(
|
|
25
|
+
* { name: 'John', age: 30, hobbies: ['reading'] },
|
|
26
|
+
* { name: 'John', age: 31, hobbies: ['reading', 'gaming'] }
|
|
27
|
+
* );
|
|
28
|
+
* console.log(diff.formatted);
|
|
29
|
+
* // Output:
|
|
30
|
+
* // Modified: age
|
|
31
|
+
* // Changed from 30 to 31
|
|
32
|
+
* // Modified: hobbies
|
|
33
|
+
* // Array length changed from 1 to 2
|
|
34
|
+
* // Added: hobbies[1]
|
|
35
|
+
* // Added "gaming"
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Types of changes that can occur in a deep diff operation
|
|
40
|
+
*/
|
|
41
|
+
export declare enum DiffChangeType {
|
|
42
|
+
/** A new property or value was added */
|
|
43
|
+
Added = "added",
|
|
44
|
+
/** An existing property or value was removed */
|
|
45
|
+
Removed = "removed",
|
|
46
|
+
/** An existing value was changed to a different value */
|
|
47
|
+
Modified = "modified",
|
|
48
|
+
/** No change detected (only included when includeUnchanged is true) */
|
|
49
|
+
Unchanged = "unchanged"
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Represents a single change detected during diff operation
|
|
53
|
+
*/
|
|
54
|
+
export interface DiffChange {
|
|
55
|
+
/** The path to the changed value (e.g., "user.profile.name" or "items[2].id") */
|
|
56
|
+
path: string;
|
|
57
|
+
/** The type of change that occurred */
|
|
58
|
+
type: DiffChangeType;
|
|
59
|
+
/** The original value (undefined for Added changes) */
|
|
60
|
+
oldValue?: any;
|
|
61
|
+
/** The new value (undefined for Removed changes) */
|
|
62
|
+
newValue?: any;
|
|
63
|
+
/** Human-readable description of the change */
|
|
64
|
+
description: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Complete result of a deep diff operation
|
|
68
|
+
*/
|
|
69
|
+
export interface DeepDiffResult {
|
|
70
|
+
/** Array of all detected changes */
|
|
71
|
+
changes: DiffChange[];
|
|
72
|
+
/** Summary statistics about the diff */
|
|
73
|
+
summary: {
|
|
74
|
+
/** Number of properties/values that were added */
|
|
75
|
+
added: number;
|
|
76
|
+
/** Number of properties/values that were removed */
|
|
77
|
+
removed: number;
|
|
78
|
+
/** Number of properties/values that were modified */
|
|
79
|
+
modified: number;
|
|
80
|
+
/** Number of properties/values that remained unchanged (if tracked) */
|
|
81
|
+
unchanged: number;
|
|
82
|
+
/** Total number of paths examined */
|
|
83
|
+
totalPaths: number;
|
|
84
|
+
};
|
|
85
|
+
/** Human-readable formatted diff output suitable for display or logging */
|
|
86
|
+
formatted: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Configuration options for deep diff generation
|
|
90
|
+
*/
|
|
91
|
+
export interface DeepDiffConfig {
|
|
92
|
+
/**
|
|
93
|
+
* Whether to include unchanged paths in the diff results.
|
|
94
|
+
* Useful for seeing the complete structure comparison.
|
|
95
|
+
* @default false
|
|
96
|
+
*/
|
|
97
|
+
includeUnchanged: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Maximum depth to traverse in nested objects.
|
|
100
|
+
* Prevents infinite recursion and controls performance.
|
|
101
|
+
* @default 10
|
|
102
|
+
*/
|
|
103
|
+
maxDepth: number;
|
|
104
|
+
/**
|
|
105
|
+
* Maximum string length before truncation in formatted output.
|
|
106
|
+
* Helps keep the output readable for large text values.
|
|
107
|
+
* @default 100
|
|
108
|
+
*/
|
|
109
|
+
maxStringLength: number;
|
|
110
|
+
/**
|
|
111
|
+
* Whether to include array indices in paths (e.g., "items[0]" vs "items").
|
|
112
|
+
* Provides more precise change tracking for arrays.
|
|
113
|
+
* @default true
|
|
114
|
+
*/
|
|
115
|
+
includeArrayIndices: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Custom value formatter for the formatted output.
|
|
118
|
+
* Allows customization of how values are displayed.
|
|
119
|
+
* @param value - The value to format
|
|
120
|
+
* @param type - The type of the value
|
|
121
|
+
* @returns Formatted string representation
|
|
122
|
+
*/
|
|
123
|
+
valueFormatter?: (value: any, type: string) => string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Deep difference generator for comparing JavaScript objects, arrays, and primitives.
|
|
127
|
+
*
|
|
128
|
+
* This class provides comprehensive comparison capabilities with configurable
|
|
129
|
+
* output formatting and depth control.
|
|
130
|
+
*/
|
|
131
|
+
export declare class DeepDiffer {
|
|
132
|
+
private config;
|
|
133
|
+
/**
|
|
134
|
+
* Creates a new DeepDiffer instance
|
|
135
|
+
* @param config - Optional configuration overrides
|
|
136
|
+
*/
|
|
137
|
+
constructor(config?: Partial<DeepDiffConfig>);
|
|
138
|
+
/**
|
|
139
|
+
* Generate a deep diff between two values
|
|
140
|
+
*
|
|
141
|
+
* @param oldValue - The original value
|
|
142
|
+
* @param newValue - The new value to compare against
|
|
143
|
+
* @returns Complete diff results including changes, summary, and formatted output
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const differ = new DeepDiffer({ includeUnchanged: true });
|
|
148
|
+
* const result = differ.diff(
|
|
149
|
+
* { users: [{ id: 1, name: 'Alice' }] },
|
|
150
|
+
* { users: [{ id: 1, name: 'Alice Cooper' }] }
|
|
151
|
+
* );
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
diff<T = any>(oldValue: T, newValue: T): DeepDiffResult;
|
|
155
|
+
/**
|
|
156
|
+
* Update configuration options
|
|
157
|
+
* @param config - Partial configuration to merge with existing config
|
|
158
|
+
*/
|
|
159
|
+
updateConfig(config: Partial<DeepDiffConfig>): void;
|
|
160
|
+
/**
|
|
161
|
+
* Recursively generate diff between two values
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
private generateDiff;
|
|
165
|
+
/**
|
|
166
|
+
* Compare two arrays and generate diff
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
private diffArrays;
|
|
170
|
+
/**
|
|
171
|
+
* Compare two objects and generate diff
|
|
172
|
+
* @private
|
|
173
|
+
*/
|
|
174
|
+
private diffObjects;
|
|
175
|
+
/**
|
|
176
|
+
* Create a human-readable description of a value
|
|
177
|
+
* @private
|
|
178
|
+
*/
|
|
179
|
+
private describeValue;
|
|
180
|
+
/**
|
|
181
|
+
* Get a description of a value for display
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
private getValueDescription;
|
|
185
|
+
/**
|
|
186
|
+
* Format the diff results as a human-readable string
|
|
187
|
+
* @private
|
|
188
|
+
*/
|
|
189
|
+
private formatDiff;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=DeepDiff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeepDiff.d.ts","sourceRoot":"","sources":["../src/DeepDiff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAIH;;GAEG;AACH,oBAAY,cAAc;IACtB,wCAAwC;IACxC,KAAK,UAAU;IACf,gDAAgD;IAChD,OAAO,YAAY;IACnB,yDAAyD;IACzD,QAAQ,aAAa;IACrB,uEAAuE;IACvE,SAAS,cAAc;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,cAAc,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,oCAAoC;IACpC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,wCAAwC;IACxC,OAAO,EAAE;QACL,kDAAkD;QAClD,KAAK,EAAE,MAAM,CAAC;QACd,oDAAoD;QACpD,OAAO,EAAE,MAAM,CAAC;QAChB,qDAAqD;QACrD,QAAQ,EAAE,MAAM,CAAC;QACjB,uEAAuE;QACvE,SAAS,EAAE,MAAM,CAAC;QAClB,qCAAqC;QACrC,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACzD;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAiB;IAE/B;;;OAGG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAU5C;;;;;;;;;;;;;;;OAeG;IACI,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,cAAc;IAkC9D;;;OAGG;IACI,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAI1D;;;OAGG;IACH,OAAO,CAAC,YAAY;IAuDpB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAkDlB;;;OAGG;IACH,OAAO,CAAC,WAAW;IA0BnB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAUrB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;OAGG;IACH,OAAO,CAAC,UAAU;CAsCrB"}
|