@blac/core 2.0.0-rn-12 → 2.0.1

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/src/testing.ts DELETED
@@ -1,252 +0,0 @@
1
- import { Blac } from './Blac';
2
- import { Bloc } from './Bloc';
3
- import { BlocBase } from './BlocBase';
4
- import { Cubit } from './Cubit';
5
- import { BlocEventConstraint } from './types';
6
-
7
- /**
8
- * Test utilities for Blac state management
9
- */
10
- export class BlocTest {
11
- private static originalInstance: Blac;
12
-
13
- /**
14
- * Sets up a clean test environment
15
- */
16
- static setUp(): void {
17
- this.originalInstance = Blac.instance;
18
- Blac.resetInstance();
19
- Blac.enableLog = false; // Disable logging in tests by default
20
- }
21
-
22
- /**
23
- * Tears down the test environment and restores original state
24
- */
25
- static tearDown(): void {
26
- Blac.resetInstance();
27
- // Note: Cannot restore original instance due to singleton pattern
28
- // Tests should use setUp/tearDown properly to manage state
29
- }
30
-
31
- /**
32
- * Creates a test bloc with automatic cleanup
33
- */
34
- static createBloc<T extends BlocBase<any>>(
35
- BlocClass: new (...args: any[]) => T,
36
- ...args: any[]
37
- ): T {
38
- const bloc = new BlocClass(...args);
39
- Blac.activateBloc(bloc);
40
- return bloc;
41
- }
42
-
43
- /**
44
- * Waits for a bloc to emit a specific state
45
- */
46
- static async waitForState<T extends BlocBase<S>, S>(
47
- bloc: T,
48
- predicate: (state: S) => boolean,
49
- timeout = 5000,
50
- ): Promise<S> {
51
- return new Promise<S>((resolve, reject) => {
52
- const timeoutId = setTimeout(() => {
53
- reject(
54
- new Error(
55
- `Timeout waiting for state matching predicate after ${timeout}ms`,
56
- ),
57
- );
58
- }, timeout);
59
-
60
- const unsubscribe = bloc._observer.subscribe({
61
- id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
62
- fn: (newState: S) => {
63
- if (predicate(newState)) {
64
- clearTimeout(timeoutId);
65
- unsubscribe();
66
- resolve(newState);
67
- }
68
- },
69
- });
70
-
71
- // Check current state immediately
72
- if (predicate(bloc.state)) {
73
- clearTimeout(timeoutId);
74
- unsubscribe();
75
- resolve(bloc.state);
76
- }
77
- });
78
- }
79
-
80
- /**
81
- * Expects a bloc to emit specific states in order
82
- */
83
- static async expectStates<T extends BlocBase<S>, S>(
84
- bloc: T,
85
- expectedStates: S[],
86
- timeout = 5000,
87
- ): Promise<void> {
88
- const receivedStates: S[] = [];
89
-
90
- return new Promise<void>((resolve, reject) => {
91
- const timeoutId = setTimeout(() => {
92
- reject(
93
- new Error(
94
- `Timeout waiting for states. Expected: ${JSON.stringify(expectedStates)}, ` +
95
- `Received: ${JSON.stringify(receivedStates)}`,
96
- ),
97
- );
98
- }, timeout);
99
-
100
- const unsubscribe = bloc._observer.subscribe({
101
- id: `test-expecter-${crypto.randomUUID()}`,
102
- fn: (newState: S) => {
103
- receivedStates.push(newState);
104
-
105
- // Check if we have all expected states
106
- if (receivedStates.length === expectedStates.length) {
107
- clearTimeout(timeoutId);
108
- unsubscribe();
109
-
110
- // Verify all states match using deep equality
111
- for (let i = 0; i < expectedStates.length; i++) {
112
- const expected = expectedStates[i];
113
- const received = receivedStates[i];
114
-
115
- // Use JSON comparison for deep equality
116
- if (JSON.stringify(expected) !== JSON.stringify(received)) {
117
- reject(
118
- new Error(
119
- `State mismatch at index ${i}. Expected: ${JSON.stringify(expected)}, ` +
120
- `Received: ${JSON.stringify(received)}`,
121
- ),
122
- );
123
- return;
124
- }
125
- }
126
-
127
- resolve();
128
- }
129
- },
130
- });
131
- });
132
- }
133
- }
134
-
135
- /**
136
- * Mock Bloc for testing
137
- */
138
- export class MockBloc<
139
- S,
140
- A extends BlocEventConstraint = BlocEventConstraint,
141
- > extends Bloc<S, A> {
142
- private mockHandlers = new Map<
143
- string,
144
- (event: A, emit: (newState: S) => void) => void | Promise<void>
145
- >();
146
-
147
- constructor(initialState: S) {
148
- super(initialState);
149
- }
150
-
151
- /**
152
- * Mock an event handler for testing
153
- */
154
- mockEventHandler<E extends A>(
155
- eventConstructor: new (...args: any[]) => E,
156
- handler: (event: E, emit: (newState: S) => void) => void | Promise<void>,
157
- ): void {
158
- // Use the on method to register the mock handler
159
- this.on(eventConstructor, handler);
160
- }
161
-
162
- /**
163
- * Get the number of registered handlers
164
- */
165
- getHandlerCount(): number {
166
- return this.eventHandlers.size;
167
- }
168
-
169
- /**
170
- * Check if a handler is registered for an event type
171
- */
172
- hasHandler(eventConstructor: new (...args: any[]) => A): boolean {
173
- return this.eventHandlers.has(eventConstructor);
174
- }
175
- }
176
-
177
- /**
178
- * Mock Cubit for testing
179
- */
180
- export class MockCubit<S> extends Cubit<S> {
181
- private stateHistory: S[] = [];
182
-
183
- constructor(initialState: S) {
184
- super(initialState);
185
- this.stateHistory.push(initialState);
186
- }
187
-
188
- /**
189
- * Override emit to track state history
190
- */
191
- emit(newState: S): void {
192
- this.stateHistory.push(newState);
193
- super.emit(newState);
194
- }
195
-
196
- /**
197
- * Get the history of all states
198
- */
199
- getStateHistory(): S[] {
200
- return [...this.stateHistory];
201
- }
202
-
203
- /**
204
- * Clear state history
205
- */
206
- clearStateHistory(): void {
207
- this.stateHistory = [this.state];
208
- }
209
- }
210
-
211
- /**
212
- * Memory leak detector for tests
213
- */
214
- export class MemoryLeakDetector {
215
- private initialStats: ReturnType<typeof Blac.getMemoryStats>;
216
-
217
- constructor() {
218
- this.initialStats = Blac.getMemoryStats();
219
- }
220
-
221
- /**
222
- * Check for memory leaks and return a report
223
- */
224
- checkForLeaks(): {
225
- hasLeaks: boolean;
226
- report: string;
227
- stats: ReturnType<typeof Blac.getMemoryStats>;
228
- } {
229
- const currentStats = Blac.getMemoryStats();
230
- const hasLeaks =
231
- currentStats.registeredBlocs > this.initialStats.registeredBlocs ||
232
- currentStats.isolatedBlocs > this.initialStats.isolatedBlocs ||
233
- currentStats.keepAliveBlocs > this.initialStats.keepAliveBlocs;
234
-
235
- const report = `
236
- Memory Leak Detection Report:
237
- - Initial registered blocs: ${this.initialStats.registeredBlocs}
238
- - Current registered blocs: ${currentStats.registeredBlocs}
239
- - Initial isolated blocs: ${this.initialStats.isolatedBlocs}
240
- - Current isolated blocs: ${currentStats.isolatedBlocs}
241
- - Initial keep-alive blocs: ${this.initialStats.keepAliveBlocs}
242
- - Current keep-alive blocs: ${currentStats.keepAliveBlocs}
243
- - Potential leaks detected: ${hasLeaks ? 'YES' : 'NO'}
244
- `.trim();
245
-
246
- return {
247
- hasLeaks,
248
- report,
249
- stats: currentStats,
250
- };
251
- }
252
- }
package/src/types.ts DELETED
@@ -1,91 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Bloc } from './Bloc';
3
- import { BlocBase } from './BlocBase';
4
- import { Cubit } from './Cubit';
5
-
6
- /**
7
- * Represents a constructor type for a Bloc that takes no parameters
8
- * @template B - The type of the Bloc instance
9
- */
10
- export type BlocClassNoParams<B> = new (args: never[]) => B;
11
-
12
- /**
13
- * Represents the abstract base types for Bloc and Cubit
14
- */
15
- export type BlocBaseAbstract =
16
- | typeof Bloc<any, any, any>
17
- | typeof Cubit<any, any>;
18
-
19
- /**
20
- * Represents a constructor type for a Bloc that can take any parameters
21
- * @template B - The type of the Bloc instance
22
- */
23
- export type BlocConstructor<B> = (new (...args: any) => B) & {
24
- isolated?: boolean;
25
- keepAlive?: boolean;
26
- };
27
-
28
- /**
29
- * Extracts the state type from a BlocBase instance
30
- * @template B - The BlocBase type to extract the state from
31
- */
32
- export type ValueType<B extends BlocBase<any>> =
33
- B extends BlocBase<infer U> ? U : never;
34
-
35
- /**
36
- * Extracts the state type from either a Bloc or Cubit
37
- * @template T - The Bloc or Cubit type to extract the state from
38
- */
39
- export type BlocState<T> = T extends BlocBase<infer S> ? S : never;
40
-
41
- /**
42
- * Extracts the props type from either a Bloc or Cubit
43
- * @template T - The Bloc or Cubit type to extract the props from
44
- */
45
- export type InferPropsFromGeneric<T> =
46
- T extends Bloc<any, any, infer P>
47
- ? P
48
- : T extends Cubit<any, infer P>
49
- ? P
50
- : never;
51
-
52
- /**
53
- * Extracts the constructor parameters type from a BlocBase
54
- * @template B - The BlocBase type to extract the constructor parameters from
55
- */
56
- export type BlocConstructorParameters<B extends BlocBase<any>> =
57
- BlocConstructor<B> extends new (...args: infer P) => B ? P : never;
58
-
59
- /**
60
- * Enhanced constraint for Bloc events - must be objects with proper constructor
61
- */
62
- export type BlocEventConstraint = object;
63
-
64
- /**
65
- * Error boundary interface for Bloc error handling
66
- */
67
- export interface BlocErrorBoundary<S, A extends BlocEventConstraint> {
68
- onError: (
69
- error: Error,
70
- event: A,
71
- currentState: S,
72
- bloc: { name: string; id: string },
73
- ) => void | Promise<void>;
74
- shouldRethrow?: (error: Error, event: A) => boolean;
75
- }
76
-
77
- /**
78
- * Function type for determining dependencies that trigger re-renders
79
- * Similar to React's useEffect dependency array - if any dependency changes, a re-render is triggered
80
- * @template S The state type
81
- * @template I The bloc instance type
82
- * @param currentState The current state
83
- * @param previousState The previous state (undefined on first call)
84
- * @param instance The bloc instance
85
- * @returns Array of dependencies - if any dependency changes, a re-render is triggered
86
- */
87
- export type BlocHookDependencyArrayFn<S, I = any> = (
88
- currentState: S,
89
- previousState: S | undefined,
90
- instance: I,
91
- ) => unknown[];
@@ -1,40 +0,0 @@
1
- /**
2
- * Performs a shallow equality comparison between two values.
3
- * For objects, it checks if all top-level properties are equal using Object.is.
4
- * @param a First value to compare
5
- * @param b Second value to compare
6
- * @returns true if values are shallowly equal, false otherwise
7
- */
8
- export function shallowEqual(a: any, b: any): boolean {
9
- if (Object.is(a, b)) {
10
- return true;
11
- }
12
-
13
- if (
14
- typeof a !== 'object' ||
15
- a === null ||
16
- typeof b !== 'object' ||
17
- b === null
18
- ) {
19
- return false;
20
- }
21
-
22
- const keysA = Object.keys(a);
23
- const keysB = Object.keys(b);
24
-
25
- if (keysA.length !== keysB.length) {
26
- return false;
27
- }
28
-
29
- for (let i = 0; i < keysA.length; i++) {
30
- const key = keysA[i];
31
- if (
32
- !Object.prototype.hasOwnProperty.call(b, key) ||
33
- !Object.is(a[key], b[key])
34
- ) {
35
- return false;
36
- }
37
- }
38
-
39
- return true;
40
- }
package/src/utils/uuid.ts DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * Cross-platform UUID v4 generator that works in all environments including React Native/Hermes
3
- * Falls back to crypto.randomUUID() when available, otherwise uses Math.random()
4
- */
5
-
6
- /**
7
- * Generates a UUID v4 string compatible with all JavaScript environments
8
- * @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
9
- */
10
- export function generateUUID(): string {
11
- // Try to use crypto.randomUUID() if available (Node.js 16+, modern browsers)
12
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
13
- return crypto.randomUUID();
14
- }
15
-
16
- // Fallback implementation for React Native/Hermes and older environments
17
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
18
- const r = (Math.random() * 16) | 0;
19
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
20
- return v.toString(16);
21
- });
22
- }