New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bloc-react

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bloc-react - npm Package Compare versions

Comparing version 0.0.7 to 0.0.8

.idea/runConfigurations/_template__of_JavaScriptTestRunnerJest.xml

41

dist/my-lib.d.ts

@@ -14,3 +14,26 @@ import { Subscription } from 'rxjs';

}
interface ChangeEvent<T> {
currentState: T;
nextState: T;
}
interface TransitionEvent<T, E> {
currentState: T;
event: E;
nextState: T;
}
interface BlocObserverOptions {
onChange?: (bloc: BlocBase<any>, event: ChangeEvent<any>) => void;
onTransition?: (bloc: BlocBase<any>, event: TransitionEvent<any, any>) => void;
}
declare class BlocObserver {
onChange: (bloc: BlocBase<any>, event: ChangeEvent<any>) => void;
onTransition: (bloc: BlocBase<any>, event: TransitionEvent<any, any>) => void;
constructor(methods?: BlocObserverOptions);
readonly addChange: (bloc: BlocBase<any>, state: any) => void;
readonly addTransition: (bloc: BlocBase<any>, state: any, event: any) => void;
private createTransitionEvent;
private createChangeEvent;
}
interface ReactBlocOptions$1 {

@@ -22,3 +45,3 @@ /** Enables debugging which calls BlocReact.observer every time a Subject is updated. Defaults to false */

declare class BlocConsumer {
observer: null | ((bloc: BlocBase<any>, value: any) => void);
observer: BlocObserver;
debug: boolean;

@@ -29,4 +52,5 @@ readonly blocListGlobal: BlocBase<any>[];

constructor(blocs: BlocBase<any>[], options?: ReactBlocOptions$1);
notify(bloc: BlocBase<any>, state: ValueType<any>): void;
addBlocObserver<T extends BlocBase<any>>(blocClass: BlocClass<T>, callback: (bloc: T, state: ValueType<T>) => unknown, scope?: BlocObserverScope): void;
notifyChange(bloc: BlocBase<any>, state: any): void;
notifyTransition(bloc: BlocBase<any>, state: any, event: any): void;
addBlocObserver<T extends BlocBase<any>>(blocClass: BlocClass<T>, callback: (bloc: T, event: ChangeEvent<T>) => unknown, scope?: BlocObserverScope): void;
addLocalBloc(key: string, bloc: BlocBase<any>): void;

@@ -54,8 +78,5 @@ removeLocalBloc(key: string): void;

onRegister: null | ((consumer: BlocConsumer) => void);
onChange: null | ((change: {
currentState: T;
nextState: T;
}) => void);
onChange: null | ((change: ChangeEvent<T>) => void);
constructor(initialValue: T, blocOptions?: BlocOptions);
private _consumer;
protected _consumer: BlocConsumer | null;
set consumer(consumer: BlocConsumer);

@@ -66,3 +87,3 @@ protected notifyChange: (state: T) => void;

declare class Bloc<E, T> extends BlocBase<T> {
protected onTransition: null | ((change: {
onTransition: null | ((change: {
currentState: T;

@@ -75,3 +96,3 @@ event: E;

add: (event: E) => void;
protected notifyTransition: (value: T, event: E) => void;
protected notifyTransition: (state: T, event: E) => void;
}

@@ -78,0 +99,0 @@

@@ -84,2 +84,3 @@ 'use strict';

this.notifyChange = (state) => {
this._consumer?.notifyChange(this, state);
this.onChange?.({

@@ -111,7 +112,8 @@ currentState: this.state,

};
this.notifyTransition = (value, event) => {
this.notifyTransition = (state, event) => {
this._consumer?.notifyTransition(this, state, event);
this.onTransition?.({
currentState: this.state,
event,
nextState: value
nextState: state
});

@@ -132,5 +134,32 @@ };

class BlocObserver {
constructor(methods = {}) {
this.addChange = (bloc, state) => {
this.onChange(bloc, this.createChangeEvent(bloc, state));
};
this.addTransition = (bloc, state, event) => {
this.onTransition(bloc, this.createTransitionEvent(bloc, state, event));
};
this.onChange = methods.onChange ? methods.onChange : () => {
};
this.onTransition = methods.onTransition ? methods.onTransition : () => {
};
}
createTransitionEvent(bloc, state, event) {
return {
currentState: bloc.state,
event,
nextState: state
};
}
createChangeEvent(bloc, state) {
return {
currentState: bloc.state,
nextState: state
};
}
}
class BlocConsumer {
constructor(blocs, options = {}) {
this.observer = null;
this._blocMapLocal = {};

@@ -140,12 +169,10 @@ this.blocObservers = [];

this.debug = options.debug || false;
this.observer = new BlocObserver();
for (const b of blocs) {
b.consumer = this;
b.subscribe((v) => this.notify(b, v));
b.onRegister?.(this);
}
}
notify(bloc, state) {
if (this.observer) {
this.observer(bloc, state);
}
notifyChange(bloc, state) {
this.observer.addChange(bloc, state);
for (const [blocClass, callback, scope] of this.blocObservers) {

@@ -155,6 +182,12 @@ const isGlobal = this.blocListGlobal.indexOf(bloc) !== -1;

if (matchesScope && bloc instanceof blocClass) {
callback(bloc, state);
callback(bloc, {
nextState: state,
currentState: bloc.state
});
}
}
}
notifyTransition(bloc, state, event) {
this.observer.addTransition(bloc, state, event);
}
addBlocObserver(blocClass, callback, scope = "all") {

@@ -165,3 +198,3 @@ this.blocObservers.push([blocClass, callback, scope]);

this._blocMapLocal[key] = bloc;
bloc.subscribe((v) => this.notify(bloc, v));
bloc.consumer = this;
}

@@ -168,0 +201,0 @@ removeLocalBloc(key) {

{
"name": "bloc-react",
"version": "0.0.7",
"version": "0.0.8",
"scripts": {

@@ -5,0 +5,0 @@ "dev": "vite",

# BLoC React
BLoC pattern implementation for react using rxjs and heavily inspired by flutter_react - https://bloclibrary.dev
[Coverage: 100%]
## This library is in early alpha and is not recommended being used for production.
TypeScript BLoC pattern implementation for react using RxJS and heavily inspired by flutter_react - https://bloclibrary.dev
The BLoC Pattern (**B**usiness **Lo**gic **C**omponent) is a battle-tested design pattern for state management coming from Flutter and Dart. It tries to separate business logic from UI as much as possible while still being simple and flexible.
Everything revolves around [**subjects**](https://rxjs-dev.firebaseapp.com/guide/subject) which are native to Dart, for JS there is a solid implementation by RxJS.
# Quickstart
[TODO: Add plain JS examples]
### 1. Create a new **Bloc/Cubit**
```typescript
// CounterCubit.ts
export default class CounterCubit extends Cubit<number> {
increment = (): void => {
this.emit(this.state + 1);
};
}
```
### 2. Create a new **BlocReact** instance and export `useBloc` from it
```typescript
// state.ts
const state = new BlocReact([new CounterCubit(0)]);
export const { useBloc } = state;
```
### 3. Use the hook to access the state and class methods
```typescript
// CounterButton.tsx
import { useBloc } from "../state";
export default function CounterButton() {
const [count, { increment }] = useBloc(CounterCubit);
return <button onClick={() => increment()}>count is: {count}</button>;
}
```
# Documentation
[TODO]
## BlocReact
[TODO]
## Bloc
[TODO]
## Cubit
[TODO]
## BlocObserver
[TODO]
import Bloc from "./Bloc";
import mockConsole from "jest-mock-console";
import { AuthEvent, TestBloc } from "../helpers/test.fixtures";

@@ -7,28 +8,5 @@ describe("Bloc", () => {

onChange: jest.fn(),
onTransition: jest.fn(),
onTransition: jest.fn()
};
enum AuthEvent {
authenticated = "authenticated",
unauthenticated = "unauthenticated",
}
class TestBloc extends Bloc<AuthEvent, boolean> {
constructor() {
super(false);
this.onChange = spy.onChange;
this.onTransition = spy.onTransition;
this.mapEventToState = (event) => {
switch (event) {
case AuthEvent.unauthenticated:
return false;
case AuthEvent.authenticated:
return true;
}
};
}
}
beforeEach(() => {

@@ -45,3 +23,6 @@ jest.resetAllMocks();

mockConsole();
class NotFullyImplemented extends Bloc<AuthEvent, boolean> {}
class NotFullyImplemented extends Bloc<AuthEvent, boolean> {
}
const bloc = new NotFullyImplemented(false);

@@ -62,2 +43,3 @@ expect(bloc.state).toBe(false);

const bloc = new TestBloc();
bloc.onChange = spy.onChange;
expect(spy.onChange).toHaveBeenCalledTimes(0);

@@ -68,3 +50,3 @@ bloc.add(AuthEvent.authenticated);

currentState: false,
nextState: true,
nextState: true
});

@@ -75,2 +57,3 @@ });

const bloc = new TestBloc();
bloc.onTransition = spy.onTransition;
expect(spy.onTransition).toHaveBeenCalledTimes(0);

@@ -82,6 +65,13 @@ bloc.add(AuthEvent.authenticated);

event: AuthEvent.authenticated,
nextState: true,
nextState: true
});
});
it("should accept payload", () => {
const bloc = new TestBloc();
expect(bloc.state).toBe(false);
bloc.add(AuthEvent.authenticated);
expect(bloc.state).toBe(true);
});
});
});

@@ -5,3 +5,3 @@ import BlocBase from "./BlocBase";

export default class Bloc<E, T> extends BlocBase<T> {
protected onTransition:
onTransition:
| null

@@ -28,9 +28,10 @@ | ((change: { currentState: T; event: E; nextState: T }) => void) = null;

protected notifyTransition = (value: T, event: E): void => {
protected notifyTransition = (state: T, event: E): void => {
this._consumer?.notifyTransition(this, state, event);
this.onTransition?.({
currentState: this.state,
event,
nextState: value,
});
nextState: state,
})
};
}
import { BlocConsumer } from "./BlocConsumer";
import StreamAbstraction from "./StreamAbstraction";
import { BlocOptions } from "./types";
import { BlocOptions, ChangeEvent } from "./types";

@@ -8,3 +8,3 @@ export default class BlocBase<T> extends StreamAbstraction<T> {

onRegister: null | ((consumer: BlocConsumer) => void) = null;
onChange: null | ((change: { currentState: T; nextState: T }) => void) = null;
onChange: null | ((change: ChangeEvent<T>) => void) = null;

@@ -15,3 +15,3 @@ constructor(initialValue: T, blocOptions: BlocOptions = {}) {

private _consumer: BlocConsumer | null = null;
protected _consumer: BlocConsumer | null = null;

@@ -23,2 +23,4 @@ set consumer(consumer: BlocConsumer) {

protected notifyChange = (state: T): void => {
this._consumer?.notifyChange(this, state);
this.onChange?.({

@@ -25,0 +27,0 @@ currentState: this.state,

@@ -1,58 +0,35 @@

import { BlocConsumer, BlocObserverScope } from "./BlocConsumer";
import Cubit from "./Cubit";
import { BlocClass } from "./types";
import { BlocConsumer } from "./BlocConsumer";
import BlocObserver from "./BlocObserver";
import { AuthEvent, Listener, Test1, TestBloc } from "../helpers/test.fixtures";
class Test1 extends Cubit<number> {
constructor(options: { register?: () => void } = {}) {
super(1);
if (options.register) {
this.onRegister = options.register;
}
}
increment = () => {
this.emit(this.state + 1);
};
}
class Listener extends Cubit<number> {
constructor(
notify: (bloc: any, state: any) => void,
listenFor: BlocClass<any>,
scope?: BlocObserverScope
) {
super(1);
this.onRegister = (consumer) => {
consumer.addBlocObserver(
listenFor,
(bloc, state) => {
notify(bloc, state);
},
scope
);
};
}
increment = () => {
this.emit(this.state + 1);
};
}
describe("BlocConsumer", function () {
it("should call function set to observer prop on any state change", function () {
describe("BlocConsumer", function() {
it("should call `onChange` on any state change", () => {
const testCubit = new Test1();
const testBlocConsumer = new BlocConsumer([testCubit]);
const fn = jest.fn();
testBlocConsumer.observer = fn;
const onChange = jest.fn();
testBlocConsumer.observer = new BlocObserver({ onChange });
testCubit.increment();
expect(fn).toHaveBeenCalledTimes(1);
expect(fn).toHaveBeenCalledWith(testCubit, 2);
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(testCubit, { currentState: 1, nextState: 2 });
});
it("should call `onRegister` when the class is registered", function () {
it("should call `onTransition` on any state change for Blocs", () => {
const testBloc = new TestBloc();
const testBlocConsumer = new BlocConsumer([testBloc]);
const onTransition = jest.fn();
testBlocConsumer.observer = new BlocObserver({ onTransition });
testBloc.add(AuthEvent.authenticated);
expect(onTransition).toHaveBeenCalledTimes(1);
expect(onTransition).toHaveBeenCalledWith(testBloc, {
currentState: false,
event: AuthEvent.authenticated,
nextState: true
});
});
it("should call `onRegister` when the class is registered", function() {
const register = jest.fn();
const testCubit = new Test1({
register,
register
});

@@ -63,4 +40,4 @@ new BlocConsumer([testCubit]);

describe("observers", function () {
it("should allow one bloc to listen to another bloc", function () {
describe("observers", function() {
it("should allow one bloc to listen to another bloc", function() {
const notify = jest.fn();

@@ -71,13 +48,12 @@ const global = new Test1();

const consumer = new BlocConsumer([global, listener]);
consumer.addLocalBloc('abc', local); // should trigger listener "all"
consumer.addLocalBloc("abc", local);
expect(notify).toHaveBeenCalledTimes(0);
global.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledTimes(1);
expect(notify).toHaveBeenCalledWith(local, 1);
global.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledWith(global, { currentState: 1, nextState: 2 });
local.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledTimes(2);
expect(notify).toHaveBeenCalledWith(global, 2);
local.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledTimes(3);
});
it("should allow filtering listener only for local blocs", function () {
it("should allow filtering listener only for local blocs", function() {
const notify = jest.fn();

@@ -88,14 +64,11 @@ const global = new Test1();

const consumer = new BlocConsumer([global, listener]);
// local blocs trigger listeners when added
consumer.addLocalBloc('abc', local); // should trigger listener "local"
expect(notify).toHaveBeenCalledTimes(1);
expect(notify).toHaveBeenCalledWith(local, 1);
consumer.addLocalBloc("abc", local); // should trigger listener "local"
global.increment(); // should not trigger listener "local"
expect(notify).toHaveBeenCalledTimes(0);
local.increment(); // should trigger listener "local"
expect(notify).toHaveBeenCalledTimes(1);
local.increment(); // should trigger listener "local"
expect(notify).toHaveBeenCalledTimes(2);
expect(notify).toHaveBeenCalledWith(local, 2);
expect(notify).toHaveBeenCalledWith(local, { currentState: 1, nextState: 2 });
});
it("should allow filtering listener only for global blocs", function () {
it("should allow filtering listener only for global blocs", function() {
const notify = jest.fn();

@@ -106,7 +79,7 @@ const global = new Test1();

const consumer = new BlocConsumer([global, listener]);
consumer.addLocalBloc('abc', local); // should not trigger listener "global"
consumer.addLocalBloc("abc", local); // should not trigger listener "global"
expect(notify).toHaveBeenCalledTimes(0);
global.increment(); // should trigger listener "global"
expect(notify).toHaveBeenCalledTimes(1);
expect(notify).toHaveBeenCalledWith(global, 2);
expect(notify).toHaveBeenCalledWith(global, { currentState: 1, nextState: 2 });
local.increment(); // should not trigger listener "global"

@@ -116,3 +89,3 @@ expect(notify).toHaveBeenCalledTimes(1);

it("should allow not notify changes after bloc has been removed", function () {
it("should allow not notify changes after bloc has been removed", function() {
const notify = jest.fn();

@@ -123,9 +96,7 @@ const global = new Test1();

const consumer = new BlocConsumer([global, listener]);
consumer.addLocalBloc('abc', local); // should trigger listener "all"
consumer.addLocalBloc("abc", local); // should trigger listener "all"
global.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledTimes(1);
expect(notify).toHaveBeenCalledWith(local, 1);
global.increment(); // should trigger listener "all"
expect(notify).toHaveBeenCalledTimes(2);
expect(notify).toHaveBeenCalledWith(global, 2);
consumer.removeLocalBloc('abc');
expect(notify).toHaveBeenCalledWith(global, { currentState: 1, nextState: 2 });
consumer.removeLocalBloc("abc");
local.increment(); // should trigger listener "all"

@@ -132,0 +103,0 @@ expect(notify).toHaveBeenCalledTimes(2);

import BlocBase from "./BlocBase";
import { BlocClass, ValueType } from "./types";
import { BlocClass, ChangeEvent } from "./types";
import BlocObserver from "./BlocObserver";

@@ -10,5 +11,5 @@ export interface ReactBlocOptions {

export type BlocObserverScope = "local" | "global" | "all";
type BlocObserver = [
type BlocObserverList = [
BlocClass<any>,
(bloc: any, state: any) => unknown,
(bloc: any, event: ChangeEvent<any>) => unknown,
BlocObserverScope

@@ -18,7 +19,7 @@ ];

export class BlocConsumer {
observer: null | ((bloc: BlocBase<any>, value: any) => void) = null;
observer: BlocObserver;
debug: boolean;
readonly blocListGlobal: BlocBase<any>[];
protected _blocMapLocal: Record<string, BlocBase<any>> = {};
private blocObservers: BlocObserver[] = [];
private blocObservers: BlocObserverList[] = [];

@@ -28,6 +29,7 @@ constructor(blocs: BlocBase<any>[], options: ReactBlocOptions = {}) {

this.debug = options.debug || false;
this.observer = new BlocObserver();
for (const b of blocs) {
b.consumer = this;
b.subscribe((v: any) => this.notify(b, v));
// b.subscribe((v: any) => this.notifyChange(b, v));
b.onRegister?.(this);

@@ -37,6 +39,4 @@ }

notify(bloc: BlocBase<any>, state: ValueType<any>): void {
if (this.observer) {
this.observer(bloc, state);
}
notifyChange(bloc: BlocBase<any>, state: any): void {
this.observer.addChange(bloc, state);

@@ -50,3 +50,6 @@ for (const [blocClass, callback, scope] of this.blocObservers) {

if (matchesScope && bloc instanceof blocClass) {
callback(bloc, state);
callback(bloc, {
nextState: state,
currentState: bloc.state
});
}

@@ -56,5 +59,9 @@ }

notifyTransition(bloc: BlocBase<any>, state: any, event: any): void {
this.observer.addTransition(bloc, state, event);
}
public addBlocObserver<T extends BlocBase<any>>(
blocClass: BlocClass<T>,
callback: (bloc: T, state: ValueType<T>) => unknown,
callback: (bloc: T, event: ChangeEvent<T>) => unknown,
scope: BlocObserverScope = "all"

@@ -67,3 +74,3 @@ ) {

this._blocMapLocal[key] = bloc;
bloc.subscribe((v: any) => this.notify(bloc, v));
bloc.consumer = this;
}

@@ -70,0 +77,0 @@

@@ -18,1 +18,13 @@ import BlocBase from "./BlocBase";

}
export interface ChangeEvent<T> {
currentState: T,
nextState: T,
}
export interface TransitionEvent<T, E> {
currentState: T,
event: E,
nextState: T,
}

@@ -5,2 +5,3 @@ import CounterCubit from "./bloc/CounterCubit";

import { BlocReact } from "../lib";
import BlocObserver from "../lib/BlocObserver";

@@ -12,3 +13,3 @@ const state = new BlocReact(

state.observer = console.log;
state.observer = new BlocObserver();

@@ -15,0 +16,0 @@ export const { useBloc, BlocBuilder, BlocProvider } = state;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc