@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.
Files changed (149) hide show
  1. package/.turbo/turbo-build.log +14 -14
  2. package/CHANGELOG.md +93 -0
  3. package/dist/compiler/babel-config.d.ts +14 -0
  4. package/dist/compiler/babel-config.d.ts.map +1 -1
  5. package/dist/compiler/babel-config.js +12 -3
  6. package/dist/compiler/babel-config.js.map +1 -1
  7. package/dist/compiler/component-compiler.d.ts +5 -0
  8. package/dist/compiler/component-compiler.d.ts.map +1 -1
  9. package/dist/compiler/component-compiler.js +24 -9
  10. package/dist/compiler/component-compiler.js.map +1 -1
  11. package/dist/compiler/index.d.ts +1 -1
  12. package/dist/compiler/index.d.ts.map +1 -1
  13. package/dist/compiler/index.js +1 -1
  14. package/dist/compiler/index.js.map +1 -1
  15. package/dist/component-manager/component-manager.d.ts +8 -0
  16. package/dist/component-manager/component-manager.d.ts.map +1 -1
  17. package/dist/component-manager/component-manager.js +18 -6
  18. package/dist/component-manager/component-manager.js.map +1 -1
  19. package/dist/index.d.ts +21 -9
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +13 -10
  22. package/dist/index.js.map +1 -1
  23. package/dist/registry/component-registry-service.d.ts +18 -0
  24. package/dist/registry/component-registry-service.d.ts.map +1 -1
  25. package/dist/registry/component-registry-service.js +65 -23
  26. package/dist/registry/component-registry-service.js.map +1 -1
  27. package/dist/registry/component-registry.d.ts +24 -1
  28. package/dist/registry/component-registry.d.ts.map +1 -1
  29. package/dist/registry/component-registry.js +74 -23
  30. package/dist/registry/component-registry.js.map +1 -1
  31. package/dist/registry/component-resolver.d.ts +10 -0
  32. package/dist/registry/component-resolver.d.ts.map +1 -1
  33. package/dist/registry/component-resolver.js +30 -9
  34. package/dist/registry/component-resolver.js.map +1 -1
  35. package/dist/registry/registry-provider.js.map +1 -1
  36. package/dist/runtime/component-hierarchy.d.ts +15 -0
  37. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  38. package/dist/runtime/component-hierarchy.js +28 -10
  39. package/dist/runtime/component-hierarchy.js.map +1 -1
  40. package/dist/runtime/error-boundary.d.ts +4 -0
  41. package/dist/runtime/error-boundary.d.ts.map +1 -1
  42. package/dist/runtime/error-boundary.js +50 -20
  43. package/dist/runtime/error-boundary.js.map +1 -1
  44. package/dist/runtime/index.d.ts +3 -3
  45. package/dist/runtime/index.d.ts.map +1 -1
  46. package/dist/runtime/index.js +3 -3
  47. package/dist/runtime/index.js.map +1 -1
  48. package/dist/runtime/prop-builder.d.ts +8 -0
  49. package/dist/runtime/prop-builder.d.ts.map +1 -1
  50. package/dist/runtime/prop-builder.js +39 -11
  51. package/dist/runtime/prop-builder.js.map +1 -1
  52. package/dist/runtime/react-root-manager.d.ts +10 -0
  53. package/dist/runtime/react-root-manager.d.ts.map +1 -1
  54. package/dist/runtime/react-root-manager.js +27 -9
  55. package/dist/runtime/react-root-manager.js.map +1 -1
  56. package/dist/runtime.umd.js +194 -125
  57. package/dist/utilities/cache-manager.d.ts +13 -0
  58. package/dist/utilities/cache-manager.d.ts.map +1 -1
  59. package/dist/utilities/cache-manager.js +40 -16
  60. package/dist/utilities/cache-manager.js.map +1 -1
  61. package/dist/utilities/component-error-analyzer.d.ts +3 -0
  62. package/dist/utilities/component-error-analyzer.d.ts.map +1 -1
  63. package/dist/utilities/component-error-analyzer.js +12 -3
  64. package/dist/utilities/component-error-analyzer.js.map +1 -1
  65. package/dist/utilities/component-hash.d.ts +1 -0
  66. package/dist/utilities/component-hash.d.ts.map +1 -1
  67. package/dist/utilities/component-hash.js +4 -1
  68. package/dist/utilities/component-hash.js.map +1 -1
  69. package/dist/utilities/component-library-theming.d.ts +4 -0
  70. package/dist/utilities/component-library-theming.d.ts.map +1 -1
  71. package/dist/utilities/component-library-theming.js +12 -6
  72. package/dist/utilities/component-library-theming.js.map +1 -1
  73. package/dist/utilities/component-styles.d.ts +1 -0
  74. package/dist/utilities/component-styles.d.ts.map +1 -1
  75. package/dist/utilities/component-styles.js +2 -1
  76. package/dist/utilities/component-styles.js.map +1 -1
  77. package/dist/utilities/component-unwrapper.d.ts +8 -2
  78. package/dist/utilities/component-unwrapper.d.ts.map +1 -1
  79. package/dist/utilities/component-unwrapper.js +19 -7
  80. package/dist/utilities/component-unwrapper.js.map +1 -1
  81. package/dist/utilities/core-libraries.d.ts +2 -0
  82. package/dist/utilities/core-libraries.d.ts.map +1 -1
  83. package/dist/utilities/core-libraries.js +9 -3
  84. package/dist/utilities/core-libraries.js.map +1 -1
  85. package/dist/utilities/entity-record-key.d.ts +1 -0
  86. package/dist/utilities/entity-record-key.d.ts.map +1 -1
  87. package/dist/utilities/entity-record-key.js +4 -1
  88. package/dist/utilities/entity-record-key.js.map +1 -1
  89. package/dist/utilities/library-dependency-resolver.d.ts +8 -0
  90. package/dist/utilities/library-dependency-resolver.d.ts.map +1 -1
  91. package/dist/utilities/library-dependency-resolver.js +39 -15
  92. package/dist/utilities/library-dependency-resolver.js.map +1 -1
  93. package/dist/utilities/library-loader.d.ts +12 -0
  94. package/dist/utilities/library-loader.d.ts.map +1 -1
  95. package/dist/utilities/library-loader.js +46 -16
  96. package/dist/utilities/library-loader.js.map +1 -1
  97. package/dist/utilities/library-registry.d.ts +5 -0
  98. package/dist/utilities/library-registry.d.ts.map +1 -1
  99. package/dist/utilities/library-registry.js +20 -5
  100. package/dist/utilities/library-registry.js.map +1 -1
  101. package/dist/utilities/resource-manager.d.ts +19 -0
  102. package/dist/utilities/resource-manager.d.ts.map +1 -1
  103. package/dist/utilities/resource-manager.js +63 -18
  104. package/dist/utilities/resource-manager.js.map +1 -1
  105. package/dist/utilities/runtime-utilities.d.ts +9 -7
  106. package/dist/utilities/runtime-utilities.d.ts.map +1 -1
  107. package/dist/utilities/runtime-utilities.js +22 -16
  108. package/dist/utilities/runtime-utilities.js.map +1 -1
  109. package/dist/utilities/standard-libraries.d.ts +10 -0
  110. package/dist/utilities/standard-libraries.d.ts.map +1 -1
  111. package/dist/utilities/standard-libraries.js +40 -10
  112. package/dist/utilities/standard-libraries.js.map +1 -1
  113. package/dist/utilities/user-state.d.ts +5 -0
  114. package/dist/utilities/user-state.d.ts.map +1 -1
  115. package/dist/utilities/user-state.js +20 -5
  116. package/dist/utilities/user-state.js.map +1 -1
  117. package/package.json +7 -7
  118. package/src/__tests__/error-boundary.test.ts +80 -0
  119. package/src/__tests__/runtime-utilities-factory.test.ts +4 -4
  120. package/src/__tests__/user-state.test.ts +44 -44
  121. package/src/compiler/babel-config.ts +18 -3
  122. package/src/compiler/component-compiler.ts +34 -9
  123. package/src/compiler/index.ts +3 -3
  124. package/src/component-manager/component-manager.ts +36 -6
  125. package/src/index.ts +35 -21
  126. package/src/registry/component-registry-service.ts +126 -23
  127. package/src/registry/component-registry.ts +122 -24
  128. package/src/registry/component-resolver.ts +51 -9
  129. package/src/registry/registry-provider.ts +40 -40
  130. package/src/runtime/component-hierarchy.ts +61 -10
  131. package/src/runtime/error-boundary.ts +77 -22
  132. package/src/runtime/index.ts +16 -16
  133. package/src/runtime/prop-builder.ts +69 -11
  134. package/src/runtime/react-root-manager.ts +48 -10
  135. package/src/utilities/cache-manager.ts +61 -16
  136. package/src/utilities/component-error-analyzer.ts +18 -3
  137. package/src/utilities/component-hash.ts +6 -1
  138. package/src/utilities/component-library-theming.ts +24 -6
  139. package/src/utilities/component-styles.ts +4 -1
  140. package/src/utilities/component-unwrapper.ts +34 -7
  141. package/src/utilities/core-libraries.ts +13 -3
  142. package/src/utilities/entity-record-key.ts +11 -1
  143. package/src/utilities/library-dependency-resolver.ts +66 -15
  144. package/src/utilities/library-loader.ts +81 -17
  145. package/src/utilities/library-registry.ts +30 -5
  146. package/src/utilities/resource-manager.ts +126 -19
  147. package/src/utilities/runtime-utilities.ts +26 -16
  148. package/src/utilities/standard-libraries.ts +60 -10
  149. 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 setConfiguration(config) {
11
+ static SetConfiguration(config) {
12
12
  this.configuration = config;
13
13
  }
14
- static getConfiguration() {
14
+ static setConfiguration(config) {
15
+ return this.SetConfiguration(config);
16
+ }
17
+ static GetConfiguration() {
15
18
  return this.configuration;
16
19
  }
17
- static getEnabledLibraries() {
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 getLibrariesByCategory(category) {
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 getCoreLibraries() {
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 getComponentLibraries() {
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 getLibraryById(id) {
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 getLibraryUrls() {
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 resetToDefault() {
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 createStandardLibraries() {
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 setConfiguration(config: LibraryConfiguration): void {\n this.configuration = config;\n }\n \n /**\n * Get the current library configuration\n */\n static getConfiguration(): LibraryConfiguration {\n return this.configuration;\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 /**\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 /**\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 /**\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 /**\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 /**\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 /**\n * Reset to default configuration\n */\n static resetToDefault(): void {\n this.configuration = DEFAULT_LIBRARY_CONFIG;\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}"]}
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 resolveUserStateScope(explicitScope, namespace, name) {
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 userStateStorageKey(scope) {
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 parseStoredUserSettings(raw) {
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 mergeUserSettings(hostDefaults, stored) {
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 applyUserSettingsUpdate(current, incoming) {
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 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/**\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/**\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/**\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/**\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"]}
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.0",
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.0",
24
- "@memberjunction/core": "6.2.0-edge.0",
25
- "@memberjunction/core-entities": "6.2.0-edge.0",
26
- "@memberjunction/global": "6.2.0-edge.0",
27
- "@memberjunction/graphql-dataprovider": "6.2.0-edge.0",
28
- "@memberjunction/interactive-component-types": "6.2.0-edge.0",
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, createRuntimeUtilities } from '../utilities/runtime-utilities';
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 = createRuntimeUtilities();
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 = createRuntimeUtilities();
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(createRuntimeUtilities()).toBeInstanceOf(RuntimeUtilities);
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
- resolveUserStateScope,
5
- userStateStorageKey,
6
- parseStoredUserSettings,
7
- mergeUserSettings,
8
- applyUserSettingsUpdate
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(resolveUserStateScope('Form/Contacts', 'crm', 'ContactForm')).toBe('form/contacts');
14
+ expect(ResolveUserStateScope('Form/Contacts', 'crm', 'ContactForm')).toBe('form/contacts');
15
15
  });
16
16
 
17
17
  it('lowercases the explicit scope', () => {
18
- expect(resolveUserStateScope('MyDashboard', null, null)).toBe('mydashboard');
18
+ expect(ResolveUserStateScope('MyDashboard', null, null)).toBe('mydashboard');
19
19
  });
20
20
 
21
21
  it('trims surrounding whitespace from the explicit scope', () => {
22
- expect(resolveUserStateScope(' Spaced ', null, null)).toBe('spaced');
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(resolveUserStateScope(undefined, 'CRM/Analytics', 'AccountDashboard'))
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(resolveUserStateScope(undefined, undefined, 'SalesReport')).toBe('salesreport');
32
- expect(resolveUserStateScope(null, ' ', 'SalesReport')).toBe('salesreport');
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(resolveUserStateScope(undefined, undefined, undefined)).toBeNull();
37
- expect(resolveUserStateScope('', '', '')).toBeNull();
38
- expect(resolveUserStateScope(' ', 'crm', ' ')).toBeNull();
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(userStateStorageKey('form/contacts')).toBe(`${USER_STATE_KEY_PREFIX}form/contacts`);
45
- expect(userStateStorageKey('form/contacts')).toBe('InteractiveComponents_UserState_Root/form/contacts');
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(userStateStorageKey(null)).toBeNull();
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(parseStoredUserSettings('{"sortBy":"Name","page":2}')).toEqual({ sortBy: 'Name', page: 2 });
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(parseStoredUserSettings(null)).toEqual({});
60
- expect(parseStoredUserSettings(undefined)).toEqual({});
61
- expect(parseStoredUserSettings('')).toEqual({});
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(parseStoredUserSettings('{not valid json')).toEqual({});
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(parseStoredUserSettings('[1,2,3]')).toEqual({});
70
- expect(parseStoredUserSettings('42')).toEqual({});
71
- expect(parseStoredUserSettings('"hello"')).toEqual({});
72
- expect(parseStoredUserSettings('null')).toEqual({});
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 = mergeUserSettings({ sortBy: 'CloseDate', viewMode: 'grid' }, { sortBy: 'Name' });
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(mergeUserSettings({ a: 1, b: 2 }, { b: 3 })).toEqual({ a: 1, b: 3 });
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(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({});
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 = mergeUserSettings(defaults, stored);
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(applyUserSettingsUpdate({ viewMode: 'grid', sortBy: 'CloseDate' }, { sortBy: 'Name' }))
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(applyUserSettingsUpdate({ viewMode: 'grid', page: 3 }, { sortBy: 'Name' }))
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 = applyUserSettingsUpdate(mountProp, { ...mountProp, sortBy: 'Name' });
121
- snapshot = applyUserSettingsUpdate(snapshot, { ...mountProp, viewMode: 'list' });
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(applyUserSettingsUpdate({ sortBy: 'Name', viewMode: 'grid' }, { sortBy: null }))
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(applyUserSettingsUpdate({ sortBy: 'Name', viewMode: 'grid' }, { sortBy: undefined }))
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(applyUserSettingsUpdate({ a: 1, b: 2 }, { a: 10, b: 20 })).toEqual({ a: 10, b: 20 });
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(applyUserSettingsUpdate(null, { x: 1 })).toEqual({ x: 1 });
141
- expect(applyUserSettingsUpdate({ x: 1 }, null)).toEqual({ x: 1 });
142
- expect(applyUserSettingsUpdate(null, null)).toEqual({});
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 = applyUserSettingsUpdate(current, incoming);
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 getBabelConfig(production: boolean = false) {
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 validateBabelPresets(babel: any): boolean {
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 getJSXConfig(reactVersion?: string) {
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
  }