@blac/core 2.0.0-rc-14 → 2.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/Blac.d.ts +246 -0
  3. package/dist/Blac.d.ts.map +1 -0
  4. package/dist/Blac.js +625 -0
  5. package/dist/Blac.js.map +1 -0
  6. package/dist/Bloc.d.ts +41 -0
  7. package/dist/Bloc.d.ts.map +1 -0
  8. package/dist/Bloc.js +140 -0
  9. package/dist/Bloc.js.map +1 -0
  10. package/dist/BlocBase.d.ts +110 -0
  11. package/dist/BlocBase.d.ts.map +1 -0
  12. package/dist/BlocBase.js +287 -0
  13. package/dist/BlocBase.js.map +1 -0
  14. package/dist/Cubit.d.ts +25 -0
  15. package/dist/Cubit.d.ts.map +1 -0
  16. package/dist/Cubit.js +64 -0
  17. package/dist/Cubit.js.map +1 -0
  18. package/dist/adapter/BlacAdapter.d.ts +71 -0
  19. package/dist/adapter/BlacAdapter.d.ts.map +1 -0
  20. package/dist/adapter/BlacAdapter.js +373 -0
  21. package/dist/adapter/BlacAdapter.js.map +1 -0
  22. package/dist/adapter/ProxyFactory.d.ts +50 -0
  23. package/dist/adapter/ProxyFactory.d.ts.map +1 -0
  24. package/dist/adapter/ProxyFactory.js +150 -0
  25. package/dist/adapter/ProxyFactory.js.map +1 -0
  26. package/{src/adapter/index.ts → dist/adapter/index.d.ts} +1 -0
  27. package/dist/adapter/index.d.ts.map +1 -0
  28. package/dist/adapter/index.js +19 -0
  29. package/dist/adapter/index.js.map +1 -0
  30. package/dist/errors/BlacError.d.ts +38 -0
  31. package/dist/errors/BlacError.d.ts.map +1 -0
  32. package/dist/errors/BlacError.js +55 -0
  33. package/dist/errors/BlacError.js.map +1 -0
  34. package/dist/errors/ErrorManager.d.ts +39 -0
  35. package/dist/errors/ErrorManager.d.ts.map +1 -0
  36. package/dist/errors/ErrorManager.js +91 -0
  37. package/dist/errors/ErrorManager.js.map +1 -0
  38. package/dist/errors/handleError.d.ts +24 -0
  39. package/dist/errors/handleError.d.ts.map +1 -0
  40. package/dist/errors/handleError.js +62 -0
  41. package/dist/errors/handleError.js.map +1 -0
  42. package/dist/errors/index.d.ts +5 -0
  43. package/dist/errors/index.d.ts.map +1 -0
  44. package/dist/errors/index.js +13 -0
  45. package/dist/errors/index.js.map +1 -0
  46. package/{src/events.ts → dist/events.d.ts} +4 -2
  47. package/dist/events.d.ts.map +1 -0
  48. package/dist/events.js +17 -0
  49. package/dist/events.js.map +1 -0
  50. package/dist/index.cjs +38 -0
  51. package/dist/index.d.ts +17 -1303
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +38 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/lifecycle/BlocLifecycle.d.ts +51 -0
  56. package/dist/lifecycle/BlocLifecycle.d.ts.map +1 -0
  57. package/dist/lifecycle/BlocLifecycle.js +123 -0
  58. package/dist/lifecycle/BlocLifecycle.js.map +1 -0
  59. package/dist/lifecycle/index.d.ts +2 -0
  60. package/dist/lifecycle/index.d.ts.map +1 -0
  61. package/dist/lifecycle/index.js +18 -0
  62. package/dist/lifecycle/index.js.map +1 -0
  63. package/dist/plugins/BlocPluginRegistry.d.ts +58 -0
  64. package/dist/plugins/BlocPluginRegistry.d.ts.map +1 -0
  65. package/dist/plugins/BlocPluginRegistry.js +201 -0
  66. package/dist/plugins/BlocPluginRegistry.js.map +1 -0
  67. package/dist/plugins/SystemPluginRegistry.d.ts +79 -0
  68. package/dist/plugins/SystemPluginRegistry.d.ts.map +1 -0
  69. package/dist/plugins/SystemPluginRegistry.js +184 -0
  70. package/dist/plugins/SystemPluginRegistry.js.map +1 -0
  71. package/{src/plugins/index.ts → dist/plugins/index.d.ts} +1 -5
  72. package/dist/plugins/index.d.ts.map +1 -0
  73. package/dist/plugins/index.js +26 -0
  74. package/dist/plugins/index.js.map +1 -0
  75. package/dist/plugins/types.d.ts +103 -0
  76. package/dist/plugins/types.d.ts.map +1 -0
  77. package/dist/plugins/types.js +3 -0
  78. package/dist/plugins/types.js.map +1 -0
  79. package/dist/subscription/SubscriptionManager.d.ts +67 -0
  80. package/dist/subscription/SubscriptionManager.d.ts.map +1 -0
  81. package/dist/subscription/SubscriptionManager.js +317 -0
  82. package/dist/subscription/SubscriptionManager.js.map +1 -0
  83. package/{src/subscription/index.ts → dist/subscription/index.d.ts} +1 -0
  84. package/dist/subscription/index.d.ts.map +1 -0
  85. package/dist/subscription/index.js +19 -0
  86. package/dist/subscription/index.js.map +1 -0
  87. package/dist/subscription/types.d.ts +65 -0
  88. package/dist/subscription/types.d.ts.map +1 -0
  89. package/dist/subscription/types.js +3 -0
  90. package/dist/subscription/types.js.map +1 -0
  91. package/dist/testing.d.ts +85 -0
  92. package/dist/testing.d.ts.map +1 -0
  93. package/dist/testing.js +186 -0
  94. package/dist/testing.js.map +1 -0
  95. package/{src/types.ts → dist/types.d.ts} +11 -28
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +3 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/utils/BatchingManager.d.ts +28 -0
  100. package/dist/utils/BatchingManager.d.ts.map +1 -0
  101. package/dist/utils/BatchingManager.js +48 -0
  102. package/dist/utils/BatchingManager.js.map +1 -0
  103. package/dist/utils/RerenderLogger.d.ts +60 -0
  104. package/dist/utils/RerenderLogger.d.ts.map +1 -0
  105. package/dist/utils/RerenderLogger.js +205 -0
  106. package/dist/utils/RerenderLogger.js.map +1 -0
  107. package/dist/utils/generateInstanceId.d.ts +11 -0
  108. package/dist/utils/generateInstanceId.d.ts.map +1 -0
  109. package/dist/utils/generateInstanceId.js +50 -0
  110. package/dist/utils/generateInstanceId.js.map +1 -0
  111. package/dist/utils/shallowEqual.d.ts +9 -0
  112. package/dist/utils/shallowEqual.d.ts.map +1 -0
  113. package/dist/utils/shallowEqual.js +35 -0
  114. package/dist/utils/shallowEqual.js.map +1 -0
  115. package/dist/utils/uuid.d.ts +10 -0
  116. package/dist/utils/uuid.d.ts.map +1 -0
  117. package/dist/utils/uuid.js +24 -0
  118. package/dist/utils/uuid.js.map +1 -0
  119. package/package.json +17 -10
  120. package/dist/index.cjs.js +0 -11
  121. package/dist/index.cjs.js.map +0 -1
  122. package/dist/index.es.js +0 -2275
  123. package/dist/index.es.js.map +0 -1
  124. package/src/Blac.ts +0 -802
  125. package/src/Bloc.ts +0 -180
  126. package/src/BlocBase.ts +0 -398
  127. package/src/Cubit.ts +0 -68
  128. package/src/__tests__/Blac.config.test.ts +0 -79
  129. package/src/__tests__/Bloc.event.test.ts +0 -394
  130. package/src/__tests__/BlocBase.subscription.test.ts +0 -349
  131. package/src/__tests__/Cubit.test.ts +0 -462
  132. package/src/__tests__/memory-leaks.test.ts +0 -383
  133. package/src/__tests__/plugins.test.ts +0 -464
  134. package/src/adapter/BlacAdapter.ts +0 -467
  135. package/src/adapter/ProxyFactory.ts +0 -249
  136. package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
  137. package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
  138. package/src/errors/BlacError.ts +0 -69
  139. package/src/errors/ErrorManager.ts +0 -101
  140. package/src/errors/handleError.ts +0 -114
  141. package/src/errors/index.ts +0 -13
  142. package/src/index.ts +0 -26
  143. package/src/lifecycle/BlocLifecycle.ts +0 -156
  144. package/src/lifecycle/index.ts +0 -1
  145. package/src/plugins/BlocPluginRegistry.ts +0 -240
  146. package/src/plugins/SystemPluginRegistry.ts +0 -242
  147. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
  148. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
  149. package/src/plugins/types.ts +0 -129
  150. package/src/subscription/README.md +0 -132
  151. package/src/subscription/SubscriptionManager.ts +0 -395
  152. package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
  153. package/src/subscription/types.ts +0 -90
  154. package/src/testing.ts +0 -246
  155. package/src/utils/BatchingManager.ts +0 -59
  156. package/src/utils/RerenderLogger.ts +0 -265
  157. package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
  158. package/src/utils/__tests__/shallowEqual.test.ts +0 -171
  159. package/src/utils/__tests__/uuid.test.ts +0 -144
  160. package/src/utils/generateInstanceId.ts +0 -54
  161. package/src/utils/shallowEqual.ts +0 -40
  162. package/src/utils/uuid.ts +0 -22
@@ -1,101 +0,0 @@
1
- import {
2
- BlacError,
3
- ErrorHandler,
4
- ErrorHandlingStrategy,
5
- DefaultErrorStrategy,
6
- } from './BlacError';
7
-
8
- /**
9
- * Centralized error management system for BlaC framework.
10
- * Handles error processing, logging, and propagation strategies.
11
- */
12
- export class ErrorManager {
13
- private static instance: ErrorManager;
14
- private handlers: Set<ErrorHandler> = new Set();
15
- private strategy: ErrorHandlingStrategy = DefaultErrorStrategy;
16
-
17
- /**
18
- * Get the singleton instance of ErrorManager
19
- */
20
- static getInstance(): ErrorManager {
21
- if (!ErrorManager.instance) {
22
- ErrorManager.instance = new ErrorManager();
23
- }
24
- return ErrorManager.instance;
25
- }
26
-
27
- /**
28
- * Set a custom error handling strategy
29
- */
30
- setStrategy(strategy: ErrorHandlingStrategy): void {
31
- this.strategy = strategy;
32
- }
33
-
34
- /**
35
- * Add a custom error handler that will be called for all errors
36
- */
37
- addHandler(handler: ErrorHandler): void {
38
- this.handlers.add(handler);
39
- }
40
-
41
- /**
42
- * Remove a previously added error handler
43
- */
44
- removeHandler(handler: ErrorHandler): void {
45
- this.handlers.delete(handler);
46
- }
47
-
48
- /**
49
- * Process an error through all handlers and apply the configured strategy
50
- */
51
- handle(error: BlacError): void {
52
- // Always notify handlers first
53
- this.handlers.forEach((handler) => {
54
- try {
55
- handler(error);
56
- } catch (handlerError) {
57
- // Prevent handler errors from breaking error handling
58
- console.error('Error in error handler:', handlerError);
59
- }
60
- });
61
-
62
- // Apply strategy
63
- this.strategy.handle(error);
64
-
65
- // Propagate if needed
66
- if (this.strategy.shouldPropagate(error)) {
67
- throw error;
68
- }
69
- }
70
-
71
- /**
72
- * Convenience method for wrapping operations with error handling
73
- */
74
- wrap<T>(operation: () => T, errorFactory: (error: unknown) => BlacError): T {
75
- try {
76
- return operation();
77
- } catch (error) {
78
- const blacError = errorFactory(error);
79
- this.handle(blacError);
80
- // Will only reach here if strategy says not to propagate
81
- return undefined as T;
82
- }
83
- }
84
-
85
- /**
86
- * Async version of wrap
87
- */
88
- async wrapAsync<T>(
89
- operation: () => Promise<T>,
90
- errorFactory: (error: unknown) => BlacError,
91
- ): Promise<T> {
92
- try {
93
- return await operation();
94
- } catch (error) {
95
- const blacError = errorFactory(error);
96
- this.handle(blacError);
97
- // Will only reach here if strategy says not to propagate
98
- return undefined as T;
99
- }
100
- }
101
- }
@@ -1,114 +0,0 @@
1
- import {
2
- BlacError,
3
- ErrorCategory,
4
- ErrorSeverity,
5
- BlacErrorContext,
6
- } from './BlacError';
7
- import { ErrorManager } from './ErrorManager';
8
-
9
- /**
10
- * Standard error handling helper for BlaC
11
- *
12
- * Usage:
13
- * - For fatal errors that should propagate: handleError.fatal(...)
14
- * - For recoverable errors: handleError.error(...)
15
- * - For warnings: handleError.warn(...)
16
- */
17
- export const handleError = {
18
- fatal: (
19
- message: string,
20
- category: ErrorCategory,
21
- context?: BlacErrorContext,
22
- cause?: unknown,
23
- ): never => {
24
- const error = new BlacError(
25
- message,
26
- category,
27
- ErrorSeverity.FATAL,
28
- context,
29
- cause,
30
- );
31
- ErrorManager.getInstance().handle(error);
32
- // This will always throw due to FATAL severity
33
- throw error;
34
- },
35
-
36
- error: (
37
- message: string,
38
- category: ErrorCategory,
39
- context?: BlacErrorContext,
40
- cause?: unknown,
41
- ): void => {
42
- const error = new BlacError(
43
- message,
44
- category,
45
- ErrorSeverity.ERROR,
46
- context,
47
- cause,
48
- );
49
- ErrorManager.getInstance().handle(error);
50
- },
51
-
52
- warn: (
53
- message: string,
54
- category: ErrorCategory,
55
- context?: BlacErrorContext,
56
- cause?: unknown,
57
- ): void => {
58
- const error = new BlacError(
59
- message,
60
- category,
61
- ErrorSeverity.WARNING,
62
- context,
63
- cause,
64
- );
65
- ErrorManager.getInstance().handle(error);
66
- },
67
-
68
- info: (
69
- message: string,
70
- category: ErrorCategory,
71
- context?: BlacErrorContext,
72
- ): void => {
73
- const error = new BlacError(message, category, ErrorSeverity.INFO, context);
74
- ErrorManager.getInstance().handle(error);
75
- },
76
-
77
- /**
78
- * Wraps a function to catch and handle errors
79
- */
80
- wrap: <T>(
81
- fn: () => T,
82
- category: ErrorCategory,
83
- context?: BlacErrorContext,
84
- severity: ErrorSeverity = ErrorSeverity.ERROR,
85
- ): T | undefined => {
86
- try {
87
- return fn();
88
- } catch (cause) {
89
- const message = cause instanceof Error ? cause.message : String(cause);
90
- const error = new BlacError(message, category, severity, context, cause);
91
- ErrorManager.getInstance().handle(error);
92
- return undefined;
93
- }
94
- },
95
-
96
- /**
97
- * Wraps an async function to catch and handle errors
98
- */
99
- wrapAsync: async <T>(
100
- fn: () => Promise<T>,
101
- category: ErrorCategory,
102
- context?: BlacErrorContext,
103
- severity: ErrorSeverity = ErrorSeverity.ERROR,
104
- ): Promise<T | undefined> => {
105
- try {
106
- return await fn();
107
- } catch (cause) {
108
- const message = cause instanceof Error ? cause.message : String(cause);
109
- const error = new BlacError(message, category, severity, context, cause);
110
- ErrorManager.getInstance().handle(error);
111
- return undefined;
112
- }
113
- },
114
- };
@@ -1,13 +0,0 @@
1
- export {
2
- BlacError,
3
- ErrorCategory,
4
- ErrorSeverity,
5
- DefaultErrorStrategy,
6
- } from './BlacError';
7
- export type {
8
- BlacErrorContext,
9
- ErrorHandler,
10
- ErrorHandlingStrategy,
11
- } from './BlacError';
12
- export { ErrorManager } from './ErrorManager';
13
- export { handleError } from './handleError';
package/src/index.ts DELETED
@@ -1,26 +0,0 @@
1
- export * from './Blac';
2
- export * from './Bloc';
3
- export * from './BlocBase';
4
- export * from './Cubit';
5
- export * from './types';
6
- export * from './events';
7
- export * from './subscription';
8
- export * from './lifecycle';
9
-
10
- // Utilities
11
- export * from './utils/uuid';
12
- export * from './utils/shallowEqual';
13
- export * from './utils/generateInstanceId';
14
- export * from './utils/RerenderLogger';
15
-
16
- // Test utilities
17
- export * from './testing';
18
-
19
- // Adapter
20
- export * from './adapter';
21
-
22
- // Plugins
23
- export * from './plugins';
24
-
25
- // Error handling
26
- export * from './errors';
@@ -1,156 +0,0 @@
1
- /**
2
- * Enum representing the lifecycle states of a Bloc instance
3
- */
4
- export enum BlocLifecycleState {
5
- ACTIVE = 'active',
6
- DISPOSAL_REQUESTED = 'disposal_requested',
7
- DISPOSING = 'disposing',
8
- DISPOSED = 'disposed',
9
- }
10
-
11
- export interface StateTransitionResult {
12
- success: boolean;
13
- currentState: BlocLifecycleState;
14
- previousState: BlocLifecycleState;
15
- }
16
-
17
- /**
18
- * Manages the lifecycle state transitions for Bloc instances.
19
- * Ensures atomic state transitions to prevent race conditions during disposal.
20
- */
21
- export class BlocLifecycleManager {
22
- private disposalState = BlocLifecycleState.ACTIVE;
23
- private disposalLock = false;
24
- private disposalTimer?: NodeJS.Timeout | number;
25
- private disposalHandler?: (bloc: unknown) => void;
26
-
27
- get currentState(): BlocLifecycleState {
28
- return this.disposalState;
29
- }
30
-
31
- get isDisposed(): boolean {
32
- return this.disposalState === BlocLifecycleState.DISPOSED;
33
- }
34
-
35
- /**
36
- * Atomic state transition for disposal
37
- */
38
- atomicStateTransition(
39
- expectedState: BlocLifecycleState,
40
- newState: BlocLifecycleState,
41
- ): StateTransitionResult {
42
- if (this.disposalLock) {
43
- return {
44
- success: false,
45
- currentState: this.disposalState,
46
- previousState: this.disposalState,
47
- };
48
- }
49
-
50
- this.disposalLock = true;
51
- try {
52
- if (this.disposalState !== expectedState) {
53
- return {
54
- success: false,
55
- currentState: this.disposalState,
56
- previousState: this.disposalState,
57
- };
58
- }
59
-
60
- const previousState = this.disposalState;
61
- this.disposalState = newState;
62
-
63
- return {
64
- success: true,
65
- currentState: newState,
66
- previousState,
67
- };
68
- } finally {
69
- this.disposalLock = false;
70
- }
71
- }
72
-
73
- /**
74
- * Schedule disposal after a delay
75
- */
76
- scheduleDisposal(
77
- delay: number,
78
- canDispose: () => boolean,
79
- onDispose: () => void,
80
- ): void {
81
- // Cancel any existing disposal timer
82
- if (this.disposalTimer) {
83
- clearTimeout(this.disposalTimer as NodeJS.Timeout);
84
- this.disposalTimer = undefined;
85
- }
86
-
87
- const transitionResult = this.atomicStateTransition(
88
- BlocLifecycleState.ACTIVE,
89
- BlocLifecycleState.DISPOSAL_REQUESTED,
90
- );
91
-
92
- if (!transitionResult.success) {
93
- return;
94
- }
95
-
96
- this.disposalTimer = setTimeout(() => {
97
- if (
98
- canDispose() &&
99
- this.disposalState === BlocLifecycleState.DISPOSAL_REQUESTED
100
- ) {
101
- onDispose();
102
- } else {
103
- this.atomicStateTransition(
104
- BlocLifecycleState.DISPOSAL_REQUESTED,
105
- BlocLifecycleState.ACTIVE,
106
- );
107
- }
108
- }, delay);
109
- }
110
-
111
- /**
112
- * Cancel disposal if in disposal requested state
113
- */
114
- cancelDisposal(): boolean {
115
- if (this.disposalState === BlocLifecycleState.DISPOSAL_REQUESTED) {
116
- // Cancel disposal timer
117
- if (this.disposalTimer) {
118
- clearTimeout(this.disposalTimer as NodeJS.Timeout);
119
- this.disposalTimer = undefined;
120
- }
121
-
122
- // Transition back to active state
123
- const result = this.atomicStateTransition(
124
- BlocLifecycleState.DISPOSAL_REQUESTED,
125
- BlocLifecycleState.ACTIVE,
126
- );
127
-
128
- return result.success;
129
- }
130
- return false;
131
- }
132
-
133
- /**
134
- * Set disposal handler
135
- */
136
- setDisposalHandler(handler: (bloc: unknown) => void): void {
137
- this.disposalHandler = handler;
138
- }
139
-
140
- /**
141
- * Get disposal handler
142
- */
143
- getDisposalHandler(): ((bloc: unknown) => void) | undefined {
144
- return this.disposalHandler;
145
- }
146
-
147
- /**
148
- * Clear disposal timer
149
- */
150
- clearDisposalTimer(): void {
151
- if (this.disposalTimer) {
152
- clearTimeout(this.disposalTimer as NodeJS.Timeout);
153
- this.disposalTimer = undefined;
154
- }
155
- }
156
- }
@@ -1 +0,0 @@
1
- export * from './BlocLifecycle';
@@ -1,240 +0,0 @@
1
- import { BlocPlugin, PluginRegistry, ErrorContext } from './types';
2
- import { handleError } from '../errors/handleError';
3
- import { ErrorCategory } from '../errors/BlacError';
4
-
5
- /**
6
- * Registry for bloc-specific plugins
7
- */
8
- export class BlocPluginRegistry<TState, TEvent = never>
9
- implements PluginRegistry<BlocPlugin<TState, TEvent>>
10
- {
11
- private plugins = new Map<string, BlocPlugin<TState, TEvent>>();
12
- private executionOrder: string[] = [];
13
- private attached = false;
14
-
15
- /**
16
- * Add a bloc plugin
17
- */
18
- add(plugin: BlocPlugin<TState, TEvent>): void {
19
- if (this.plugins.has(plugin.name)) {
20
- throw new Error(`Plugin '${plugin.name}' is already registered`);
21
- }
22
-
23
- // Validate capabilities
24
- if (plugin.capabilities) {
25
- this.validateCapabilities(plugin);
26
- }
27
-
28
- this.plugins.set(plugin.name, plugin);
29
- this.executionOrder.push(plugin.name);
30
- }
31
-
32
- /**
33
- * Remove a bloc plugin
34
- */
35
- remove(pluginName: string): boolean {
36
- const plugin = this.plugins.get(pluginName);
37
- if (!plugin) return false;
38
-
39
- // Call onDetach if attached
40
- if (this.attached && plugin.onDetach) {
41
- handleError.wrap(() => plugin.onDetach!(), ErrorCategory.PLUGIN, {
42
- pluginName,
43
- operation: 'onDetach',
44
- });
45
- }
46
-
47
- this.plugins.delete(pluginName);
48
- this.executionOrder = this.executionOrder.filter(
49
- (name) => name !== pluginName,
50
- );
51
-
52
- return true;
53
- }
54
-
55
- /**
56
- * Get a plugin by name
57
- */
58
- get(pluginName: string): BlocPlugin<TState, TEvent> | undefined {
59
- return this.plugins.get(pluginName);
60
- }
61
-
62
- /**
63
- * Get all plugins in execution order
64
- */
65
- getAll(): ReadonlyArray<BlocPlugin<TState, TEvent>> {
66
- return this.executionOrder.map((name) => this.plugins.get(name)!);
67
- }
68
-
69
- /**
70
- * Clear all plugins
71
- */
72
- clear(): void {
73
- // Detach all plugins first
74
- if (this.attached) {
75
- for (const plugin of this.getAll()) {
76
- if (plugin.onDetach) {
77
- handleError.wrap(() => plugin.onDetach!(), ErrorCategory.PLUGIN, {
78
- pluginName: plugin.name,
79
- operation: 'onDetach',
80
- });
81
- }
82
- }
83
- }
84
-
85
- this.plugins.clear();
86
- this.executionOrder = [];
87
- this.attached = false;
88
- }
89
-
90
- /**
91
- * Attach all plugins to a bloc
92
- */
93
- attach(bloc: any): void {
94
- if (this.attached) {
95
- throw new Error('Plugins are already attached');
96
- }
97
-
98
- for (const plugin of this.getAll()) {
99
- if (plugin.onAttach) {
100
- try {
101
- plugin.onAttach(bloc);
102
- } catch (error) {
103
- console.error(`Plugin '${plugin.name}' error in onAttach:`, error);
104
- // Remove failing plugin
105
- this.remove(plugin.name);
106
- }
107
- }
108
- }
109
-
110
- this.attached = true;
111
- }
112
-
113
- /**
114
- * Transform state through all plugins
115
- */
116
- transformState(previousState: TState, nextState: TState): TState {
117
- let transformedState = nextState;
118
-
119
- for (const plugin of this.getAll()) {
120
- if (plugin.transformState && this.canTransformState(plugin)) {
121
- try {
122
- transformedState = plugin.transformState(
123
- previousState,
124
- transformedState,
125
- );
126
- } catch (error) {
127
- console.error(
128
- `Plugin '${plugin.name}' error in transformState:`,
129
- error,
130
- );
131
- // Continue with untransformed state
132
- }
133
- }
134
- }
135
-
136
- return transformedState;
137
- }
138
-
139
- /**
140
- * Transform event through all plugins
141
- */
142
- transformEvent(event: TEvent): TEvent | null {
143
- let transformedEvent: TEvent | null = event;
144
-
145
- for (const plugin of this.getAll()) {
146
- if (transformedEvent === null) break;
147
-
148
- if (plugin.transformEvent && this.canInterceptEvents(plugin)) {
149
- try {
150
- transformedEvent = plugin.transformEvent(transformedEvent);
151
- } catch (error) {
152
- console.error(
153
- `Plugin '${plugin.name}' error in transformEvent:`,
154
- error,
155
- );
156
- // Continue with untransformed event
157
- }
158
- }
159
- }
160
-
161
- return transformedEvent;
162
- }
163
-
164
- /**
165
- * Notify plugins of state change
166
- */
167
- notifyStateChange(previousState: TState, currentState: TState): void {
168
- for (const plugin of this.getAll()) {
169
- if (plugin.onStateChange && this.canReadState(plugin)) {
170
- try {
171
- plugin.onStateChange(previousState, currentState);
172
- } catch (error) {
173
- console.error(
174
- `Plugin '${plugin.name}' error in onStateChange:`,
175
- error,
176
- );
177
- }
178
- }
179
- }
180
- }
181
-
182
- /**
183
- * Notify plugins of event
184
- */
185
- notifyEvent(event: TEvent): void {
186
- for (const plugin of this.getAll()) {
187
- if (plugin.onEvent && this.canReadState(plugin)) {
188
- try {
189
- plugin.onEvent(event);
190
- } catch (error) {
191
- console.error(`Plugin '${plugin.name}' error in onEvent:`, error);
192
- }
193
- }
194
- }
195
- }
196
-
197
- /**
198
- * Notify plugins of error
199
- */
200
- notifyError(error: Error, context: ErrorContext): void {
201
- for (const plugin of this.getAll()) {
202
- if (plugin.onError) {
203
- try {
204
- plugin.onError(error, context);
205
- } catch (hookError) {
206
- console.error(`Plugin '${plugin.name}' error in onError:`, hookError);
207
- }
208
- }
209
- }
210
- }
211
-
212
- private validateCapabilities(plugin: BlocPlugin<TState, TEvent>): void {
213
- const caps = plugin.capabilities!;
214
-
215
- // Validate logical constraints
216
- if (caps.transformState && !caps.readState) {
217
- throw new Error(
218
- `Plugin '${plugin.name}': transformState requires readState capability`,
219
- );
220
- }
221
-
222
- if (caps.interceptEvents && !caps.readState) {
223
- throw new Error(
224
- `Plugin '${plugin.name}': interceptEvents requires readState capability`,
225
- );
226
- }
227
- }
228
-
229
- private canReadState(plugin: BlocPlugin<TState, TEvent>): boolean {
230
- return !plugin.capabilities || plugin.capabilities.readState !== false;
231
- }
232
-
233
- private canTransformState(plugin: BlocPlugin<TState, TEvent>): boolean {
234
- return !plugin.capabilities || plugin.capabilities.transformState === true;
235
- }
236
-
237
- private canInterceptEvents(plugin: BlocPlugin<TState, TEvent>): boolean {
238
- return !plugin.capabilities || plugin.capabilities.interceptEvents === true;
239
- }
240
- }