@blac/core 2.0.0-rc-16 → 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.
- package/dist/.tsbuildinfo +1 -0
- package/dist/Blac.d.ts +246 -0
- package/dist/Blac.d.ts.map +1 -0
- package/dist/Blac.js +625 -0
- package/dist/Blac.js.map +1 -0
- package/dist/Bloc.d.ts +41 -0
- package/dist/Bloc.d.ts.map +1 -0
- package/dist/Bloc.js +140 -0
- package/dist/Bloc.js.map +1 -0
- package/dist/BlocBase.d.ts +110 -0
- package/dist/BlocBase.d.ts.map +1 -0
- package/dist/BlocBase.js +287 -0
- package/dist/BlocBase.js.map +1 -0
- package/dist/Cubit.d.ts +25 -0
- package/dist/Cubit.d.ts.map +1 -0
- package/dist/Cubit.js +64 -0
- package/dist/Cubit.js.map +1 -0
- package/dist/adapter/BlacAdapter.d.ts +71 -0
- package/dist/adapter/BlacAdapter.d.ts.map +1 -0
- package/dist/adapter/BlacAdapter.js +373 -0
- package/dist/adapter/BlacAdapter.js.map +1 -0
- package/dist/adapter/ProxyFactory.d.ts +50 -0
- package/dist/adapter/ProxyFactory.d.ts.map +1 -0
- package/dist/adapter/ProxyFactory.js +150 -0
- package/dist/adapter/ProxyFactory.js.map +1 -0
- package/{src/adapter/index.ts → dist/adapter/index.d.ts} +1 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +19 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/errors/BlacError.d.ts +38 -0
- package/dist/errors/BlacError.d.ts.map +1 -0
- package/dist/errors/BlacError.js +55 -0
- package/dist/errors/BlacError.js.map +1 -0
- package/dist/errors/ErrorManager.d.ts +39 -0
- package/dist/errors/ErrorManager.d.ts.map +1 -0
- package/dist/errors/ErrorManager.js +91 -0
- package/dist/errors/ErrorManager.js.map +1 -0
- package/dist/errors/handleError.d.ts +24 -0
- package/dist/errors/handleError.d.ts.map +1 -0
- package/dist/errors/handleError.js +62 -0
- package/dist/errors/handleError.js.map +1 -0
- package/dist/errors/index.d.ts +5 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +13 -0
- package/dist/errors/index.js.map +1 -0
- package/{src/events.ts → dist/events.d.ts} +4 -2
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +17 -0
- package/dist/events.js.map +1 -0
- package/dist/index.cjs +38 -0
- package/{src/index.ts → dist/index.d.ts} +1 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/BlocLifecycle.d.ts +51 -0
- package/dist/lifecycle/BlocLifecycle.d.ts.map +1 -0
- package/dist/lifecycle/BlocLifecycle.js +123 -0
- package/dist/lifecycle/BlocLifecycle.js.map +1 -0
- package/dist/lifecycle/index.d.ts +2 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +18 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/plugins/BlocPluginRegistry.d.ts +58 -0
- package/dist/plugins/BlocPluginRegistry.d.ts.map +1 -0
- package/dist/plugins/BlocPluginRegistry.js +201 -0
- package/dist/plugins/BlocPluginRegistry.js.map +1 -0
- package/dist/plugins/SystemPluginRegistry.d.ts +79 -0
- package/dist/plugins/SystemPluginRegistry.d.ts.map +1 -0
- package/dist/plugins/SystemPluginRegistry.js +184 -0
- package/dist/plugins/SystemPluginRegistry.js.map +1 -0
- package/{src/plugins/index.ts → dist/plugins/index.d.ts} +1 -5
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +26 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +103 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +3 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/subscription/SubscriptionManager.d.ts +67 -0
- package/dist/subscription/SubscriptionManager.d.ts.map +1 -0
- package/dist/subscription/SubscriptionManager.js +317 -0
- package/dist/subscription/SubscriptionManager.js.map +1 -0
- package/{src/subscription/index.ts → dist/subscription/index.d.ts} +1 -0
- package/dist/subscription/index.d.ts.map +1 -0
- package/dist/subscription/index.js +19 -0
- package/dist/subscription/index.js.map +1 -0
- package/dist/subscription/types.d.ts +65 -0
- package/dist/subscription/types.d.ts.map +1 -0
- package/dist/subscription/types.js +3 -0
- package/dist/subscription/types.js.map +1 -0
- package/dist/testing.d.ts +85 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +186 -0
- package/dist/testing.js.map +1 -0
- package/{src/types.ts → dist/types.d.ts} +11 -28
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/BatchingManager.d.ts +28 -0
- package/dist/utils/BatchingManager.d.ts.map +1 -0
- package/dist/utils/BatchingManager.js +48 -0
- package/dist/utils/BatchingManager.js.map +1 -0
- package/dist/utils/RerenderLogger.d.ts +60 -0
- package/dist/utils/RerenderLogger.d.ts.map +1 -0
- package/dist/utils/RerenderLogger.js +205 -0
- package/dist/utils/RerenderLogger.js.map +1 -0
- package/dist/utils/generateInstanceId.d.ts +11 -0
- package/dist/utils/generateInstanceId.d.ts.map +1 -0
- package/dist/utils/generateInstanceId.js +50 -0
- package/dist/utils/generateInstanceId.js.map +1 -0
- package/dist/utils/shallowEqual.d.ts +9 -0
- package/dist/utils/shallowEqual.d.ts.map +1 -0
- package/dist/utils/shallowEqual.js +35 -0
- package/dist/utils/shallowEqual.js.map +1 -0
- package/dist/utils/uuid.d.ts +10 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +24 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +17 -6
- package/src/Blac.ts +0 -802
- package/src/Bloc.ts +0 -180
- package/src/BlocBase.ts +0 -398
- package/src/Cubit.ts +0 -68
- package/src/__tests__/Blac.config.test.ts +0 -79
- package/src/__tests__/Bloc.event.test.ts +0 -394
- package/src/__tests__/BlocBase.subscription.test.ts +0 -349
- package/src/__tests__/Cubit.test.ts +0 -462
- package/src/__tests__/memory-leaks.test.ts +0 -383
- package/src/__tests__/plugins.test.ts +0 -464
- package/src/adapter/BlacAdapter.ts +0 -467
- package/src/adapter/ProxyFactory.ts +0 -249
- package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
- package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
- package/src/errors/BlacError.ts +0 -69
- package/src/errors/ErrorManager.ts +0 -101
- package/src/errors/handleError.ts +0 -114
- package/src/errors/index.ts +0 -13
- package/src/lifecycle/BlocLifecycle.ts +0 -156
- package/src/lifecycle/index.ts +0 -1
- package/src/plugins/BlocPluginRegistry.ts +0 -240
- package/src/plugins/SystemPluginRegistry.ts +0 -242
- package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
- package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
- package/src/plugins/types.ts +0 -129
- package/src/subscription/README.md +0 -132
- package/src/subscription/SubscriptionManager.ts +0 -395
- package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
- package/src/subscription/types.ts +0 -90
- package/src/testing.ts +0 -246
- package/src/utils/BatchingManager.ts +0 -59
- package/src/utils/RerenderLogger.ts +0 -265
- package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
- package/src/utils/__tests__/shallowEqual.test.ts +0 -171
- package/src/utils/__tests__/uuid.test.ts +0 -144
- package/src/utils/generateInstanceId.ts +0 -54
- package/src/utils/shallowEqual.ts +0 -40
- 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
|
-
};
|
package/src/errors/index.ts
DELETED
|
@@ -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';
|
|
@@ -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
|
-
}
|
package/src/lifecycle/index.ts
DELETED
|
@@ -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
|
-
}
|