@memberjunction/react-runtime 6.2.0-edge.0 → 6.2.0-edge.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +14 -14
- package/CHANGELOG.md +93 -0
- package/dist/compiler/babel-config.d.ts +14 -0
- package/dist/compiler/babel-config.d.ts.map +1 -1
- package/dist/compiler/babel-config.js +12 -3
- package/dist/compiler/babel-config.js.map +1 -1
- package/dist/compiler/component-compiler.d.ts +5 -0
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +24 -9
- package/dist/compiler/component-compiler.js.map +1 -1
- package/dist/compiler/index.d.ts +1 -1
- package/dist/compiler/index.d.ts.map +1 -1
- package/dist/compiler/index.js +1 -1
- package/dist/compiler/index.js.map +1 -1
- package/dist/component-manager/component-manager.d.ts +8 -0
- package/dist/component-manager/component-manager.d.ts.map +1 -1
- package/dist/component-manager/component-manager.js +18 -6
- package/dist/component-manager/component-manager.js.map +1 -1
- package/dist/index.d.ts +21 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/dist/registry/component-registry-service.d.ts +18 -0
- package/dist/registry/component-registry-service.d.ts.map +1 -1
- package/dist/registry/component-registry-service.js +65 -23
- package/dist/registry/component-registry-service.js.map +1 -1
- package/dist/registry/component-registry.d.ts +24 -1
- package/dist/registry/component-registry.d.ts.map +1 -1
- package/dist/registry/component-registry.js +74 -23
- package/dist/registry/component-registry.js.map +1 -1
- package/dist/registry/component-resolver.d.ts +10 -0
- package/dist/registry/component-resolver.d.ts.map +1 -1
- package/dist/registry/component-resolver.js +30 -9
- package/dist/registry/component-resolver.js.map +1 -1
- package/dist/registry/registry-provider.js.map +1 -1
- package/dist/runtime/component-hierarchy.d.ts +15 -0
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +28 -10
- package/dist/runtime/component-hierarchy.js.map +1 -1
- package/dist/runtime/error-boundary.d.ts +4 -0
- package/dist/runtime/error-boundary.d.ts.map +1 -1
- package/dist/runtime/error-boundary.js +50 -20
- package/dist/runtime/error-boundary.js.map +1 -1
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +3 -3
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/prop-builder.d.ts +8 -0
- package/dist/runtime/prop-builder.d.ts.map +1 -1
- package/dist/runtime/prop-builder.js +39 -11
- package/dist/runtime/prop-builder.js.map +1 -1
- package/dist/runtime/react-root-manager.d.ts +10 -0
- package/dist/runtime/react-root-manager.d.ts.map +1 -1
- package/dist/runtime/react-root-manager.js +27 -9
- package/dist/runtime/react-root-manager.js.map +1 -1
- package/dist/runtime.umd.js +194 -125
- package/dist/utilities/cache-manager.d.ts +13 -0
- package/dist/utilities/cache-manager.d.ts.map +1 -1
- package/dist/utilities/cache-manager.js +40 -16
- package/dist/utilities/cache-manager.js.map +1 -1
- package/dist/utilities/component-error-analyzer.d.ts +3 -0
- package/dist/utilities/component-error-analyzer.d.ts.map +1 -1
- package/dist/utilities/component-error-analyzer.js +12 -3
- package/dist/utilities/component-error-analyzer.js.map +1 -1
- package/dist/utilities/component-hash.d.ts +1 -0
- package/dist/utilities/component-hash.d.ts.map +1 -1
- package/dist/utilities/component-hash.js +4 -1
- package/dist/utilities/component-hash.js.map +1 -1
- package/dist/utilities/component-library-theming.d.ts +4 -0
- package/dist/utilities/component-library-theming.d.ts.map +1 -1
- package/dist/utilities/component-library-theming.js +12 -6
- package/dist/utilities/component-library-theming.js.map +1 -1
- package/dist/utilities/component-styles.d.ts +1 -0
- package/dist/utilities/component-styles.d.ts.map +1 -1
- package/dist/utilities/component-styles.js +2 -1
- package/dist/utilities/component-styles.js.map +1 -1
- package/dist/utilities/component-unwrapper.d.ts +8 -2
- package/dist/utilities/component-unwrapper.d.ts.map +1 -1
- package/dist/utilities/component-unwrapper.js +19 -7
- package/dist/utilities/component-unwrapper.js.map +1 -1
- package/dist/utilities/core-libraries.d.ts +2 -0
- package/dist/utilities/core-libraries.d.ts.map +1 -1
- package/dist/utilities/core-libraries.js +9 -3
- package/dist/utilities/core-libraries.js.map +1 -1
- package/dist/utilities/entity-record-key.d.ts +1 -0
- package/dist/utilities/entity-record-key.d.ts.map +1 -1
- package/dist/utilities/entity-record-key.js +4 -1
- package/dist/utilities/entity-record-key.js.map +1 -1
- package/dist/utilities/library-dependency-resolver.d.ts +8 -0
- package/dist/utilities/library-dependency-resolver.d.ts.map +1 -1
- package/dist/utilities/library-dependency-resolver.js +39 -15
- package/dist/utilities/library-dependency-resolver.js.map +1 -1
- package/dist/utilities/library-loader.d.ts +12 -0
- package/dist/utilities/library-loader.d.ts.map +1 -1
- package/dist/utilities/library-loader.js +46 -16
- package/dist/utilities/library-loader.js.map +1 -1
- package/dist/utilities/library-registry.d.ts +5 -0
- package/dist/utilities/library-registry.d.ts.map +1 -1
- package/dist/utilities/library-registry.js +20 -5
- package/dist/utilities/library-registry.js.map +1 -1
- package/dist/utilities/resource-manager.d.ts +19 -0
- package/dist/utilities/resource-manager.d.ts.map +1 -1
- package/dist/utilities/resource-manager.js +63 -18
- package/dist/utilities/resource-manager.js.map +1 -1
- package/dist/utilities/runtime-utilities.d.ts +9 -7
- package/dist/utilities/runtime-utilities.d.ts.map +1 -1
- package/dist/utilities/runtime-utilities.js +22 -16
- package/dist/utilities/runtime-utilities.js.map +1 -1
- package/dist/utilities/standard-libraries.d.ts +10 -0
- package/dist/utilities/standard-libraries.d.ts.map +1 -1
- package/dist/utilities/standard-libraries.js +40 -10
- package/dist/utilities/standard-libraries.js.map +1 -1
- package/dist/utilities/user-state.d.ts +5 -0
- package/dist/utilities/user-state.d.ts.map +1 -1
- package/dist/utilities/user-state.js +20 -5
- package/dist/utilities/user-state.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/error-boundary.test.ts +80 -0
- package/src/__tests__/runtime-utilities-factory.test.ts +4 -4
- package/src/__tests__/user-state.test.ts +44 -44
- package/src/compiler/babel-config.ts +18 -3
- package/src/compiler/component-compiler.ts +34 -9
- package/src/compiler/index.ts +3 -3
- package/src/component-manager/component-manager.ts +36 -6
- package/src/index.ts +35 -21
- package/src/registry/component-registry-service.ts +126 -23
- package/src/registry/component-registry.ts +122 -24
- package/src/registry/component-resolver.ts +51 -9
- package/src/registry/registry-provider.ts +40 -40
- package/src/runtime/component-hierarchy.ts +61 -10
- package/src/runtime/error-boundary.ts +77 -22
- package/src/runtime/index.ts +16 -16
- package/src/runtime/prop-builder.ts +69 -11
- package/src/runtime/react-root-manager.ts +48 -10
- package/src/utilities/cache-manager.ts +61 -16
- package/src/utilities/component-error-analyzer.ts +18 -3
- package/src/utilities/component-hash.ts +6 -1
- package/src/utilities/component-library-theming.ts +24 -6
- package/src/utilities/component-styles.ts +4 -1
- package/src/utilities/component-unwrapper.ts +34 -7
- package/src/utilities/core-libraries.ts +13 -3
- package/src/utilities/entity-record-key.ts +11 -1
- package/src/utilities/library-dependency-resolver.ts +66 -15
- package/src/utilities/library-loader.ts +81 -17
- package/src/utilities/library-registry.ts +30 -5
- package/src/utilities/resource-manager.ts +126 -19
- package/src/utilities/runtime-utilities.ts +26 -16
- package/src/utilities/standard-libraries.ts +60 -10
- package/src/utilities/user-state.ts +40 -5
|
@@ -8,28 +8,49 @@ const DEFAULT_LIBRARY_CONFIG = {
|
|
|
8
8
|
};
|
|
9
9
|
export class StandardLibraryManager {
|
|
10
10
|
static { this.configuration = DEFAULT_LIBRARY_CONFIG; }
|
|
11
|
-
static
|
|
11
|
+
static SetConfiguration(config) {
|
|
12
12
|
this.configuration = config;
|
|
13
13
|
}
|
|
14
|
-
static
|
|
14
|
+
static setConfiguration(config) {
|
|
15
|
+
return this.SetConfiguration(config);
|
|
16
|
+
}
|
|
17
|
+
static GetConfiguration() {
|
|
15
18
|
return this.configuration;
|
|
16
19
|
}
|
|
17
|
-
static
|
|
20
|
+
static getConfiguration() {
|
|
21
|
+
return this.GetConfiguration();
|
|
22
|
+
}
|
|
23
|
+
static GetEnabledLibraries() {
|
|
18
24
|
return this.configuration.libraries.filter(lib => lib.isEnabled);
|
|
19
25
|
}
|
|
20
|
-
static
|
|
26
|
+
static getEnabledLibraries() {
|
|
27
|
+
return this.GetEnabledLibraries();
|
|
28
|
+
}
|
|
29
|
+
static GetLibrariesByCategory(category) {
|
|
21
30
|
return this.configuration.libraries.filter(lib => lib.category === category && lib.isEnabled);
|
|
22
31
|
}
|
|
23
|
-
static
|
|
32
|
+
static getLibrariesByCategory(category) {
|
|
33
|
+
return this.GetLibrariesByCategory(category);
|
|
34
|
+
}
|
|
35
|
+
static GetCoreLibraries() {
|
|
24
36
|
return this.configuration.libraries.filter(lib => lib.isCore && lib.isEnabled);
|
|
25
37
|
}
|
|
26
|
-
static
|
|
38
|
+
static getCoreLibraries() {
|
|
39
|
+
return this.GetCoreLibraries();
|
|
40
|
+
}
|
|
41
|
+
static GetComponentLibraries() {
|
|
27
42
|
return this.configuration.libraries.filter(lib => !lib.isRuntimeOnly && lib.isEnabled);
|
|
28
43
|
}
|
|
29
|
-
static
|
|
44
|
+
static getComponentLibraries() {
|
|
45
|
+
return this.GetComponentLibraries();
|
|
46
|
+
}
|
|
47
|
+
static GetLibraryById(id) {
|
|
30
48
|
return this.configuration.libraries.find(lib => lib.id === id);
|
|
31
49
|
}
|
|
32
|
-
static
|
|
50
|
+
static getLibraryById(id) {
|
|
51
|
+
return this.GetLibraryById(id);
|
|
52
|
+
}
|
|
53
|
+
static GetLibraryUrls() {
|
|
33
54
|
const urls = {};
|
|
34
55
|
this.configuration.libraries
|
|
35
56
|
.filter(lib => lib.isEnabled)
|
|
@@ -42,11 +63,17 @@ export class StandardLibraryManager {
|
|
|
42
63
|
});
|
|
43
64
|
return urls;
|
|
44
65
|
}
|
|
45
|
-
static
|
|
66
|
+
static getLibraryUrls() {
|
|
67
|
+
return this.GetLibraryUrls();
|
|
68
|
+
}
|
|
69
|
+
static ResetToDefault() {
|
|
46
70
|
this.configuration = DEFAULT_LIBRARY_CONFIG;
|
|
47
71
|
}
|
|
72
|
+
static resetToDefault() {
|
|
73
|
+
return this.ResetToDefault();
|
|
74
|
+
}
|
|
48
75
|
}
|
|
49
|
-
export function
|
|
76
|
+
export function CreateStandardLibraries() {
|
|
50
77
|
if (typeof window === 'undefined') {
|
|
51
78
|
return {};
|
|
52
79
|
}
|
|
@@ -59,4 +86,7 @@ export function createStandardLibraries() {
|
|
|
59
86
|
});
|
|
60
87
|
return libs;
|
|
61
88
|
}
|
|
89
|
+
export function createStandardLibraries() {
|
|
90
|
+
return CreateStandardLibraries();
|
|
91
|
+
}
|
|
62
92
|
//# sourceMappingURL=standard-libraries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard-libraries.js","sourceRoot":"","sources":["../../src/utilities/standard-libraries.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Standard libraries configuration for React components\n * @module @memberjunction/react-runtime/utilities\n */\n\nimport { LibraryConfiguration, ExternalLibraryConfig } from '../types/library-config';\n\n\n/**\n * Type for dynamically loaded libraries available to React components\n */\nexport type StandardLibraries = Record<string, any>;\n\n/**\n * Default empty library configuration\n * Libraries should be configured dynamically at runtime\n */\nconst DEFAULT_LIBRARY_CONFIG: LibraryConfiguration = {\n libraries: [],\n metadata: {\n version: '1.0.0',\n lastUpdated: new Date().toISOString(),\n description: 'Empty default configuration - libraries should be configured at runtime'\n }\n};\n\n/**\n * Manages standard library configurations with dynamic loading support\n */\nexport class StandardLibraryManager {\n private static configuration: LibraryConfiguration = DEFAULT_LIBRARY_CONFIG;\n \n /**\n * Set a custom library configuration\n */\n static
|
|
1
|
+
{"version":3,"file":"standard-libraries.js","sourceRoot":"","sources":["../../src/utilities/standard-libraries.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Standard libraries configuration for React components\n * @module @memberjunction/react-runtime/utilities\n */\n\nimport { LibraryConfiguration, ExternalLibraryConfig } from '../types/library-config';\n\n\n/**\n * Type for dynamically loaded libraries available to React components\n */\nexport type StandardLibraries = Record<string, any>;\n\n/**\n * Default empty library configuration\n * Libraries should be configured dynamically at runtime\n */\nconst DEFAULT_LIBRARY_CONFIG: LibraryConfiguration = {\n libraries: [],\n metadata: {\n version: '1.0.0',\n lastUpdated: new Date().toISOString(),\n description: 'Empty default configuration - libraries should be configured at runtime'\n }\n};\n\n/**\n * Manages standard library configurations with dynamic loading support\n */\nexport class StandardLibraryManager {\n private static configuration: LibraryConfiguration = DEFAULT_LIBRARY_CONFIG;\n \n /**\n * Set a custom library configuration\n */\n static SetConfiguration(config: LibraryConfiguration): void {\n this.configuration = config;\n }\n\n /** @deprecated Use {@link SetConfiguration}. */\n static setConfiguration(config: LibraryConfiguration): void {\n return this.SetConfiguration(config);\n }\n \n /**\n * Get the current library configuration\n */\n static GetConfiguration(): LibraryConfiguration {\n return this.configuration;\n }\n\n /** @deprecated Use {@link GetConfiguration}. */\n static getConfiguration(): LibraryConfiguration {\n return this.GetConfiguration();\n }\n \n /**\n * Get all enabled libraries\n */\n static GetEnabledLibraries(): ExternalLibraryConfig[] {\n return this.configuration.libraries.filter(lib => lib.isEnabled);\n }\n\n /** @deprecated Use {@link GetEnabledLibraries}. */\n static getEnabledLibraries(): ExternalLibraryConfig[] {\n return this.GetEnabledLibraries();\n }\n \n /**\n * Get libraries by category\n */\n static GetLibrariesByCategory(category: ExternalLibraryConfig['category']): ExternalLibraryConfig[] {\n return this.configuration.libraries.filter(lib => lib.category === category && lib.isEnabled);\n }\n\n /** @deprecated Use {@link GetLibrariesByCategory}. */\n static getLibrariesByCategory(category: ExternalLibraryConfig['category']): ExternalLibraryConfig[] {\n return this.GetLibrariesByCategory(category);\n }\n \n /**\n * Get core libraries (runtime essentials)\n */\n static GetCoreLibraries(): ExternalLibraryConfig[] {\n return this.configuration.libraries.filter(lib => lib.isCore && lib.isEnabled);\n }\n\n /** @deprecated Use {@link GetCoreLibraries}. */\n static getCoreLibraries(): ExternalLibraryConfig[] {\n return this.GetCoreLibraries();\n }\n \n /**\n * Get component libraries (non-runtime)\n */\n static GetComponentLibraries(): ExternalLibraryConfig[] {\n return this.configuration.libraries.filter(lib => !lib.isRuntimeOnly && lib.isEnabled);\n }\n\n /** @deprecated Use {@link GetComponentLibraries}. */\n static getComponentLibraries(): ExternalLibraryConfig[] {\n return this.GetComponentLibraries();\n }\n \n /**\n * Get library by ID\n */\n static GetLibraryById(id: string): ExternalLibraryConfig | undefined {\n return this.configuration.libraries.find(lib => lib.id === id);\n }\n\n /** @deprecated Use {@link GetLibraryById}. */\n static getLibraryById(id: string): ExternalLibraryConfig | undefined {\n return this.GetLibraryById(id);\n }\n \n /**\n * Get library URLs as a simple object (for backward compatibility)\n */\n static GetLibraryUrls(): Record<string, string> {\n const urls: Record<string, string> = {};\n this.configuration.libraries\n .filter(lib => lib.isEnabled)\n .forEach(lib => {\n // Use uppercase key for backward compatibility\n const key = lib.id.replace(/-/g, '_').toUpperCase();\n urls[key] = lib.cdnUrl;\n if (lib.cdnCssUrl) {\n urls[`${key}_CSS`] = lib.cdnCssUrl;\n }\n });\n return urls;\n }\n\n /** @deprecated Use {@link GetLibraryUrls}. */\n static getLibraryUrls(): Record<string, string> {\n return this.GetLibraryUrls();\n }\n \n /**\n * Reset to default configuration\n */\n static ResetToDefault(): void {\n this.configuration = DEFAULT_LIBRARY_CONFIG;\n }\n\n /** @deprecated Use {@link ResetToDefault}. */\n static resetToDefault(): void {\n return this.ResetToDefault();\n }\n}\n\n\n/**\n * Creates a standard libraries object for browser environments\n * Dynamically collects all libraries based on current configuration\n */\nexport function CreateStandardLibraries(): StandardLibraries {\n if (typeof window === 'undefined') {\n // Return empty object in Node.js environments\n return {};\n }\n \n const libs: StandardLibraries = {};\n \n // Add all component libraries as globals based on configuration\n StandardLibraryManager.getComponentLibraries().forEach(lib => {\n const globalValue = (window as any)[lib.globalVariable];\n if (globalValue !== undefined) {\n libs[lib.globalVariable] = globalValue;\n }\n });\n \n return libs;\n}\n\n/** @deprecated Use {@link CreateStandardLibraries}. */\nexport function createStandardLibraries(): StandardLibraries {\n return CreateStandardLibraries();\n}"]}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export declare const USER_STATE_KEY_PREFIX = "InteractiveComponents_UserState_Root/";
|
|
2
|
+
export declare function ResolveUserStateScope(explicitScope: string | undefined | null, namespace: string | undefined | null, name: string | undefined | null): string | null;
|
|
2
3
|
export declare function resolveUserStateScope(explicitScope: string | undefined | null, namespace: string | undefined | null, name: string | undefined | null): string | null;
|
|
4
|
+
export declare function UserStateStorageKey(scope: string | null): string | null;
|
|
3
5
|
export declare function userStateStorageKey(scope: string | null): string | null;
|
|
6
|
+
export declare function ParseStoredUserSettings(raw: string | undefined | null): Record<string, unknown>;
|
|
4
7
|
export declare function parseStoredUserSettings(raw: string | undefined | null): Record<string, unknown>;
|
|
8
|
+
export declare function MergeUserSettings(hostDefaults: Record<string, unknown> | undefined | null, stored: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
5
9
|
export declare function mergeUserSettings(hostDefaults: Record<string, unknown> | undefined | null, stored: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
10
|
+
export declare function ApplyUserSettingsUpdate(current: Record<string, unknown> | undefined | null, incoming: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
6
11
|
export declare function applyUserSettingsUpdate(current: Record<string, unknown> | undefined | null, incoming: Record<string, unknown> | undefined | null): Record<string, unknown>;
|
|
7
12
|
//# sourceMappingURL=user-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-state.d.ts","sourceRoot":"","sources":["../../src/utilities/user-state.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,qBAAqB,0CAA0C,CAAC;AAiB7E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACxC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACpC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC9B,MAAM,GAAG,IAAI,CAYf;AAMD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEvE;AAOD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/F;AAOD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACxD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACjD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAsBD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB"}
|
|
1
|
+
{"version":3,"file":"user-state.d.ts","sourceRoot":"","sources":["../../src/utilities/user-state.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,qBAAqB,0CAA0C,CAAC;AAiB7E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACxC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACpC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC9B,MAAM,GAAG,IAAI,CAYf;AAGD,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACxC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACpC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAC9B,MAAM,GAAG,IAAI,CAEf;AAMD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEvE;AAGD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEvE;AAOD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/F;AAGD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/F;AAOD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACxD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACjD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAGD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACxD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACjD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAsBD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAGD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const USER_STATE_KEY_PREFIX = 'InteractiveComponents_UserState_Root/';
|
|
2
|
-
export function
|
|
2
|
+
export function ResolveUserStateScope(explicitScope, namespace, name) {
|
|
3
3
|
const explicit = explicitScope?.trim();
|
|
4
4
|
if (explicit) {
|
|
5
5
|
return explicit.toLowerCase();
|
|
@@ -12,10 +12,16 @@ export function resolveUserStateScope(explicitScope, namespace, name) {
|
|
|
12
12
|
const scope = cleanNamespace ? `${cleanNamespace}/${cleanName}` : cleanName;
|
|
13
13
|
return scope.toLowerCase();
|
|
14
14
|
}
|
|
15
|
-
export function
|
|
15
|
+
export function resolveUserStateScope(explicitScope, namespace, name) {
|
|
16
|
+
return ResolveUserStateScope(explicitScope, namespace, name);
|
|
17
|
+
}
|
|
18
|
+
export function UserStateStorageKey(scope) {
|
|
16
19
|
return scope ? `${USER_STATE_KEY_PREFIX}${scope}` : null;
|
|
17
20
|
}
|
|
18
|
-
export function
|
|
21
|
+
export function userStateStorageKey(scope) {
|
|
22
|
+
return UserStateStorageKey(scope);
|
|
23
|
+
}
|
|
24
|
+
export function ParseStoredUserSettings(raw) {
|
|
19
25
|
if (!raw) {
|
|
20
26
|
return {};
|
|
21
27
|
}
|
|
@@ -30,10 +36,16 @@ export function parseStoredUserSettings(raw) {
|
|
|
30
36
|
return {};
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
|
-
export function
|
|
39
|
+
export function parseStoredUserSettings(raw) {
|
|
40
|
+
return ParseStoredUserSettings(raw);
|
|
41
|
+
}
|
|
42
|
+
export function MergeUserSettings(hostDefaults, stored) {
|
|
34
43
|
return { ...(hostDefaults ?? {}), ...(stored ?? {}) };
|
|
35
44
|
}
|
|
36
|
-
export function
|
|
45
|
+
export function mergeUserSettings(hostDefaults, stored) {
|
|
46
|
+
return MergeUserSettings(hostDefaults, stored);
|
|
47
|
+
}
|
|
48
|
+
export function ApplyUserSettingsUpdate(current, incoming) {
|
|
37
49
|
const next = { ...(current ?? {}) };
|
|
38
50
|
for (const [key, value] of Object.entries(incoming ?? {})) {
|
|
39
51
|
if (value === null || value === undefined) {
|
|
@@ -45,4 +57,7 @@ export function applyUserSettingsUpdate(current, incoming) {
|
|
|
45
57
|
}
|
|
46
58
|
return next;
|
|
47
59
|
}
|
|
60
|
+
export function applyUserSettingsUpdate(current, incoming) {
|
|
61
|
+
return ApplyUserSettingsUpdate(current, incoming);
|
|
62
|
+
}
|
|
48
63
|
//# sourceMappingURL=user-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-state.js","sourceRoot":"","sources":["../../src/utilities/user-state.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,qBAAqB,GAAG,uCAAuC,CAAC;AAiB7E,MAAM,UAAU,qBAAqB,CACnC,aAAwC,EACxC,SAAoC,EACpC,IAA+B;IAE/B,MAAM,QAAQ,GAAG,aAAa,EAAE,IAAI,EAAE,CAAC;IACvC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,cAAc,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC;AAMD,MAAM,UAAU,mBAAmB,CAAC,KAAoB;IACtD,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,qBAAqB,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAOD,MAAM,UAAU,uBAAuB,CAAC,GAA8B;IACpE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,MAAiC,CAAC;QAC3C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAC/B,YAAwD,EACxD,MAAkD;IAElD,OAAO,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAsBD,MAAM,UAAU,uBAAuB,CACrC,OAAmD,EACnD,QAAoD;IAEpD,MAAM,IAAI,GAA4B,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;IAC7D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;QAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["/**\n * @fileoverview Helpers for the per-user interactive-component settings contract\n * (`savedUserSettings` in / `onSaveUserSettings` out).\n *\n * These helpers are intentionally **pure and framework-agnostic** so the Angular\n * host bridge and the Node test harness share one implementation and the scoping /\n * serialization logic can be unit tested in isolation. The host wires these to a\n * durable per-user store (e.g. `UserInfoEngine`); the runtime itself never persists.\n *\n * @module @memberjunction/react-runtime\n */\n\n/**\n * Prefix applied to every interactive-component user-settings storage key. The\n * full key is `InteractiveComponents_UserState_Root/<scope>`, where `<scope>` is\n * resolved by {@link resolveUserStateScope}. It is deliberately long and unique\n * to avoid collisions with other namespaced keys in the shared\n * `MJ: User Settings` keyspace. Keeping the prefix in one place also avoids\n * stringly-typed drift between the seed (read) and persist (write) paths.\n */\nexport const USER_STATE_KEY_PREFIX = 'InteractiveComponents_UserState_Root/';\n\n/**\n * Resolve the stable per-component scope used to namespace a component's\n * persisted user settings.\n *\n * An explicit, host-supplied scope always wins (used when a host needs to\n * differentiate two instances of the same component spec — e.g. scope a form's\n * settings by the entity it edits). Otherwise the scope is derived from the\n * component spec's `namespace` + `name`.\n *\n * The result is lowercased to avoid case-variant duplicate rows in the settings\n * store (per MJ's user-settings key convention).\n *\n * @returns the resolved scope, or `null` when no stable scope can be derived\n * (e.g. an unnamed component) — signaling the caller to skip persistence.\n */\nexport function
|
|
1
|
+
{"version":3,"file":"user-state.js","sourceRoot":"","sources":["../../src/utilities/user-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Helpers for the per-user interactive-component settings contract\n * (`savedUserSettings` in / `onSaveUserSettings` out).\n *\n * These helpers are intentionally **pure and framework-agnostic** so the Angular\n * host bridge and the Node test harness share one implementation and the scoping /\n * serialization logic can be unit tested in isolation. The host wires these to a\n * durable per-user store (e.g. `UserInfoEngine`); the runtime itself never persists.\n *\n * @module @memberjunction/react-runtime\n */\n\n/**\n * Prefix applied to every interactive-component user-settings storage key. The\n * full key is `InteractiveComponents_UserState_Root/<scope>`, where `<scope>` is\n * resolved by {@link resolveUserStateScope}. It is deliberately long and unique\n * to avoid collisions with other namespaced keys in the shared\n * `MJ: User Settings` keyspace. Keeping the prefix in one place also avoids\n * stringly-typed drift between the seed (read) and persist (write) paths.\n */\nexport const USER_STATE_KEY_PREFIX = 'InteractiveComponents_UserState_Root/';\n\n/**\n * Resolve the stable per-component scope used to namespace a component's\n * persisted user settings.\n *\n * An explicit, host-supplied scope always wins (used when a host needs to\n * differentiate two instances of the same component spec — e.g. scope a form's\n * settings by the entity it edits). Otherwise the scope is derived from the\n * component spec's `namespace` + `name`.\n *\n * The result is lowercased to avoid case-variant duplicate rows in the settings\n * store (per MJ's user-settings key convention).\n *\n * @returns the resolved scope, or `null` when no stable scope can be derived\n * (e.g. an unnamed component) — signaling the caller to skip persistence.\n */\nexport function ResolveUserStateScope(\n explicitScope: string | undefined | null,\n namespace: string | undefined | null,\n name: string | undefined | null\n): string | null {\n const explicit = explicitScope?.trim();\n if (explicit) {\n return explicit.toLowerCase();\n }\n const cleanName = name?.trim();\n if (!cleanName) {\n return null;\n }\n const cleanNamespace = namespace?.trim();\n const scope = cleanNamespace ? `${cleanNamespace}/${cleanName}` : cleanName;\n return scope.toLowerCase();\n}\n\n/** @deprecated Use {@link ResolveUserStateScope}. */\nexport function resolveUserStateScope(\n explicitScope: string | undefined | null,\n namespace: string | undefined | null,\n name: string | undefined | null\n): string | null {\n return ResolveUserStateScope(explicitScope, namespace, name);\n}\n\n/**\n * Build the full storage key for a resolved scope, or `null` when the scope is\n * `null` (persistence should be skipped).\n */\nexport function UserStateStorageKey(scope: string | null): string | null {\n return scope ? `${USER_STATE_KEY_PREFIX}${scope}` : null;\n}\n\n/** @deprecated Use {@link UserStateStorageKey}. */\nexport function userStateStorageKey(scope: string | null): string | null {\n return UserStateStorageKey(scope);\n}\n\n/**\n * Safely parse a stored settings blob into a plain object. Returns `{}` for\n * null/empty input, invalid JSON, or any non-object JSON (arrays, primitives) —\n * persisted user settings are always a flat key/value object.\n */\nexport function ParseStoredUserSettings(raw: string | undefined | null): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n return {};\n } catch {\n return {};\n }\n}\n\n/** @deprecated Use {@link ParseStoredUserSettings}. */\nexport function parseStoredUserSettings(raw: string | undefined | null): Record<string, unknown> {\n return ParseStoredUserSettings(raw);\n}\n\n/**\n * Merge host-provided defaults with the stored per-user settings. Stored values\n * win, so a returning user sees their saved preferences while a host can still\n * seed sensible first-run defaults that fill any gaps.\n */\nexport function MergeUserSettings(\n hostDefaults: Record<string, unknown> | undefined | null,\n stored: Record<string, unknown> | undefined | null\n): Record<string, unknown> {\n return { ...(hostDefaults ?? {}), ...(stored ?? {}) };\n}\n\n/** @deprecated Use {@link MergeUserSettings}. */\nexport function mergeUserSettings(\n hostDefaults: Record<string, unknown> | undefined | null,\n stored: Record<string, unknown> | undefined | null\n): Record<string, unknown> {\n return MergeUserSettings(hostDefaults, stored);\n}\n\n/**\n * Apply an `onSaveUserSettings` payload to the host's current settings snapshot.\n *\n * **Merge, not replace.** The contract asks components to pass the complete\n * settings object, but the host must be resilient to a component (especially an\n * AI-generated one) passing only the changed keys — and to the stale-prop case\n * where a component spreads the mount-time `savedUserSettings` prop, which the\n * host deliberately never refreshes mid-session (no re-render on save). Under\n * full-replace semantics either slip silently wipes every other saved\n * preference; under merge the worst case is a no-op.\n *\n * **Removing a key requires explicit intent**: set its value to `null` and the\n * key is deleted from the snapshot (reads fall back to defaults via the\n * documented `savedUserSettings?.key ?? fallback` pattern). `undefined` values\n * are treated the same way, since `JSON.stringify` would drop them from the\n * persisted blob anyway and the in-memory snapshot must stay consistent with\n * what is stored.\n *\n * @returns a new object — neither input is mutated.\n */\nexport function ApplyUserSettingsUpdate(\n current: Record<string, unknown> | undefined | null,\n incoming: Record<string, unknown> | undefined | null\n): Record<string, unknown> {\n const next: Record<string, unknown> = { ...(current ?? {}) };\n for (const [key, value] of Object.entries(incoming ?? {})) {\n if (value === null || value === undefined) {\n delete next[key];\n } else {\n next[key] = value;\n }\n }\n return next;\n}\n\n/** @deprecated Use {@link ApplyUserSettingsUpdate}. */\nexport function applyUserSettingsUpdate(\n current: Record<string, unknown> | undefined | null,\n incoming: Record<string, unknown> | undefined | null\n): Record<string, unknown> {\n return ApplyUserSettingsUpdate(current, incoming);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/react-runtime",
|
|
3
|
-
"version": "6.2.0-edge.
|
|
3
|
+
"version": "6.2.0-edge.2",
|
|
4
4
|
"description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"homepage": "https://github.com/MemberJunction/MJ#readme",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@babel/standalone": "^7.29.1",
|
|
23
|
-
"@memberjunction/ai-vectors-memory": "6.2.0-edge.
|
|
24
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
25
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
26
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
27
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
28
|
-
"@memberjunction/interactive-component-types": "6.2.0-edge.
|
|
23
|
+
"@memberjunction/ai-vectors-memory": "6.2.0-edge.2",
|
|
24
|
+
"@memberjunction/core": "6.2.0-edge.2",
|
|
25
|
+
"@memberjunction/core-entities": "6.2.0-edge.2",
|
|
26
|
+
"@memberjunction/global": "6.2.0-edge.2",
|
|
27
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.2",
|
|
28
|
+
"@memberjunction/interactive-component-types": "6.2.0-edge.2",
|
|
29
29
|
"rxjs": "^7.8.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { CreateErrorBoundary } from '../runtime/error-boundary';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Minimal stand-in for the React the runtime is handed at call time. This package takes
|
|
6
|
+
* React as an injected `any` and has no react dependency of its own, so the tests below
|
|
7
|
+
* reproduce React's calling convention rather than importing the library.
|
|
8
|
+
*/
|
|
9
|
+
function makeFakeReact() {
|
|
10
|
+
return {
|
|
11
|
+
Component: class {
|
|
12
|
+
props: any;
|
|
13
|
+
state: any;
|
|
14
|
+
constructor(props: any) {
|
|
15
|
+
this.props = props;
|
|
16
|
+
}
|
|
17
|
+
setState(update: any) {
|
|
18
|
+
const next = typeof update === 'function' ? update(this.state) : update;
|
|
19
|
+
this.state = { ...this.state, ...next };
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
createElement: (type: any, props: any, ...children: any[]) => ({ type, props, children }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('CreateErrorBoundary — React lifecycle contract', () => {
|
|
27
|
+
/**
|
|
28
|
+
* react-dom reads the static into a local and invokes it with no receiver:
|
|
29
|
+
*
|
|
30
|
+
* var getDerivedStateFromError = fiber.type.getDerivedStateFromError;
|
|
31
|
+
* ... getDerivedStateFromError(error);
|
|
32
|
+
*
|
|
33
|
+
* Anything that reaches `this` in that call throws — and it throws while React is
|
|
34
|
+
* already handling the child's error, so the boundary never renders and the whole
|
|
35
|
+
* tree unmounts. The name must therefore sit on the real declaration, never on a
|
|
36
|
+
* forwarding stub.
|
|
37
|
+
*/
|
|
38
|
+
it('exposes getDerivedStateFromError as a static that survives an unbound call', () => {
|
|
39
|
+
const Boundary = CreateErrorBoundary(makeFakeReact(), { logErrors: false });
|
|
40
|
+
|
|
41
|
+
const getDerivedStateFromError = Boundary.getDerivedStateFromError;
|
|
42
|
+
expect(typeof getDerivedStateFromError).toBe('function');
|
|
43
|
+
|
|
44
|
+
const error = new Error('boom');
|
|
45
|
+
const next = getDerivedStateFromError(error);
|
|
46
|
+
|
|
47
|
+
expect(next).toEqual({ hasError: true, error });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/** React calls this one ON the instance, so an ordinary prototype method is correct. */
|
|
51
|
+
it('calls the error handler from componentDidCatch on the instance', () => {
|
|
52
|
+
const onError = vi.fn();
|
|
53
|
+
const React = makeFakeReact();
|
|
54
|
+
const Boundary = CreateErrorBoundary(React, { logErrors: false, onError });
|
|
55
|
+
|
|
56
|
+
const instance = new Boundary({});
|
|
57
|
+
const error = new Error('boom');
|
|
58
|
+
const errorInfo = { componentStack: 'at Boom' };
|
|
59
|
+
|
|
60
|
+
instance.componentDidCatch(error, errorInfo);
|
|
61
|
+
|
|
62
|
+
expect(onError).toHaveBeenCalledWith(error, errorInfo);
|
|
63
|
+
expect(instance.State.errorInfo).toBe(errorInfo);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/** The fallback is what the two members above exist to reach. */
|
|
67
|
+
it('renders the fallback once the error state is applied', () => {
|
|
68
|
+
const React = makeFakeReact();
|
|
69
|
+
const Boundary = CreateErrorBoundary(React, {
|
|
70
|
+
logErrors: false,
|
|
71
|
+
fallback: () => React.createElement('div', null, 'FALLBACK'),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const instance = new Boundary({});
|
|
75
|
+
instance.setState(Boundary.getDerivedStateFromError(new Error('boom')));
|
|
76
|
+
|
|
77
|
+
const tree = instance.render();
|
|
78
|
+
expect(tree.children).toContain('FALLBACK');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { describe, it, expect, beforeEach } from 'vitest';
|
|
15
15
|
import { MJGlobal, RegisterClass } from '@memberjunction/global';
|
|
16
|
-
import { RuntimeUtilities,
|
|
16
|
+
import { RuntimeUtilities, CreateRuntimeUtilities } from '../utilities/runtime-utilities';
|
|
17
17
|
|
|
18
18
|
/** A host's substitute implementation, registered above the base. */
|
|
19
19
|
@RegisterClass(RuntimeUtilities, 'RuntimeUtilities', 10)
|
|
@@ -29,13 +29,13 @@ describe('createRuntimeUtilities', () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('resolves a registered subclass in a browser environment', () => {
|
|
32
|
-
const utilities =
|
|
32
|
+
const utilities = CreateRuntimeUtilities();
|
|
33
33
|
expect(utilities).toBeInstanceOf(HostRuntimeUtilities);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it('returns something that is still a RuntimeUtilities', () => {
|
|
37
37
|
// The contract callers rely on: whatever comes back exposes `buildUtilities`.
|
|
38
|
-
const utilities =
|
|
38
|
+
const utilities = CreateRuntimeUtilities();
|
|
39
39
|
expect(utilities).toBeInstanceOf(RuntimeUtilities);
|
|
40
40
|
expect(typeof utilities.buildUtilities).toBe('function');
|
|
41
41
|
});
|
|
@@ -51,7 +51,7 @@ describe('createRuntimeUtilities', () => {
|
|
|
51
51
|
throw new Error('simulated resolution failure');
|
|
52
52
|
};
|
|
53
53
|
try {
|
|
54
|
-
expect(
|
|
54
|
+
expect(CreateRuntimeUtilities()).toBeInstanceOf(RuntimeUtilities);
|
|
55
55
|
} finally {
|
|
56
56
|
factory.CreateInstance = original;
|
|
57
57
|
}
|
|
@@ -1,99 +1,99 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import {
|
|
3
3
|
USER_STATE_KEY_PREFIX,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
ResolveUserStateScope,
|
|
5
|
+
UserStateStorageKey,
|
|
6
|
+
ParseStoredUserSettings,
|
|
7
|
+
MergeUserSettings,
|
|
8
|
+
ApplyUserSettingsUpdate
|
|
9
9
|
} from '../utilities/user-state';
|
|
10
10
|
|
|
11
11
|
describe('user-state helpers', () => {
|
|
12
12
|
describe('resolveUserStateScope', () => {
|
|
13
13
|
it('prefers an explicit scope over namespace/name', () => {
|
|
14
|
-
expect(
|
|
14
|
+
expect(ResolveUserStateScope('Form/Contacts', 'crm', 'ContactForm')).toBe('form/contacts');
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('lowercases the explicit scope', () => {
|
|
18
|
-
expect(
|
|
18
|
+
expect(ResolveUserStateScope('MyDashboard', null, null)).toBe('mydashboard');
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('trims surrounding whitespace from the explicit scope', () => {
|
|
22
|
-
expect(
|
|
22
|
+
expect(ResolveUserStateScope(' Spaced ', null, null)).toBe('spaced');
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
it('combines namespace and name when no explicit scope is given', () => {
|
|
26
|
-
expect(
|
|
26
|
+
expect(ResolveUserStateScope(undefined, 'CRM/Analytics', 'AccountDashboard'))
|
|
27
27
|
.toBe('crm/analytics/accountdashboard');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('uses just the name when there is no namespace', () => {
|
|
31
|
-
expect(
|
|
32
|
-
expect(
|
|
31
|
+
expect(ResolveUserStateScope(undefined, undefined, 'SalesReport')).toBe('salesreport');
|
|
32
|
+
expect(ResolveUserStateScope(null, ' ', 'SalesReport')).toBe('salesreport');
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('returns null when no stable scope can be derived', () => {
|
|
36
|
-
expect(
|
|
37
|
-
expect(
|
|
38
|
-
expect(
|
|
36
|
+
expect(ResolveUserStateScope(undefined, undefined, undefined)).toBeNull();
|
|
37
|
+
expect(ResolveUserStateScope('', '', '')).toBeNull();
|
|
38
|
+
expect(ResolveUserStateScope(' ', 'crm', ' ')).toBeNull();
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
describe('userStateStorageKey', () => {
|
|
43
43
|
it('prefixes a resolved scope with the unique root namespace', () => {
|
|
44
|
-
expect(
|
|
45
|
-
expect(
|
|
44
|
+
expect(UserStateStorageKey('form/contacts')).toBe(`${USER_STATE_KEY_PREFIX}form/contacts`);
|
|
45
|
+
expect(UserStateStorageKey('form/contacts')).toBe('InteractiveComponents_UserState_Root/form/contacts');
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('returns null for a null scope', () => {
|
|
49
|
-
expect(
|
|
49
|
+
expect(UserStateStorageKey(null)).toBeNull();
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
describe('parseStoredUserSettings', () => {
|
|
54
54
|
it('parses a valid JSON object', () => {
|
|
55
|
-
expect(
|
|
55
|
+
expect(ParseStoredUserSettings('{"sortBy":"Name","page":2}')).toEqual({ sortBy: 'Name', page: 2 });
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it('returns an empty object for null/undefined/empty input', () => {
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
61
|
-
expect(
|
|
59
|
+
expect(ParseStoredUserSettings(null)).toEqual({});
|
|
60
|
+
expect(ParseStoredUserSettings(undefined)).toEqual({});
|
|
61
|
+
expect(ParseStoredUserSettings('')).toEqual({});
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
it('returns an empty object for invalid JSON instead of throwing', () => {
|
|
65
|
-
expect(
|
|
65
|
+
expect(ParseStoredUserSettings('{not valid json')).toEqual({});
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('returns an empty object for non-object JSON (arrays, primitives)', () => {
|
|
69
|
-
expect(
|
|
70
|
-
expect(
|
|
71
|
-
expect(
|
|
72
|
-
expect(
|
|
69
|
+
expect(ParseStoredUserSettings('[1,2,3]')).toEqual({});
|
|
70
|
+
expect(ParseStoredUserSettings('42')).toEqual({});
|
|
71
|
+
expect(ParseStoredUserSettings('"hello"')).toEqual({});
|
|
72
|
+
expect(ParseStoredUserSettings('null')).toEqual({});
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
describe('mergeUserSettings', () => {
|
|
77
77
|
it('lets stored values win over host defaults', () => {
|
|
78
|
-
const merged =
|
|
78
|
+
const merged = MergeUserSettings({ sortBy: 'CloseDate', viewMode: 'grid' }, { sortBy: 'Name' });
|
|
79
79
|
expect(merged).toEqual({ sortBy: 'Name', viewMode: 'grid' });
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('keeps host defaults that the stored settings do not override', () => {
|
|
83
|
-
expect(
|
|
83
|
+
expect(MergeUserSettings({ a: 1, b: 2 }, { b: 3 })).toEqual({ a: 1, b: 3 });
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it('handles null/undefined on either side', () => {
|
|
87
|
-
expect(
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
90
|
-
expect(
|
|
87
|
+
expect(MergeUserSettings(null, { x: 1 })).toEqual({ x: 1 });
|
|
88
|
+
expect(MergeUserSettings({ x: 1 }, null)).toEqual({ x: 1 });
|
|
89
|
+
expect(MergeUserSettings(null, null)).toEqual({});
|
|
90
|
+
expect(MergeUserSettings(undefined, undefined)).toEqual({});
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('returns a new object (does not mutate inputs)', () => {
|
|
94
94
|
const defaults = { a: 1 };
|
|
95
95
|
const stored = { b: 2 };
|
|
96
|
-
const merged =
|
|
96
|
+
const merged = MergeUserSettings(defaults, stored);
|
|
97
97
|
expect(merged).not.toBe(defaults);
|
|
98
98
|
expect(merged).not.toBe(stored);
|
|
99
99
|
expect(defaults).toEqual({ a: 1 });
|
|
@@ -103,13 +103,13 @@ describe('user-state helpers', () => {
|
|
|
103
103
|
|
|
104
104
|
describe('applyUserSettingsUpdate', () => {
|
|
105
105
|
it('overlays incoming keys onto the current snapshot', () => {
|
|
106
|
-
expect(
|
|
106
|
+
expect(ApplyUserSettingsUpdate({ viewMode: 'grid', sortBy: 'CloseDate' }, { sortBy: 'Name' }))
|
|
107
107
|
.toEqual({ viewMode: 'grid', sortBy: 'Name' });
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
it('preserves untouched keys when a component passes only a delta', () => {
|
|
111
111
|
// The AI-forgot-the-spread case: a delta must not wipe other preferences.
|
|
112
|
-
expect(
|
|
112
|
+
expect(ApplyUserSettingsUpdate({ viewMode: 'grid', page: 3 }, { sortBy: 'Name' }))
|
|
113
113
|
.toEqual({ viewMode: 'grid', page: 3, sortBy: 'Name' });
|
|
114
114
|
});
|
|
115
115
|
|
|
@@ -117,35 +117,35 @@ describe('user-state helpers', () => {
|
|
|
117
117
|
// Component spreads the mount-time prop both times; the host snapshot
|
|
118
118
|
// must still accumulate both changes.
|
|
119
119
|
const mountProp = { viewMode: 'grid' };
|
|
120
|
-
let snapshot =
|
|
121
|
-
snapshot =
|
|
120
|
+
let snapshot = ApplyUserSettingsUpdate(mountProp, { ...mountProp, sortBy: 'Name' });
|
|
121
|
+
snapshot = ApplyUserSettingsUpdate(snapshot, { ...mountProp, viewMode: 'list' });
|
|
122
122
|
expect(snapshot).toEqual({ viewMode: 'list', sortBy: 'Name' });
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
it('removes a key when its incoming value is explicitly null', () => {
|
|
126
|
-
expect(
|
|
126
|
+
expect(ApplyUserSettingsUpdate({ sortBy: 'Name', viewMode: 'grid' }, { sortBy: null }))
|
|
127
127
|
.toEqual({ viewMode: 'grid' });
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
it('removes a key when its incoming value is undefined', () => {
|
|
131
|
-
expect(
|
|
131
|
+
expect(ApplyUserSettingsUpdate({ sortBy: 'Name', viewMode: 'grid' }, { sortBy: undefined }))
|
|
132
132
|
.toEqual({ viewMode: 'grid' });
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
it('treats a full-object payload as a superset (replace-equivalent)', () => {
|
|
136
|
-
expect(
|
|
136
|
+
expect(ApplyUserSettingsUpdate({ a: 1, b: 2 }, { a: 10, b: 20 })).toEqual({ a: 10, b: 20 });
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
it('handles null/undefined on either side', () => {
|
|
140
|
-
expect(
|
|
141
|
-
expect(
|
|
142
|
-
expect(
|
|
140
|
+
expect(ApplyUserSettingsUpdate(null, { x: 1 })).toEqual({ x: 1 });
|
|
141
|
+
expect(ApplyUserSettingsUpdate({ x: 1 }, null)).toEqual({ x: 1 });
|
|
142
|
+
expect(ApplyUserSettingsUpdate(null, null)).toEqual({});
|
|
143
143
|
});
|
|
144
144
|
|
|
145
145
|
it('returns a new object (does not mutate inputs)', () => {
|
|
146
146
|
const current = { a: 1 };
|
|
147
147
|
const incoming = { b: 2 };
|
|
148
|
-
const next =
|
|
148
|
+
const next = ApplyUserSettingsUpdate(current, incoming);
|
|
149
149
|
expect(next).not.toBe(current);
|
|
150
150
|
expect(next).not.toBe(incoming);
|
|
151
151
|
expect(current).toEqual({ a: 1 });
|
|
@@ -51,16 +51,21 @@ export const DEVELOPMENT_CONFIG = {
|
|
|
51
51
|
* @param production - Whether to use production configuration
|
|
52
52
|
* @returns Babel configuration object
|
|
53
53
|
*/
|
|
54
|
-
export function
|
|
54
|
+
export function GetBabelConfig(production: boolean = false) {
|
|
55
55
|
return production ? PRODUCTION_CONFIG : DEVELOPMENT_CONFIG;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/** @deprecated Use {@link GetBabelConfig}. */
|
|
59
|
+
export function getBabelConfig(production: boolean = false) {
|
|
60
|
+
return GetBabelConfig(production);
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
/**
|
|
59
64
|
* Validates that required Babel presets are available
|
|
60
65
|
* @param babel - Babel instance to check
|
|
61
66
|
* @returns true if all required presets are available
|
|
62
67
|
*/
|
|
63
|
-
export function
|
|
68
|
+
export function ValidateBabelPresets(babel: any): boolean {
|
|
64
69
|
if (!babel || !babel.availablePresets) {
|
|
65
70
|
return false;
|
|
66
71
|
}
|
|
@@ -69,6 +74,11 @@ export function validateBabelPresets(babel: any): boolean {
|
|
|
69
74
|
return 'react' in babel.availablePresets;
|
|
70
75
|
}
|
|
71
76
|
|
|
77
|
+
/** @deprecated Use {@link ValidateBabelPresets}. */
|
|
78
|
+
export function validateBabelPresets(babel: any): boolean {
|
|
79
|
+
return ValidateBabelPresets(babel);
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
/**
|
|
73
83
|
* Common JSX pragma options for different React versions
|
|
74
84
|
*/
|
|
@@ -88,10 +98,15 @@ export const JSX_PRAGMAS = {
|
|
|
88
98
|
* @param reactVersion - React version (e.g., "18.2.0")
|
|
89
99
|
* @returns JSX configuration options
|
|
90
100
|
*/
|
|
91
|
-
export function
|
|
101
|
+
export function GetJSXConfig(reactVersion?: string) {
|
|
92
102
|
// React 17+ supports the new JSX transform
|
|
93
103
|
if (reactVersion && parseInt(reactVersion.split('.')[0]) >= 17) {
|
|
94
104
|
return JSX_PRAGMAS.automatic;
|
|
95
105
|
}
|
|
96
106
|
return JSX_PRAGMAS.classic;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** @deprecated Use {@link GetJSXConfig}. */
|
|
110
|
+
export function getJSXConfig(reactVersion?: string) {
|
|
111
|
+
return GetJSXConfig(reactVersion);
|
|
97
112
|
}
|