Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

reducer-composer

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reducer-composer - npm Package Compare versions

Comparing version 0.0.2 to 0.0.4

dist/readme.d.ts

5

dist/createReducer.d.ts

@@ -1,2 +0,3 @@

export declare function createReducer<State>(): <Handlers extends Record<string, (state: State, payload: any) => State>>(handlers: Handlers) => (state: State, action: { [Type in keyof Handlers]: Parameters<Handlers[Type]>[1] extends undefined ? {
import { DeepReadonly } from "./utility";
export declare function createReducer<State>(): <Handlers extends Record<string, (state: DeepReadonly<State>, payload: any) => DeepReadonly<State>>>(handlers: Handlers) => (state: DeepReadonly<State>, action: { [Type in keyof Handlers]: Parameters<Handlers[Type]>[1] extends undefined ? {
type: Type;

@@ -7,2 +8,2 @@ payload?: undefined;

payload: Parameters<Handlers[Type]>[1];
}; }[keyof Handlers]) => State;
}; }[keyof Handlers]) => DeepReadonly<State>;

2

dist/createReducer.js

@@ -6,3 +6,3 @@ "use strict";

return function (state, action) {
return action.type in handlers
return Object.prototype.hasOwnProperty.call(handlers, action.type)
? handlers[action.type](state, action.payload)

@@ -9,0 +9,0 @@ : state;

export declare function createReducerCrudHandlers<Entity, EntityPayload, KeyPayload>(entitySelector: (payload: EntityPayload) => [string, Entity], keySelector: (payload: KeyPayload) => string): {
create: (record: Record<string, Entity>, payload: EntityPayload) => Record<string, Entity>;
update: (record: Record<string, Entity>, payload: EntityPayload) => Record<string, Entity>;
delete: (record: Record<string, Entity>, payload: KeyPayload) => Record<string, Entity>;
upsert: (record: Record<string, Entity>, payload: EntityPayload) => Record<string, Entity>;
discard: (record: Record<string, Entity>, payload: KeyPayload) => Record<string, Entity>;
create: (record: import("./utility").DeepReadonlyObject<Record<string, Entity>>, payload: EntityPayload) => import("./utility").DeepReadonlyObject<Record<string, Entity>>;
update: (record: import("./utility").DeepReadonlyObject<Record<string, Entity>>, payload: EntityPayload) => import("./utility").DeepReadonlyObject<Record<string, Entity>>;
delete: (record: import("./utility").DeepReadonlyObject<Record<string, Entity>>, payload: KeyPayload) => import("./utility").DeepReadonlyObject<Record<string, Entity>>;
upsert: (record: import("./utility").DeepReadonlyObject<Record<string, Entity>>, payload: EntityPayload) => import("./utility").DeepReadonlyObject<Record<string, Entity>>;
discard: (record: import("./utility").DeepReadonlyObject<Record<string, Entity>>, payload: KeyPayload) => import("./utility").DeepReadonlyObject<Record<string, Entity>>;
};

@@ -25,3 +25,4 @@ "use strict";

var withEntity = function (f) { return function (record, payload) {
return f.apply(void 0, [record].concat(entitySelector(payload)));
var _a = entitySelector(payload), key = _a[0], entity = _a[1];
return f(record, key, entity);
}; };

@@ -34,3 +35,3 @@ var withKey = function (f) { return function (record, payload) {

var _a;
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
throw new Error();

@@ -42,3 +43,3 @@ }

var _a;
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
return __assign({}, state, (_a = {}, _a[key] = entity, _a));

@@ -49,3 +50,3 @@ }

delete: withKey(function (state, key) {
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
var _a = key, removed = state[_a], rest = __rest(state, [typeof _a === "symbol" ? _a : _a + ""]);

@@ -52,0 +53,0 @@ return rest;

@@ -0,11 +1,12 @@

import { DeepReadonly } from "./utility";
export declare function createReducerOnAction<State, Action extends {
type: string;
payload?: any;
}>(): <Handlers extends { [Type in Action["type"]]: (state: State, payload: Extract<Action, {
}>(): <Handlers extends { [Type in Action["type"]]: (state: DeepReadonly<State>, payload: Extract<Action, {
type: Type;
}>["payload"]) => State; }>(handlers: Handlers) => (state: State, action: { [Type in keyof { [Type in keyof Handlers]: (state: State, payload: Extract<Action, {
}>["payload"]) => DeepReadonly<State>; }>(handlers: Handlers) => (state: DeepReadonly<State>, action: { [Type in keyof { [Type in keyof Handlers]: (state: DeepReadonly<State>, payload: Extract<Action, {
type: Type;
}>["payload"]) => State; }]: Parameters<{ [Type in keyof Handlers]: (state: State, payload: Extract<Action, {
}>["payload"]) => DeepReadonly<State>; }]: Parameters<{ [Type in keyof Handlers]: (state: DeepReadonly<State>, payload: Extract<Action, {
type: Type;
}>["payload"]) => State; }[Type]>[1] extends undefined ? {
}>["payload"]) => DeepReadonly<State>; }[Type]>[1] extends undefined ? {
type: Type;

@@ -15,5 +16,5 @@ payload?: undefined;

type: Type;
payload: Parameters<{ [Type in keyof Handlers]: (state: State, payload: Extract<Action, {
payload: Parameters<{ [Type in keyof Handlers]: (state: DeepReadonly<State>, payload: Extract<Action, {
type: Type;
}>["payload"]) => State; }[Type]>[1];
}; }[keyof Handlers]) => State;
}>["payload"]) => DeepReadonly<State>; }[Type]>[1];
}; }[keyof Handlers]) => DeepReadonly<State>;

@@ -14,4 +14,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var _1 = require("./");
var createReducerCrudHandlers_1 = require("./createReducerCrudHandlers");
var reducer_composer_1 = require("reducer-composer");
var userInitialState = {

@@ -22,3 +21,3 @@ id: "",

};
var userReducer = _1.createReducer()({
var userReducer = reducer_composer_1.createReducer()({
USER_CHANGE_NAME: function (user, _a) {

@@ -42,3 +41,3 @@ var name = _a.name;

var clickInitialState = 0;
var clickReducer = _1.createReducer()({
var clickReducer = reducer_composer_1.createReducer()({
CLICK: function (clicks) {

@@ -55,3 +54,3 @@ return clicks + 1;

// createCombinedReducer
var userClickReducer = _1.createCombinedReducer({
var userClickReducer = reducer_composer_1.createCombinedReducer({
user: userReducer,

@@ -72,7 +71,7 @@ click: clickReducer

});
var nestedUserClickReducer = _1.createCombinedReducer({
var nestedUserClickReducer = reducer_composer_1.createCombinedReducer({
nested: userClickReducer
});
// createBatchReducer
var userClickBatchReducer = _1.createBatchReducer("CLICKS", userClickReducer);
var userClickBatchReducer = reducer_composer_1.createBatchReducer("CLICKS", userClickReducer);
userClickBatchReducer(userClickInitialState, { type: "CLICK" });

@@ -87,7 +86,7 @@ userClickBatchReducer(userClickInitialState, {

// keyedReducer
var usersReducer = _1.createKeyedReducer("id", userReducer);
var usersReducer = reducer_composer_1.createKeyedReducer("id", userReducer);
usersReducer({}, { type: "USER_CHANGE_NAME", payload: { id: "42", name: "John Doe" } });
// createReducerSequence
var usersInitialState = {};
var usersReducerWithAdd = _1.createReducerSequence(usersReducer, _1.createReducer()({
var usersReducerWithAdd = reducer_composer_1.createReducerSequence(usersReducer, reducer_composer_1.createReducer()({
USER_ADD: function (state, user) {

@@ -100,3 +99,3 @@ var _a;

usersReducerWithAdd({}, { type: "USER_ADD", payload: { id: "42", name: "John", birth: new Date() } });
var multitenantUsersReducer = _1.createKeyedReducer("company", usersReducerWithAdd);
var multitenantUsersReducer = reducer_composer_1.createKeyedReducer("company", usersReducerWithAdd);
multitenantUsersReducer({}, {

@@ -110,8 +109,8 @@ type: "USER_ADD",

});
var usersActionCounterReducer = _1.createReducerOnAction()({
var usersActionCounterReducer = reducer_composer_1.createReducerOnAction()({
USER_ADD: function (count) {
return count + 1;
},
USER_CHANGE_BIRTH: _1.ignore,
USER_CHANGE_NAME: _1.ignore
USER_CHANGE_BIRTH: reducer_composer_1.ignore,
USER_CHANGE_NAME: reducer_composer_1.ignore
});

@@ -122,4 +121,4 @@ usersActionCounterReducer(0, {

});
var carCrud = createReducerCrudHandlers_1.createReducerCrudHandlers(function (payload) { return [payload.id, payload]; }, function (payload) { return payload.id; });
var carReducer = _1.createReducer()({
var carCrud = reducer_composer_1.createReducerCrudHandlers(function (payload) { return [payload.id, payload]; }, function (payload) { return payload.id; });
var carReducer = reducer_composer_1.createReducer()({
CAR_ADD: carCrud.create,

@@ -129,3 +128,3 @@ CAR_UPDATE: carCrud.update,

});
var rentReducer = _1.createReducer()({
var rentReducer = reducer_composer_1.createReducer()({
RENT_CHANGE_USER: function (state, _a) {

@@ -136,13 +135,13 @@ var user = _a.user;

});
var rentKeyedReducer = _1.createKeyedReducer("id", rentReducer);
var rentsCrud = createReducerCrudHandlers_1.createReducerCrudHandlers(function (rent) { return [rent.id, rent]; }, function (_a) {
var rentKeyedReducer = reducer_composer_1.createKeyedReducer("id", rentReducer);
var rentsCrud = reducer_composer_1.createReducerCrudHandlers(function (rent) { return [rent.id, rent]; }, function (_a) {
var id = _a.id;
return id;
});
var rentsCrudReducer = _1.createReducer()({
var rentsCrudReducer = reducer_composer_1.createReducer()({
RENT: rentsCrud.create,
RENT_CANCEL: rentsCrud.delete
});
var rentsReducer = _1.createReducerSequence(rentKeyedReducer, rentsCrudReducer);
var carRentCompanyReducer = _1.createCombinedReducer({
var rentsReducer = reducer_composer_1.createReducerSequence(rentKeyedReducer, rentsCrudReducer);
var carRentCompanyReducer = reducer_composer_1.createCombinedReducer({
users: usersReducerWithAdd,

@@ -198,3 +197,3 @@ cars: carReducer,

}
var precondition = _1.createReducerOnAction()({
var precondition = reducer_composer_1.createReducerOnAction()({
CAR_DESTROY: function (state, _a) {

@@ -214,13 +213,13 @@ var id = _a.id;

},
CAR_ADD: _1.ignore,
CAR_UPDATE: _1.ignore,
RENT: _1.ignore,
RENT_CANCEL: _1.ignore,
RENT_CHANGE_USER: _1.ignore,
USER_ADD: _1.ignore,
USER_CHANGE_BIRTH: _1.ignore,
USER_CHANGE_NAME: _1.ignore
CAR_ADD: reducer_composer_1.ignore,
CAR_UPDATE: reducer_composer_1.ignore,
RENT: reducer_composer_1.ignore,
RENT_CANCEL: reducer_composer_1.ignore,
RENT_CHANGE_USER: reducer_composer_1.ignore,
USER_ADD: reducer_composer_1.ignore,
USER_CHANGE_BIRTH: reducer_composer_1.ignore,
USER_CHANGE_NAME: reducer_composer_1.ignore
});
var safeCarRentCompanyReducer = _1.createReducerSequence(precondition, carRentCompanyReducer, postCondition);
var transactionalSafeCarRentCompanyReducer = _1.createBatchReducer("CAR_TRANSACTION", safeCarRentCompanyReducer);
var safeCarRentCompanyReducer = reducer_composer_1.createReducerSequence(precondition, carRentCompanyReducer, postCondition);
var transactionalSafeCarRentCompanyReducer = reducer_composer_1.createBatchReducer("CAR_TRANSACTION", safeCarRentCompanyReducer);
transactionalSafeCarRentCompanyReducer(carRentCompanyInitialState, {

@@ -227,0 +226,0 @@ type: "CAR_TRANSACTION",

@@ -10,1 +10,7 @@ export declare type Values<O> = O[keyof O];

export declare function get<Attribute extends string>(attribute: Attribute): <Value>(object: { [K in Attribute]: Value; }) => { [K in Attribute]: Value; }[Attribute];
export interface DeepReadonlyArray<A> extends ReadonlyArray<DeepReadonly<A>> {
}
export declare type DeepReadonlyObject<A> = {
readonly [K in keyof A]: DeepReadonly<A[K]>;
};
export declare type DeepReadonly<A> = A extends Array<infer B> ? DeepReadonlyArray<B> : DeepReadonlyObject<A>;

@@ -11,3 +11,3 @@ {

],
"version": "0.0.2",
"version": "0.0.4",
"license": "MIT",

@@ -14,0 +14,0 @@ "author": "Frederik Batuna",

# reducer-composer
compose your reducers effortlessly, with intellisense and strict type-checking
Compose your reducers **effortlessly**, with **intellisense** and **strict type-checking**.
## [Usage](src/usage.ts)
## Usage
[![Edit reducer-composer](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/52zq6r02ln?hidenavigation=1&view=editor)
```typescript
import {
createReducer,
createCombinedReducer,
createReducerSequence,
createBatchReducer,
createKeyedReducer,
createReducerCrudHandlers,
createReducerOnAction,
ActionOfReducer,
ignore
} from "reducer-composer";
interface User {
id: string;
name: string;
birth: Date;
}
const user = createReducer<User>()({
USER_CHANGE_NAME(user, { name }: { name: string }) {
return { ...user, name };
},
USER_CHANGE_BIRTH(user, { birth }: { birth: Date }) {
return { ...user, birth };
}
});
const click = createReducer<number>()({
CLICK(clicks) {
return clicks + 1;
},
CLICK_SET(_, { clicks }: { clicks: number }) {
return clicks;
}
});
const userClick = createCombinedReducer({
user,
click
});
const userClickBatchReducer = createBatchReducer("CLICKS", userClick);
const usersReducer = createKeyedReducer("id", user);
const companyUsers = createReducerSequence(
usersReducer,
createReducer<Record<string, User>>()({
USER_ADD(state, user: User) {
return { ...state, [user.id]: user };
}
})
);
const usersCounter = createReducerOnAction<
number,
ActionOfReducer<typeof companyUsers>
>()({
USER_ADD(count) {
return count + 1;
},
USER_CHANGE_BIRTH: ignore,
USER_CHANGE_NAME: ignore
});
interface Car {
id: string;
name: string;
km: number;
}
const carCrud = createReducerCrudHandlers(
(payload: Car) => [payload.id, payload],
(payload: { id: string }) => payload.id
);
const car = createReducer<Record<string, Car>>()({
CAR_ADD: carCrud.create,
CAR_UPDATE: carCrud.update,
CAR_DESTROY: carCrud.discard
});
```
[more usage](src/usage.ts)
## License MIT

@@ -1,6 +0,9 @@

import { Values } from "./utility";
import { Values, DeepReadonly } from "./utility";
export function createReducer<State>() {
return <
Handlers extends Record<string, (state: State, payload: any) => State>
Handlers extends Record<
string,
(state: DeepReadonly<State>, payload: any) => DeepReadonly<State>
>
>(

@@ -10,3 +13,3 @@ handlers: Handlers

return (
state: State,
state: DeepReadonly<State>,
action: Values<

@@ -22,3 +25,3 @@ {

) =>
action.type in handlers
Object.prototype.hasOwnProperty.call(handlers, action.type)
? handlers[action.type](state, action.payload)

@@ -25,0 +28,0 @@ : state;

@@ -0,1 +1,3 @@

import { DeepReadonly } from "./utility";
export function createReducerCrudHandlers<Entity, EntityPayload, KeyPayload>(

@@ -7,15 +9,23 @@ entitySelector: (payload: EntityPayload) => [string, Entity],

f: (
record: Record<string, Entity>,
record: DeepReadonly<Record<string, Entity>>,
key: string,
entity: Entity
) => Record<string, Entity>
) => (record: Record<string, Entity>, payload: EntityPayload) =>
f(record, ...entitySelector(payload));
entity: DeepReadonly<Entity>
) => DeepReadonly<Record<string, Entity>>
) => (
record: DeepReadonly<Record<string, Entity>>,
payload: EntityPayload
) => {
const [key, entity] = entitySelector(payload);
return f(record, key, (entity as unknown) as DeepReadonly<Entity>);
};
const withKey = (
f: (record: Record<string, Entity>, key: string) => Record<string, Entity>
) => (record: Record<string, Entity>, payload: KeyPayload) =>
f: (
record: DeepReadonly<Record<string, Entity>>,
key: string
) => DeepReadonly<Record<string, Entity>>
) => (record: DeepReadonly<Record<string, Entity>>, payload: KeyPayload) =>
f(record, keySelector(payload));
return {
create: withEntity((state, key, entity) => {
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
throw new Error();

@@ -26,3 +36,3 @@ }

update: withEntity((state, key, entity) => {
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
return { ...state, [key]: entity };

@@ -33,5 +43,5 @@ }

delete: withKey((state, key) => {
if (key in state) {
if (Object.prototype.hasOwnProperty.call(state, key)) {
const { [key]: removed, ...rest } = state;
return rest as Record<string, Entity>;
return rest as DeepReadonly<Record<string, Entity>>;
}

@@ -45,5 +55,5 @@ throw new Error();

const { [key]: removed, ...rest } = state;
return rest as Record<string, Entity>;
return rest as DeepReadonly<Record<string, Entity>>;
})
};
}
import { createReducer } from "./createReducer";
import { DeepReadonly } from "./utility";

@@ -10,5 +11,5 @@ export function createReducerOnAction<

[Type in Action["type"]]: (
state: State,
state: DeepReadonly<State>,
payload: Extract<Action, { type: Type }>["payload"]
) => State
) => DeepReadonly<State>
}

@@ -20,6 +21,6 @@ >(

[Type in keyof Handlers]: (
state: State,
state: DeepReadonly<State>,
payload: Extract<Action, { type: Type }>["payload"]
) => State
) => DeepReadonly<State>
});
}

@@ -11,5 +11,5 @@ import {

createBatchReducer,
ignore
} from "./";
import { createReducerCrudHandlers } from "./createReducerCrudHandlers";
ignore,
createReducerCrudHandlers
} from "reducer-composer";

@@ -188,5 +188,5 @@ // createReducer

const rentKeyedReducer = createKeyedReducer("id", rentReducer);
const rentsCrud = createReducerCrudHandlers(
(rent: Rent) => [rent.id, rent],
({ id }: { id: string }) => id
const rentsCrud = createReducerCrudHandlers<Rent, Rent, { id: string }>(
rent => [rent.id, rent],
({ id }) => id
);

@@ -193,0 +193,0 @@ const rentsCrudReducer = createReducer<Record<string, Rent>>()({

@@ -17,1 +17,11 @@ export type Values<O> = O[keyof O];

}
export interface DeepReadonlyArray<A> extends ReadonlyArray<DeepReadonly<A>> {}
export type DeepReadonlyObject<A> = {
readonly [K in keyof A]: DeepReadonly<A[K]>
};
export type DeepReadonly<A> = A extends Array<infer B>
? DeepReadonlyArray<B>
: DeepReadonlyObject<A>;
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