@coherent.js/core 1.0.0-beta.5 → 1.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coherent.d.ts +150 -10
- package/dist/coherent.d.ts.map +1 -1
- package/dist/coherent.js +166 -33
- package/dist/coherent.js.map +1 -1
- package/dist/components/component-system.js +109 -109
- package/dist/components/lifecycle.d.ts +212 -0
- package/dist/components/lifecycle.d.ts.map +1 -0
- package/dist/components/lifecycle.js +525 -0
- package/dist/components/lifecycle.js.map +1 -0
- package/dist/core/html-utils.js +5 -5
- package/dist/core/object-factory.js +21 -21
- package/dist/core/object-utils.js +2 -2
- package/dist/dev/dev-tools.d.ts +1 -1
- package/dist/dev/dev-tools.js +28 -28
- package/dist/forms/validation.d.ts +271 -0
- package/dist/forms/validation.d.ts.map +1 -0
- package/dist/forms/validation.js +573 -0
- package/dist/forms/validation.js.map +1 -0
- package/dist/index.cjs +2839 -1464
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +2837 -1473
- package/dist/index.js.map +4 -4
- package/dist/performance/bundle-optimizer.js +11 -11
- package/dist/performance/cache-manager.js +6 -6
- package/dist/performance/component-cache.d.ts +120 -0
- package/dist/performance/component-cache.d.ts.map +1 -0
- package/dist/performance/component-cache.js +364 -0
- package/dist/performance/component-cache.js.map +1 -0
- package/dist/performance/monitor.js +10 -10
- package/dist/performance/monitor.js.map +1 -1
- package/dist/rendering/base-renderer.js +13 -13
- package/dist/rendering/css-manager.d.ts +73 -0
- package/dist/rendering/css-manager.d.ts.map +1 -0
- package/dist/rendering/css-manager.js +176 -0
- package/dist/rendering/css-manager.js.map +1 -0
- package/dist/rendering/dom-renderer.d.ts +23 -0
- package/dist/rendering/dom-renderer.d.ts.map +1 -1
- package/dist/rendering/dom-renderer.js +77 -9
- package/dist/rendering/dom-renderer.js.map +1 -1
- package/dist/rendering/html-renderer.d.ts +15 -0
- package/dist/rendering/html-renderer.d.ts.map +1 -1
- package/dist/rendering/html-renderer.js +85 -4
- package/dist/rendering/html-renderer.js.map +1 -1
- package/dist/rendering/streaming-renderer.js +12 -12
- package/dist/rendering/vdom-diff.d.ts +47 -0
- package/dist/rendering/vdom-diff.d.ts.map +1 -0
- package/dist/rendering/vdom-diff.js +416 -0
- package/dist/rendering/vdom-diff.js.map +1 -0
- package/dist/routing/router.d.ts +241 -0
- package/dist/routing/router.d.ts.map +1 -0
- package/dist/routing/router.js +648 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/state/reactive-state.d.ts +166 -0
- package/dist/state/reactive-state.d.ts.map +1 -0
- package/dist/state/reactive-state.js +546 -0
- package/dist/state/reactive-state.js.map +1 -0
- package/dist/utils/dependency-utils.js +2 -2
- package/dist/utils/error-handler.d.ts +148 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +468 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/normalization.js +1 -1
- package/dist/utils/validation.js +1 -1
- package/package.json +7 -22
- package/types/elements.d.ts +1080 -0
- package/types/index.d.ts +199 -65
- package/dist/database/adapters/mongodb.d.ts +0 -15
- package/dist/database/adapters/mongodb.d.ts.map +0 -1
- package/dist/database/adapters/mongodb.js +0 -216
- package/dist/database/adapters/mongodb.js.map +0 -1
- package/dist/database/adapters/mysql.d.ts +0 -12
- package/dist/database/adapters/mysql.d.ts.map +0 -1
- package/dist/database/adapters/mysql.js +0 -171
- package/dist/database/adapters/mysql.js.map +0 -1
- package/dist/database/adapters/postgresql.d.ts +0 -12
- package/dist/database/adapters/postgresql.d.ts.map +0 -1
- package/dist/database/adapters/postgresql.js +0 -177
- package/dist/database/adapters/postgresql.js.map +0 -1
- package/dist/database/adapters/sqlite.d.ts +0 -15
- package/dist/database/adapters/sqlite.d.ts.map +0 -1
- package/dist/database/adapters/sqlite.js +0 -241
- package/dist/database/adapters/sqlite.js.map +0 -1
- package/dist/database/connection-manager.d.ts +0 -135
- package/dist/database/connection-manager.d.ts.map +0 -1
- package/dist/database/connection-manager.js +0 -362
- package/dist/database/connection-manager.js.map +0 -1
- package/dist/database/index.d.ts +0 -38
- package/dist/database/index.d.ts.map +0 -1
- package/dist/database/index.js +0 -60
- package/dist/database/index.js.map +0 -1
- package/dist/database/middleware.d.ts +0 -122
- package/dist/database/middleware.d.ts.map +0 -1
- package/dist/database/middleware.js +0 -390
- package/dist/database/middleware.js.map +0 -1
- package/dist/database/migration.d.ts +0 -62
- package/dist/database/migration.d.ts.map +0 -1
- package/dist/database/migration.js +0 -423
- package/dist/database/migration.js.map +0 -1
- package/dist/database/model.d.ts +0 -8
- package/dist/database/model.d.ts.map +0 -1
- package/dist/database/model.js +0 -167
- package/dist/database/model.js.map +0 -1
- package/dist/database/query-builder.d.ts +0 -111
- package/dist/database/query-builder.d.ts.map +0 -1
- package/dist/database/query-builder.js +0 -187
- package/dist/database/query-builder.js.map +0 -1
- package/dist/database/utils.d.ts +0 -196
- package/dist/database/utils.d.ts.map +0 -1
- package/dist/database/utils.js +0 -372
- package/dist/database/utils.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -24,9 +24,14 @@ __export(index_exports, {
|
|
|
24
24
|
ComponentLifecycle: () => ComponentLifecycle,
|
|
25
25
|
DOMEventIntegration: () => DOMEventIntegration,
|
|
26
26
|
EventBus: () => EventBus,
|
|
27
|
+
FORBIDDEN_CHILDREN: () => FORBIDDEN_CHILDREN,
|
|
27
28
|
GlobalErrorHandler: () => GlobalErrorHandler,
|
|
29
|
+
HTMLNestingError: () => HTMLNestingError,
|
|
30
|
+
Island: () => Island,
|
|
28
31
|
LIFECYCLE_PHASES: () => LIFECYCLE_PHASES,
|
|
29
32
|
VERSION: () => VERSION,
|
|
33
|
+
checkPeerDependencies: () => checkPeerDependencies,
|
|
34
|
+
compose: () => compose,
|
|
30
35
|
createActionHandlers: () => createActionHandlers,
|
|
31
36
|
createAsyncErrorBoundary: () => createAsyncErrorBoundary,
|
|
32
37
|
createComponent: () => createComponent,
|
|
@@ -34,10 +39,12 @@ __export(index_exports, {
|
|
|
34
39
|
createElement: () => createElement,
|
|
35
40
|
createErrorBoundary: () => createErrorBoundary,
|
|
36
41
|
createErrorFallback: () => createErrorFallback,
|
|
42
|
+
createErrorResponse: () => createErrorResponse,
|
|
37
43
|
createEventBus: () => createEventBus,
|
|
38
44
|
createEventComponent: () => createEventComponent,
|
|
39
45
|
createEventHandlers: () => createEventHandlers,
|
|
40
46
|
createGlobalErrorHandler: () => createGlobalErrorHandler,
|
|
47
|
+
createLazyIntegration: () => createLazyIntegration,
|
|
41
48
|
createLifecycleHooks: () => createLifecycleHooks,
|
|
42
49
|
createStateManager: () => createStateManager,
|
|
43
50
|
createTextNode: () => createTextNode,
|
|
@@ -49,29 +56,40 @@ __export(index_exports, {
|
|
|
49
56
|
emitSync: () => emitSync,
|
|
50
57
|
evaluateLazy: () => evaluateLazy,
|
|
51
58
|
eventSystem: () => events_default,
|
|
59
|
+
fp: () => fp,
|
|
52
60
|
getComponent: () => getComponent,
|
|
53
61
|
getRegisteredComponents: () => getRegisteredComponents,
|
|
54
62
|
globalDOMIntegration: () => globalDOMIntegration,
|
|
55
63
|
globalEventBus: () => globalEventBus,
|
|
56
64
|
h: () => h,
|
|
57
65
|
handleAction: () => handleAction,
|
|
66
|
+
hasChildren: () => hasChildren,
|
|
67
|
+
hoc: () => hoc,
|
|
68
|
+
importPeerDependency: () => importPeerDependency,
|
|
58
69
|
initializeDOMIntegration: () => initializeDOMIntegration,
|
|
59
|
-
|
|
70
|
+
isCoherentComponent: () => isCoherentComponent,
|
|
71
|
+
isCoherentObject: () => isCoherentObject2,
|
|
60
72
|
isLazy: () => isLazy,
|
|
73
|
+
isPeerDependencyAvailable: () => isPeerDependencyAvailable,
|
|
61
74
|
lazy: () => lazy,
|
|
62
75
|
lifecycleUtils: () => componentUtils,
|
|
63
76
|
memo: () => memo2,
|
|
64
77
|
memoize: () => memoize,
|
|
78
|
+
normalizeChildren: () => normalizeChildren,
|
|
65
79
|
off: () => off,
|
|
66
80
|
on: () => on,
|
|
67
81
|
once: () => once,
|
|
68
82
|
performanceMonitor: () => performanceMonitor,
|
|
69
83
|
registerAction: () => registerAction,
|
|
70
84
|
registerComponent: () => registerComponent,
|
|
71
|
-
render: () =>
|
|
85
|
+
render: () => render2,
|
|
86
|
+
renderComponentFactory: () => renderComponentFactory,
|
|
87
|
+
renderWithMonitoring: () => renderWithMonitoring,
|
|
88
|
+
renderWithTemplate: () => renderWithTemplate,
|
|
72
89
|
shadowDOM: () => shadow_dom_exports,
|
|
73
90
|
useHooks: () => useHooks,
|
|
74
91
|
validateComponent: () => validateComponent2,
|
|
92
|
+
validateNesting: () => validateNesting,
|
|
75
93
|
withErrorBoundary: () => withErrorBoundary,
|
|
76
94
|
withEventBus: () => withEventBus,
|
|
77
95
|
withEventState: () => withEventState,
|
|
@@ -80,6 +98,7 @@ __export(index_exports, {
|
|
|
80
98
|
withStateUtils: () => withStateUtils
|
|
81
99
|
});
|
|
82
100
|
module.exports = __toCommonJS(index_exports);
|
|
101
|
+
var import_node_fs = require("node:fs");
|
|
83
102
|
|
|
84
103
|
// src/performance/monitor.js
|
|
85
104
|
function createPerformanceMonitor(options = {}) {
|
|
@@ -670,1580 +689,2734 @@ function validateComponent(component, path = "root") {
|
|
|
670
689
|
}
|
|
671
690
|
throw new Error(`Invalid component type at ${path}: ${typeof component}`);
|
|
672
691
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
var COMPONENT_METADATA = /* @__PURE__ */ new WeakMap();
|
|
677
|
-
var ComponentState = class {
|
|
678
|
-
constructor(initialState = {}) {
|
|
679
|
-
this.state = { ...initialState };
|
|
680
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
681
|
-
this.isUpdating = false;
|
|
692
|
+
function isCoherentObject(obj) {
|
|
693
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
694
|
+
return false;
|
|
682
695
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
* @param {string} [key] - State key to retrieve
|
|
687
|
-
* @returns {*} State value or entire state object
|
|
688
|
-
*/
|
|
689
|
-
get(key) {
|
|
690
|
-
return key ? this.state[key] : { ...this.state };
|
|
696
|
+
const keys = Object.keys(obj);
|
|
697
|
+
if (keys.length === 0) {
|
|
698
|
+
return false;
|
|
691
699
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
700
|
+
return keys.every((key) => {
|
|
701
|
+
if (key === "text") return true;
|
|
702
|
+
return /^[a-zA-Z][a-zA-Z0-9-]*$/.test(key);
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function extractProps(coherentObj) {
|
|
706
|
+
if (!isCoherentObject(coherentObj)) {
|
|
707
|
+
return {};
|
|
708
|
+
}
|
|
709
|
+
const props = {};
|
|
710
|
+
const keys = Object.keys(coherentObj);
|
|
711
|
+
keys.forEach((tag) => {
|
|
712
|
+
const value = coherentObj[tag];
|
|
713
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
714
|
+
props[tag] = { ...value };
|
|
715
|
+
} else {
|
|
716
|
+
props[tag] = { text: value };
|
|
703
717
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
return () => this.listeners.delete(listener);
|
|
718
|
+
});
|
|
719
|
+
return props;
|
|
720
|
+
}
|
|
721
|
+
function hasChildren(component) {
|
|
722
|
+
if (Array.isArray(component)) {
|
|
723
|
+
return component.length > 0;
|
|
711
724
|
}
|
|
712
|
-
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
}
|
|
725
|
+
if (isCoherentObject(component)) {
|
|
726
|
+
if (component.children !== void 0 && component.children !== null) {
|
|
727
|
+
return Array.isArray(component.children) ? component.children.length > 0 : true;
|
|
728
|
+
}
|
|
729
|
+
const keys = Object.keys(component);
|
|
730
|
+
return keys.some((key) => {
|
|
731
|
+
const value = component[key];
|
|
732
|
+
return value && typeof value === "object" && value.children;
|
|
721
733
|
});
|
|
722
|
-
this.isUpdating = false;
|
|
723
734
|
}
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
function normalizeChildren(children) {
|
|
738
|
+
if (children === null || children === void 0) {
|
|
739
|
+
return [];
|
|
740
|
+
}
|
|
741
|
+
if (Array.isArray(children)) {
|
|
742
|
+
return children.flat().filter((child) => child !== null && child !== void 0);
|
|
743
|
+
}
|
|
744
|
+
return [children];
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/rendering/base-renderer.js
|
|
748
|
+
var DEFAULT_RENDERER_CONFIG = {
|
|
749
|
+
// Core rendering options
|
|
750
|
+
maxDepth: 100,
|
|
751
|
+
enableValidation: true,
|
|
752
|
+
enableMonitoring: false,
|
|
753
|
+
validateInput: true,
|
|
754
|
+
// HTML Renderer specific options
|
|
755
|
+
enableCache: true,
|
|
756
|
+
minify: false,
|
|
757
|
+
cacheSize: 1e3,
|
|
758
|
+
cacheTTL: 3e5,
|
|
759
|
+
// 5 minutes
|
|
760
|
+
// Streaming Renderer specific options
|
|
761
|
+
chunkSize: 1024,
|
|
762
|
+
// Size of each chunk in bytes
|
|
763
|
+
bufferSize: 4096,
|
|
764
|
+
// Internal buffer size
|
|
765
|
+
enableMetrics: false,
|
|
766
|
+
// Track streaming metrics
|
|
767
|
+
yieldThreshold: 100,
|
|
768
|
+
// Yield control after N elements
|
|
769
|
+
encoding: "utf8",
|
|
770
|
+
// Output encoding
|
|
771
|
+
// DOM Renderer specific options
|
|
772
|
+
enableHydration: true,
|
|
773
|
+
// Enable hydration support
|
|
774
|
+
namespace: null,
|
|
775
|
+
// SVG namespace support
|
|
776
|
+
// Performance options
|
|
777
|
+
enablePerformanceTracking: false,
|
|
778
|
+
performanceThreshold: 10,
|
|
779
|
+
// ms threshold for slow renders
|
|
780
|
+
// Development options
|
|
781
|
+
enableDevWarnings: typeof process !== "undefined" && process.env && true,
|
|
782
|
+
enableDebugLogging: false,
|
|
783
|
+
// Error handling options
|
|
784
|
+
errorFallback: "",
|
|
785
|
+
// Fallback content on errors
|
|
786
|
+
throwOnError: true
|
|
787
|
+
// Whether to throw or return fallback
|
|
724
788
|
};
|
|
725
|
-
var
|
|
726
|
-
constructor(
|
|
727
|
-
this.
|
|
728
|
-
this.
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
this.parent = null;
|
|
733
|
-
this.rendered = null;
|
|
734
|
-
this.isMounted = false;
|
|
735
|
-
this.isDestroyed = false;
|
|
736
|
-
this.hooks = {
|
|
737
|
-
beforeCreate: definition.beforeCreate || (() => {
|
|
738
|
-
}),
|
|
739
|
-
created: definition.created || (() => {
|
|
740
|
-
}),
|
|
741
|
-
beforeMount: definition.beforeMount || (() => {
|
|
742
|
-
}),
|
|
743
|
-
mounted: definition.mounted || (() => {
|
|
744
|
-
}),
|
|
745
|
-
beforeUpdate: definition.beforeUpdate || (() => {
|
|
746
|
-
}),
|
|
747
|
-
updated: definition.updated || (() => {
|
|
748
|
-
}),
|
|
749
|
-
beforeDestroy: definition.beforeDestroy || (() => {
|
|
750
|
-
}),
|
|
751
|
-
destroyed: definition.destroyed || (() => {
|
|
752
|
-
}),
|
|
753
|
-
errorCaptured: definition.errorCaptured || (() => {
|
|
754
|
-
})
|
|
789
|
+
var BaseRenderer = class {
|
|
790
|
+
constructor(options = {}) {
|
|
791
|
+
this.config = this.validateAndMergeConfig(options);
|
|
792
|
+
this.metrics = {
|
|
793
|
+
startTime: null,
|
|
794
|
+
endTime: null,
|
|
795
|
+
elementsProcessed: 0
|
|
755
796
|
};
|
|
756
|
-
this.methods = definition.methods || {};
|
|
757
|
-
Object.keys(this.methods).forEach((methodName) => {
|
|
758
|
-
if (typeof this.methods[methodName] === "function") {
|
|
759
|
-
this[methodName] = this.methods[methodName].bind(this);
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
this.computed = definition.computed || {};
|
|
763
|
-
this.computedCache = /* @__PURE__ */ new Map();
|
|
764
|
-
this.watchers = definition.watch || {};
|
|
765
|
-
this.setupWatchers();
|
|
766
|
-
COMPONENT_METADATA.set(this, {
|
|
767
|
-
createdAt: Date.now(),
|
|
768
|
-
updateCount: 0,
|
|
769
|
-
renderCount: 0
|
|
770
|
-
});
|
|
771
|
-
this.callHook("beforeCreate");
|
|
772
|
-
this.initialize();
|
|
773
|
-
this.callHook("created");
|
|
774
797
|
}
|
|
775
798
|
/**
|
|
776
|
-
*
|
|
799
|
+
* Validate and merge configuration options
|
|
777
800
|
*/
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
801
|
+
validateAndMergeConfig(options) {
|
|
802
|
+
const config = { ...DEFAULT_RENDERER_CONFIG, ...options };
|
|
803
|
+
if (typeof config.maxDepth !== "number") {
|
|
804
|
+
throw new Error("maxDepth must be a number");
|
|
805
|
+
}
|
|
806
|
+
if (config.maxDepth <= 0) {
|
|
807
|
+
throw new Error("maxDepth must be a positive number");
|
|
808
|
+
}
|
|
809
|
+
if (typeof config.chunkSize !== "number") {
|
|
810
|
+
throw new Error("chunkSize must be a number");
|
|
811
|
+
}
|
|
812
|
+
if (config.chunkSize <= 0) {
|
|
813
|
+
throw new Error("chunkSize must be a positive number");
|
|
814
|
+
}
|
|
815
|
+
if (typeof config.yieldThreshold !== "number") {
|
|
816
|
+
throw new Error("yieldThreshold must be a number");
|
|
817
|
+
}
|
|
818
|
+
if (config.yieldThreshold <= 0) {
|
|
819
|
+
throw new Error("yieldThreshold must be a positive number");
|
|
820
|
+
}
|
|
821
|
+
if (config.enableDevWarnings) {
|
|
822
|
+
if (config.maxDepth > 1e3) {
|
|
823
|
+
console.warn("Coherent.js: maxDepth > 1000 may cause performance issues");
|
|
824
|
+
}
|
|
825
|
+
if (config.chunkSize > 16384) {
|
|
826
|
+
console.warn("Coherent.js: Large chunkSize may increase memory usage");
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return config;
|
|
783
830
|
}
|
|
784
831
|
/**
|
|
785
|
-
*
|
|
832
|
+
* Get configuration for specific renderer type
|
|
786
833
|
*/
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
834
|
+
getRendererConfig(rendererType) {
|
|
835
|
+
const baseConfig = { ...this.config };
|
|
836
|
+
switch (rendererType) {
|
|
837
|
+
case "html":
|
|
838
|
+
return {
|
|
839
|
+
...baseConfig,
|
|
840
|
+
// HTML-specific defaults
|
|
841
|
+
enableCache: baseConfig.enableCache !== false,
|
|
842
|
+
enableMonitoring: baseConfig.enableMonitoring !== false
|
|
843
|
+
};
|
|
844
|
+
case "streaming":
|
|
845
|
+
return {
|
|
846
|
+
...baseConfig,
|
|
847
|
+
// Streaming-specific defaults
|
|
848
|
+
enableMetrics: baseConfig.enableMetrics ?? false,
|
|
849
|
+
maxDepth: baseConfig.maxDepth ?? 1e3
|
|
850
|
+
// Higher default for streaming
|
|
851
|
+
};
|
|
852
|
+
case "dom":
|
|
853
|
+
return {
|
|
854
|
+
...baseConfig,
|
|
855
|
+
// DOM-specific defaults
|
|
856
|
+
enableHydration: baseConfig.enableHydration !== false
|
|
857
|
+
};
|
|
858
|
+
default:
|
|
859
|
+
return baseConfig;
|
|
860
|
+
}
|
|
796
861
|
}
|
|
797
862
|
/**
|
|
798
|
-
*
|
|
863
|
+
* Validate component structure
|
|
799
864
|
*/
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
const value = this.computed[key].call(this);
|
|
806
|
-
this.computedCache.set(key, value);
|
|
807
|
-
}
|
|
808
|
-
return this.computedCache.get(key);
|
|
809
|
-
},
|
|
810
|
-
enumerable: true
|
|
811
|
-
});
|
|
812
|
-
});
|
|
865
|
+
validateComponent(component) {
|
|
866
|
+
if (this.config.validateInput !== false) {
|
|
867
|
+
return validateComponent(component);
|
|
868
|
+
}
|
|
869
|
+
return true;
|
|
813
870
|
}
|
|
814
871
|
/**
|
|
815
|
-
*
|
|
872
|
+
* Check if component is valid for rendering
|
|
816
873
|
*/
|
|
817
|
-
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
if (
|
|
821
|
-
|
|
822
|
-
|
|
874
|
+
isValidComponent(component) {
|
|
875
|
+
if (component === null || component === void 0) return true;
|
|
876
|
+
if (typeof component === "string" || typeof component === "number") return true;
|
|
877
|
+
if (typeof component === "function") return true;
|
|
878
|
+
if (Array.isArray(component)) return component.every((child) => this.isValidComponent(child));
|
|
879
|
+
if (isCoherentObject(component)) return true;
|
|
880
|
+
return false;
|
|
823
881
|
}
|
|
824
882
|
/**
|
|
825
|
-
*
|
|
883
|
+
* Validate rendering depth to prevent stack overflow
|
|
826
884
|
*/
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
return this.hooks[hookName].call(this, ...args);
|
|
831
|
-
}
|
|
832
|
-
} catch (_error) {
|
|
833
|
-
this.handleError(_error, `${hookName} hook`);
|
|
885
|
+
validateDepth(depth) {
|
|
886
|
+
if (depth > this.config.maxDepth) {
|
|
887
|
+
throw new Error(`Maximum render depth (${this.config.maxDepth}) exceeded`);
|
|
834
888
|
}
|
|
835
889
|
}
|
|
836
890
|
/**
|
|
837
|
-
* Handle component
|
|
891
|
+
* Handle different component types with consistent logic
|
|
838
892
|
*/
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
893
|
+
processComponentType(component) {
|
|
894
|
+
if (component === null || component === void 0) {
|
|
895
|
+
return { type: "empty", value: "" };
|
|
896
|
+
}
|
|
897
|
+
if (typeof component === "string") {
|
|
898
|
+
return { type: "text", value: component };
|
|
899
|
+
}
|
|
900
|
+
if (typeof component === "number" || typeof component === "boolean") {
|
|
901
|
+
return { type: "text", value: String(component) };
|
|
902
|
+
}
|
|
903
|
+
if (typeof component === "function") {
|
|
904
|
+
return { type: "function", value: component };
|
|
905
|
+
}
|
|
906
|
+
if (Array.isArray(component)) {
|
|
907
|
+
return { type: "array", value: component };
|
|
844
908
|
}
|
|
909
|
+
if (isCoherentObject(component)) {
|
|
910
|
+
return { type: "element", value: component };
|
|
911
|
+
}
|
|
912
|
+
return { type: "unknown", value: component };
|
|
845
913
|
}
|
|
846
914
|
/**
|
|
847
|
-
*
|
|
915
|
+
* Execute function components with _error handling
|
|
848
916
|
*/
|
|
849
|
-
|
|
850
|
-
if (this.isDestroyed) {
|
|
851
|
-
console.warn(`Attempting to render destroyed component: ${this.name}`);
|
|
852
|
-
return null;
|
|
853
|
-
}
|
|
917
|
+
executeFunctionComponent(func, depth = 0) {
|
|
854
918
|
try {
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
this.rendered = this.definition.render.call(this, this.props, this.state.get());
|
|
862
|
-
} else if (typeof this.definition.template !== "undefined") {
|
|
863
|
-
this.rendered = this.processTemplate(this.definition.template, this.props, this.state.get());
|
|
919
|
+
const isContextProvider = func.length > 0 || func.isContextProvider;
|
|
920
|
+
let result;
|
|
921
|
+
if (isContextProvider) {
|
|
922
|
+
result = func((children) => {
|
|
923
|
+
return this.renderComponent(children, this.config, depth + 1);
|
|
924
|
+
});
|
|
864
925
|
} else {
|
|
865
|
-
|
|
926
|
+
result = func();
|
|
866
927
|
}
|
|
867
|
-
if (
|
|
868
|
-
|
|
928
|
+
if (typeof result === "function") {
|
|
929
|
+
return this.executeFunctionComponent(result, depth);
|
|
869
930
|
}
|
|
870
|
-
return
|
|
931
|
+
return result;
|
|
871
932
|
} catch (_error) {
|
|
872
|
-
this.
|
|
873
|
-
|
|
933
|
+
if (this.config.enableMonitoring) {
|
|
934
|
+
performanceMonitor.recordError("functionComponent", _error);
|
|
935
|
+
}
|
|
936
|
+
if (typeof process !== "undefined" && process.env && true) {
|
|
937
|
+
console.warn("Coherent.js Function Component Error:", _error.message);
|
|
938
|
+
}
|
|
939
|
+
return null;
|
|
874
940
|
}
|
|
875
941
|
}
|
|
876
942
|
/**
|
|
877
|
-
* Process
|
|
943
|
+
* Process element children consistently
|
|
878
944
|
*/
|
|
879
|
-
|
|
880
|
-
if (
|
|
881
|
-
return
|
|
882
|
-
}
|
|
883
|
-
if (typeof template === "string") {
|
|
884
|
-
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
885
|
-
return props[key] || state[key] || "";
|
|
886
|
-
});
|
|
945
|
+
processChildren(children, options, depth) {
|
|
946
|
+
if (!hasChildren({ children })) {
|
|
947
|
+
return [];
|
|
887
948
|
}
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
949
|
+
const normalizedChildren = normalizeChildren(children);
|
|
950
|
+
return normalizedChildren.map(
|
|
951
|
+
(child) => this.renderComponent(child, options, depth + 1)
|
|
952
|
+
);
|
|
891
953
|
}
|
|
892
954
|
/**
|
|
893
|
-
*
|
|
955
|
+
* Extract and process element attributes
|
|
894
956
|
*/
|
|
895
|
-
|
|
896
|
-
if (typeof
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
}
|
|
902
|
-
if (obj && typeof obj === "object") {
|
|
903
|
-
Object.keys(obj).forEach((key) => {
|
|
904
|
-
obj[key] = this.interpolateObject(obj[key], data);
|
|
905
|
-
});
|
|
906
|
-
}
|
|
907
|
-
return obj;
|
|
957
|
+
extractElementAttributes(props) {
|
|
958
|
+
if (!props || typeof props !== "object") return {};
|
|
959
|
+
const attributes = { ...props };
|
|
960
|
+
delete attributes.children;
|
|
961
|
+
delete attributes.text;
|
|
962
|
+
return attributes;
|
|
908
963
|
}
|
|
909
964
|
/**
|
|
910
|
-
*
|
|
965
|
+
* Record performance metrics
|
|
911
966
|
*/
|
|
912
|
-
|
|
913
|
-
if (this.
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
967
|
+
recordPerformance(operation, startTime, fromCache = false, metadata = {}) {
|
|
968
|
+
if (this.config.enableMonitoring) {
|
|
969
|
+
performanceMonitor.recordRender(
|
|
970
|
+
operation,
|
|
971
|
+
this.getCurrentTime() - startTime,
|
|
972
|
+
fromCache,
|
|
973
|
+
metadata
|
|
974
|
+
);
|
|
975
|
+
}
|
|
918
976
|
}
|
|
919
977
|
/**
|
|
920
|
-
*
|
|
978
|
+
* Record _error for monitoring
|
|
921
979
|
*/
|
|
922
|
-
|
|
923
|
-
if (
|
|
924
|
-
|
|
925
|
-
if (metadata) {
|
|
926
|
-
metadata.updateCount++;
|
|
980
|
+
recordError(operation, _error, metadata = {}) {
|
|
981
|
+
if (this.config.enableMonitoring) {
|
|
982
|
+
performanceMonitor.recordError(operation, _error, metadata);
|
|
927
983
|
}
|
|
928
|
-
this.callHook("beforeUpdate");
|
|
929
|
-
this.callHook("updated");
|
|
930
|
-
return this;
|
|
931
984
|
}
|
|
932
985
|
/**
|
|
933
|
-
*
|
|
986
|
+
* Get current timestamp with fallback
|
|
934
987
|
*/
|
|
935
|
-
|
|
936
|
-
if (
|
|
937
|
-
|
|
938
|
-
if (this.unsubscribeState) {
|
|
939
|
-
this.unsubscribeState();
|
|
988
|
+
getCurrentTime() {
|
|
989
|
+
if (typeof performance !== "undefined" && performance.now) {
|
|
990
|
+
return performance.now();
|
|
940
991
|
}
|
|
941
|
-
|
|
942
|
-
if (child.destroy) {
|
|
943
|
-
child.destroy();
|
|
944
|
-
}
|
|
945
|
-
});
|
|
946
|
-
this.isMounted = false;
|
|
947
|
-
this.isDestroyed = true;
|
|
948
|
-
this.children = [];
|
|
949
|
-
this.parent = null;
|
|
950
|
-
this.callHook("destroyed");
|
|
951
|
-
return this;
|
|
992
|
+
return Date.now();
|
|
952
993
|
}
|
|
953
994
|
/**
|
|
954
|
-
*
|
|
995
|
+
* Start performance timing
|
|
955
996
|
*/
|
|
956
|
-
|
|
957
|
-
|
|
997
|
+
startTiming() {
|
|
998
|
+
this.metrics.startTime = this.getCurrentTime();
|
|
958
999
|
}
|
|
959
1000
|
/**
|
|
960
|
-
*
|
|
1001
|
+
* End performance timing
|
|
961
1002
|
*/
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return new _Component(newDefinition);
|
|
1003
|
+
endTiming() {
|
|
1004
|
+
this.metrics.endTime = this.getCurrentTime();
|
|
965
1005
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1006
|
+
/**
|
|
1007
|
+
* Get performance metrics
|
|
1008
|
+
*/
|
|
1009
|
+
getMetrics() {
|
|
1010
|
+
const duration = this.metrics.endTime ? this.metrics.endTime - this.metrics.startTime : this.getCurrentTime() - this.metrics.startTime;
|
|
1011
|
+
return {
|
|
1012
|
+
...this.metrics,
|
|
1013
|
+
duration,
|
|
1014
|
+
elementsPerSecond: this.metrics.elementsProcessed / (duration / 1e3)
|
|
972
1015
|
};
|
|
973
1016
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1017
|
+
/**
|
|
1018
|
+
* Reset metrics for new render
|
|
1019
|
+
*/
|
|
1020
|
+
resetMetrics() {
|
|
1021
|
+
this.metrics = {
|
|
1022
|
+
startTime: null,
|
|
1023
|
+
endTime: null,
|
|
1024
|
+
elementsProcessed: 0
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Abstract method - must be implemented by subclasses
|
|
1029
|
+
*/
|
|
1030
|
+
renderComponent() {
|
|
1031
|
+
throw new Error("renderComponent must be implemented by subclass");
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Abstract method - must be implemented by subclasses
|
|
1035
|
+
*/
|
|
1036
|
+
render() {
|
|
1037
|
+
throw new Error("render must be implemented by subclass");
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
var RendererUtils = {
|
|
1041
|
+
/**
|
|
1042
|
+
* Check if element is static (no functions or circular references)
|
|
1043
|
+
*/
|
|
1044
|
+
isStaticElement(element, visited = /* @__PURE__ */ new WeakSet()) {
|
|
1045
|
+
if (!element || typeof element !== "object") {
|
|
1046
|
+
return typeof element === "string" || typeof element === "number";
|
|
1047
|
+
}
|
|
1048
|
+
if (visited.has(element)) {
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
visited.add(element);
|
|
1052
|
+
for (const [_key, value] of Object.entries(element)) {
|
|
1053
|
+
if (typeof value === "function") return false;
|
|
1054
|
+
if (Array.isArray(value)) {
|
|
1055
|
+
const allStatic = value.every((child) => RendererUtils.isStaticElement(child, visited));
|
|
1056
|
+
if (!allStatic) return false;
|
|
1057
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1058
|
+
if (!RendererUtils.isStaticElement(value, visited)) return false;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
return true;
|
|
1062
|
+
},
|
|
1063
|
+
/**
|
|
1064
|
+
* Check if object has functions (for caching decisions)
|
|
1065
|
+
*/
|
|
1066
|
+
hasFunctions(obj, visited = /* @__PURE__ */ new WeakSet()) {
|
|
1067
|
+
if (visited.has(obj)) return false;
|
|
1068
|
+
visited.add(obj);
|
|
1069
|
+
for (const value of Object.values(obj)) {
|
|
1070
|
+
if (typeof value === "function") return true;
|
|
1071
|
+
if (typeof value === "object" && value !== null && RendererUtils.hasFunctions(value, visited)) {
|
|
1072
|
+
return true;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
return false;
|
|
1076
|
+
},
|
|
1077
|
+
/**
|
|
1078
|
+
* Get element complexity score
|
|
1079
|
+
*/
|
|
1080
|
+
getElementComplexity(element) {
|
|
1081
|
+
if (!element || typeof element !== "object") return 1;
|
|
1082
|
+
let complexity = Object.keys(element).length;
|
|
1083
|
+
if (element.children && Array.isArray(element.children)) {
|
|
1084
|
+
complexity += element.children.reduce(
|
|
1085
|
+
(sum, child) => sum + RendererUtils.getElementComplexity(child),
|
|
1086
|
+
0
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
return complexity;
|
|
1090
|
+
},
|
|
1091
|
+
/**
|
|
1092
|
+
* Generate cache key for element
|
|
1093
|
+
*/
|
|
1094
|
+
generateCacheKey(tagName, element) {
|
|
1095
|
+
try {
|
|
1096
|
+
const keyData = {
|
|
1097
|
+
tag: tagName,
|
|
1098
|
+
props: extractProps(element),
|
|
1099
|
+
hasChildren: hasChildren(element),
|
|
1100
|
+
childrenType: Array.isArray(element.children) ? "array" : typeof element.children
|
|
1101
|
+
};
|
|
1102
|
+
return `element:${JSON.stringify(keyData)}`;
|
|
1103
|
+
} catch (_error) {
|
|
1104
|
+
if (typeof process !== "undefined" && process.env && true) {
|
|
1105
|
+
console.warn("Failed to generate cache key:", _error);
|
|
1106
|
+
}
|
|
1107
|
+
return null;
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
/**
|
|
1111
|
+
* Check if element is cacheable
|
|
1112
|
+
*/
|
|
1113
|
+
isCacheable(element, options) {
|
|
1114
|
+
if (!options.enableCache) return false;
|
|
1115
|
+
if (RendererUtils.hasFunctions(element)) return false;
|
|
1116
|
+
if (RendererUtils.getElementComplexity(element) > 1e3) return false;
|
|
1117
|
+
const cacheKey = RendererUtils.generateCacheKey(element.tagName || "unknown", element);
|
|
1118
|
+
if (!cacheKey) return false;
|
|
1119
|
+
return true;
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
|
|
1123
|
+
// src/core/html-nesting-rules.js
|
|
1124
|
+
var FORBIDDEN_CHILDREN = {
|
|
1125
|
+
// Phrasing content only - cannot contain flow content
|
|
1126
|
+
p: /* @__PURE__ */ new Set([
|
|
1127
|
+
"address",
|
|
1128
|
+
"article",
|
|
1129
|
+
"aside",
|
|
1130
|
+
"blockquote",
|
|
1131
|
+
"div",
|
|
1132
|
+
"dl",
|
|
1133
|
+
"fieldset",
|
|
1134
|
+
"footer",
|
|
1135
|
+
"form",
|
|
1136
|
+
"h1",
|
|
1137
|
+
"h2",
|
|
1138
|
+
"h3",
|
|
1139
|
+
"h4",
|
|
1140
|
+
"h5",
|
|
1141
|
+
"h6",
|
|
1142
|
+
"header",
|
|
1143
|
+
"hr",
|
|
1144
|
+
"main",
|
|
1145
|
+
"nav",
|
|
1146
|
+
"ol",
|
|
1147
|
+
"p",
|
|
1148
|
+
"pre",
|
|
1149
|
+
"section",
|
|
1150
|
+
"table",
|
|
1151
|
+
"ul",
|
|
1152
|
+
"figure",
|
|
1153
|
+
"figcaption"
|
|
1154
|
+
]),
|
|
1155
|
+
// Interactive content restrictions
|
|
1156
|
+
a: /* @__PURE__ */ new Set(["a"]),
|
|
1157
|
+
// Links cannot nest
|
|
1158
|
+
button: /* @__PURE__ */ new Set(["button", "a", "input", "select", "textarea", "label"]),
|
|
1159
|
+
label: /* @__PURE__ */ new Set(["label"]),
|
|
1160
|
+
// Table structure restrictions
|
|
1161
|
+
thead: /* @__PURE__ */ new Set(["thead", "tbody", "tfoot", "caption", "colgroup", "tr"]),
|
|
1162
|
+
tbody: /* @__PURE__ */ new Set(["thead", "tbody", "tfoot", "caption", "colgroup"]),
|
|
1163
|
+
tfoot: /* @__PURE__ */ new Set(["thead", "tbody", "tfoot", "caption", "colgroup"]),
|
|
1164
|
+
tr: /* @__PURE__ */ new Set(["tr", "thead", "tbody", "tfoot", "table"]),
|
|
1165
|
+
td: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot", "table"]),
|
|
1166
|
+
th: /* @__PURE__ */ new Set(["td", "th", "tr", "thead", "tbody", "tfoot", "table"]),
|
|
1167
|
+
// Other common restrictions
|
|
1168
|
+
select: /* @__PURE__ */ new Set(["select", "input", "textarea"]),
|
|
1169
|
+
option: /* @__PURE__ */ new Set(["option", "optgroup"])
|
|
1170
|
+
};
|
|
1171
|
+
function validateNesting(parentTag, childTag, path = "", options = {}) {
|
|
1172
|
+
if (!parentTag || !childTag) {
|
|
1173
|
+
return true;
|
|
1174
|
+
}
|
|
1175
|
+
const parent = parentTag.toLowerCase();
|
|
1176
|
+
const child = childTag.toLowerCase();
|
|
1177
|
+
const forbidden = FORBIDDEN_CHILDREN[parent];
|
|
1178
|
+
if (!forbidden || !forbidden.has(child)) {
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
const pathSuffix = path ? ` at ${path}` : "";
|
|
1182
|
+
const message = `Invalid HTML nesting: <${child}> cannot be a child of <${parent}>${pathSuffix}. Browsers will auto-correct this, causing potential hydration mismatches.`;
|
|
1183
|
+
if (options.throwOnError) {
|
|
1184
|
+
throw new HTMLNestingError(message, { parent, child, path });
|
|
1185
|
+
}
|
|
1186
|
+
const shouldWarn = options.warn !== false && (typeof process === "undefined" || !process.env || true);
|
|
1187
|
+
if (shouldWarn) {
|
|
1188
|
+
console.warn(`[Coherent.js] ${message}`);
|
|
1189
|
+
}
|
|
1190
|
+
return false;
|
|
984
1191
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1192
|
+
var HTMLNestingError = class extends Error {
|
|
1193
|
+
constructor(message, context2 = {}) {
|
|
1194
|
+
super(message);
|
|
1195
|
+
this.name = "HTMLNestingError";
|
|
1196
|
+
this.parent = context2.parent;
|
|
1197
|
+
this.child = context2.child;
|
|
1198
|
+
this.path = context2.path;
|
|
988
1199
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
// src/core/html-utils.js
|
|
1203
|
+
function escapeHtml(text) {
|
|
1204
|
+
if (typeof text !== "string") return text;
|
|
1205
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
992
1206
|
}
|
|
993
|
-
function
|
|
994
|
-
|
|
1207
|
+
function isVoidElement(tagName) {
|
|
1208
|
+
if (typeof tagName !== "string") {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
const voidElements = /* @__PURE__ */ new Set([
|
|
1212
|
+
"area",
|
|
1213
|
+
"base",
|
|
1214
|
+
"br",
|
|
1215
|
+
"col",
|
|
1216
|
+
"embed",
|
|
1217
|
+
"hr",
|
|
1218
|
+
"img",
|
|
1219
|
+
"input",
|
|
1220
|
+
"link",
|
|
1221
|
+
"meta",
|
|
1222
|
+
"param",
|
|
1223
|
+
"source",
|
|
1224
|
+
"track",
|
|
1225
|
+
"wbr"
|
|
1226
|
+
]);
|
|
1227
|
+
return voidElements.has(tagName.toLowerCase());
|
|
995
1228
|
}
|
|
996
|
-
function
|
|
997
|
-
|
|
1229
|
+
function formatAttributes(props) {
|
|
1230
|
+
let formatted = "";
|
|
1231
|
+
for (const key in props) {
|
|
1232
|
+
if (props.hasOwnProperty(key)) {
|
|
1233
|
+
let value = props[key];
|
|
1234
|
+
const attributeName = key === "className" ? "class" : key;
|
|
1235
|
+
if (typeof value === "function") {
|
|
1236
|
+
if (attributeName.startsWith("on")) {
|
|
1237
|
+
const actionId = `__coherent_action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
1238
|
+
const DEBUG = typeof process !== "undefined" && process && process.env && (process.env.COHERENT_DEBUG === "1" || true) || typeof window !== "undefined" && window && window.COHERENT_DEBUG === true;
|
|
1239
|
+
if (typeof global !== "undefined") {
|
|
1240
|
+
if (!global.__coherentActionRegistry) {
|
|
1241
|
+
global.__coherentActionRegistry = {};
|
|
1242
|
+
if (DEBUG) console.log("Initialized global action registry");
|
|
1243
|
+
}
|
|
1244
|
+
global.__coherentActionRegistry[actionId] = value;
|
|
1245
|
+
if (DEBUG) console.log(`Added action ${actionId} to global registry, total: ${Object.keys(global.__coherentActionRegistry).length}`);
|
|
1246
|
+
if (DEBUG) console.log(`Global registry keys: ${Object.keys(global.__coherentActionRegistry).join(", ")}`);
|
|
1247
|
+
if (DEBUG) {
|
|
1248
|
+
if (typeof global.__coherentActionRegistryLog === "undefined") {
|
|
1249
|
+
global.__coherentActionRegistryLog = [];
|
|
1250
|
+
}
|
|
1251
|
+
global.__coherentActionRegistryLog.push({
|
|
1252
|
+
action: "add",
|
|
1253
|
+
actionId,
|
|
1254
|
+
timestamp: Date.now(),
|
|
1255
|
+
registrySize: Object.keys(global.__coherentActionRegistry).length
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
} else if (typeof window !== "undefined") {
|
|
1259
|
+
if (!window.__coherentActionRegistry) {
|
|
1260
|
+
window.__coherentActionRegistry = {};
|
|
1261
|
+
if (DEBUG) console.log("Initialized window action registry");
|
|
1262
|
+
}
|
|
1263
|
+
window.__coherentActionRegistry[actionId] = value;
|
|
1264
|
+
if (DEBUG) console.log(`Added action ${actionId} to window registry, total: ${Object.keys(window.__coherentActionRegistry).length}`);
|
|
1265
|
+
if (DEBUG) console.log(`Window registry keys: ${Object.keys(window.__coherentActionRegistry).join(", ")}`);
|
|
1266
|
+
}
|
|
1267
|
+
const eventType = attributeName.substring(2);
|
|
1268
|
+
formatted += ` data-action="${actionId}" data-event="${eventType}"`;
|
|
1269
|
+
continue;
|
|
1270
|
+
} else {
|
|
1271
|
+
try {
|
|
1272
|
+
value = value();
|
|
1273
|
+
} catch (_error) {
|
|
1274
|
+
console.warn(`Error executing function for attribute '${key}':`, {
|
|
1275
|
+
_error: _error.message,
|
|
1276
|
+
stack: _error.stack,
|
|
1277
|
+
attributeKey: key
|
|
1278
|
+
});
|
|
1279
|
+
value = "";
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (attributeName === "style" && typeof value === "object" && value !== null) {
|
|
1284
|
+
const cssString = Object.entries(value).map(([prop, val]) => {
|
|
1285
|
+
const kebabProp = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
1286
|
+
return `${kebabProp}: ${val}`;
|
|
1287
|
+
}).join("; ");
|
|
1288
|
+
formatted += ` ${attributeName}="${escapeHtml(cssString)}"`;
|
|
1289
|
+
} else if (value === true) {
|
|
1290
|
+
formatted += ` ${attributeName}`;
|
|
1291
|
+
} else if (value !== false && value !== null && value !== void 0) {
|
|
1292
|
+
formatted += ` ${attributeName}="${escapeHtml(String(value))}"`;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return formatted.trim();
|
|
998
1297
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const start = performance.now();
|
|
1003
|
-
const result = originalRender.apply(this, args);
|
|
1004
|
-
const duration = performance.now() - start;
|
|
1005
|
-
performanceMonitor.recordMetric("renderTime", duration, {
|
|
1006
|
-
type: "component",
|
|
1007
|
-
name: this.name,
|
|
1008
|
-
propsSize: JSON.stringify(this.props || {}).length,
|
|
1009
|
-
hasState: Object.keys(this.state?.get() || {}).length > 0
|
|
1010
|
-
});
|
|
1011
|
-
return result;
|
|
1012
|
-
};
|
|
1298
|
+
function minifyHtml(html, options = {}) {
|
|
1299
|
+
if (!options.minify) return html;
|
|
1300
|
+
return html.replace(/<!--[\s\S]*?-->/g, "").replace(/\s+/g, " ").replace(/>\s+</g, "><").trim();
|
|
1013
1301
|
}
|
|
1014
|
-
|
|
1302
|
+
|
|
1303
|
+
// src/performance/cache-manager.js
|
|
1304
|
+
function createCacheManager(options = {}) {
|
|
1015
1305
|
const {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
//
|
|
1020
|
-
|
|
1021
|
-
// Fallback value if evaluation fails
|
|
1022
|
-
onError = null,
|
|
1023
|
-
// Error handler
|
|
1024
|
-
dependencies = []
|
|
1025
|
-
// Dependencies that invalidate cache
|
|
1306
|
+
maxCacheSize = 1e3,
|
|
1307
|
+
maxMemoryMB = 100,
|
|
1308
|
+
ttlMs = 1e3 * 60 * 5,
|
|
1309
|
+
// 5 minutes
|
|
1310
|
+
enableStatistics = true
|
|
1026
1311
|
} = options;
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1312
|
+
const caches = {
|
|
1313
|
+
static: /* @__PURE__ */ new Map(),
|
|
1314
|
+
// Never-changing components
|
|
1315
|
+
component: /* @__PURE__ */ new Map(),
|
|
1316
|
+
// Component results with deps
|
|
1317
|
+
template: /* @__PURE__ */ new Map(),
|
|
1318
|
+
// Template strings
|
|
1319
|
+
data: /* @__PURE__ */ new Map()
|
|
1320
|
+
// General purpose data
|
|
1321
|
+
};
|
|
1322
|
+
let memoryUsage = 0;
|
|
1323
|
+
const stats = {
|
|
1324
|
+
hits: 0,
|
|
1325
|
+
misses: 0,
|
|
1326
|
+
hitRate: {
|
|
1327
|
+
static: 0,
|
|
1328
|
+
component: 0,
|
|
1329
|
+
template: 0,
|
|
1330
|
+
data: 0
|
|
1331
|
+
},
|
|
1332
|
+
accessCount: {
|
|
1333
|
+
static: 0,
|
|
1334
|
+
component: 0,
|
|
1335
|
+
template: 0,
|
|
1336
|
+
data: 0
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
let cleanupInterval;
|
|
1340
|
+
if (typeof setInterval === "function") {
|
|
1341
|
+
cleanupInterval = setInterval(() => cleanup(), 3e4);
|
|
1342
|
+
if (cleanupInterval.unref) {
|
|
1343
|
+
cleanupInterval.unref();
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
function generateCacheKey(component, props = {}, context2 = {}) {
|
|
1347
|
+
const componentStr = typeof component === "function" ? component.name || component.toString() : JSON.stringify(component);
|
|
1348
|
+
const propsStr = JSON.stringify(props, Object.keys(props).sort());
|
|
1349
|
+
const contextStr = JSON.stringify(context2);
|
|
1350
|
+
const hash = simpleHash(componentStr + propsStr + contextStr);
|
|
1351
|
+
return `${extractComponentName(component)}_${hash}`;
|
|
1352
|
+
}
|
|
1353
|
+
function get(key, type = "component") {
|
|
1354
|
+
const cache = caches[type] || caches.component;
|
|
1355
|
+
const entry = cache.get(key);
|
|
1356
|
+
if (!entry) {
|
|
1357
|
+
stats.misses++;
|
|
1358
|
+
if (enableStatistics) stats.accessCount[type]++;
|
|
1359
|
+
return null;
|
|
1360
|
+
}
|
|
1361
|
+
if (Date.now() - entry.timestamp > ttlMs) {
|
|
1362
|
+
cache.delete(key);
|
|
1363
|
+
updateMemoryUsage(-entry.size);
|
|
1364
|
+
stats.misses++;
|
|
1365
|
+
if (enableStatistics) stats.accessCount[type]++;
|
|
1366
|
+
return null;
|
|
1367
|
+
}
|
|
1368
|
+
entry.lastAccess = Date.now();
|
|
1369
|
+
entry.accessCount++;
|
|
1370
|
+
stats.hits++;
|
|
1371
|
+
if (enableStatistics) {
|
|
1372
|
+
stats.accessCount[type]++;
|
|
1373
|
+
stats.hitRate[type] = stats.hits / (stats.hits + stats.misses) * 100;
|
|
1374
|
+
}
|
|
1375
|
+
return entry.value;
|
|
1376
|
+
}
|
|
1377
|
+
function set(key, value, type = "component", metadata = {}) {
|
|
1378
|
+
const cache = caches[type] || caches.component;
|
|
1379
|
+
const size = calculateSize(value);
|
|
1380
|
+
if (memoryUsage + size > maxMemoryMB * 1024 * 1024) {
|
|
1381
|
+
optimize(type, size);
|
|
1382
|
+
}
|
|
1383
|
+
const entry = {
|
|
1384
|
+
value,
|
|
1385
|
+
timestamp: Date.now(),
|
|
1386
|
+
lastAccess: Date.now(),
|
|
1387
|
+
size,
|
|
1388
|
+
metadata,
|
|
1389
|
+
accessCount: 0
|
|
1390
|
+
};
|
|
1391
|
+
const existing = cache.get(key);
|
|
1392
|
+
if (existing) {
|
|
1393
|
+
updateMemoryUsage(-existing.size);
|
|
1394
|
+
}
|
|
1395
|
+
cache.set(key, entry);
|
|
1396
|
+
updateMemoryUsage(size);
|
|
1397
|
+
if (cache.size > maxCacheSize) {
|
|
1398
|
+
optimize(type);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
function remove(key, type) {
|
|
1402
|
+
if (type) {
|
|
1403
|
+
const cache = caches[type];
|
|
1404
|
+
if (!cache) return false;
|
|
1405
|
+
const entry = cache.get(key);
|
|
1406
|
+
if (entry) {
|
|
1407
|
+
updateMemoryUsage(-entry.size);
|
|
1408
|
+
return cache.delete(key);
|
|
1041
1409
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
for (const [, cache] of Object.entries(caches)) {
|
|
1413
|
+
const entry = cache.get(key);
|
|
1414
|
+
if (entry) {
|
|
1415
|
+
updateMemoryUsage(-entry.size);
|
|
1416
|
+
return cache.delete(key);
|
|
1049
1417
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1418
|
+
}
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
function clear(type) {
|
|
1422
|
+
if (type) {
|
|
1423
|
+
const cache = caches[type];
|
|
1424
|
+
if (cache) {
|
|
1425
|
+
cache.clear();
|
|
1052
1426
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1427
|
+
} else {
|
|
1428
|
+
Object.values(caches).forEach((cache) => cache.clear());
|
|
1429
|
+
}
|
|
1430
|
+
memoryUsage = 0;
|
|
1431
|
+
}
|
|
1432
|
+
function getStats() {
|
|
1433
|
+
const entries = Object.values(caches).reduce((sum, cache) => sum + cache.size, 0);
|
|
1434
|
+
return {
|
|
1435
|
+
hits: stats.hits,
|
|
1436
|
+
misses: stats.misses,
|
|
1437
|
+
size: memoryUsage,
|
|
1438
|
+
entries,
|
|
1439
|
+
hitRate: stats.hitRate,
|
|
1440
|
+
accessCount: stats.accessCount
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
function cleanup() {
|
|
1444
|
+
const now = Date.now();
|
|
1445
|
+
let freed = 0;
|
|
1446
|
+
for (const [, cache] of Object.entries(caches)) {
|
|
1447
|
+
for (const [key, entry] of cache.entries()) {
|
|
1448
|
+
if (now - entry.timestamp > ttlMs) {
|
|
1449
|
+
cache.delete(key);
|
|
1450
|
+
updateMemoryUsage(-entry.size);
|
|
1451
|
+
freed++;
|
|
1077
1452
|
}
|
|
1078
|
-
return fallback;
|
|
1079
|
-
} finally {
|
|
1080
|
-
isEvaluating = false;
|
|
1081
1453
|
}
|
|
1082
|
-
},
|
|
1083
|
-
// Force re-evaluation
|
|
1084
|
-
invalidate() {
|
|
1085
|
-
cached = false;
|
|
1086
|
-
cachedValue = null;
|
|
1087
|
-
lastDependencyHash = null;
|
|
1088
|
-
return this;
|
|
1089
|
-
},
|
|
1090
|
-
// Check if evaluated
|
|
1091
|
-
isEvaluated() {
|
|
1092
|
-
return cached;
|
|
1093
|
-
},
|
|
1094
|
-
// Get cached value without evaluation
|
|
1095
|
-
getCachedValue() {
|
|
1096
|
-
return cachedValue;
|
|
1097
|
-
},
|
|
1098
|
-
// Transform the lazy value
|
|
1099
|
-
map(transform) {
|
|
1100
|
-
return lazy((...args) => {
|
|
1101
|
-
const value = this.evaluate(...args);
|
|
1102
|
-
return transform(value);
|
|
1103
|
-
}, { ...options, cache: false });
|
|
1104
|
-
},
|
|
1105
|
-
// Chain lazy evaluations
|
|
1106
|
-
flatMap(transform) {
|
|
1107
|
-
return lazy((...args) => {
|
|
1108
|
-
const value = this.evaluate(...args);
|
|
1109
|
-
const transformed = transform(value);
|
|
1110
|
-
if (isLazy(transformed)) {
|
|
1111
|
-
return transformed.evaluate(...args);
|
|
1112
|
-
}
|
|
1113
|
-
return transformed;
|
|
1114
|
-
}, { ...options, cache: false });
|
|
1115
|
-
},
|
|
1116
|
-
// Convert to string for debugging
|
|
1117
|
-
toString() {
|
|
1118
|
-
return `[Lazy${cached ? " (cached)" : ""}]`;
|
|
1119
|
-
},
|
|
1120
|
-
// JSON serialization
|
|
1121
|
-
toJSON() {
|
|
1122
|
-
return this.evaluate();
|
|
1123
|
-
}
|
|
1124
|
-
};
|
|
1125
|
-
return lazyWrapper;
|
|
1126
|
-
}
|
|
1127
|
-
function isLazy(value) {
|
|
1128
|
-
return value && typeof value === "object" && value.__isLazy === true;
|
|
1129
|
-
}
|
|
1130
|
-
function evaluateLazy(obj, ...args) {
|
|
1131
|
-
if (isLazy(obj)) {
|
|
1132
|
-
return obj.evaluate(...args);
|
|
1133
|
-
}
|
|
1134
|
-
if (Array.isArray(obj)) {
|
|
1135
|
-
return obj.map((item) => evaluateLazy(item, ...args));
|
|
1136
|
-
}
|
|
1137
|
-
if (obj && typeof obj === "object") {
|
|
1138
|
-
const result = {};
|
|
1139
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1140
|
-
result[key] = evaluateLazy(value, ...args);
|
|
1141
1454
|
}
|
|
1142
|
-
return
|
|
1455
|
+
return { freed };
|
|
1143
1456
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
if (typeof
|
|
1149
|
-
|
|
1457
|
+
function calculateSize(value) {
|
|
1458
|
+
if (value === null || value === void 0) return 0;
|
|
1459
|
+
if (typeof value === "string") return value.length * 2;
|
|
1460
|
+
if (typeof value === "number") return 8;
|
|
1461
|
+
if (typeof value === "boolean") return 4;
|
|
1462
|
+
if (Array.isArray(value)) {
|
|
1463
|
+
return value.reduce((sum, item) => sum + calculateSize(item), 0);
|
|
1150
1464
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
}
|
|
1154
|
-
function evaluateWithTimeout(factory, timeout, args, fallback) {
|
|
1155
|
-
return new Promise((resolve, reject) => {
|
|
1156
|
-
const timer = setTimeout(() => {
|
|
1157
|
-
reject(new Error(`Lazy evaluation timeout after ${timeout}ms`));
|
|
1158
|
-
}, timeout);
|
|
1159
|
-
try {
|
|
1160
|
-
const result = factory(...args);
|
|
1161
|
-
if (result && typeof result.then === "function") {
|
|
1162
|
-
result.then((value) => {
|
|
1163
|
-
clearTimeout(timer);
|
|
1164
|
-
resolve(value);
|
|
1165
|
-
}).catch((_error) => {
|
|
1166
|
-
clearTimeout(timer);
|
|
1167
|
-
reject(_error);
|
|
1168
|
-
});
|
|
1169
|
-
} else {
|
|
1170
|
-
clearTimeout(timer);
|
|
1171
|
-
resolve(result);
|
|
1172
|
-
}
|
|
1173
|
-
} catch (_error) {
|
|
1174
|
-
clearTimeout(timer);
|
|
1175
|
-
reject(_error);
|
|
1465
|
+
if (typeof value === "object") {
|
|
1466
|
+
return Object.values(value).reduce((sum, val) => sum + calculateSize(val), 0);
|
|
1176
1467
|
}
|
|
1177
|
-
|
|
1178
|
-
}
|
|
1179
|
-
function memo(fn, options = {}) {
|
|
1180
|
-
const {
|
|
1181
|
-
// Caching strategy
|
|
1182
|
-
strategy = "lru",
|
|
1183
|
-
// 'lru', 'ttl', 'weak', 'simple'
|
|
1184
|
-
maxSize = 100,
|
|
1185
|
-
// Maximum cache entries
|
|
1186
|
-
ttl = null,
|
|
1187
|
-
// Time to live in milliseconds
|
|
1188
|
-
// Key generation
|
|
1189
|
-
keyFn = null,
|
|
1190
|
-
// Custom key function
|
|
1191
|
-
keySerializer = JSON.stringify,
|
|
1192
|
-
// Default serialization
|
|
1193
|
-
// Comparison
|
|
1194
|
-
// eslint-disable-next-line no-unused-vars
|
|
1195
|
-
compareFn = null,
|
|
1196
|
-
// Custom equality comparison
|
|
1197
|
-
// eslint-disable-next-line no-unused-vars
|
|
1198
|
-
shallow = false,
|
|
1199
|
-
// Shallow comparison for objects
|
|
1200
|
-
// Lifecycle hooks
|
|
1201
|
-
onHit = null,
|
|
1202
|
-
// Called on cache hit
|
|
1203
|
-
onMiss = null,
|
|
1204
|
-
// Called on cache miss
|
|
1205
|
-
onEvict = null,
|
|
1206
|
-
// Called when item evicted
|
|
1207
|
-
// Performance
|
|
1208
|
-
stats = false,
|
|
1209
|
-
// Track hit/miss statistics
|
|
1210
|
-
// Development
|
|
1211
|
-
debug = false
|
|
1212
|
-
// Debug logging
|
|
1213
|
-
} = options;
|
|
1214
|
-
let cache;
|
|
1215
|
-
const stats_data = stats ? { hits: 0, misses: 0, evictions: 0 } : null;
|
|
1216
|
-
switch (strategy) {
|
|
1217
|
-
case "lru":
|
|
1218
|
-
cache = new LRUCache(maxSize, { onEvict });
|
|
1219
|
-
break;
|
|
1220
|
-
case "ttl":
|
|
1221
|
-
cache = new TTLCache(ttl, { onEvict });
|
|
1222
|
-
break;
|
|
1223
|
-
case "weak":
|
|
1224
|
-
cache = /* @__PURE__ */ new WeakMap();
|
|
1225
|
-
break;
|
|
1226
|
-
default:
|
|
1227
|
-
cache = /* @__PURE__ */ new Map();
|
|
1468
|
+
return 0;
|
|
1228
1469
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
if (args.length === 1) return keySerializer(args[0]);
|
|
1232
|
-
return keySerializer(args);
|
|
1233
|
-
});
|
|
1234
|
-
const memoizedFn = (...args) => {
|
|
1235
|
-
const key = generateKey(...args);
|
|
1236
|
-
if (cache.has(key)) {
|
|
1237
|
-
const cached = cache.get(key);
|
|
1238
|
-
if (cached && (!cached.expires || Date.now() < cached.expires)) {
|
|
1239
|
-
if (debug) console.log(`Memo cache hit for key: ${key}`);
|
|
1240
|
-
if (onHit) onHit(key, cached.value, args);
|
|
1241
|
-
if (stats_data) stats_data.hits++;
|
|
1242
|
-
return cached.value || cached;
|
|
1243
|
-
} else {
|
|
1244
|
-
cache.delete(key);
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
if (debug) console.log(`Memo cache miss for key: ${key}`);
|
|
1248
|
-
if (onMiss) onMiss(key, args);
|
|
1249
|
-
if (stats_data) stats_data.misses++;
|
|
1250
|
-
const result = fn(...args);
|
|
1251
|
-
const cacheEntry = ttl ? { value: result, expires: Date.now() + ttl } : result;
|
|
1252
|
-
cache.set(key, cacheEntry);
|
|
1253
|
-
return result;
|
|
1254
|
-
};
|
|
1255
|
-
memoizedFn.cache = cache;
|
|
1256
|
-
memoizedFn.clear = () => cache.clear();
|
|
1257
|
-
memoizedFn.delete = (key) => cache.delete(key);
|
|
1258
|
-
memoizedFn.has = (key) => cache.has(key);
|
|
1259
|
-
memoizedFn.size = () => cache.size;
|
|
1260
|
-
if (stats_data) {
|
|
1261
|
-
memoizedFn.stats = () => ({ ...stats_data });
|
|
1262
|
-
memoizedFn.resetStats = () => {
|
|
1263
|
-
stats_data.hits = 0;
|
|
1264
|
-
stats_data.misses = 0;
|
|
1265
|
-
stats_data.evictions = 0;
|
|
1266
|
-
};
|
|
1470
|
+
function updateMemoryUsage(delta) {
|
|
1471
|
+
memoryUsage = Math.max(0, memoryUsage + delta);
|
|
1267
1472
|
}
|
|
1268
|
-
|
|
1269
|
-
const
|
|
1270
|
-
cache.
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
this.onEvict = options.onEvict;
|
|
1473
|
+
function optimize(type, requiredSpace = 0) {
|
|
1474
|
+
const cache = caches[type] || caches.component;
|
|
1475
|
+
const entries = Array.from(cache.entries()).sort(([, a], [, b]) => a.lastAccess - b.lastAccess);
|
|
1476
|
+
let freed = 0;
|
|
1477
|
+
for (const [key, entry] of entries) {
|
|
1478
|
+
if (freed >= requiredSpace) break;
|
|
1479
|
+
cache.delete(key);
|
|
1480
|
+
updateMemoryUsage(-entry.size);
|
|
1481
|
+
freed += entry.size;
|
|
1482
|
+
}
|
|
1483
|
+
return { freed };
|
|
1280
1484
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1485
|
+
function simpleHash(str) {
|
|
1486
|
+
let hash = 0;
|
|
1487
|
+
for (let i = 0; i < str.length; i++) {
|
|
1488
|
+
const char = str.charCodeAt(i);
|
|
1489
|
+
hash = (hash << 5) - hash + char;
|
|
1490
|
+
hash = hash & hash;
|
|
1287
1491
|
}
|
|
1288
|
-
return
|
|
1492
|
+
return Math.abs(hash).toString(36);
|
|
1289
1493
|
}
|
|
1290
|
-
|
|
1291
|
-
if (
|
|
1292
|
-
|
|
1293
|
-
} else if (this.cache.size >= this.maxSize) {
|
|
1294
|
-
const firstKey = this.cache.keys().next().value;
|
|
1295
|
-
const evicted = this.cache.get(firstKey);
|
|
1296
|
-
this.cache.delete(firstKey);
|
|
1297
|
-
if (this.onEvict) {
|
|
1298
|
-
this.onEvict(firstKey, evicted);
|
|
1299
|
-
}
|
|
1494
|
+
function extractComponentName(component) {
|
|
1495
|
+
if (typeof component === "function") {
|
|
1496
|
+
return component.name || "AnonymousComponent";
|
|
1300
1497
|
}
|
|
1301
|
-
|
|
1498
|
+
if (component && typeof component === "object") {
|
|
1499
|
+
const keys = Object.keys(component);
|
|
1500
|
+
return keys.length > 0 ? keys[0] : "ObjectComponent";
|
|
1501
|
+
}
|
|
1502
|
+
return "UnknownComponent";
|
|
1302
1503
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1504
|
+
function destroy() {
|
|
1505
|
+
if (cleanupInterval) {
|
|
1506
|
+
clearInterval(cleanupInterval);
|
|
1507
|
+
}
|
|
1508
|
+
clear();
|
|
1305
1509
|
}
|
|
1306
|
-
|
|
1307
|
-
return
|
|
1510
|
+
function hashObject(obj) {
|
|
1511
|
+
return simpleHash(JSON.stringify(obj));
|
|
1308
1512
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1513
|
+
return {
|
|
1514
|
+
get,
|
|
1515
|
+
set,
|
|
1516
|
+
remove,
|
|
1517
|
+
clear,
|
|
1518
|
+
getStats,
|
|
1519
|
+
cleanup,
|
|
1520
|
+
destroy,
|
|
1521
|
+
generateCacheKey,
|
|
1522
|
+
hashObject,
|
|
1523
|
+
get memoryUsage() {
|
|
1524
|
+
return memoryUsage;
|
|
1525
|
+
},
|
|
1526
|
+
get maxMemory() {
|
|
1527
|
+
return maxMemoryMB * 1024 * 1024;
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
var cacheManager = createCacheManager();
|
|
1532
|
+
|
|
1533
|
+
// src/utils/error-handler.js
|
|
1534
|
+
var CoherentError = class _CoherentError extends Error {
|
|
1535
|
+
constructor(message, options = {}) {
|
|
1536
|
+
super(message);
|
|
1537
|
+
this.name = "CoherentError";
|
|
1538
|
+
this.type = options.type || "generic";
|
|
1539
|
+
this.code = options.code || `COHERENT_${String(this.type).toUpperCase()}`;
|
|
1540
|
+
this.docsUrl = options.docsUrl || `/docs/core/errors#${this.code}`;
|
|
1541
|
+
this.component = options.component;
|
|
1542
|
+
this.context = options.context;
|
|
1543
|
+
this.suggestions = options.suggestions || [];
|
|
1544
|
+
this.timestamp = Date.now();
|
|
1545
|
+
if (Error.captureStackTrace) {
|
|
1546
|
+
Error.captureStackTrace(this, _CoherentError);
|
|
1547
|
+
}
|
|
1311
1548
|
}
|
|
1312
|
-
|
|
1313
|
-
return
|
|
1549
|
+
toJSON() {
|
|
1550
|
+
return {
|
|
1551
|
+
name: this.name,
|
|
1552
|
+
message: this.message,
|
|
1553
|
+
type: this.type,
|
|
1554
|
+
code: this.code,
|
|
1555
|
+
docsUrl: this.docsUrl,
|
|
1556
|
+
component: this.component,
|
|
1557
|
+
context: this.context,
|
|
1558
|
+
suggestions: this.suggestions,
|
|
1559
|
+
timestamp: this.timestamp,
|
|
1560
|
+
stack: this.stack
|
|
1561
|
+
};
|
|
1314
1562
|
}
|
|
1315
1563
|
};
|
|
1316
|
-
var
|
|
1317
|
-
constructor(
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
this.delete(key);
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
return void 0;
|
|
1564
|
+
var ComponentValidationError = class extends CoherentError {
|
|
1565
|
+
constructor(message, component, suggestions = []) {
|
|
1566
|
+
super(message, {
|
|
1567
|
+
type: "validation",
|
|
1568
|
+
component,
|
|
1569
|
+
suggestions: [
|
|
1570
|
+
"Check component structure and syntax",
|
|
1571
|
+
"Ensure all required properties are present",
|
|
1572
|
+
"Validate prop types and values",
|
|
1573
|
+
...suggestions
|
|
1574
|
+
]
|
|
1575
|
+
});
|
|
1576
|
+
this.name = "ComponentValidationError";
|
|
1333
1577
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1578
|
+
};
|
|
1579
|
+
var RenderingError = class extends CoherentError {
|
|
1580
|
+
constructor(message, component, context2, suggestions = []) {
|
|
1581
|
+
super(message, {
|
|
1582
|
+
type: "rendering",
|
|
1583
|
+
component,
|
|
1584
|
+
context: context2,
|
|
1585
|
+
suggestions: [
|
|
1586
|
+
"Check for circular references",
|
|
1587
|
+
"Validate component depth",
|
|
1588
|
+
"Ensure all functions return valid components",
|
|
1589
|
+
...suggestions
|
|
1590
|
+
]
|
|
1591
|
+
});
|
|
1592
|
+
this.name = "RenderingError";
|
|
1593
|
+
if (context2 && context2.path) {
|
|
1594
|
+
this.renderPath = context2.path;
|
|
1337
1595
|
}
|
|
1338
|
-
const expires = Date.now() + this.ttl;
|
|
1339
|
-
this.cache.set(key, { value, expires });
|
|
1340
|
-
const timer = setTimeout(() => {
|
|
1341
|
-
this.delete(key);
|
|
1342
|
-
}, this.ttl);
|
|
1343
|
-
this.timers.set(key, timer);
|
|
1344
1596
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1597
|
+
};
|
|
1598
|
+
var PerformanceError = class extends CoherentError {
|
|
1599
|
+
constructor(message, metrics, suggestions = []) {
|
|
1600
|
+
super(message, {
|
|
1601
|
+
type: "performance",
|
|
1602
|
+
context: metrics,
|
|
1603
|
+
suggestions: [
|
|
1604
|
+
"Consider component memoization",
|
|
1605
|
+
"Reduce component complexity",
|
|
1606
|
+
"Enable caching",
|
|
1607
|
+
...suggestions
|
|
1608
|
+
]
|
|
1609
|
+
});
|
|
1610
|
+
this.name = "PerformanceError";
|
|
1351
1611
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1612
|
+
};
|
|
1613
|
+
var StateError = class extends CoherentError {
|
|
1614
|
+
constructor(message, state, suggestions = []) {
|
|
1615
|
+
super(message, {
|
|
1616
|
+
type: "state",
|
|
1617
|
+
context: state,
|
|
1618
|
+
suggestions: [
|
|
1619
|
+
"Check state mutations",
|
|
1620
|
+
"Ensure proper state initialization",
|
|
1621
|
+
"Validate state transitions",
|
|
1622
|
+
...suggestions
|
|
1623
|
+
]
|
|
1624
|
+
});
|
|
1625
|
+
this.name = "StateError";
|
|
1626
|
+
}
|
|
1627
|
+
};
|
|
1628
|
+
var ErrorHandler = class {
|
|
1629
|
+
constructor(options = {}) {
|
|
1630
|
+
const isDev = typeof process !== "undefined" && process.env && true;
|
|
1631
|
+
const envForceSilent = typeof process !== "undefined" && process.env && process.env.COHERENT_SILENT === "1";
|
|
1632
|
+
const envForceDebug = typeof process !== "undefined" && process.env && process.env.COHERENT_DEBUG === "1";
|
|
1633
|
+
const defaultEnableLogging = envForceSilent ? false : envForceDebug ? true : isDev;
|
|
1634
|
+
this.options = {
|
|
1635
|
+
enableStackTrace: options.enableStackTrace !== false,
|
|
1636
|
+
enableSuggestions: options.enableSuggestions !== false,
|
|
1637
|
+
enableLogging: options.enableLogging ?? defaultEnableLogging,
|
|
1638
|
+
logLevel: options.logLevel || "_error",
|
|
1639
|
+
maxErrorHistory: options.maxErrorHistory || 100,
|
|
1640
|
+
...options
|
|
1641
|
+
};
|
|
1642
|
+
this.errorHistory = [];
|
|
1643
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
1644
|
+
this.suppressedErrors = /* @__PURE__ */ new Set();
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Handle and report errors with detailed context
|
|
1648
|
+
*/
|
|
1649
|
+
handle(_error, context2 = {}) {
|
|
1650
|
+
const enhancedError = this.enhanceError(_error, context2);
|
|
1651
|
+
this.addToHistory(enhancedError);
|
|
1652
|
+
if (this.options.enableLogging) {
|
|
1653
|
+
this.logError(enhancedError);
|
|
1364
1654
|
}
|
|
1365
|
-
return
|
|
1655
|
+
return enhancedError;
|
|
1366
1656
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1657
|
+
/**
|
|
1658
|
+
* Enhance existing errors with more context
|
|
1659
|
+
*/
|
|
1660
|
+
enhanceError(_error, context2 = {}) {
|
|
1661
|
+
if (_error instanceof CoherentError) {
|
|
1662
|
+
return _error;
|
|
1663
|
+
}
|
|
1664
|
+
const errorType = this.classifyError(_error, context2);
|
|
1665
|
+
switch (errorType) {
|
|
1666
|
+
case "validation":
|
|
1667
|
+
return new ComponentValidationError(
|
|
1668
|
+
_error.message,
|
|
1669
|
+
context2.component,
|
|
1670
|
+
this.generateSuggestions(_error, context2)
|
|
1671
|
+
);
|
|
1672
|
+
case "rendering":
|
|
1673
|
+
return new RenderingError(
|
|
1674
|
+
_error.message,
|
|
1675
|
+
context2.component,
|
|
1676
|
+
context2.renderContext,
|
|
1677
|
+
this.generateSuggestions(_error, context2)
|
|
1678
|
+
);
|
|
1679
|
+
case "performance":
|
|
1680
|
+
return new PerformanceError(
|
|
1681
|
+
_error.message,
|
|
1682
|
+
context2.metrics,
|
|
1683
|
+
this.generateSuggestions(_error, context2)
|
|
1684
|
+
);
|
|
1685
|
+
case "state":
|
|
1686
|
+
return new StateError(
|
|
1687
|
+
_error.message,
|
|
1688
|
+
context2.state,
|
|
1689
|
+
this.generateSuggestions(_error, context2)
|
|
1690
|
+
);
|
|
1691
|
+
default:
|
|
1692
|
+
return new CoherentError(_error.message, {
|
|
1693
|
+
type: errorType,
|
|
1694
|
+
component: context2.component,
|
|
1695
|
+
context: context2.context,
|
|
1696
|
+
suggestions: this.generateSuggestions(_error, context2)
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1371
1699
|
}
|
|
1372
|
-
|
|
1373
|
-
|
|
1700
|
+
/**
|
|
1701
|
+
* Classify _error type based on message and context
|
|
1702
|
+
*/
|
|
1703
|
+
classifyError(_error, context2) {
|
|
1704
|
+
const message = _error.message.toLowerCase();
|
|
1705
|
+
if (message.includes("invalid") || message.includes("validation") || message.includes("required") || message.includes("type")) {
|
|
1706
|
+
return "validation";
|
|
1707
|
+
}
|
|
1708
|
+
if (message.includes("render") || message.includes("circular") || message.includes("depth") || message.includes("cannot render")) {
|
|
1709
|
+
return "rendering";
|
|
1710
|
+
}
|
|
1711
|
+
if (message.includes("slow") || message.includes("memory") || message.includes("performance") || message.includes("timeout")) {
|
|
1712
|
+
return "performance";
|
|
1713
|
+
}
|
|
1714
|
+
if (message.includes("state") || message.includes("mutation") || message.includes("store") || context2.state) {
|
|
1715
|
+
return "state";
|
|
1716
|
+
}
|
|
1717
|
+
if (context2.component) return "validation";
|
|
1718
|
+
if (context2.renderContext) return "rendering";
|
|
1719
|
+
if (context2.metrics) return "performance";
|
|
1720
|
+
return "generic";
|
|
1374
1721
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1722
|
+
/**
|
|
1723
|
+
* Generate helpful suggestions based on _error
|
|
1724
|
+
*/
|
|
1725
|
+
generateSuggestions(_error, context2 = {}) {
|
|
1726
|
+
const suggestions = [];
|
|
1727
|
+
const message = _error.message.toLowerCase();
|
|
1728
|
+
const patterns = [
|
|
1729
|
+
{
|
|
1730
|
+
pattern: /cannot render|render.*failed/,
|
|
1731
|
+
suggestions: [
|
|
1732
|
+
"Check if component returns a valid object structure",
|
|
1733
|
+
"Ensure all properties are properly defined",
|
|
1734
|
+
"Look for undefined variables or null references"
|
|
1735
|
+
]
|
|
1388
1736
|
},
|
|
1389
|
-
|
|
1390
|
-
|
|
1737
|
+
{
|
|
1738
|
+
pattern: /circular.*reference/,
|
|
1739
|
+
suggestions: [
|
|
1740
|
+
"Remove circular references between components",
|
|
1741
|
+
"Use lazy loading or memoization to break cycles",
|
|
1742
|
+
"Check for self-referencing components"
|
|
1743
|
+
]
|
|
1391
1744
|
},
|
|
1392
|
-
|
|
1393
|
-
|
|
1745
|
+
{
|
|
1746
|
+
pattern: /maximum.*depth/,
|
|
1747
|
+
suggestions: [
|
|
1748
|
+
"Reduce component nesting depth",
|
|
1749
|
+
"Break complex components into smaller parts",
|
|
1750
|
+
"Check for infinite recursion in component functions"
|
|
1751
|
+
]
|
|
1394
1752
|
},
|
|
1395
|
-
|
|
1396
|
-
|
|
1753
|
+
{
|
|
1754
|
+
pattern: /invalid.*component/,
|
|
1755
|
+
suggestions: [
|
|
1756
|
+
"Ensure component follows the expected object structure",
|
|
1757
|
+
"Check property names and values for typos",
|
|
1758
|
+
"Verify component is not null or undefined"
|
|
1759
|
+
]
|
|
1760
|
+
},
|
|
1761
|
+
{
|
|
1762
|
+
pattern: /performance|slow|timeout/,
|
|
1763
|
+
suggestions: [
|
|
1764
|
+
"Enable component caching",
|
|
1765
|
+
"Use memoization for expensive operations",
|
|
1766
|
+
"Reduce component complexity",
|
|
1767
|
+
"Consider lazy loading for large components"
|
|
1768
|
+
]
|
|
1397
1769
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
// Transform state before injection
|
|
1403
|
-
propName = "state",
|
|
1404
|
-
// Prop name for state injection
|
|
1405
|
-
actionsName = "actions",
|
|
1406
|
-
// Prop name for action injection
|
|
1407
|
-
// Reducers and actions
|
|
1408
|
-
reducer = null,
|
|
1409
|
-
// State reducer function
|
|
1410
|
-
actions = {},
|
|
1411
|
-
// Action creators
|
|
1412
|
-
middleware = [],
|
|
1413
|
-
// State middleware
|
|
1414
|
-
// Performance
|
|
1415
|
-
memoizeState = false,
|
|
1416
|
-
// Memoize state transformations
|
|
1417
|
-
// eslint-disable-next-line no-unused-vars
|
|
1418
|
-
shallow = false,
|
|
1419
|
-
// Shallow state comparison
|
|
1420
|
-
// Development
|
|
1421
|
-
// eslint-disable-next-line no-unused-vars
|
|
1422
|
-
devTools = false,
|
|
1423
|
-
// Connect to dev tools
|
|
1424
|
-
debug = false,
|
|
1425
|
-
// Debug logging
|
|
1426
|
-
displayName = null,
|
|
1427
|
-
// Component name for debugging
|
|
1428
|
-
// Lifecycle hooks
|
|
1429
|
-
onStateChange = null,
|
|
1430
|
-
// Called when state changes
|
|
1431
|
-
onMount = null,
|
|
1432
|
-
// Called when component mounts
|
|
1433
|
-
onUnmount = null,
|
|
1434
|
-
// Called when component unmounts
|
|
1435
|
-
// Validation
|
|
1436
|
-
validator = null,
|
|
1437
|
-
// State validator function
|
|
1438
|
-
// Async state
|
|
1439
|
-
supportAsync = false
|
|
1440
|
-
// Support async state updates
|
|
1441
|
-
} = options;
|
|
1442
|
-
return function withStateHOC(WrappedComponent) {
|
|
1443
|
-
const stateContainer = createStateContainer(initialState, {
|
|
1444
|
-
persistent,
|
|
1445
|
-
storageKey: storageKey || `${getComponentName(WrappedComponent)}_state`,
|
|
1446
|
-
storage,
|
|
1447
|
-
reducer,
|
|
1448
|
-
middleware,
|
|
1449
|
-
validator,
|
|
1450
|
-
onStateChange,
|
|
1451
|
-
debug
|
|
1452
|
-
});
|
|
1453
|
-
function WithStateComponent(props = {}, globalState = {}, context2 = {}) {
|
|
1454
|
-
if (!stateContainer.initialized) {
|
|
1455
|
-
stateContainer.initialize();
|
|
1456
|
-
if (onMount) {
|
|
1457
|
-
onMount(stateContainer.getState(), props, context2);
|
|
1458
|
-
}
|
|
1770
|
+
];
|
|
1771
|
+
patterns.forEach(({ pattern, suggestions: patternSuggestions }) => {
|
|
1772
|
+
if (pattern.test(message)) {
|
|
1773
|
+
suggestions.push(...patternSuggestions);
|
|
1459
1774
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1775
|
+
});
|
|
1776
|
+
if (context2.component) {
|
|
1777
|
+
const componentType = typeof context2.component;
|
|
1778
|
+
if (componentType === "function") {
|
|
1779
|
+
suggestions.push("Check function component return value");
|
|
1780
|
+
} else if (componentType === "object" && context2.component === null) {
|
|
1781
|
+
suggestions.push("Component is null - ensure proper initialization");
|
|
1782
|
+
} else if (Array.isArray(context2.component)) {
|
|
1783
|
+
suggestions.push("Arrays should contain valid component objects");
|
|
1464
1784
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1785
|
+
}
|
|
1786
|
+
if (suggestions.length === 0) {
|
|
1787
|
+
suggestions.push(
|
|
1788
|
+
"Enable development tools for more detailed debugging",
|
|
1789
|
+
"Check browser console for additional _error details",
|
|
1790
|
+
"Use component validation tools to identify issues"
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
return [...new Set(suggestions)];
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Add _error to history with deduplication
|
|
1797
|
+
*/
|
|
1798
|
+
addToHistory(_error) {
|
|
1799
|
+
const errorKey = `${_error.name}:${_error.message}`;
|
|
1800
|
+
this.errorCounts.set(errorKey, (this.errorCounts.get(errorKey) || 0) + 1);
|
|
1801
|
+
const historyEntry = {
|
|
1802
|
+
..._error.toJSON(),
|
|
1803
|
+
count: this.errorCounts.get(errorKey),
|
|
1804
|
+
firstSeen: this.errorHistory.find((e) => e.key === errorKey)?.firstSeen || _error.timestamp,
|
|
1805
|
+
key: errorKey
|
|
1806
|
+
};
|
|
1807
|
+
this.errorHistory = this.errorHistory.filter((e) => e.key !== errorKey);
|
|
1808
|
+
this.errorHistory.unshift(historyEntry);
|
|
1809
|
+
if (this.errorHistory.length > this.options.maxErrorHistory) {
|
|
1810
|
+
this.errorHistory = this.errorHistory.slice(0, this.options.maxErrorHistory);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Log _error with enhanced formatting
|
|
1815
|
+
*/
|
|
1816
|
+
logError(_error) {
|
|
1817
|
+
if (this.suppressedErrors.has(`${_error.name}:${_error.message}`)) {
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
const isRepeated = this.errorCounts.get(`${_error.name}:${_error.message}`) > 1;
|
|
1821
|
+
const errorGroup = `\u{1F6A8} ${_error.name}${isRepeated ? ` (\xD7${this.errorCounts.get(`${_error.name}:${_error.message}`)})` : ""}`;
|
|
1822
|
+
console.group(errorGroup);
|
|
1823
|
+
console.error(`\u274C ${_error.message}`);
|
|
1824
|
+
if (_error.code) {
|
|
1825
|
+
console.log("\u{1F3F7}\uFE0F Code:", _error.code);
|
|
1826
|
+
}
|
|
1827
|
+
if (_error.docsUrl) {
|
|
1828
|
+
console.log("\u{1F4D6} Docs:", _error.docsUrl);
|
|
1829
|
+
}
|
|
1830
|
+
if (_error.component) {
|
|
1831
|
+
console.log("\u{1F50D} Component:", this.formatComponent(_error.component));
|
|
1832
|
+
}
|
|
1833
|
+
if (_error.context) {
|
|
1834
|
+
console.log("\u{1F4CB} Context:", _error.context);
|
|
1835
|
+
}
|
|
1836
|
+
if (_error.context && typeof _error.context === "object" && _error.context.path) {
|
|
1837
|
+
console.log("\u{1F4CD} Path:", _error.context.path);
|
|
1838
|
+
}
|
|
1839
|
+
if (this.options.enableSuggestions && _error.suggestions.length > 0) {
|
|
1840
|
+
console.group("\u{1F4A1} Suggestions:");
|
|
1841
|
+
_error.suggestions.forEach((suggestion, index) => {
|
|
1842
|
+
console.log(`${index + 1}. ${suggestion}`);
|
|
1470
1843
|
});
|
|
1471
|
-
|
|
1472
|
-
// Basic state operations
|
|
1473
|
-
setState: stateContainer.setState.bind(stateContainer),
|
|
1474
|
-
getState: stateContainer.getState.bind(stateContainer),
|
|
1475
|
-
resetState: () => stateContainer.setState(initialState),
|
|
1476
|
-
// Advanced operations
|
|
1477
|
-
updateState: (updater) => {
|
|
1478
|
-
const current = stateContainer.getState();
|
|
1479
|
-
const next = typeof updater === "function" ? updater(current) : updater;
|
|
1480
|
-
stateContainer.setState(next);
|
|
1481
|
-
},
|
|
1482
|
-
// Batch updates
|
|
1483
|
-
batchUpdate: (updates) => {
|
|
1484
|
-
stateContainer.batch(() => {
|
|
1485
|
-
updates.forEach((update) => {
|
|
1486
|
-
if (typeof update === "function") {
|
|
1487
|
-
update(stateContainer);
|
|
1488
|
-
} else {
|
|
1489
|
-
stateContainer.setState(update);
|
|
1490
|
-
}
|
|
1491
|
-
});
|
|
1492
|
-
});
|
|
1493
|
-
},
|
|
1494
|
-
// Computed state
|
|
1495
|
-
computed: (computeFn) => {
|
|
1496
|
-
return memoizeState ? memo(computeFn)(transformedState) : computeFn(transformedState);
|
|
1497
|
-
},
|
|
1498
|
-
// State subscription
|
|
1499
|
-
subscribe: stateContainer.subscribe.bind(stateContainer),
|
|
1500
|
-
unsubscribe: stateContainer.unsubscribe.bind(stateContainer),
|
|
1501
|
-
// Async state operations
|
|
1502
|
-
...supportAsync && {
|
|
1503
|
-
setStateAsync: async (stateOrPromise) => {
|
|
1504
|
-
const resolved = await Promise.resolve(stateOrPromise);
|
|
1505
|
-
stateContainer.setState(resolved);
|
|
1506
|
-
},
|
|
1507
|
-
updateStateAsync: async (asyncUpdater) => {
|
|
1508
|
-
const current = stateContainer.getState();
|
|
1509
|
-
const next = await Promise.resolve(asyncUpdater(current));
|
|
1510
|
-
stateContainer.setState(next);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
};
|
|
1514
|
-
const enhancedProps = {
|
|
1515
|
-
...props,
|
|
1516
|
-
[propName]: transformedState,
|
|
1517
|
-
[actionsName]: boundActions,
|
|
1518
|
-
stateUtils
|
|
1519
|
-
};
|
|
1520
|
-
if (debug) {
|
|
1521
|
-
console.log("withState render:", {
|
|
1522
|
-
component: getComponentName(WrappedComponent),
|
|
1523
|
-
state: transformedState,
|
|
1524
|
-
props: enhancedProps
|
|
1525
|
-
});
|
|
1526
|
-
}
|
|
1527
|
-
return typeof WrappedComponent === "function" ? WrappedComponent(enhancedProps, globalState, context2) : WrappedComponent;
|
|
1844
|
+
console.groupEnd();
|
|
1528
1845
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1846
|
+
if (this.options.enableStackTrace && _error.stack) {
|
|
1847
|
+
console.log("\u{1F4DA} Stack trace:", _error.stack);
|
|
1848
|
+
}
|
|
1849
|
+
console.groupEnd();
|
|
1850
|
+
}
|
|
1851
|
+
/**
|
|
1852
|
+
* Format component for logging
|
|
1853
|
+
*/
|
|
1854
|
+
formatComponent(component, maxDepth = 2, currentDepth = 0) {
|
|
1855
|
+
if (currentDepth > maxDepth) {
|
|
1856
|
+
return "[...deep]";
|
|
1857
|
+
}
|
|
1858
|
+
if (typeof component === "function") {
|
|
1859
|
+
return `[Function: ${component.name || "anonymous"}]`;
|
|
1860
|
+
}
|
|
1861
|
+
if (Array.isArray(component)) {
|
|
1862
|
+
return component.slice(0, 3).map(
|
|
1863
|
+
(item) => this.formatComponent(item, maxDepth, currentDepth + 1)
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
if (component && typeof component === "object") {
|
|
1867
|
+
const formatted = {};
|
|
1868
|
+
const keys = Object.keys(component).slice(0, 5);
|
|
1869
|
+
for (const key of keys) {
|
|
1870
|
+
if (key === "children" && component[key]) {
|
|
1871
|
+
formatted[key] = this.formatComponent(component[key], maxDepth, currentDepth + 1);
|
|
1872
|
+
} else {
|
|
1873
|
+
formatted[key] = component[key];
|
|
1874
|
+
}
|
|
1537
1875
|
}
|
|
1538
|
-
if (
|
|
1539
|
-
|
|
1876
|
+
if (Object.keys(component).length > 5) {
|
|
1877
|
+
formatted["..."] = `(${Object.keys(component).length - 5} more)`;
|
|
1540
1878
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1879
|
+
return formatted;
|
|
1880
|
+
}
|
|
1881
|
+
return component;
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Suppress specific _error types
|
|
1885
|
+
*/
|
|
1886
|
+
suppress(errorPattern) {
|
|
1887
|
+
this.suppressedErrors.add(errorPattern);
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Clear _error history
|
|
1891
|
+
*/
|
|
1892
|
+
clearHistory() {
|
|
1893
|
+
this.errorHistory = [];
|
|
1894
|
+
this.errorCounts.clear();
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Get _error statistics
|
|
1898
|
+
*/
|
|
1899
|
+
getStats() {
|
|
1900
|
+
const errorsByType = {};
|
|
1901
|
+
const errorsByTime = {};
|
|
1902
|
+
this.errorHistory.forEach((_error) => {
|
|
1903
|
+
errorsByType[_error.type] = (errorsByType[_error.type] || 0) + _error.count;
|
|
1904
|
+
const hour = new Date(_error.timestamp).toISOString().slice(0, 13);
|
|
1905
|
+
errorsByTime[hour] = (errorsByTime[hour] || 0) + _error.count;
|
|
1906
|
+
});
|
|
1907
|
+
return {
|
|
1908
|
+
totalErrors: this.errorHistory.reduce((sum, e) => sum + e.count, 0),
|
|
1909
|
+
uniqueErrors: this.errorHistory.length,
|
|
1910
|
+
errorsByType,
|
|
1911
|
+
errorsByTime,
|
|
1912
|
+
mostCommonErrors: this.getMostCommonErrors(5),
|
|
1913
|
+
recentErrors: this.errorHistory.slice(0, 10)
|
|
1914
|
+
};
|
|
1915
|
+
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Get most common errors
|
|
1918
|
+
*/
|
|
1919
|
+
getMostCommonErrors(limit = 10) {
|
|
1920
|
+
return this.errorHistory.sort((a, b) => b.count - a.count).slice(0, limit).map(({ name, message, count, type }) => ({
|
|
1921
|
+
name,
|
|
1922
|
+
message,
|
|
1923
|
+
count,
|
|
1924
|
+
type
|
|
1925
|
+
}));
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
var globalErrorHandler = new ErrorHandler();
|
|
1929
|
+
|
|
1930
|
+
// src/rendering/html-renderer.js
|
|
1931
|
+
var rendererCache = createCacheManager({
|
|
1932
|
+
maxSize: 1e3,
|
|
1933
|
+
ttlMs: 3e5
|
|
1934
|
+
// 5 minutes
|
|
1935
|
+
});
|
|
1936
|
+
function formatRenderPath(path) {
|
|
1937
|
+
if (!path || path.length === 0) return "root";
|
|
1938
|
+
let rendered = "root";
|
|
1939
|
+
for (const segment of path) {
|
|
1940
|
+
if (typeof segment !== "string" || segment.length === 0) continue;
|
|
1941
|
+
if (segment.startsWith("[")) {
|
|
1942
|
+
rendered += segment;
|
|
1943
|
+
} else {
|
|
1944
|
+
rendered += `.${segment}`;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return rendered;
|
|
1948
|
+
}
|
|
1949
|
+
var HTMLRenderer = class extends BaseRenderer {
|
|
1950
|
+
constructor(options = {}) {
|
|
1951
|
+
super({
|
|
1952
|
+
enableCache: options.enableCache !== false,
|
|
1953
|
+
enableMonitoring: options.enableMonitoring !== false,
|
|
1954
|
+
minify: options.minify || false,
|
|
1955
|
+
streaming: options.streaming || false,
|
|
1956
|
+
maxDepth: options.maxDepth || 100,
|
|
1957
|
+
...options
|
|
1958
|
+
});
|
|
1959
|
+
if (this.config.enableCache && !this.cache) {
|
|
1960
|
+
this.cache = rendererCache;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
/**
|
|
1964
|
+
* Main render method - converts components to HTML string
|
|
1965
|
+
*
|
|
1966
|
+
* @param {Object|Array|string|Function} component - Component to render
|
|
1967
|
+
* @param {Object} [options={}] - Rendering options
|
|
1968
|
+
* @param {Object} [options.context] - Rendering context
|
|
1969
|
+
* @param {boolean} [options.enableCache] - Override cache setting
|
|
1970
|
+
* @param {number} [options.depth=0] - Current rendering depth
|
|
1971
|
+
* @returns {string} Rendered HTML string
|
|
1972
|
+
*
|
|
1973
|
+
* @example
|
|
1974
|
+
* const html = renderer.render({
|
|
1975
|
+
* div: {
|
|
1976
|
+
* className: 'container',
|
|
1977
|
+
* children: [
|
|
1978
|
+
* { h1: { text: 'Title' } },
|
|
1979
|
+
* { p: { text: 'Content' } }
|
|
1980
|
+
* ]
|
|
1981
|
+
* }
|
|
1982
|
+
* });
|
|
1983
|
+
*/
|
|
1984
|
+
render(component, options = {}) {
|
|
1985
|
+
const config = { ...this.config, ...options };
|
|
1986
|
+
this.startTiming();
|
|
1987
|
+
try {
|
|
1988
|
+
if (config.validateInput && !this.isValidComponent(component)) {
|
|
1989
|
+
throw new Error("Invalid component structure");
|
|
1572
1990
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1991
|
+
const renderOptions = {
|
|
1992
|
+
...config,
|
|
1993
|
+
seenObjects: /* @__PURE__ */ new WeakSet()
|
|
1994
|
+
};
|
|
1995
|
+
const html = this.renderComponent(component, renderOptions, 0, []);
|
|
1996
|
+
const finalHtml = config.minify ? minifyHtml(html, config) : html;
|
|
1997
|
+
this.endTiming();
|
|
1998
|
+
this.recordPerformance("render", this.metrics.startTime, false, {
|
|
1999
|
+
cacheEnabled: config.enableCache
|
|
2000
|
+
});
|
|
2001
|
+
return finalHtml;
|
|
2002
|
+
} catch (_error) {
|
|
2003
|
+
this.recordError("render", _error);
|
|
2004
|
+
const enhancedError = globalErrorHandler.handle(_error, {
|
|
2005
|
+
renderContext: { path: "root", renderer: "html" }
|
|
2006
|
+
});
|
|
2007
|
+
if (config.throwOnError === false) {
|
|
2008
|
+
return config.errorFallback;
|
|
1584
2009
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
2010
|
+
throw enhancedError;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Render a single component with full optimization pipeline
|
|
2015
|
+
*/
|
|
2016
|
+
renderComponent(component, options, depth = 0, path = []) {
|
|
2017
|
+
if (component === null || component === void 0) {
|
|
2018
|
+
return "";
|
|
2019
|
+
}
|
|
2020
|
+
if (Array.isArray(component) && component.length === 0) {
|
|
2021
|
+
return "";
|
|
2022
|
+
}
|
|
2023
|
+
if (typeof component === "object" && component !== null && !Array.isArray(component)) {
|
|
2024
|
+
if (options.seenObjects && options.seenObjects.has(component)) {
|
|
2025
|
+
throw new RenderingError(
|
|
2026
|
+
"Circular reference detected in component tree",
|
|
2027
|
+
component,
|
|
2028
|
+
{ path: formatRenderPath(path) },
|
|
2029
|
+
["Remove the circular reference", "Use lazy loading to break the cycle"]
|
|
2030
|
+
);
|
|
1589
2031
|
}
|
|
1590
|
-
|
|
1591
|
-
(
|
|
1592
|
-
state
|
|
1593
|
-
);
|
|
1594
|
-
if (persistent && storageKey) {
|
|
1595
|
-
try {
|
|
1596
|
-
storage.setItem(storageKey, JSON.stringify(state));
|
|
1597
|
-
} catch (_error) {
|
|
1598
|
-
if (debug) console.warn("Failed to persist state:", _error);
|
|
1599
|
-
}
|
|
2032
|
+
if (options.seenObjects) {
|
|
2033
|
+
options.seenObjects.add(component);
|
|
1600
2034
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
2035
|
+
}
|
|
2036
|
+
this.validateDepth(depth);
|
|
2037
|
+
try {
|
|
2038
|
+
const { type, value } = this.processComponentType(component);
|
|
2039
|
+
switch (type) {
|
|
2040
|
+
case "empty":
|
|
2041
|
+
return "";
|
|
2042
|
+
case "text":
|
|
2043
|
+
return escapeHtml(value);
|
|
2044
|
+
case "function": {
|
|
2045
|
+
const result = this.executeFunctionComponent(value, depth);
|
|
2046
|
+
return this.renderComponent(result, options, depth + 1, [...path, "()"]);
|
|
2047
|
+
}
|
|
2048
|
+
case "array":
|
|
2049
|
+
if (typeof process !== "undefined" && process.env && true && value.length > 1) {
|
|
2050
|
+
const missingKeyCount = value.filter((child) => {
|
|
2051
|
+
if (child && typeof child === "object" && !Array.isArray(child)) {
|
|
2052
|
+
const tagName = Object.keys(child)[0];
|
|
2053
|
+
const props = child[tagName];
|
|
2054
|
+
return props && typeof props === "object" && props.key === void 0;
|
|
2055
|
+
}
|
|
2056
|
+
return false;
|
|
2057
|
+
}).length;
|
|
2058
|
+
if (missingKeyCount > 0) {
|
|
2059
|
+
console.warn(
|
|
2060
|
+
`[Coherent.js] Array of ${value.length} elements at ${formatRenderPath(path)} has ${missingKeyCount} items missing "key" props. Keys help identify which items changed for efficient updates. Add unique key props like: { div: { key: 'unique-id', ... } }`
|
|
2061
|
+
);
|
|
2062
|
+
}
|
|
1607
2063
|
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
2064
|
+
return value.map((child, index) => this.renderComponent(child, options, depth + 1, [...path, `[${index}]`])).join("");
|
|
2065
|
+
case "element": {
|
|
2066
|
+
const tagName = Object.keys(value)[0];
|
|
2067
|
+
const elementContent = value[tagName];
|
|
2068
|
+
return this.renderElement(tagName, elementContent, options, depth, [...path, tagName]);
|
|
1611
2069
|
}
|
|
2070
|
+
default:
|
|
2071
|
+
this.recordError("renderComponent", new Error(`Unknown component type: ${type}`));
|
|
2072
|
+
return "";
|
|
1612
2073
|
}
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
return listeners.delete(listener);
|
|
1621
|
-
},
|
|
1622
|
-
batch(batchFn) {
|
|
1623
|
-
const originalListeners = listeners;
|
|
1624
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1625
|
-
try {
|
|
1626
|
-
batchFn();
|
|
1627
|
-
} finally {
|
|
1628
|
-
listeners = originalListeners;
|
|
1629
|
-
listeners.forEach((listener) => listener(state));
|
|
1630
|
-
}
|
|
1631
|
-
},
|
|
1632
|
-
destroy() {
|
|
1633
|
-
listeners.clear();
|
|
1634
|
-
if (persistent && storageKey) {
|
|
1635
|
-
try {
|
|
1636
|
-
storage.removeItem(storageKey);
|
|
1637
|
-
} catch (_error) {
|
|
1638
|
-
if (debug) console.warn("Failed to remove persisted state:", _error);
|
|
2074
|
+
} catch (_error) {
|
|
2075
|
+
const renderPath = formatRenderPath(path);
|
|
2076
|
+
if (_error instanceof CoherentError) {
|
|
2077
|
+
if (!_error.context || typeof _error.context !== "object") {
|
|
2078
|
+
_error.context = { path: renderPath };
|
|
2079
|
+
} else if (!_error.context.path) {
|
|
2080
|
+
_error.context = { ..._error.context, path: renderPath };
|
|
1639
2081
|
}
|
|
2082
|
+
throw _error;
|
|
1640
2083
|
}
|
|
2084
|
+
throw new RenderingError(_error.message, void 0, { path: renderPath, renderer: "html" });
|
|
1641
2085
|
}
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Render an HTML element with advanced caching and optimization
|
|
2089
|
+
*/
|
|
2090
|
+
renderElement(tagName, element, options, depth = 0, path = []) {
|
|
2091
|
+
const startTime = performance.now();
|
|
2092
|
+
if (element && typeof element === "object" && !Array.isArray(element)) {
|
|
2093
|
+
if (options.seenObjects && options.seenObjects.has(element)) {
|
|
2094
|
+
throw new RenderingError(
|
|
2095
|
+
"Circular reference detected in component tree",
|
|
2096
|
+
element,
|
|
2097
|
+
{ path: formatRenderPath(path) },
|
|
2098
|
+
["Remove the circular reference", "Use lazy loading to break the cycle"]
|
|
1655
2099
|
);
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
2100
|
+
}
|
|
2101
|
+
if (options.seenObjects) {
|
|
2102
|
+
options.seenObjects.add(element);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
if (options.enableMonitoring && this.cache) {
|
|
2106
|
+
}
|
|
2107
|
+
if (options.enableCache && this.cache && RendererUtils.isStaticElement(element)) {
|
|
2108
|
+
try {
|
|
2109
|
+
const cacheKey = `static:${tagName}:${JSON.stringify(element)}`;
|
|
2110
|
+
const cached = this.cache.get("static", cacheKey);
|
|
2111
|
+
if (cached) {
|
|
2112
|
+
this.recordPerformance(tagName, startTime, true);
|
|
2113
|
+
return cached.value;
|
|
1661
2114
|
}
|
|
1662
|
-
|
|
1663
|
-
} catch (_error) {
|
|
1664
|
-
if (debug) console.error(`Action ${actionName} failed:`, _error);
|
|
1665
|
-
throw _error;
|
|
2115
|
+
} catch {
|
|
1666
2116
|
}
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
2117
|
+
}
|
|
2118
|
+
if (typeof element === "string" || typeof element === "number" || typeof element === "boolean") {
|
|
2119
|
+
const html2 = isVoidElement(tagName) ? `<${tagName}>` : `<${tagName}>${escapeHtml(String(element))}</${tagName}>`;
|
|
2120
|
+
this.cacheIfStatic(tagName, element, html2, options);
|
|
2121
|
+
this.recordPerformance(tagName, startTime, false);
|
|
2122
|
+
return html2;
|
|
2123
|
+
}
|
|
2124
|
+
if (typeof element === "function") {
|
|
2125
|
+
const result = this.executeFunctionComponent(element, depth);
|
|
2126
|
+
return this.renderElement(tagName, result, options, depth, [...path, "()"]);
|
|
2127
|
+
}
|
|
2128
|
+
if (element && typeof element === "object") {
|
|
2129
|
+
return this.renderObjectElement(tagName, element, options, depth, path);
|
|
2130
|
+
}
|
|
2131
|
+
if (element === null || element === void 0) {
|
|
2132
|
+
const html2 = isVoidElement(tagName) ? `<${tagName}>` : `<${tagName}></${tagName}>`;
|
|
2133
|
+
this.recordPerformance(tagName, startTime, false);
|
|
2134
|
+
return html2;
|
|
2135
|
+
}
|
|
2136
|
+
const html = `<${tagName}>${escapeHtml(String(element))}</${tagName}>`;
|
|
2137
|
+
this.recordPerformance(tagName, startTime, false);
|
|
2138
|
+
return html;
|
|
2139
|
+
}
|
|
1683
2140
|
/**
|
|
1684
|
-
*
|
|
2141
|
+
* Cache element if it's static
|
|
1685
2142
|
*/
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2143
|
+
cacheIfStatic(tagName, element, html) {
|
|
2144
|
+
if (this.config.enableCache && this.cache && RendererUtils.isStaticElement(element)) {
|
|
2145
|
+
try {
|
|
2146
|
+
const cacheKey = `static:${tagName}:${JSON.stringify(element)}`;
|
|
2147
|
+
this.cache.set("static", cacheKey, html, {
|
|
2148
|
+
ttlMs: this.config.cacheTTL || 5 * 60 * 1e3,
|
|
2149
|
+
// 5 minutes default
|
|
2150
|
+
size: html.length
|
|
2151
|
+
// Approximate size
|
|
2152
|
+
});
|
|
2153
|
+
} catch {
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
1690
2157
|
/**
|
|
1691
|
-
*
|
|
2158
|
+
* Render complex object elements with attributes and children
|
|
1692
2159
|
*/
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
2160
|
+
renderObjectElement(tagName, element, options, depth = 0, path = []) {
|
|
2161
|
+
const startTime = performance.now();
|
|
2162
|
+
if (options.enableCache && this.cache) {
|
|
2163
|
+
const cacheKey = RendererUtils.generateCacheKey(tagName, element);
|
|
2164
|
+
if (cacheKey) {
|
|
2165
|
+
const cached = this.cache.get(cacheKey);
|
|
2166
|
+
if (cached) {
|
|
2167
|
+
this.recordPerformance(tagName, startTime, true);
|
|
2168
|
+
return cached;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
const { children, text, key: _key, html: _rawHtml, ...attributes } = element || {};
|
|
2173
|
+
const attributeString = formatAttributes(attributes);
|
|
2174
|
+
const openingTag = attributeString ? `<${tagName} ${attributeString}>` : `<${tagName}>`;
|
|
2175
|
+
let textContent = "";
|
|
2176
|
+
if (text !== void 0) {
|
|
2177
|
+
const isScript = tagName === "script";
|
|
2178
|
+
const isStyle = tagName === "style";
|
|
2179
|
+
const isRawTag = isScript || isStyle;
|
|
2180
|
+
const raw = typeof text === "function" ? String(text()) : String(text);
|
|
2181
|
+
if (isRawTag) {
|
|
2182
|
+
const safe = raw.replace(/<\/(script)/gi, "<\\/$1").replace(/<\/(style)/gi, "<\\/$1").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2183
|
+
textContent = safe;
|
|
2184
|
+
} else {
|
|
2185
|
+
textContent = escapeHtml(raw);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
let childrenHtml = "";
|
|
2189
|
+
if (hasChildren(element)) {
|
|
2190
|
+
const normalizedChildren = normalizeChildren(children);
|
|
2191
|
+
childrenHtml = normalizedChildren.map((child, index) => {
|
|
2192
|
+
if (child && typeof child === "object" && !Array.isArray(child)) {
|
|
2193
|
+
const childTagName = Object.keys(child)[0];
|
|
2194
|
+
if (childTagName) {
|
|
2195
|
+
validateNesting(tagName, childTagName, formatRenderPath([...path, `children[${index}]`]));
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
return this.renderComponent(child, options, depth + 1, [...path, `children[${index}]`]);
|
|
2199
|
+
}).join("");
|
|
2200
|
+
}
|
|
2201
|
+
const html = `${openingTag}${textContent}${childrenHtml}</${tagName}>`;
|
|
2202
|
+
if (options.enableCache && this.cache && RendererUtils.isCacheable(element, options)) {
|
|
2203
|
+
const cacheKey = RendererUtils.generateCacheKey(tagName, element);
|
|
2204
|
+
if (cacheKey) {
|
|
2205
|
+
this.cache.set(cacheKey, html);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
this.recordPerformance(tagName, startTime, false);
|
|
2209
|
+
return html;
|
|
2210
|
+
}
|
|
2211
|
+
};
|
|
2212
|
+
function render(component, options = {}) {
|
|
2213
|
+
const mergedOptions = {
|
|
2214
|
+
enableCache: true,
|
|
2215
|
+
enableMonitoring: false,
|
|
2216
|
+
...options
|
|
2217
|
+
};
|
|
2218
|
+
const renderer = new HTMLRenderer(mergedOptions);
|
|
2219
|
+
return renderer.render(component, mergedOptions);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
// src/components/component-system.js
|
|
2223
|
+
var COMPONENT_REGISTRY = /* @__PURE__ */ new Map();
|
|
2224
|
+
var COMPONENT_METADATA = /* @__PURE__ */ new WeakMap();
|
|
2225
|
+
var ComponentState = class {
|
|
2226
|
+
constructor(initialState = {}) {
|
|
2227
|
+
this.state = { ...initialState };
|
|
2228
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
2229
|
+
this.isUpdating = false;
|
|
2230
|
+
}
|
|
1697
2231
|
/**
|
|
1698
|
-
*
|
|
2232
|
+
* Get state value by key or entire state
|
|
2233
|
+
*
|
|
2234
|
+
* @param {string} [key] - State key to retrieve
|
|
2235
|
+
* @returns {*} State value or entire state object
|
|
1699
2236
|
*/
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
}),
|
|
2237
|
+
get(key) {
|
|
2238
|
+
return key ? this.state[key] : { ...this.state };
|
|
2239
|
+
}
|
|
1704
2240
|
/**
|
|
1705
|
-
*
|
|
2241
|
+
* Update state with new values
|
|
2242
|
+
*
|
|
2243
|
+
* @param {Object} updates - State updates to apply
|
|
2244
|
+
* @returns {ComponentState} This instance for chaining
|
|
1706
2245
|
*/
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
2246
|
+
set(updates) {
|
|
2247
|
+
if (this.isUpdating) return this;
|
|
2248
|
+
const oldState = { ...this.state };
|
|
2249
|
+
if (typeof updates === "function") {
|
|
2250
|
+
updates = updates(oldState);
|
|
2251
|
+
}
|
|
2252
|
+
this.state = { ...this.state, ...updates };
|
|
2253
|
+
this.notifyListeners(oldState, this.state);
|
|
2254
|
+
return this;
|
|
2255
|
+
}
|
|
2256
|
+
subscribe(listener) {
|
|
2257
|
+
this.listeners.add(listener);
|
|
2258
|
+
return () => this.listeners.delete(listener);
|
|
2259
|
+
}
|
|
2260
|
+
notifyListeners(oldState, newState) {
|
|
2261
|
+
if (this.listeners.size === 0) return;
|
|
2262
|
+
this.isUpdating = true;
|
|
2263
|
+
this.listeners.forEach((listener) => {
|
|
2264
|
+
try {
|
|
2265
|
+
listener(newState, oldState);
|
|
2266
|
+
} catch (_error) {
|
|
2267
|
+
console.error("State listener _error:", _error);
|
|
1723
2268
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
2269
|
+
});
|
|
2270
|
+
this.isUpdating = false;
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
var Component = class _Component {
|
|
2274
|
+
constructor(definition = {}) {
|
|
2275
|
+
this.definition = definition;
|
|
2276
|
+
this.name = definition.name || "AnonymousComponent";
|
|
2277
|
+
this.props = {};
|
|
2278
|
+
this.state = new ComponentState(definition.state || {});
|
|
2279
|
+
this.children = [];
|
|
2280
|
+
this.parent = null;
|
|
2281
|
+
this.rendered = null;
|
|
2282
|
+
this.isMounted = false;
|
|
2283
|
+
this.isDestroyed = false;
|
|
2284
|
+
this.hooks = {
|
|
2285
|
+
beforeCreate: definition.beforeCreate || (() => {
|
|
2286
|
+
}),
|
|
2287
|
+
created: definition.created || (() => {
|
|
2288
|
+
}),
|
|
2289
|
+
beforeMount: definition.beforeMount || (() => {
|
|
2290
|
+
}),
|
|
2291
|
+
mounted: definition.mounted || (() => {
|
|
2292
|
+
}),
|
|
2293
|
+
beforeUpdate: definition.beforeUpdate || (() => {
|
|
2294
|
+
}),
|
|
2295
|
+
updated: definition.updated || (() => {
|
|
2296
|
+
}),
|
|
2297
|
+
beforeDestroy: definition.beforeDestroy || (() => {
|
|
2298
|
+
}),
|
|
2299
|
+
destroyed: definition.destroyed || (() => {
|
|
2300
|
+
}),
|
|
2301
|
+
errorCaptured: definition.errorCaptured || (() => {
|
|
2302
|
+
})
|
|
1726
2303
|
};
|
|
1727
|
-
|
|
2304
|
+
this.methods = definition.methods || {};
|
|
2305
|
+
Object.keys(this.methods).forEach((methodName) => {
|
|
2306
|
+
if (typeof this.methods[methodName] === "function") {
|
|
2307
|
+
this[methodName] = this.methods[methodName].bind(this);
|
|
2308
|
+
}
|
|
2309
|
+
});
|
|
2310
|
+
this.computed = definition.computed || {};
|
|
2311
|
+
this.computedCache = /* @__PURE__ */ new Map();
|
|
2312
|
+
this.watchers = definition.watch || {};
|
|
2313
|
+
this.setupWatchers();
|
|
2314
|
+
COMPONENT_METADATA.set(this, {
|
|
2315
|
+
createdAt: Date.now(),
|
|
2316
|
+
updateCount: 0,
|
|
2317
|
+
renderCount: 0
|
|
2318
|
+
});
|
|
2319
|
+
this.callHook("beforeCreate");
|
|
2320
|
+
this.initialize();
|
|
2321
|
+
this.callHook("created");
|
|
2322
|
+
}
|
|
1728
2323
|
/**
|
|
1729
|
-
*
|
|
2324
|
+
* Initialize component
|
|
1730
2325
|
*/
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
setState(updates);
|
|
1738
|
-
},
|
|
1739
|
-
resetForm: (state, setState) => {
|
|
1740
|
-
setState(initialFormState);
|
|
1741
|
-
},
|
|
1742
|
-
validateForm: (state, setState, { args: [validator] }) => {
|
|
1743
|
-
const errors = validator(state);
|
|
1744
|
-
setState({ _errors: errors });
|
|
1745
|
-
return Object.keys(errors).length === 0;
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
}),
|
|
2326
|
+
initialize() {
|
|
2327
|
+
this.unsubscribeState = this.state.subscribe((newState, oldState) => {
|
|
2328
|
+
this.onStateChange(newState, oldState);
|
|
2329
|
+
});
|
|
2330
|
+
this.initializeComputed();
|
|
2331
|
+
}
|
|
1749
2332
|
/**
|
|
1750
|
-
*
|
|
2333
|
+
* Set up watchers for reactive data
|
|
1751
2334
|
*/
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
actions: {
|
|
1759
|
-
setLoading: (state, setState, { args: [loading] }) => {
|
|
1760
|
-
setState({ _loading: loading });
|
|
1761
|
-
},
|
|
1762
|
-
setError: (state, setState, { args: [_error] }) => {
|
|
1763
|
-
setState({ _error, _loading: false });
|
|
1764
|
-
},
|
|
1765
|
-
clearError: (state, setState) => {
|
|
1766
|
-
setState({ _error: null });
|
|
1767
|
-
},
|
|
1768
|
-
asyncAction: async (state, setState, { args: [asyncFn] }) => {
|
|
1769
|
-
setState({ _loading: true, _error: null });
|
|
1770
|
-
try {
|
|
1771
|
-
const result = await asyncFn(state);
|
|
1772
|
-
setState({ _loading: false });
|
|
1773
|
-
return result;
|
|
1774
|
-
} catch (_error) {
|
|
1775
|
-
setState({ _loading: false, _error });
|
|
1776
|
-
throw _error;
|
|
2335
|
+
setupWatchers() {
|
|
2336
|
+
Object.keys(this.watchers).forEach((key) => {
|
|
2337
|
+
const handler = this.watchers[key];
|
|
2338
|
+
this.state.subscribe((newState, oldState) => {
|
|
2339
|
+
if (newState[key] !== oldState[key]) {
|
|
2340
|
+
handler.call(this, newState[key], oldState[key]);
|
|
1777
2341
|
}
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
2342
|
+
});
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
1781
2345
|
/**
|
|
1782
|
-
*
|
|
2346
|
+
* Initialize computed properties
|
|
1783
2347
|
*/
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
if (state.past.length === 0) return;
|
|
1794
|
-
const previous = state.past[state.past.length - 1];
|
|
1795
|
-
const newPast = state.past.slice(0, state.past.length - 1);
|
|
1796
|
-
setState({
|
|
1797
|
-
past: newPast,
|
|
1798
|
-
present: previous,
|
|
1799
|
-
future: [state.present, ...state.future]
|
|
1800
|
-
});
|
|
1801
|
-
},
|
|
1802
|
-
redo: (state, setState) => {
|
|
1803
|
-
if (state.future.length === 0) return;
|
|
1804
|
-
const next = state.future[0];
|
|
1805
|
-
const newFuture = state.future.slice(1);
|
|
1806
|
-
setState({
|
|
1807
|
-
past: [...state.past, state.present],
|
|
1808
|
-
present: next,
|
|
1809
|
-
future: newFuture
|
|
1810
|
-
});
|
|
1811
|
-
},
|
|
1812
|
-
updatePresent: (state, setState, { args: [newPresent] }) => {
|
|
1813
|
-
setState({
|
|
1814
|
-
past: [...state.past, state.present].slice(-maxHistory),
|
|
1815
|
-
present: newPresent,
|
|
1816
|
-
future: []
|
|
1817
|
-
});
|
|
2348
|
+
initializeComputed() {
|
|
2349
|
+
Object.keys(this.computed).forEach((key) => {
|
|
2350
|
+
Object.defineProperty(this, key, {
|
|
2351
|
+
get: () => {
|
|
2352
|
+
if (!this.computedCache.has(key)) {
|
|
2353
|
+
const value = this.computed[key].call(this);
|
|
2354
|
+
this.computedCache.set(key, value);
|
|
2355
|
+
}
|
|
2356
|
+
return this.computedCache.get(key);
|
|
1818
2357
|
},
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
}
|
|
2358
|
+
enumerable: true
|
|
2359
|
+
});
|
|
1822
2360
|
});
|
|
1823
|
-
}
|
|
2361
|
+
}
|
|
1824
2362
|
/**
|
|
1825
|
-
*
|
|
2363
|
+
* Handle state changes
|
|
1826
2364
|
*/
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
});
|
|
1833
|
-
return { ...state, ...computed };
|
|
1834
|
-
},
|
|
1835
|
-
memoizeState: true
|
|
1836
|
-
})
|
|
1837
|
-
};
|
|
1838
|
-
function createStateManager(config) {
|
|
1839
|
-
const {
|
|
1840
|
-
initialState = {},
|
|
1841
|
-
reducers = {},
|
|
1842
|
-
actions = {},
|
|
1843
|
-
middleware = [],
|
|
1844
|
-
plugins = []
|
|
1845
|
-
} = config;
|
|
1846
|
-
const rootReducer = (state, action) => {
|
|
1847
|
-
let nextState = state;
|
|
1848
|
-
Object.entries(reducers).forEach(([key, reducer]) => {
|
|
1849
|
-
nextState = {
|
|
1850
|
-
...nextState,
|
|
1851
|
-
[key]: reducer(nextState[key], action)
|
|
1852
|
-
};
|
|
1853
|
-
});
|
|
1854
|
-
return nextState;
|
|
1855
|
-
};
|
|
1856
|
-
const enhancedConfig = plugins.reduce(
|
|
1857
|
-
(acc, plugin) => plugin(acc),
|
|
1858
|
-
{ initialState, reducer: rootReducer, actions, middleware }
|
|
1859
|
-
);
|
|
1860
|
-
return withState(enhancedConfig.initialState, {
|
|
1861
|
-
reducer: enhancedConfig.reducer,
|
|
1862
|
-
actions: enhancedConfig.actions,
|
|
1863
|
-
middleware: enhancedConfig.middleware
|
|
1864
|
-
});
|
|
1865
|
-
}
|
|
1866
|
-
function getComponentName(component) {
|
|
1867
|
-
if (!component) return "Component";
|
|
1868
|
-
return component.displayName || component.name || component.constructor?.name || "Component";
|
|
1869
|
-
}
|
|
1870
|
-
|
|
1871
|
-
// src/utils/error-handler.js
|
|
1872
|
-
var CoherentError = class _CoherentError extends Error {
|
|
1873
|
-
constructor(message, options = {}) {
|
|
1874
|
-
super(message);
|
|
1875
|
-
this.name = "CoherentError";
|
|
1876
|
-
this.type = options.type || "generic";
|
|
1877
|
-
this.component = options.component;
|
|
1878
|
-
this.context = options.context;
|
|
1879
|
-
this.suggestions = options.suggestions || [];
|
|
1880
|
-
this.timestamp = Date.now();
|
|
1881
|
-
if (Error.captureStackTrace) {
|
|
1882
|
-
Error.captureStackTrace(this, _CoherentError);
|
|
2365
|
+
onStateChange() {
|
|
2366
|
+
if (this.isDestroyed) return;
|
|
2367
|
+
this.computedCache.clear();
|
|
2368
|
+
if (this.isMounted) {
|
|
2369
|
+
this.update();
|
|
1883
2370
|
}
|
|
1884
2371
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
};
|
|
1898
|
-
var ComponentValidationError = class extends CoherentError {
|
|
1899
|
-
constructor(message, component, suggestions = []) {
|
|
1900
|
-
super(message, {
|
|
1901
|
-
type: "validation",
|
|
1902
|
-
component,
|
|
1903
|
-
suggestions: [
|
|
1904
|
-
"Check component structure and syntax",
|
|
1905
|
-
"Ensure all required properties are present",
|
|
1906
|
-
"Validate prop types and values",
|
|
1907
|
-
...suggestions
|
|
1908
|
-
]
|
|
1909
|
-
});
|
|
1910
|
-
this.name = "ComponentValidationError";
|
|
1911
|
-
}
|
|
1912
|
-
};
|
|
1913
|
-
var RenderingError = class extends CoherentError {
|
|
1914
|
-
constructor(message, component, context2, suggestions = []) {
|
|
1915
|
-
super(message, {
|
|
1916
|
-
type: "rendering",
|
|
1917
|
-
component,
|
|
1918
|
-
context: context2,
|
|
1919
|
-
suggestions: [
|
|
1920
|
-
"Check for circular references",
|
|
1921
|
-
"Validate component depth",
|
|
1922
|
-
"Ensure all functions return valid components",
|
|
1923
|
-
...suggestions
|
|
1924
|
-
]
|
|
1925
|
-
});
|
|
1926
|
-
this.name = "RenderingError";
|
|
1927
|
-
}
|
|
1928
|
-
};
|
|
1929
|
-
var PerformanceError = class extends CoherentError {
|
|
1930
|
-
constructor(message, metrics, suggestions = []) {
|
|
1931
|
-
super(message, {
|
|
1932
|
-
type: "performance",
|
|
1933
|
-
context: metrics,
|
|
1934
|
-
suggestions: [
|
|
1935
|
-
"Consider component memoization",
|
|
1936
|
-
"Reduce component complexity",
|
|
1937
|
-
"Enable caching",
|
|
1938
|
-
...suggestions
|
|
1939
|
-
]
|
|
1940
|
-
});
|
|
1941
|
-
this.name = "PerformanceError";
|
|
1942
|
-
}
|
|
1943
|
-
};
|
|
1944
|
-
var StateError = class extends CoherentError {
|
|
1945
|
-
constructor(message, state, suggestions = []) {
|
|
1946
|
-
super(message, {
|
|
1947
|
-
type: "state",
|
|
1948
|
-
context: state,
|
|
1949
|
-
suggestions: [
|
|
1950
|
-
"Check state mutations",
|
|
1951
|
-
"Ensure proper state initialization",
|
|
1952
|
-
"Validate state transitions",
|
|
1953
|
-
...suggestions
|
|
1954
|
-
]
|
|
1955
|
-
});
|
|
1956
|
-
this.name = "StateError";
|
|
2372
|
+
/**
|
|
2373
|
+
* Call lifecycle hook
|
|
2374
|
+
*/
|
|
2375
|
+
callHook(hookName, ...args) {
|
|
2376
|
+
try {
|
|
2377
|
+
if (this.hooks[hookName]) {
|
|
2378
|
+
return this.hooks[hookName].call(this, ...args);
|
|
2379
|
+
}
|
|
2380
|
+
} catch (_error) {
|
|
2381
|
+
this.handleError(_error, `${hookName} hook`);
|
|
2382
|
+
}
|
|
1957
2383
|
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
...options
|
|
1968
|
-
};
|
|
1969
|
-
this.errorHistory = [];
|
|
1970
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
1971
|
-
this.suppressedErrors = /* @__PURE__ */ new Set();
|
|
2384
|
+
/**
|
|
2385
|
+
* Handle component errors
|
|
2386
|
+
*/
|
|
2387
|
+
handleError(_error) {
|
|
2388
|
+
console.error(`Component Error in ${this.name}:`, _error);
|
|
2389
|
+
this.callHook("errorCaptured", _error);
|
|
2390
|
+
if (this.parent && this.parent.handleError) {
|
|
2391
|
+
this.parent.handleError(_error, `${this.name} -> ${context}`);
|
|
2392
|
+
}
|
|
1972
2393
|
}
|
|
1973
2394
|
/**
|
|
1974
|
-
*
|
|
2395
|
+
* Render the component
|
|
1975
2396
|
*/
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2397
|
+
render(props = {}) {
|
|
2398
|
+
if (this.isDestroyed) {
|
|
2399
|
+
console.warn(`Attempting to render destroyed component: ${this.name}`);
|
|
2400
|
+
return null;
|
|
2401
|
+
}
|
|
2402
|
+
try {
|
|
2403
|
+
const metadata = COMPONENT_METADATA.get(this);
|
|
2404
|
+
if (metadata) {
|
|
2405
|
+
metadata.renderCount++;
|
|
2406
|
+
}
|
|
2407
|
+
this.props = { ...props };
|
|
2408
|
+
if (typeof this.definition.render === "function") {
|
|
2409
|
+
this.rendered = this.definition.render.call(this, this.props, this.state.get());
|
|
2410
|
+
} else if (typeof this.definition.template !== "undefined") {
|
|
2411
|
+
this.rendered = this.processTemplate(this.definition.template, this.props, this.state.get());
|
|
2412
|
+
} else {
|
|
2413
|
+
throw new Error(`Component ${this.name} must have either render method or template`);
|
|
2414
|
+
}
|
|
2415
|
+
if (this.rendered !== null) {
|
|
2416
|
+
validateComponent(this.rendered, this.name);
|
|
2417
|
+
}
|
|
2418
|
+
return this.rendered;
|
|
2419
|
+
} catch (_error) {
|
|
2420
|
+
this.handleError(_error);
|
|
2421
|
+
return { div: { className: "component-_error", text: `Error in ${this.name}` } };
|
|
1981
2422
|
}
|
|
1982
|
-
return enhancedError;
|
|
1983
2423
|
}
|
|
1984
2424
|
/**
|
|
1985
|
-
*
|
|
2425
|
+
* Process template with data
|
|
1986
2426
|
*/
|
|
1987
|
-
|
|
1988
|
-
if (
|
|
1989
|
-
return
|
|
2427
|
+
processTemplate(template, props, state) {
|
|
2428
|
+
if (typeof template === "function") {
|
|
2429
|
+
return template.call(this, props, state);
|
|
1990
2430
|
}
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
_error.message,
|
|
1996
|
-
context2.component,
|
|
1997
|
-
this.generateSuggestions(_error, context2)
|
|
1998
|
-
);
|
|
1999
|
-
case "rendering":
|
|
2000
|
-
return new RenderingError(
|
|
2001
|
-
_error.message,
|
|
2002
|
-
context2.component,
|
|
2003
|
-
context2.renderContext,
|
|
2004
|
-
this.generateSuggestions(_error, context2)
|
|
2005
|
-
);
|
|
2006
|
-
case "performance":
|
|
2007
|
-
return new PerformanceError(
|
|
2008
|
-
_error.message,
|
|
2009
|
-
context2.metrics,
|
|
2010
|
-
this.generateSuggestions(_error, context2)
|
|
2011
|
-
);
|
|
2012
|
-
case "state":
|
|
2013
|
-
return new StateError(
|
|
2014
|
-
_error.message,
|
|
2015
|
-
context2.state,
|
|
2016
|
-
this.generateSuggestions(_error, context2)
|
|
2017
|
-
);
|
|
2018
|
-
default:
|
|
2019
|
-
return new CoherentError(_error.message, {
|
|
2020
|
-
type: errorType,
|
|
2021
|
-
component: context2.component,
|
|
2022
|
-
context: context2.context,
|
|
2023
|
-
suggestions: this.generateSuggestions(_error, context2)
|
|
2024
|
-
});
|
|
2431
|
+
if (typeof template === "string") {
|
|
2432
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
2433
|
+
return props[key] || state[key] || "";
|
|
2434
|
+
});
|
|
2025
2435
|
}
|
|
2436
|
+
const processed = deepClone(template);
|
|
2437
|
+
this.interpolateObject(processed, { ...props, ...state });
|
|
2438
|
+
return processed;
|
|
2026
2439
|
}
|
|
2027
2440
|
/**
|
|
2028
|
-
*
|
|
2441
|
+
* Interpolate object with data
|
|
2029
2442
|
*/
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
return "validation";
|
|
2443
|
+
interpolateObject(obj, data) {
|
|
2444
|
+
if (typeof obj === "string") {
|
|
2445
|
+
return obj.replace(/\{\{(\w+)\}\}/g, (match, key) => data[key] || "");
|
|
2034
2446
|
}
|
|
2035
|
-
if (
|
|
2036
|
-
return
|
|
2447
|
+
if (Array.isArray(obj)) {
|
|
2448
|
+
return obj.map((item) => this.interpolateObject(item, data));
|
|
2037
2449
|
}
|
|
2038
|
-
if (
|
|
2039
|
-
|
|
2450
|
+
if (obj && typeof obj === "object") {
|
|
2451
|
+
Object.keys(obj).forEach((key) => {
|
|
2452
|
+
obj[key] = this.interpolateObject(obj[key], data);
|
|
2453
|
+
});
|
|
2040
2454
|
}
|
|
2041
|
-
|
|
2042
|
-
|
|
2455
|
+
return obj;
|
|
2456
|
+
}
|
|
2457
|
+
/**
|
|
2458
|
+
* Mount the component
|
|
2459
|
+
*/
|
|
2460
|
+
mount() {
|
|
2461
|
+
if (this.isMounted || this.isDestroyed) return this;
|
|
2462
|
+
this.callHook("beforeMount");
|
|
2463
|
+
this.isMounted = true;
|
|
2464
|
+
this.callHook("mounted");
|
|
2465
|
+
return this;
|
|
2466
|
+
}
|
|
2467
|
+
/**
|
|
2468
|
+
* Update the component
|
|
2469
|
+
*/
|
|
2470
|
+
update() {
|
|
2471
|
+
if (!this.isMounted || this.isDestroyed) return this;
|
|
2472
|
+
const metadata = COMPONENT_METADATA.get(this);
|
|
2473
|
+
if (metadata) {
|
|
2474
|
+
metadata.updateCount++;
|
|
2043
2475
|
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
return "generic";
|
|
2476
|
+
this.callHook("beforeUpdate");
|
|
2477
|
+
this.callHook("updated");
|
|
2478
|
+
return this;
|
|
2048
2479
|
}
|
|
2049
2480
|
/**
|
|
2050
|
-
*
|
|
2481
|
+
* Destroy the component
|
|
2051
2482
|
*/
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2483
|
+
destroy() {
|
|
2484
|
+
if (this.isDestroyed) return this;
|
|
2485
|
+
this.callHook("beforeDestroy");
|
|
2486
|
+
if (this.unsubscribeState) {
|
|
2487
|
+
this.unsubscribeState();
|
|
2488
|
+
}
|
|
2489
|
+
this.children.forEach((child) => {
|
|
2490
|
+
if (child.destroy) {
|
|
2491
|
+
child.destroy();
|
|
2492
|
+
}
|
|
2493
|
+
});
|
|
2494
|
+
this.isMounted = false;
|
|
2495
|
+
this.isDestroyed = true;
|
|
2496
|
+
this.children = [];
|
|
2497
|
+
this.parent = null;
|
|
2498
|
+
this.callHook("destroyed");
|
|
2499
|
+
return this;
|
|
2500
|
+
}
|
|
2501
|
+
/**
|
|
2502
|
+
* Get component metadata
|
|
2503
|
+
*/
|
|
2504
|
+
getMetadata() {
|
|
2505
|
+
return COMPONENT_METADATA.get(this) || {};
|
|
2506
|
+
}
|
|
2507
|
+
/**
|
|
2508
|
+
* Clone component with new props/state
|
|
2509
|
+
*/
|
|
2510
|
+
clone(overrides = {}) {
|
|
2511
|
+
const newDefinition = { ...this.definition, ...overrides };
|
|
2512
|
+
return new _Component(newDefinition);
|
|
2513
|
+
}
|
|
2514
|
+
};
|
|
2515
|
+
function createComponent(definition) {
|
|
2516
|
+
if (typeof definition === "function") {
|
|
2517
|
+
definition = {
|
|
2518
|
+
name: definition.name || "FunctionalComponent",
|
|
2519
|
+
render: definition
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
return new Component(definition);
|
|
2523
|
+
}
|
|
2524
|
+
function defineComponent(definition) {
|
|
2525
|
+
const componentFactory = (props) => {
|
|
2526
|
+
const component = new Component(definition);
|
|
2527
|
+
return component.render(props);
|
|
2528
|
+
};
|
|
2529
|
+
componentFactory.componentName = definition.name || "Component";
|
|
2530
|
+
componentFactory.definition = definition;
|
|
2531
|
+
return componentFactory;
|
|
2532
|
+
}
|
|
2533
|
+
function registerComponent(name, definition) {
|
|
2534
|
+
if (COMPONENT_REGISTRY.has(name)) {
|
|
2535
|
+
console.warn(`Component ${name} is already registered. Overriding.`);
|
|
2536
|
+
}
|
|
2537
|
+
const component = typeof definition === "function" ? defineComponent({ name, render: definition }) : defineComponent(definition);
|
|
2538
|
+
COMPONENT_REGISTRY.set(name, component);
|
|
2539
|
+
return component;
|
|
2540
|
+
}
|
|
2541
|
+
function getComponent(name) {
|
|
2542
|
+
return COMPONENT_REGISTRY.get(name);
|
|
2543
|
+
}
|
|
2544
|
+
function getRegisteredComponents() {
|
|
2545
|
+
return new Map(COMPONENT_REGISTRY);
|
|
2546
|
+
}
|
|
2547
|
+
if (performanceMonitor) {
|
|
2548
|
+
const originalRender = Component.prototype.render;
|
|
2549
|
+
Component.prototype.render = function(...args) {
|
|
2550
|
+
const start = performance.now();
|
|
2551
|
+
const result = originalRender.apply(this, args);
|
|
2552
|
+
const duration = performance.now() - start;
|
|
2553
|
+
performanceMonitor.recordMetric("renderTime", duration, {
|
|
2554
|
+
type: "component",
|
|
2555
|
+
name: this.name,
|
|
2556
|
+
propsSize: JSON.stringify(this.props || {}).length,
|
|
2557
|
+
hasState: Object.keys(this.state?.get() || {}).length > 0
|
|
2558
|
+
});
|
|
2559
|
+
return result;
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
function lazy(factory, options = {}) {
|
|
2563
|
+
const {
|
|
2564
|
+
cache = true,
|
|
2565
|
+
// Cache the result after first evaluation
|
|
2566
|
+
timeout = null,
|
|
2567
|
+
// Optional timeout for evaluation
|
|
2568
|
+
fallback = null,
|
|
2569
|
+
// Fallback value if evaluation fails
|
|
2570
|
+
onError = null,
|
|
2571
|
+
// Error handler
|
|
2572
|
+
dependencies = []
|
|
2573
|
+
// Dependencies that invalidate cache
|
|
2574
|
+
} = options;
|
|
2575
|
+
let cached = false;
|
|
2576
|
+
let cachedValue = null;
|
|
2577
|
+
let isEvaluating = false;
|
|
2578
|
+
let lastDependencyHash = null;
|
|
2579
|
+
const lazyWrapper = {
|
|
2580
|
+
// Mark as lazy for identification
|
|
2581
|
+
__isLazy: true,
|
|
2582
|
+
__factory: factory,
|
|
2583
|
+
__options: options,
|
|
2584
|
+
// Evaluation method
|
|
2585
|
+
evaluate(...args) {
|
|
2586
|
+
if (isEvaluating) {
|
|
2587
|
+
console.warn("Lazy evaluation cycle detected, returning fallback");
|
|
2588
|
+
return fallback;
|
|
2589
|
+
}
|
|
2590
|
+
if (cache && dependencies.length > 0) {
|
|
2591
|
+
const currentHash = hashDependencies(dependencies);
|
|
2592
|
+
if (lastDependencyHash !== null && lastDependencyHash !== currentHash) {
|
|
2593
|
+
cached = false;
|
|
2594
|
+
cachedValue = null;
|
|
2595
|
+
}
|
|
2596
|
+
lastDependencyHash = currentHash;
|
|
2597
|
+
}
|
|
2598
|
+
if (cache && cached) {
|
|
2599
|
+
return cachedValue;
|
|
2600
|
+
}
|
|
2601
|
+
isEvaluating = true;
|
|
2602
|
+
try {
|
|
2603
|
+
let result;
|
|
2604
|
+
if (timeout) {
|
|
2605
|
+
result = evaluateWithTimeout(factory, timeout, args, fallback);
|
|
2606
|
+
} else {
|
|
2607
|
+
result = typeof factory === "function" ? factory(...args) : factory;
|
|
2608
|
+
}
|
|
2609
|
+
if (result && typeof result.then === "function") {
|
|
2610
|
+
return result.catch((_error) => {
|
|
2611
|
+
if (onError) onError(_error);
|
|
2612
|
+
return fallback;
|
|
2613
|
+
});
|
|
2614
|
+
}
|
|
2615
|
+
if (cache) {
|
|
2616
|
+
cached = true;
|
|
2617
|
+
cachedValue = result;
|
|
2618
|
+
}
|
|
2619
|
+
return result;
|
|
2620
|
+
} catch (_error) {
|
|
2621
|
+
if (onError) {
|
|
2622
|
+
onError(_error);
|
|
2623
|
+
} else {
|
|
2624
|
+
console.error("Lazy evaluation _error:", _error);
|
|
2625
|
+
}
|
|
2626
|
+
return fallback;
|
|
2627
|
+
} finally {
|
|
2628
|
+
isEvaluating = false;
|
|
2629
|
+
}
|
|
2630
|
+
},
|
|
2631
|
+
// Force re-evaluation
|
|
2632
|
+
invalidate() {
|
|
2633
|
+
cached = false;
|
|
2634
|
+
cachedValue = null;
|
|
2635
|
+
lastDependencyHash = null;
|
|
2636
|
+
return this;
|
|
2637
|
+
},
|
|
2638
|
+
// Check if evaluated
|
|
2639
|
+
isEvaluated() {
|
|
2640
|
+
return cached;
|
|
2641
|
+
},
|
|
2642
|
+
// Get cached value without evaluation
|
|
2643
|
+
getCachedValue() {
|
|
2644
|
+
return cachedValue;
|
|
2645
|
+
},
|
|
2646
|
+
// Transform the lazy value
|
|
2647
|
+
map(transform) {
|
|
2648
|
+
return lazy((...args) => {
|
|
2649
|
+
const value = this.evaluate(...args);
|
|
2650
|
+
return transform(value);
|
|
2651
|
+
}, { ...options, cache: false });
|
|
2652
|
+
},
|
|
2653
|
+
// Chain lazy evaluations
|
|
2654
|
+
flatMap(transform) {
|
|
2655
|
+
return lazy((...args) => {
|
|
2656
|
+
const value = this.evaluate(...args);
|
|
2657
|
+
const transformed = transform(value);
|
|
2658
|
+
if (isLazy(transformed)) {
|
|
2659
|
+
return transformed.evaluate(...args);
|
|
2660
|
+
}
|
|
2661
|
+
return transformed;
|
|
2662
|
+
}, { ...options, cache: false });
|
|
2663
|
+
},
|
|
2664
|
+
// Convert to string for debugging
|
|
2665
|
+
toString() {
|
|
2666
|
+
return `[Lazy${cached ? " (cached)" : ""}]`;
|
|
2667
|
+
},
|
|
2668
|
+
// JSON serialization
|
|
2669
|
+
toJSON() {
|
|
2670
|
+
return this.evaluate();
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
return lazyWrapper;
|
|
2674
|
+
}
|
|
2675
|
+
function isLazy(value) {
|
|
2676
|
+
return value && typeof value === "object" && value.__isLazy === true;
|
|
2677
|
+
}
|
|
2678
|
+
function evaluateLazy(obj, ...args) {
|
|
2679
|
+
if (isLazy(obj)) {
|
|
2680
|
+
return obj.evaluate(...args);
|
|
2681
|
+
}
|
|
2682
|
+
if (Array.isArray(obj)) {
|
|
2683
|
+
return obj.map((item) => evaluateLazy(item, ...args));
|
|
2684
|
+
}
|
|
2685
|
+
if (obj && typeof obj === "object") {
|
|
2686
|
+
const result = {};
|
|
2687
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2688
|
+
result[key] = evaluateLazy(value, ...args);
|
|
2689
|
+
}
|
|
2690
|
+
return result;
|
|
2691
|
+
}
|
|
2692
|
+
return obj;
|
|
2693
|
+
}
|
|
2694
|
+
function hashDependencies(dependencies) {
|
|
2695
|
+
return dependencies.map((dep) => {
|
|
2696
|
+
if (typeof dep === "function") {
|
|
2697
|
+
return dep.toString();
|
|
2698
|
+
}
|
|
2699
|
+
return JSON.stringify(dep);
|
|
2700
|
+
}).join("|");
|
|
2701
|
+
}
|
|
2702
|
+
function evaluateWithTimeout(factory, timeout, args, fallback) {
|
|
2703
|
+
return new Promise((resolve, reject) => {
|
|
2704
|
+
const timer = setTimeout(() => {
|
|
2705
|
+
reject(new Error(`Lazy evaluation timeout after ${timeout}ms`));
|
|
2706
|
+
}, timeout);
|
|
2707
|
+
try {
|
|
2708
|
+
const result = factory(...args);
|
|
2709
|
+
if (result && typeof result.then === "function") {
|
|
2710
|
+
result.then((value) => {
|
|
2711
|
+
clearTimeout(timer);
|
|
2712
|
+
resolve(value);
|
|
2713
|
+
}).catch((_error) => {
|
|
2714
|
+
clearTimeout(timer);
|
|
2715
|
+
reject(_error);
|
|
2716
|
+
});
|
|
2717
|
+
} else {
|
|
2718
|
+
clearTimeout(timer);
|
|
2719
|
+
resolve(result);
|
|
2720
|
+
}
|
|
2721
|
+
} catch (_error) {
|
|
2722
|
+
clearTimeout(timer);
|
|
2723
|
+
reject(_error);
|
|
2724
|
+
}
|
|
2725
|
+
}).catch(() => fallback);
|
|
2726
|
+
}
|
|
2727
|
+
function memo(fn, options = {}) {
|
|
2728
|
+
const {
|
|
2729
|
+
// Caching strategy
|
|
2730
|
+
strategy = "lru",
|
|
2731
|
+
// 'lru', 'ttl', 'weak', 'simple'
|
|
2732
|
+
maxSize = 100,
|
|
2733
|
+
// Maximum cache entries
|
|
2734
|
+
ttl = null,
|
|
2735
|
+
// Time to live in milliseconds
|
|
2736
|
+
// Key generation
|
|
2737
|
+
keyFn = null,
|
|
2738
|
+
// Custom key function
|
|
2739
|
+
keySerializer = JSON.stringify,
|
|
2740
|
+
// Default serialization
|
|
2741
|
+
// Comparison
|
|
2742
|
+
// eslint-disable-next-line no-unused-vars
|
|
2743
|
+
compareFn = null,
|
|
2744
|
+
// Custom equality comparison
|
|
2745
|
+
// eslint-disable-next-line no-unused-vars
|
|
2746
|
+
shallow = false,
|
|
2747
|
+
// Shallow comparison for objects
|
|
2748
|
+
// Lifecycle hooks
|
|
2749
|
+
onHit = null,
|
|
2750
|
+
// Called on cache hit
|
|
2751
|
+
onMiss = null,
|
|
2752
|
+
// Called on cache miss
|
|
2753
|
+
onEvict = null,
|
|
2754
|
+
// Called when item evicted
|
|
2755
|
+
// Performance
|
|
2756
|
+
stats = false,
|
|
2757
|
+
// Track hit/miss statistics
|
|
2758
|
+
// Development
|
|
2759
|
+
debug = false
|
|
2760
|
+
// Debug logging
|
|
2761
|
+
} = options;
|
|
2762
|
+
let cache;
|
|
2763
|
+
const stats_data = stats ? { hits: 0, misses: 0, evictions: 0 } : null;
|
|
2764
|
+
switch (strategy) {
|
|
2765
|
+
case "lru":
|
|
2766
|
+
cache = new LRUCache(maxSize, { onEvict });
|
|
2767
|
+
break;
|
|
2768
|
+
case "ttl":
|
|
2769
|
+
cache = new TTLCache(ttl, { onEvict });
|
|
2770
|
+
break;
|
|
2771
|
+
case "weak":
|
|
2772
|
+
cache = /* @__PURE__ */ new WeakMap();
|
|
2773
|
+
break;
|
|
2774
|
+
default:
|
|
2775
|
+
cache = /* @__PURE__ */ new Map();
|
|
2776
|
+
}
|
|
2777
|
+
const generateKey = keyFn || ((...args) => {
|
|
2778
|
+
if (args.length === 0) return "__empty__";
|
|
2779
|
+
if (args.length === 1) return keySerializer(args[0]);
|
|
2780
|
+
return keySerializer(args);
|
|
2781
|
+
});
|
|
2782
|
+
const memoizedFn = (...args) => {
|
|
2783
|
+
const key = generateKey(...args);
|
|
2784
|
+
if (cache.has(key)) {
|
|
2785
|
+
const cached = cache.get(key);
|
|
2786
|
+
if (cached && (!cached.expires || Date.now() < cached.expires)) {
|
|
2787
|
+
if (debug) console.log(`Memo cache hit for key: ${key}`);
|
|
2788
|
+
if (onHit) onHit(key, cached.value, args);
|
|
2789
|
+
if (stats_data) stats_data.hits++;
|
|
2790
|
+
return cached.value || cached;
|
|
2791
|
+
} else {
|
|
2792
|
+
cache.delete(key);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
if (debug) console.log(`Memo cache miss for key: ${key}`);
|
|
2796
|
+
if (onMiss) onMiss(key, args);
|
|
2797
|
+
if (stats_data) stats_data.misses++;
|
|
2798
|
+
const result = fn(...args);
|
|
2799
|
+
const cacheEntry = ttl ? { value: result, expires: Date.now() + ttl } : result;
|
|
2800
|
+
cache.set(key, cacheEntry);
|
|
2801
|
+
return result;
|
|
2802
|
+
};
|
|
2803
|
+
memoizedFn.cache = cache;
|
|
2804
|
+
memoizedFn.clear = () => cache.clear();
|
|
2805
|
+
memoizedFn.delete = (key) => cache.delete(key);
|
|
2806
|
+
memoizedFn.has = (key) => cache.has(key);
|
|
2807
|
+
memoizedFn.size = () => cache.size;
|
|
2808
|
+
if (stats_data) {
|
|
2809
|
+
memoizedFn.stats = () => ({ ...stats_data });
|
|
2810
|
+
memoizedFn.resetStats = () => {
|
|
2811
|
+
stats_data.hits = 0;
|
|
2812
|
+
stats_data.misses = 0;
|
|
2813
|
+
stats_data.evictions = 0;
|
|
2814
|
+
};
|
|
2815
|
+
}
|
|
2816
|
+
memoizedFn.refresh = (...args) => {
|
|
2817
|
+
const key = generateKey(...args);
|
|
2818
|
+
cache.delete(key);
|
|
2819
|
+
return memoizedFn(...args);
|
|
2820
|
+
};
|
|
2821
|
+
return memoizedFn;
|
|
2822
|
+
}
|
|
2823
|
+
var LRUCache = class {
|
|
2824
|
+
constructor(maxSize = 100, options = {}) {
|
|
2825
|
+
this.maxSize = maxSize;
|
|
2826
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2827
|
+
this.onEvict = options.onEvict;
|
|
2828
|
+
}
|
|
2829
|
+
get(key) {
|
|
2830
|
+
if (this.cache.has(key)) {
|
|
2831
|
+
const value = this.cache.get(key);
|
|
2832
|
+
this.cache.delete(key);
|
|
2833
|
+
this.cache.set(key, value);
|
|
2834
|
+
return value;
|
|
2835
|
+
}
|
|
2836
|
+
return void 0;
|
|
2837
|
+
}
|
|
2838
|
+
set(key, value) {
|
|
2839
|
+
if (this.cache.has(key)) {
|
|
2840
|
+
this.cache.delete(key);
|
|
2841
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
2842
|
+
const firstKey = this.cache.keys().next().value;
|
|
2843
|
+
const evicted = this.cache.get(firstKey);
|
|
2844
|
+
this.cache.delete(firstKey);
|
|
2845
|
+
if (this.onEvict) {
|
|
2846
|
+
this.onEvict(firstKey, evicted);
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
this.cache.set(key, value);
|
|
2850
|
+
}
|
|
2851
|
+
has(key) {
|
|
2852
|
+
return this.cache.has(key);
|
|
2853
|
+
}
|
|
2854
|
+
delete(key) {
|
|
2855
|
+
return this.cache.delete(key);
|
|
2856
|
+
}
|
|
2857
|
+
clear() {
|
|
2858
|
+
this.cache.clear();
|
|
2859
|
+
}
|
|
2860
|
+
get size() {
|
|
2861
|
+
return this.cache.size;
|
|
2862
|
+
}
|
|
2863
|
+
};
|
|
2864
|
+
var TTLCache = class {
|
|
2865
|
+
constructor(ttl, options = {}) {
|
|
2866
|
+
this.ttl = ttl;
|
|
2867
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2868
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
2869
|
+
this.onEvict = options.onEvict;
|
|
2870
|
+
}
|
|
2871
|
+
get(key) {
|
|
2872
|
+
if (this.cache.has(key)) {
|
|
2873
|
+
const entry = this.cache.get(key);
|
|
2874
|
+
if (Date.now() < entry.expires) {
|
|
2875
|
+
return entry.value;
|
|
2876
|
+
} else {
|
|
2877
|
+
this.delete(key);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
return void 0;
|
|
2881
|
+
}
|
|
2882
|
+
set(key, value) {
|
|
2883
|
+
if (this.timers.has(key)) {
|
|
2884
|
+
clearTimeout(this.timers.get(key));
|
|
2885
|
+
}
|
|
2886
|
+
const expires = Date.now() + this.ttl;
|
|
2887
|
+
this.cache.set(key, { value, expires });
|
|
2888
|
+
const timer = setTimeout(() => {
|
|
2889
|
+
this.delete(key);
|
|
2890
|
+
}, this.ttl);
|
|
2891
|
+
this.timers.set(key, timer);
|
|
2892
|
+
}
|
|
2893
|
+
has(key) {
|
|
2894
|
+
if (this.cache.has(key)) {
|
|
2895
|
+
const entry = this.cache.get(key);
|
|
2896
|
+
return Date.now() < entry.expires;
|
|
2897
|
+
}
|
|
2898
|
+
return false;
|
|
2899
|
+
}
|
|
2900
|
+
delete(key) {
|
|
2901
|
+
const had = this.cache.has(key);
|
|
2902
|
+
if (had) {
|
|
2903
|
+
const entry = this.cache.get(key);
|
|
2904
|
+
this.cache.delete(key);
|
|
2905
|
+
if (this.timers.has(key)) {
|
|
2906
|
+
clearTimeout(this.timers.get(key));
|
|
2907
|
+
this.timers.delete(key);
|
|
2908
|
+
}
|
|
2909
|
+
if (this.onEvict) {
|
|
2910
|
+
this.onEvict(key, entry.value);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
return had;
|
|
2914
|
+
}
|
|
2915
|
+
clear() {
|
|
2916
|
+
this.timers.forEach((timer) => clearTimeout(timer));
|
|
2917
|
+
this.timers.clear();
|
|
2918
|
+
this.cache.clear();
|
|
2919
|
+
}
|
|
2920
|
+
get size() {
|
|
2921
|
+
return this.cache.size;
|
|
2922
|
+
}
|
|
2923
|
+
};
|
|
2924
|
+
function withState(initialState = {}, options = {}) {
|
|
2925
|
+
const {
|
|
2926
|
+
// State options
|
|
2927
|
+
persistent = false,
|
|
2928
|
+
// Persist state across component unmounts
|
|
2929
|
+
storageKey = null,
|
|
2930
|
+
// Key for persistent storage
|
|
2931
|
+
storage = typeof window !== "undefined" && typeof window.localStorage !== "undefined" ? window.localStorage : {
|
|
2932
|
+
// Fallback storage for Node.js environments
|
|
2933
|
+
_data: /* @__PURE__ */ new Map(),
|
|
2934
|
+
setItem(key, value) {
|
|
2935
|
+
this._data.set(key, value);
|
|
2071
2936
|
},
|
|
2072
|
-
{
|
|
2073
|
-
|
|
2074
|
-
suggestions: [
|
|
2075
|
-
"Reduce component nesting depth",
|
|
2076
|
-
"Break complex components into smaller parts",
|
|
2077
|
-
"Check for infinite recursion in component functions"
|
|
2078
|
-
]
|
|
2937
|
+
getItem(key) {
|
|
2938
|
+
return this._data.get(key) || null;
|
|
2079
2939
|
},
|
|
2080
|
-
{
|
|
2081
|
-
|
|
2082
|
-
suggestions: [
|
|
2083
|
-
"Ensure component follows the expected object structure",
|
|
2084
|
-
"Check property names and values for typos",
|
|
2085
|
-
"Verify component is not null or undefined"
|
|
2086
|
-
]
|
|
2940
|
+
removeItem(key) {
|
|
2941
|
+
this._data.delete(key);
|
|
2087
2942
|
},
|
|
2088
|
-
{
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2943
|
+
clear() {
|
|
2944
|
+
this._data.clear();
|
|
2945
|
+
}
|
|
2946
|
+
},
|
|
2947
|
+
// Storage mechanism
|
|
2948
|
+
// State transformation
|
|
2949
|
+
stateTransform = null,
|
|
2950
|
+
// Transform state before injection
|
|
2951
|
+
propName = "state",
|
|
2952
|
+
// Prop name for state injection
|
|
2953
|
+
actionsName = "actions",
|
|
2954
|
+
// Prop name for action injection
|
|
2955
|
+
// Reducers and actions
|
|
2956
|
+
reducer = null,
|
|
2957
|
+
// State reducer function
|
|
2958
|
+
actions = {},
|
|
2959
|
+
// Action creators
|
|
2960
|
+
middleware = [],
|
|
2961
|
+
// State middleware
|
|
2962
|
+
// Performance
|
|
2963
|
+
memoizeState = false,
|
|
2964
|
+
// Memoize state transformations
|
|
2965
|
+
// eslint-disable-next-line no-unused-vars
|
|
2966
|
+
shallow = false,
|
|
2967
|
+
// Shallow state comparison
|
|
2968
|
+
// Development
|
|
2969
|
+
// eslint-disable-next-line no-unused-vars
|
|
2970
|
+
devTools = false,
|
|
2971
|
+
// Connect to dev tools
|
|
2972
|
+
debug = false,
|
|
2973
|
+
// Debug logging
|
|
2974
|
+
displayName = null,
|
|
2975
|
+
// Component name for debugging
|
|
2976
|
+
// Lifecycle hooks
|
|
2977
|
+
onStateChange = null,
|
|
2978
|
+
// Called when state changes
|
|
2979
|
+
onMount = null,
|
|
2980
|
+
// Called when component mounts
|
|
2981
|
+
onUnmount = null,
|
|
2982
|
+
// Called when component unmounts
|
|
2983
|
+
// Validation
|
|
2984
|
+
validator = null,
|
|
2985
|
+
// State validator function
|
|
2986
|
+
// Async state
|
|
2987
|
+
supportAsync = false
|
|
2988
|
+
// Support async state updates
|
|
2989
|
+
} = options;
|
|
2990
|
+
return function withStateHOC(WrappedComponent) {
|
|
2991
|
+
const stateContainer = createStateContainer(initialState, {
|
|
2992
|
+
persistent,
|
|
2993
|
+
storageKey: storageKey || `${getComponentName(WrappedComponent)}_state`,
|
|
2994
|
+
storage,
|
|
2995
|
+
reducer,
|
|
2996
|
+
middleware,
|
|
2997
|
+
validator,
|
|
2998
|
+
onStateChange,
|
|
2999
|
+
debug
|
|
3000
|
+
});
|
|
3001
|
+
function WithStateComponent(props = {}, globalState = {}, context2 = {}) {
|
|
3002
|
+
if (!stateContainer.initialized) {
|
|
3003
|
+
stateContainer.initialize();
|
|
3004
|
+
if (onMount) {
|
|
3005
|
+
onMount(stateContainer.getState(), props, context2);
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
const currentState = stateContainer.getState();
|
|
3009
|
+
let transformedState = currentState;
|
|
3010
|
+
if (stateTransform) {
|
|
3011
|
+
transformedState = stateTransform(currentState, props, context2);
|
|
3012
|
+
}
|
|
3013
|
+
const boundActions = createBoundActions(actions, stateContainer, {
|
|
3014
|
+
props,
|
|
3015
|
+
context: context2,
|
|
3016
|
+
supportAsync,
|
|
3017
|
+
debug
|
|
3018
|
+
});
|
|
3019
|
+
const stateUtils = {
|
|
3020
|
+
// Basic state operations
|
|
3021
|
+
setState: stateContainer.setState.bind(stateContainer),
|
|
3022
|
+
getState: stateContainer.getState.bind(stateContainer),
|
|
3023
|
+
resetState: () => stateContainer.setState(initialState),
|
|
3024
|
+
// Advanced operations
|
|
3025
|
+
updateState: (updater) => {
|
|
3026
|
+
const current = stateContainer.getState();
|
|
3027
|
+
const next = typeof updater === "function" ? updater(current) : updater;
|
|
3028
|
+
stateContainer.setState(next);
|
|
3029
|
+
},
|
|
3030
|
+
// Batch updates
|
|
3031
|
+
batchUpdate: (updates) => {
|
|
3032
|
+
stateContainer.batch(() => {
|
|
3033
|
+
updates.forEach((update) => {
|
|
3034
|
+
if (typeof update === "function") {
|
|
3035
|
+
update(stateContainer);
|
|
3036
|
+
} else {
|
|
3037
|
+
stateContainer.setState(update);
|
|
3038
|
+
}
|
|
3039
|
+
});
|
|
3040
|
+
});
|
|
3041
|
+
},
|
|
3042
|
+
// Computed state
|
|
3043
|
+
computed: (computeFn) => {
|
|
3044
|
+
return memoizeState ? memo(computeFn)(transformedState) : computeFn(transformedState);
|
|
3045
|
+
},
|
|
3046
|
+
// State subscription
|
|
3047
|
+
subscribe: stateContainer.subscribe.bind(stateContainer),
|
|
3048
|
+
unsubscribe: stateContainer.unsubscribe.bind(stateContainer),
|
|
3049
|
+
// Async state operations
|
|
3050
|
+
...supportAsync && {
|
|
3051
|
+
setStateAsync: async (stateOrPromise) => {
|
|
3052
|
+
const resolved = await Promise.resolve(stateOrPromise);
|
|
3053
|
+
stateContainer.setState(resolved);
|
|
3054
|
+
},
|
|
3055
|
+
updateStateAsync: async (asyncUpdater) => {
|
|
3056
|
+
const current = stateContainer.getState();
|
|
3057
|
+
const next = await Promise.resolve(asyncUpdater(current));
|
|
3058
|
+
stateContainer.setState(next);
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
};
|
|
3062
|
+
const enhancedProps = {
|
|
3063
|
+
...props,
|
|
3064
|
+
[propName]: transformedState,
|
|
3065
|
+
[actionsName]: boundActions,
|
|
3066
|
+
setState: stateUtils.setState,
|
|
3067
|
+
getState: stateUtils.getState,
|
|
3068
|
+
stateUtils
|
|
3069
|
+
};
|
|
3070
|
+
if (debug) {
|
|
3071
|
+
console.log("withState render:", {
|
|
3072
|
+
component: getComponentName(WrappedComponent),
|
|
3073
|
+
state: transformedState,
|
|
3074
|
+
props: enhancedProps
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
return typeof WrappedComponent === "function" ? WrappedComponent(enhancedProps, globalState, context2) : WrappedComponent;
|
|
3078
|
+
}
|
|
3079
|
+
WithStateComponent.displayName = displayName || `withState(${getComponentName(WrappedComponent)})`;
|
|
3080
|
+
WithStateComponent.__isHOC = true;
|
|
3081
|
+
WithStateComponent.__hasState = true;
|
|
3082
|
+
WithStateComponent.__stateContainer = stateContainer;
|
|
3083
|
+
WithStateComponent.__wrappedComponent = WrappedComponent;
|
|
3084
|
+
WithStateComponent.cleanup = () => {
|
|
3085
|
+
if (onUnmount) {
|
|
3086
|
+
onUnmount(stateContainer.getState());
|
|
3087
|
+
}
|
|
3088
|
+
if (!persistent) {
|
|
3089
|
+
stateContainer.destroy();
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
return WithStateComponent;
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
function createStateContainer(initialState, options) {
|
|
3096
|
+
const {
|
|
3097
|
+
persistent,
|
|
3098
|
+
storageKey,
|
|
3099
|
+
storage,
|
|
3100
|
+
reducer,
|
|
3101
|
+
middleware,
|
|
3102
|
+
validator,
|
|
3103
|
+
onStateChange,
|
|
3104
|
+
debug
|
|
3105
|
+
} = options;
|
|
3106
|
+
let state = deepClone(initialState);
|
|
3107
|
+
let listeners = /* @__PURE__ */ new Set();
|
|
3108
|
+
const middlewareStack = [...middleware];
|
|
3109
|
+
const container = {
|
|
3110
|
+
initialized: false,
|
|
3111
|
+
initialize() {
|
|
3112
|
+
if (persistent && storageKey) {
|
|
3113
|
+
try {
|
|
3114
|
+
const saved = storage.getItem(storageKey);
|
|
3115
|
+
if (saved) {
|
|
3116
|
+
const parsed = JSON.parse(saved);
|
|
3117
|
+
state = { ...state, ...parsed };
|
|
3118
|
+
}
|
|
3119
|
+
} catch (_error) {
|
|
3120
|
+
if (debug) console.warn("Failed to load persisted state:", _error);
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
container.initialized = true;
|
|
3124
|
+
},
|
|
3125
|
+
getState() {
|
|
3126
|
+
return deepClone(state);
|
|
3127
|
+
},
|
|
3128
|
+
setState(newState) {
|
|
3129
|
+
const prevState = state;
|
|
3130
|
+
if (reducer) {
|
|
3131
|
+
state = reducer(state, { type: "SET_STATE", payload: newState });
|
|
3132
|
+
} else {
|
|
3133
|
+
state = typeof newState === "function" ? newState(state) : { ...state, ...newState };
|
|
3134
|
+
}
|
|
3135
|
+
if (validator && !validator(state)) {
|
|
3136
|
+
if (debug) console.warn("State validation failed, reverting:", state);
|
|
3137
|
+
state = prevState;
|
|
3138
|
+
return false;
|
|
3139
|
+
}
|
|
3140
|
+
state = middlewareStack.reduce(
|
|
3141
|
+
(acc, middleware2) => middleware2(acc, prevState) || acc,
|
|
3142
|
+
state
|
|
3143
|
+
);
|
|
3144
|
+
if (persistent && storageKey) {
|
|
3145
|
+
try {
|
|
3146
|
+
storage.setItem(storageKey, JSON.stringify(state));
|
|
3147
|
+
} catch (_error) {
|
|
3148
|
+
if (debug) console.warn("Failed to persist state:", _error);
|
|
3149
|
+
}
|
|
2096
3150
|
}
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
3151
|
+
if (state !== prevState) {
|
|
3152
|
+
listeners.forEach((listener) => {
|
|
3153
|
+
try {
|
|
3154
|
+
listener(state, prevState);
|
|
3155
|
+
} catch (_error) {
|
|
3156
|
+
if (debug) console.error("State listener _error:", _error);
|
|
3157
|
+
}
|
|
3158
|
+
});
|
|
3159
|
+
if (onStateChange) {
|
|
3160
|
+
onStateChange(state, prevState);
|
|
3161
|
+
}
|
|
2101
3162
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
3163
|
+
return true;
|
|
3164
|
+
},
|
|
3165
|
+
subscribe(listener) {
|
|
3166
|
+
listeners.add(listener);
|
|
3167
|
+
return () => listeners.delete(listener);
|
|
3168
|
+
},
|
|
3169
|
+
unsubscribe(listener) {
|
|
3170
|
+
return listeners.delete(listener);
|
|
3171
|
+
},
|
|
3172
|
+
batch(batchFn) {
|
|
3173
|
+
const originalListeners = listeners;
|
|
3174
|
+
listeners = /* @__PURE__ */ new Set();
|
|
3175
|
+
try {
|
|
3176
|
+
batchFn();
|
|
3177
|
+
} finally {
|
|
3178
|
+
listeners = originalListeners;
|
|
3179
|
+
listeners.forEach((listener) => listener(state));
|
|
3180
|
+
}
|
|
3181
|
+
},
|
|
3182
|
+
destroy() {
|
|
3183
|
+
listeners.clear();
|
|
3184
|
+
if (persistent && storageKey) {
|
|
3185
|
+
try {
|
|
3186
|
+
storage.removeItem(storageKey);
|
|
3187
|
+
} catch (_error) {
|
|
3188
|
+
if (debug) console.warn("Failed to remove persisted state:", _error);
|
|
3189
|
+
}
|
|
2111
3190
|
}
|
|
2112
3191
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
3192
|
+
};
|
|
3193
|
+
return container;
|
|
3194
|
+
}
|
|
3195
|
+
function createBoundActions(actions, stateContainer, options) {
|
|
3196
|
+
const { props, context: context2, supportAsync, debug } = options;
|
|
3197
|
+
const boundActions = {};
|
|
3198
|
+
Object.entries(actions).forEach(([actionName, actionCreator]) => {
|
|
3199
|
+
boundActions[actionName] = (...args) => {
|
|
3200
|
+
try {
|
|
3201
|
+
const result = actionCreator(
|
|
3202
|
+
stateContainer.getState(),
|
|
3203
|
+
stateContainer.setState.bind(stateContainer),
|
|
3204
|
+
{ props, context: context2, args }
|
|
3205
|
+
);
|
|
3206
|
+
if (supportAsync && result && typeof result.then === "function") {
|
|
3207
|
+
return result.catch((_error) => {
|
|
3208
|
+
if (debug) console.error(`Async action ${actionName} failed:`, _error);
|
|
3209
|
+
throw _error;
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
return result;
|
|
3213
|
+
} catch (_error) {
|
|
3214
|
+
if (debug) console.error(`Action ${actionName} failed:`, _error);
|
|
3215
|
+
throw _error;
|
|
3216
|
+
}
|
|
3217
|
+
};
|
|
3218
|
+
});
|
|
3219
|
+
return boundActions;
|
|
3220
|
+
}
|
|
3221
|
+
var withStateUtils = {
|
|
2122
3222
|
/**
|
|
2123
|
-
*
|
|
3223
|
+
* Simple local state
|
|
2124
3224
|
*/
|
|
2125
|
-
|
|
2126
|
-
const errorKey = `${_error.name}:${_error.message}`;
|
|
2127
|
-
this.errorCounts.set(errorKey, (this.errorCounts.get(errorKey) || 0) + 1);
|
|
2128
|
-
const historyEntry = {
|
|
2129
|
-
..._error.toJSON(),
|
|
2130
|
-
count: this.errorCounts.get(errorKey),
|
|
2131
|
-
firstSeen: this.errorHistory.find((e) => e.key === errorKey)?.firstSeen || _error.timestamp,
|
|
2132
|
-
key: errorKey
|
|
2133
|
-
};
|
|
2134
|
-
this.errorHistory = this.errorHistory.filter((e) => e.key !== errorKey);
|
|
2135
|
-
this.errorHistory.unshift(historyEntry);
|
|
2136
|
-
if (this.errorHistory.length > this.options.maxErrorHistory) {
|
|
2137
|
-
this.errorHistory = this.errorHistory.slice(0, this.options.maxErrorHistory);
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
3225
|
+
local: (initialState) => withState(initialState),
|
|
2140
3226
|
/**
|
|
2141
|
-
*
|
|
3227
|
+
* Persistent state with localStorage
|
|
2142
3228
|
*/
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
const isRepeated = this.errorCounts.get(`${_error.name}:${_error.message}`) > 1;
|
|
2148
|
-
const errorGroup = `\u{1F6A8} ${_error.name}${isRepeated ? ` (\xD7${this.errorCounts.get(`${_error.name}:${_error.message}`)})` : ""}`;
|
|
2149
|
-
console.group(errorGroup);
|
|
2150
|
-
console.error(`\u274C ${_error.message}`);
|
|
2151
|
-
if (_error.component) {
|
|
2152
|
-
console.log("\u{1F50D} Component:", this.formatComponent(_error.component));
|
|
2153
|
-
}
|
|
2154
|
-
if (_error.context) {
|
|
2155
|
-
console.log("\u{1F4CB} Context:", _error.context);
|
|
2156
|
-
}
|
|
2157
|
-
if (this.options.enableSuggestions && _error.suggestions.length > 0) {
|
|
2158
|
-
console.group("\u{1F4A1} Suggestions:");
|
|
2159
|
-
_error.suggestions.forEach((suggestion, index) => {
|
|
2160
|
-
console.log(`${index + 1}. ${suggestion}`);
|
|
2161
|
-
});
|
|
2162
|
-
console.groupEnd();
|
|
2163
|
-
}
|
|
2164
|
-
if (this.options.enableStackTrace && _error.stack) {
|
|
2165
|
-
console.log("\u{1F4DA} Stack trace:", _error.stack);
|
|
2166
|
-
}
|
|
2167
|
-
console.groupEnd();
|
|
2168
|
-
}
|
|
3229
|
+
persistent: (initialState, key) => withState(initialState, {
|
|
3230
|
+
persistent: true,
|
|
3231
|
+
storageKey: key
|
|
3232
|
+
}),
|
|
2169
3233
|
/**
|
|
2170
|
-
*
|
|
3234
|
+
* State with reducer pattern
|
|
2171
3235
|
*/
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
3236
|
+
reducer: (initialState, reducer, actions = {}) => withState(initialState, {
|
|
3237
|
+
reducer,
|
|
3238
|
+
actions
|
|
3239
|
+
}),
|
|
3240
|
+
/**
|
|
3241
|
+
* Async state management
|
|
3242
|
+
*/
|
|
3243
|
+
async: (initialState, asyncActions = {}) => withState(initialState, {
|
|
3244
|
+
supportAsync: true,
|
|
3245
|
+
actions: asyncActions
|
|
3246
|
+
}),
|
|
3247
|
+
/**
|
|
3248
|
+
* State with validation
|
|
3249
|
+
*/
|
|
3250
|
+
validated: (initialState, validator) => withState(initialState, {
|
|
3251
|
+
validator,
|
|
3252
|
+
debug: true
|
|
3253
|
+
}),
|
|
3254
|
+
/**
|
|
3255
|
+
* Shared state across components
|
|
3256
|
+
*/
|
|
3257
|
+
shared: (initialState, sharedKey) => {
|
|
3258
|
+
const sharedStates = withStateUtils._shared || (withStateUtils._shared = /* @__PURE__ */ new Map());
|
|
3259
|
+
if (!sharedStates.has(sharedKey)) {
|
|
3260
|
+
sharedStates.set(sharedKey, createStateContainer(initialState, {}));
|
|
2183
3261
|
}
|
|
2184
|
-
|
|
2185
|
-
const
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
formatted["..."] = `(${Object.keys(component).length - 5} more)`;
|
|
3262
|
+
return (WrappedComponent) => {
|
|
3263
|
+
const sharedContainer = sharedStates.get(sharedKey);
|
|
3264
|
+
function SharedStateComponent(props, globalState, context2) {
|
|
3265
|
+
const currentState = sharedContainer.getState();
|
|
3266
|
+
const enhancedProps = {
|
|
3267
|
+
...props,
|
|
3268
|
+
state: currentState,
|
|
3269
|
+
setState: sharedContainer.setState.bind(sharedContainer),
|
|
3270
|
+
subscribe: sharedContainer.subscribe.bind(sharedContainer)
|
|
3271
|
+
};
|
|
3272
|
+
return typeof WrappedComponent === "function" ? WrappedComponent(enhancedProps, globalState, context2) : WrappedComponent;
|
|
2196
3273
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
}
|
|
3274
|
+
SharedStateComponent.displayName = `withSharedState(${getComponentName(WrappedComponent)})`;
|
|
3275
|
+
return SharedStateComponent;
|
|
3276
|
+
};
|
|
3277
|
+
},
|
|
2201
3278
|
/**
|
|
2202
|
-
*
|
|
3279
|
+
* State with form utilities
|
|
2203
3280
|
*/
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
3281
|
+
form: (initialFormState) => withState(initialFormState, {
|
|
3282
|
+
actions: {
|
|
3283
|
+
updateField: (state, setState, { args: [field, value] }) => {
|
|
3284
|
+
setState({ [field]: value });
|
|
3285
|
+
},
|
|
3286
|
+
updateMultiple: (state, setState, { args: [updates] }) => {
|
|
3287
|
+
setState(updates);
|
|
3288
|
+
},
|
|
3289
|
+
resetForm: (state, setState) => {
|
|
3290
|
+
setState(initialFormState);
|
|
3291
|
+
},
|
|
3292
|
+
validateForm: (state, setState, { args: [validator] }) => {
|
|
3293
|
+
const errors = validator(state);
|
|
3294
|
+
setState({ _errors: errors });
|
|
3295
|
+
return Object.keys(errors).length === 0;
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
}),
|
|
2207
3299
|
/**
|
|
2208
|
-
*
|
|
3300
|
+
* State with loading/_error handling
|
|
2209
3301
|
*/
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
3302
|
+
withLoading: async (initialState) => withState({
|
|
3303
|
+
...initialState,
|
|
3304
|
+
_loading: false,
|
|
3305
|
+
_error: null
|
|
3306
|
+
}, {
|
|
3307
|
+
supportAsync: true,
|
|
3308
|
+
actions: {
|
|
3309
|
+
setLoading: (state, setState, { args: [loading] }) => {
|
|
3310
|
+
setState({ _loading: loading });
|
|
3311
|
+
},
|
|
3312
|
+
setError: (state, setState, { args: [_error] }) => {
|
|
3313
|
+
setState({ _error, _loading: false });
|
|
3314
|
+
},
|
|
3315
|
+
clearError: (state, setState) => {
|
|
3316
|
+
setState({ _error: null });
|
|
3317
|
+
},
|
|
3318
|
+
asyncAction: async (state, setState, { args: [asyncFn] }) => {
|
|
3319
|
+
setState({ _loading: true, _error: null });
|
|
3320
|
+
try {
|
|
3321
|
+
const result = await asyncFn(state);
|
|
3322
|
+
setState({ _loading: false });
|
|
3323
|
+
return result;
|
|
3324
|
+
} catch (_error) {
|
|
3325
|
+
setState({ _loading: false, _error });
|
|
3326
|
+
throw _error;
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
}),
|
|
2214
3331
|
/**
|
|
2215
|
-
*
|
|
3332
|
+
* State with undo/redo functionality
|
|
2216
3333
|
*/
|
|
2217
|
-
|
|
2218
|
-
const
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
const hour = new Date(_error.timestamp).toISOString().slice(0, 13);
|
|
2223
|
-
errorsByTime[hour] = (errorsByTime[hour] || 0) + _error.count;
|
|
2224
|
-
});
|
|
2225
|
-
return {
|
|
2226
|
-
totalErrors: this.errorHistory.reduce((sum, e) => sum + e.count, 0),
|
|
2227
|
-
uniqueErrors: this.errorHistory.length,
|
|
2228
|
-
errorsByType,
|
|
2229
|
-
errorsByTime,
|
|
2230
|
-
mostCommonErrors: this.getMostCommonErrors(5),
|
|
2231
|
-
recentErrors: this.errorHistory.slice(0, 10)
|
|
3334
|
+
withHistory: (initialState, maxHistory = 10) => {
|
|
3335
|
+
const historyState = {
|
|
3336
|
+
present: initialState,
|
|
3337
|
+
past: [],
|
|
3338
|
+
future: []
|
|
2232
3339
|
};
|
|
2233
|
-
|
|
3340
|
+
return withState(historyState, {
|
|
3341
|
+
actions: {
|
|
3342
|
+
undo: (state, setState) => {
|
|
3343
|
+
if (state.past.length === 0) return;
|
|
3344
|
+
const previous = state.past[state.past.length - 1];
|
|
3345
|
+
const newPast = state.past.slice(0, state.past.length - 1);
|
|
3346
|
+
setState({
|
|
3347
|
+
past: newPast,
|
|
3348
|
+
present: previous,
|
|
3349
|
+
future: [state.present, ...state.future]
|
|
3350
|
+
});
|
|
3351
|
+
},
|
|
3352
|
+
redo: (state, setState) => {
|
|
3353
|
+
if (state.future.length === 0) return;
|
|
3354
|
+
const next = state.future[0];
|
|
3355
|
+
const newFuture = state.future.slice(1);
|
|
3356
|
+
setState({
|
|
3357
|
+
past: [...state.past, state.present],
|
|
3358
|
+
present: next,
|
|
3359
|
+
future: newFuture
|
|
3360
|
+
});
|
|
3361
|
+
},
|
|
3362
|
+
updatePresent: (state, setState, { args: [newPresent] }) => {
|
|
3363
|
+
setState({
|
|
3364
|
+
past: [...state.past, state.present].slice(-maxHistory),
|
|
3365
|
+
present: newPresent,
|
|
3366
|
+
future: []
|
|
3367
|
+
});
|
|
3368
|
+
},
|
|
3369
|
+
canUndo: (state) => state.past.length > 0,
|
|
3370
|
+
canRedo: (state) => state.future.length > 0
|
|
3371
|
+
}
|
|
3372
|
+
});
|
|
3373
|
+
},
|
|
2234
3374
|
/**
|
|
2235
|
-
*
|
|
3375
|
+
* Computed state properties
|
|
2236
3376
|
*/
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
3377
|
+
computed: (initialState, computedProps) => withState(initialState, {
|
|
3378
|
+
stateTransform: (state) => {
|
|
3379
|
+
const computed = {};
|
|
3380
|
+
Object.entries(computedProps).forEach(([key, computeFn]) => {
|
|
3381
|
+
computed[key] = computeFn(state);
|
|
3382
|
+
});
|
|
3383
|
+
return { ...state, ...computed };
|
|
3384
|
+
},
|
|
3385
|
+
memoizeState: true
|
|
3386
|
+
})
|
|
2245
3387
|
};
|
|
2246
|
-
|
|
3388
|
+
function createStateManager(config) {
|
|
3389
|
+
const {
|
|
3390
|
+
initialState = {},
|
|
3391
|
+
reducers = {},
|
|
3392
|
+
actions = {},
|
|
3393
|
+
middleware = [],
|
|
3394
|
+
plugins = []
|
|
3395
|
+
} = config;
|
|
3396
|
+
const rootReducer = (state, action) => {
|
|
3397
|
+
let nextState = state;
|
|
3398
|
+
Object.entries(reducers).forEach(([key, reducer]) => {
|
|
3399
|
+
nextState = {
|
|
3400
|
+
...nextState,
|
|
3401
|
+
[key]: reducer(nextState[key], action)
|
|
3402
|
+
};
|
|
3403
|
+
});
|
|
3404
|
+
return nextState;
|
|
3405
|
+
};
|
|
3406
|
+
const enhancedConfig = plugins.reduce(
|
|
3407
|
+
(acc, plugin) => plugin(acc),
|
|
3408
|
+
{ initialState, reducer: rootReducer, actions, middleware }
|
|
3409
|
+
);
|
|
3410
|
+
return withState(enhancedConfig.initialState, {
|
|
3411
|
+
reducer: enhancedConfig.reducer,
|
|
3412
|
+
actions: enhancedConfig.actions,
|
|
3413
|
+
middleware: enhancedConfig.middleware
|
|
3414
|
+
});
|
|
3415
|
+
}
|
|
3416
|
+
function getComponentName(component) {
|
|
3417
|
+
if (!component) return "Component";
|
|
3418
|
+
return component.displayName || component.name || component.constructor?.name || "Component";
|
|
3419
|
+
}
|
|
2247
3420
|
|
|
2248
3421
|
// src/components/lifecycle.js
|
|
2249
3422
|
var LIFECYCLE_PHASES = {
|
|
@@ -3485,6 +4658,117 @@ function createGlobalErrorHandler(options = {}) {
|
|
|
3485
4658
|
return new GlobalErrorHandler(options);
|
|
3486
4659
|
}
|
|
3487
4660
|
|
|
4661
|
+
// src/utils/render-utils.js
|
|
4662
|
+
function renderWithMonitoring(component, options = {}) {
|
|
4663
|
+
const {
|
|
4664
|
+
enablePerformanceMonitoring = false
|
|
4665
|
+
} = options;
|
|
4666
|
+
let html;
|
|
4667
|
+
if (enablePerformanceMonitoring) {
|
|
4668
|
+
const renderId = performanceMonitor.startRender();
|
|
4669
|
+
html = render(component);
|
|
4670
|
+
performanceMonitor.endRender(renderId);
|
|
4671
|
+
} else {
|
|
4672
|
+
html = render(component);
|
|
4673
|
+
}
|
|
4674
|
+
return html;
|
|
4675
|
+
}
|
|
4676
|
+
function renderWithTemplate(component, options = {}) {
|
|
4677
|
+
const {
|
|
4678
|
+
template = "<!DOCTYPE html>\n{{content}}"
|
|
4679
|
+
} = options;
|
|
4680
|
+
const html = renderWithMonitoring(component, options);
|
|
4681
|
+
return template.replace("{{content}}", html);
|
|
4682
|
+
}
|
|
4683
|
+
async function renderComponentFactory(componentFactory, factoryArgs, options = {}) {
|
|
4684
|
+
const component = await Promise.resolve(
|
|
4685
|
+
componentFactory(...factoryArgs)
|
|
4686
|
+
);
|
|
4687
|
+
if (!component) {
|
|
4688
|
+
throw new Error("Component factory returned null/undefined");
|
|
4689
|
+
}
|
|
4690
|
+
return renderWithTemplate(component, options);
|
|
4691
|
+
}
|
|
4692
|
+
function isCoherentComponent(obj) {
|
|
4693
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
4694
|
+
return false;
|
|
4695
|
+
}
|
|
4696
|
+
const keys = Object.keys(obj);
|
|
4697
|
+
return keys.length === 1;
|
|
4698
|
+
}
|
|
4699
|
+
function createErrorResponse(error, context2 = "rendering") {
|
|
4700
|
+
return {
|
|
4701
|
+
error: "Internal Server Error",
|
|
4702
|
+
message: error.message,
|
|
4703
|
+
context: context2,
|
|
4704
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4705
|
+
};
|
|
4706
|
+
}
|
|
4707
|
+
|
|
4708
|
+
// src/utils/dependency-utils.js
|
|
4709
|
+
function isPeerDependencyAvailable(packageName) {
|
|
4710
|
+
try {
|
|
4711
|
+
if (typeof require !== "undefined" && require.resolve) {
|
|
4712
|
+
require.resolve(packageName);
|
|
4713
|
+
return true;
|
|
4714
|
+
}
|
|
4715
|
+
return false;
|
|
4716
|
+
} catch {
|
|
4717
|
+
return false;
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4720
|
+
async function importPeerDependency(packageName, integrationName) {
|
|
4721
|
+
try {
|
|
4722
|
+
return await import(packageName);
|
|
4723
|
+
} catch {
|
|
4724
|
+
throw new Error(
|
|
4725
|
+
`${integrationName} integration requires the '${packageName}' package to be installed.
|
|
4726
|
+
Please install it with: npm install ${packageName}
|
|
4727
|
+
Or with pnpm: pnpm add ${packageName}
|
|
4728
|
+
Or with yarn: yarn add ${packageName}`
|
|
4729
|
+
);
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
function createLazyIntegration(packageName, integrationName, createIntegration) {
|
|
4733
|
+
let cachedIntegration = null;
|
|
4734
|
+
let importPromise = null;
|
|
4735
|
+
return async function(...args) {
|
|
4736
|
+
if (cachedIntegration) {
|
|
4737
|
+
return cachedIntegration(...args);
|
|
4738
|
+
}
|
|
4739
|
+
if (!importPromise) {
|
|
4740
|
+
importPromise = importPeerDependency(packageName, integrationName).then((module2) => {
|
|
4741
|
+
cachedIntegration = createIntegration(module2);
|
|
4742
|
+
return cachedIntegration;
|
|
4743
|
+
});
|
|
4744
|
+
}
|
|
4745
|
+
const integration = await importPromise;
|
|
4746
|
+
return integration(...args);
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4749
|
+
function checkPeerDependencies(dependencies) {
|
|
4750
|
+
const results = {};
|
|
4751
|
+
const missing = [];
|
|
4752
|
+
for (const { package: packageName, integration } of dependencies) {
|
|
4753
|
+
const available = isPeerDependencyAvailable(packageName);
|
|
4754
|
+
results[packageName] = available;
|
|
4755
|
+
if (!available) {
|
|
4756
|
+
missing.push({ package: packageName, integration });
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
if (missing.length > 0) {
|
|
4760
|
+
const installCommands = missing.map(({ package: pkg }) => pkg).join(" ");
|
|
4761
|
+
const integrationsList = missing.map(({ integration }) => integration).join(", ");
|
|
4762
|
+
console.warn(
|
|
4763
|
+
`Optional dependencies missing for ${integrationsList} integration(s).
|
|
4764
|
+
To use these integrations, install: npm install ${installCommands}
|
|
4765
|
+
Or with pnpm: pnpm add ${installCommands}
|
|
4766
|
+
Or with yarn: yarn add ${installCommands}`
|
|
4767
|
+
);
|
|
4768
|
+
}
|
|
4769
|
+
return results;
|
|
4770
|
+
}
|
|
4771
|
+
|
|
3488
4772
|
// src/shadow-dom.js
|
|
3489
4773
|
var shadow_dom_exports = {};
|
|
3490
4774
|
__export(shadow_dom_exports, {
|
|
@@ -4950,7 +6234,99 @@ var eventSystem2 = {
|
|
|
4950
6234
|
};
|
|
4951
6235
|
var events_default = eventSystem2;
|
|
4952
6236
|
|
|
6237
|
+
// src/components/enhanced-composition.js
|
|
6238
|
+
var hoc = {
|
|
6239
|
+
/**
|
|
6240
|
+
* Wrap component with additional props
|
|
6241
|
+
*/
|
|
6242
|
+
withProps(additionalProps) {
|
|
6243
|
+
return (Component2) => (props) => {
|
|
6244
|
+
return Component2({ ...props, ...additionalProps });
|
|
6245
|
+
};
|
|
6246
|
+
},
|
|
6247
|
+
/**
|
|
6248
|
+
* Conditional rendering HOC
|
|
6249
|
+
*/
|
|
6250
|
+
withCondition(condition) {
|
|
6251
|
+
return (Component2) => (props) => {
|
|
6252
|
+
return condition(props) ? Component2(props) : null;
|
|
6253
|
+
};
|
|
6254
|
+
},
|
|
6255
|
+
/**
|
|
6256
|
+
* Loading state HOC
|
|
6257
|
+
*/
|
|
6258
|
+
withLoading(loadingComponent) {
|
|
6259
|
+
return (Component2) => (props) => {
|
|
6260
|
+
return props.loading ? loadingComponent(props) : Component2(props);
|
|
6261
|
+
};
|
|
6262
|
+
},
|
|
6263
|
+
/**
|
|
6264
|
+
* Error boundary HOC
|
|
6265
|
+
*/
|
|
6266
|
+
withError(errorComponent) {
|
|
6267
|
+
return (Component2) => (props) => {
|
|
6268
|
+
try {
|
|
6269
|
+
return Component2(props);
|
|
6270
|
+
} catch (error) {
|
|
6271
|
+
return errorComponent({ error, ...props });
|
|
6272
|
+
}
|
|
6273
|
+
};
|
|
6274
|
+
},
|
|
6275
|
+
/**
|
|
6276
|
+
* Memoization HOC
|
|
6277
|
+
*/
|
|
6278
|
+
withMemo(getMemoKey) {
|
|
6279
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6280
|
+
return (Component2) => (props) => {
|
|
6281
|
+
const key = getMemoKey ? getMemoKey(props) : JSON.stringify(props);
|
|
6282
|
+
if (cache.has(key)) {
|
|
6283
|
+
return cache.get(key);
|
|
6284
|
+
}
|
|
6285
|
+
const result = Component2(props);
|
|
6286
|
+
cache.set(key, result);
|
|
6287
|
+
return result;
|
|
6288
|
+
};
|
|
6289
|
+
}
|
|
6290
|
+
};
|
|
6291
|
+
var compose = {
|
|
6292
|
+
/**
|
|
6293
|
+
* Combine multiple components into one
|
|
6294
|
+
*/
|
|
6295
|
+
combine(...components) {
|
|
6296
|
+
return (props) => ({
|
|
6297
|
+
fragment: {
|
|
6298
|
+
children: components.map((Component2) => Component2(props))
|
|
6299
|
+
}
|
|
6300
|
+
});
|
|
6301
|
+
},
|
|
6302
|
+
/**
|
|
6303
|
+
* Pipe components through transformations
|
|
6304
|
+
*/
|
|
6305
|
+
pipe(...transformers) {
|
|
6306
|
+
return (Component2) => {
|
|
6307
|
+
return transformers.reduce((acc, transformer) => transformer(acc), Component2);
|
|
6308
|
+
};
|
|
6309
|
+
},
|
|
6310
|
+
/**
|
|
6311
|
+
* Branch based on conditions
|
|
6312
|
+
*/
|
|
6313
|
+
branch(condition, leftComponent, rightComponent) {
|
|
6314
|
+
return (props) => {
|
|
6315
|
+
return condition(props) ? leftComponent(props) : rightComponent(props);
|
|
6316
|
+
};
|
|
6317
|
+
},
|
|
6318
|
+
/**
|
|
6319
|
+
* Render component or fallback
|
|
6320
|
+
*/
|
|
6321
|
+
maybe(Component2, fallback = null) {
|
|
6322
|
+
return (props) => {
|
|
6323
|
+
return Component2 ? Component2(props) : fallback;
|
|
6324
|
+
};
|
|
6325
|
+
}
|
|
6326
|
+
};
|
|
6327
|
+
|
|
4953
6328
|
// src/index.js
|
|
6329
|
+
var import_meta = {};
|
|
4954
6330
|
var scopeCounter = { value: 0 };
|
|
4955
6331
|
function generateScopeId() {
|
|
4956
6332
|
return `coh-${scopeCounter.value++}`;
|
|
@@ -4994,7 +6370,7 @@ function applyScopeToElement(element, scopeId) {
|
|
|
4994
6370
|
}
|
|
4995
6371
|
return element;
|
|
4996
6372
|
}
|
|
4997
|
-
function
|
|
6373
|
+
function escapeHtml2(text) {
|
|
4998
6374
|
if (typeof text !== "string") return text;
|
|
4999
6375
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5000
6376
|
}
|
|
@@ -5004,83 +6380,47 @@ function dangerouslySetInnerContent(content) {
|
|
|
5004
6380
|
__trusted: true
|
|
5005
6381
|
};
|
|
5006
6382
|
}
|
|
5007
|
-
function
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
function isVoidElement(tagName) {
|
|
5011
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
5012
|
-
"area",
|
|
5013
|
-
"base",
|
|
5014
|
-
"br",
|
|
5015
|
-
"col",
|
|
5016
|
-
"embed",
|
|
5017
|
-
"hr",
|
|
5018
|
-
"img",
|
|
5019
|
-
"input",
|
|
5020
|
-
"link",
|
|
5021
|
-
"meta",
|
|
5022
|
-
"param",
|
|
5023
|
-
"source",
|
|
5024
|
-
"track",
|
|
5025
|
-
"wbr"
|
|
5026
|
-
]);
|
|
5027
|
-
return voidElements.has(tagName.toLowerCase());
|
|
5028
|
-
}
|
|
5029
|
-
function formatAttributes(attrs) {
|
|
5030
|
-
if (!attrs || typeof attrs !== "object") return "";
|
|
5031
|
-
return Object.entries(attrs).filter(([, value]) => value !== null && value !== void 0 && value !== false).map(([key, value]) => {
|
|
5032
|
-
if (typeof value === "function") {
|
|
5033
|
-
value = value();
|
|
5034
|
-
}
|
|
5035
|
-
const attrName = key === "className" ? "class" : key;
|
|
5036
|
-
if (value === true) return attrName;
|
|
5037
|
-
return `${attrName}="${escapeHtml(String(value))}"`;
|
|
5038
|
-
}).join(" ");
|
|
5039
|
-
}
|
|
5040
|
-
function renderRaw(obj) {
|
|
5041
|
-
if (obj === null || obj === void 0) return "";
|
|
5042
|
-
if (typeof obj === "string" || typeof obj === "number") return escapeHtml(String(obj));
|
|
5043
|
-
if (Array.isArray(obj)) return obj.map(renderRaw).join("");
|
|
5044
|
-
if (typeof obj === "function") {
|
|
5045
|
-
const result = obj(renderRaw);
|
|
5046
|
-
return renderRaw(result);
|
|
6383
|
+
function injectHydrationAttributes(component, options) {
|
|
6384
|
+
if (!component || typeof component !== "object" || Array.isArray(component)) {
|
|
6385
|
+
return component;
|
|
5047
6386
|
}
|
|
5048
|
-
|
|
5049
|
-
if (
|
|
5050
|
-
|
|
6387
|
+
const tagName = Object.keys(component)[0];
|
|
6388
|
+
if (!tagName) return component;
|
|
6389
|
+
const props = component[tagName];
|
|
6390
|
+
if (typeof props !== "object" || props === null) return component;
|
|
6391
|
+
const injected = { ...props };
|
|
6392
|
+
if (options.hydratable) {
|
|
6393
|
+
injected["data-hydratable"] = "true";
|
|
5051
6394
|
}
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
const { children, text, ...attributes } = props;
|
|
5055
|
-
const attrsStr = formatAttributes(attributes);
|
|
5056
|
-
const openTag = attrsStr ? `<${tagName} ${attrsStr}>` : `<${tagName}>`;
|
|
5057
|
-
if (isVoidElement(tagName)) {
|
|
5058
|
-
return openTag.replace(">", " />");
|
|
5059
|
-
}
|
|
5060
|
-
let content = "";
|
|
5061
|
-
if (text !== void 0) {
|
|
5062
|
-
if (isTrustedContent(text)) {
|
|
5063
|
-
content = text.__html;
|
|
5064
|
-
} else {
|
|
5065
|
-
content = escapeHtml(String(text));
|
|
5066
|
-
}
|
|
5067
|
-
} else if (children) {
|
|
5068
|
-
content = renderRaw(children);
|
|
5069
|
-
}
|
|
5070
|
-
return `${openTag}${content}</${tagName}>`;
|
|
5071
|
-
} else if (typeof props === "string") {
|
|
5072
|
-
const content = isTrustedContent(props) ? props.__html : escapeHtml(props);
|
|
5073
|
-
return isVoidElement(tagName) ? `<${tagName} />` : `<${tagName}>${content}</${tagName}>`;
|
|
5074
|
-
}
|
|
6395
|
+
if (options.island) {
|
|
6396
|
+
injected["data-coherent-island"] = "true";
|
|
5075
6397
|
}
|
|
5076
|
-
|
|
6398
|
+
if (options._islandComponentName) {
|
|
6399
|
+
injected["data-coherent-island-component"] = options._islandComponentName;
|
|
6400
|
+
}
|
|
6401
|
+
return { [tagName]: injected };
|
|
6402
|
+
}
|
|
6403
|
+
function Island(componentFn) {
|
|
6404
|
+
const componentName = componentFn.name || "Anonymous";
|
|
6405
|
+
return function IslandComponent(props) {
|
|
6406
|
+
const result = componentFn(props);
|
|
6407
|
+
return injectHydrationAttributes(result, {
|
|
6408
|
+
island: true,
|
|
6409
|
+
_islandComponentName: componentName
|
|
6410
|
+
});
|
|
6411
|
+
};
|
|
5077
6412
|
}
|
|
5078
|
-
function
|
|
5079
|
-
const
|
|
5080
|
-
|
|
5081
|
-
|
|
6413
|
+
function render2(obj, options = {}) {
|
|
6414
|
+
const scoped = options.scoped ?? options.encapsulate ?? false;
|
|
6415
|
+
const { scoped: _scoped, encapsulate: _encapsulate, hydratable: _hydratable, island: _island, ...rendererOptions } = options;
|
|
6416
|
+
let component = scoped ? renderScopedComponent(obj) : obj;
|
|
6417
|
+
if (typeof component === "function") {
|
|
6418
|
+
component = component(options);
|
|
6419
|
+
}
|
|
6420
|
+
if (_hydratable || _island) {
|
|
6421
|
+
component = injectHydrationAttributes(component, { hydratable: _hydratable, island: _island });
|
|
5082
6422
|
}
|
|
5083
|
-
return
|
|
6423
|
+
return render(component, rendererOptions);
|
|
5084
6424
|
}
|
|
5085
6425
|
function renderScopedComponent(component) {
|
|
5086
6426
|
const scopeId = generateScopeId();
|
|
@@ -5112,7 +6452,7 @@ function renderScopedComponent(component) {
|
|
|
5112
6452
|
}
|
|
5113
6453
|
const processedComponent = processScopedElement(component);
|
|
5114
6454
|
const scopedComponent = applyScopeToElement(processedComponent, scopeId);
|
|
5115
|
-
return
|
|
6455
|
+
return scopedComponent;
|
|
5116
6456
|
}
|
|
5117
6457
|
var memoCache = /* @__PURE__ */ new Map();
|
|
5118
6458
|
function memo2(component, keyGenerator) {
|
|
@@ -5136,7 +6476,7 @@ function validateComponent2(obj) {
|
|
|
5136
6476
|
}
|
|
5137
6477
|
return true;
|
|
5138
6478
|
}
|
|
5139
|
-
function
|
|
6479
|
+
function isCoherentObject2(obj) {
|
|
5140
6480
|
return obj && typeof obj === "object" && !Array.isArray(obj);
|
|
5141
6481
|
}
|
|
5142
6482
|
function deepClone2(obj) {
|
|
@@ -5149,10 +6489,21 @@ function deepClone2(obj) {
|
|
|
5149
6489
|
}
|
|
5150
6490
|
return cloned;
|
|
5151
6491
|
}
|
|
5152
|
-
var
|
|
6492
|
+
var _corePackageJson = JSON.parse(
|
|
6493
|
+
(0, import_node_fs.readFileSync)(new URL("../package.json", import_meta.url), "utf-8")
|
|
6494
|
+
);
|
|
6495
|
+
var VERSION = _corePackageJson.version;
|
|
6496
|
+
var fp = {
|
|
6497
|
+
/**
|
|
6498
|
+
* Curried map: fp.map(fn)(array)
|
|
6499
|
+
*/
|
|
6500
|
+
map(fn) {
|
|
6501
|
+
return (array) => array.map(fn);
|
|
6502
|
+
}
|
|
6503
|
+
};
|
|
5153
6504
|
var coherent = {
|
|
5154
6505
|
// Core rendering
|
|
5155
|
-
render,
|
|
6506
|
+
render: render2,
|
|
5156
6507
|
// Shadow DOM (client-side only)
|
|
5157
6508
|
shadowDOM: shadow_dom_exports,
|
|
5158
6509
|
// Component system
|
|
@@ -5204,9 +6555,9 @@ var coherent = {
|
|
|
5204
6555
|
withEventState,
|
|
5205
6556
|
// Utilities
|
|
5206
6557
|
validateComponent: validateComponent2,
|
|
5207
|
-
isCoherentObject,
|
|
6558
|
+
isCoherentObject: isCoherentObject2,
|
|
5208
6559
|
deepClone: deepClone2,
|
|
5209
|
-
escapeHtml,
|
|
6560
|
+
escapeHtml: escapeHtml2,
|
|
5210
6561
|
performanceMonitor,
|
|
5211
6562
|
VERSION
|
|
5212
6563
|
};
|
|
@@ -5217,9 +6568,14 @@ var index_default = coherent;
|
|
|
5217
6568
|
ComponentLifecycle,
|
|
5218
6569
|
DOMEventIntegration,
|
|
5219
6570
|
EventBus,
|
|
6571
|
+
FORBIDDEN_CHILDREN,
|
|
5220
6572
|
GlobalErrorHandler,
|
|
6573
|
+
HTMLNestingError,
|
|
6574
|
+
Island,
|
|
5221
6575
|
LIFECYCLE_PHASES,
|
|
5222
6576
|
VERSION,
|
|
6577
|
+
checkPeerDependencies,
|
|
6578
|
+
compose,
|
|
5223
6579
|
createActionHandlers,
|
|
5224
6580
|
createAsyncErrorBoundary,
|
|
5225
6581
|
createComponent,
|
|
@@ -5227,10 +6583,12 @@ var index_default = coherent;
|
|
|
5227
6583
|
createElement,
|
|
5228
6584
|
createErrorBoundary,
|
|
5229
6585
|
createErrorFallback,
|
|
6586
|
+
createErrorResponse,
|
|
5230
6587
|
createEventBus,
|
|
5231
6588
|
createEventComponent,
|
|
5232
6589
|
createEventHandlers,
|
|
5233
6590
|
createGlobalErrorHandler,
|
|
6591
|
+
createLazyIntegration,
|
|
5234
6592
|
createLifecycleHooks,
|
|
5235
6593
|
createStateManager,
|
|
5236
6594
|
createTextNode,
|
|
@@ -5241,19 +6599,26 @@ var index_default = coherent;
|
|
|
5241
6599
|
emitSync,
|
|
5242
6600
|
evaluateLazy,
|
|
5243
6601
|
eventSystem,
|
|
6602
|
+
fp,
|
|
5244
6603
|
getComponent,
|
|
5245
6604
|
getRegisteredComponents,
|
|
5246
6605
|
globalDOMIntegration,
|
|
5247
6606
|
globalEventBus,
|
|
5248
6607
|
h,
|
|
5249
6608
|
handleAction,
|
|
6609
|
+
hasChildren,
|
|
6610
|
+
hoc,
|
|
6611
|
+
importPeerDependency,
|
|
5250
6612
|
initializeDOMIntegration,
|
|
6613
|
+
isCoherentComponent,
|
|
5251
6614
|
isCoherentObject,
|
|
5252
6615
|
isLazy,
|
|
6616
|
+
isPeerDependencyAvailable,
|
|
5253
6617
|
lazy,
|
|
5254
6618
|
lifecycleUtils,
|
|
5255
6619
|
memo,
|
|
5256
6620
|
memoize,
|
|
6621
|
+
normalizeChildren,
|
|
5257
6622
|
off,
|
|
5258
6623
|
on,
|
|
5259
6624
|
once,
|
|
@@ -5261,9 +6626,13 @@ var index_default = coherent;
|
|
|
5261
6626
|
registerAction,
|
|
5262
6627
|
registerComponent,
|
|
5263
6628
|
render,
|
|
6629
|
+
renderComponentFactory,
|
|
6630
|
+
renderWithMonitoring,
|
|
6631
|
+
renderWithTemplate,
|
|
5264
6632
|
shadowDOM,
|
|
5265
6633
|
useHooks,
|
|
5266
6634
|
validateComponent,
|
|
6635
|
+
validateNesting,
|
|
5267
6636
|
withErrorBoundary,
|
|
5268
6637
|
withEventBus,
|
|
5269
6638
|
withEventState,
|
|
@@ -5271,11 +6640,17 @@ var index_default = coherent;
|
|
|
5271
6640
|
withState,
|
|
5272
6641
|
withStateUtils
|
|
5273
6642
|
});
|
|
6643
|
+
/**
|
|
6644
|
+
* Advanced caching system with memory management and smart invalidation for Coherent.js
|
|
6645
|
+
*
|
|
6646
|
+
* @module @coherent/performance/cache-manager
|
|
6647
|
+
* @license MIT
|
|
6648
|
+
*/
|
|
5274
6649
|
/**
|
|
5275
6650
|
* Coherent.js - Object-Based Rendering Framework
|
|
5276
6651
|
* A pure JavaScript framework for server-side rendering using natural object syntax
|
|
5277
6652
|
*
|
|
5278
|
-
* @version
|
|
6653
|
+
* @version 1.0.0-beta.7
|
|
5279
6654
|
* @author Coherent Framework Team
|
|
5280
6655
|
* @license MIT
|
|
5281
6656
|
*/
|