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

tinysaga

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tinysaga - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

src/defineAction.ts

18

lib/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var defineAction_1 = require("./defineAction");
Object.defineProperty(exports, "defineAction", { enumerable: true, get: function () { return defineAction_1.defineAction; } });
var effects_1 = require("./effects");
Object.defineProperty(exports, "off", { enumerable: true, get: function () { return effects_1.off; } });
Object.defineProperty(exports, "on", { enumerable: true, get: function () { return effects_1.on; } });
Object.defineProperty(exports, "once", { enumerable: true, get: function () { return effects_1.once; } });
Object.defineProperty(exports, "put", { enumerable: true, get: function () { return effects_1.put; } });
Object.defineProperty(exports, "take", { enumerable: true, get: function () { return effects_1.take; } });
var Emitter_1 = require("./Emitter");
Object.defineProperty(exports, "Emitter", { enumerable: true, get: function () { return Emitter_1.Emitter; } });
var functions_1 = require("./functions");
Object.defineProperty(exports, "defineAction", { enumerable: true, get: function () { return functions_1.defineAction; } });
Object.defineProperty(exports, "off", { enumerable: true, get: function () { return functions_1.off; } });
Object.defineProperty(exports, "on", { enumerable: true, get: function () { return functions_1.on; } });
Object.defineProperty(exports, "once", { enumerable: true, get: function () { return functions_1.once; } });
Object.defineProperty(exports, "take", { enumerable: true, get: function () { return functions_1.take; } });
var ViewStore_1 = require("./ViewStore");
Object.defineProperty(exports, "ViewStore", { enumerable: true, get: function () { return ViewStore_1.ViewStore; } });
var Store_1 = require("./Store");
Object.defineProperty(exports, "Store", { enumerable: true, get: function () { return Store_1.Store; } });
{
"name": "tinysaga",
"version": "0.2.1",
"version": "0.3.0",
"main": "lib/index.js",

@@ -5,0 +5,0 @@ "module": "esm/index.js",

[![](https://img.shields.io/circleci/build/github/crazytoucan/tinysaga)](https://app.circleci.com/pipelines/github/crazytoucan/tinysaga?branch=master)
[![](https://img.shields.io/npm/v/tinysaga)](https://www.npmjs.com/package/tinysaga)
# tinysaga
Simple state update infrastructure for modern React apps.
Allows both copy-on-write stores as used by React-Redux and mutable stores for computationally intensive desktop applications.
Simple state update pattern for modern React apps.
Allows for updating both immutable state as used by React-Redux and mutable state for computationally intensive desktop applications.
No generators.
More documentation coming soon.
## Installation
```sh
$ yarn add tinysaga
```
Comes with TypeScript typings out of the box, as well as ESM support and tree shaking.
## Motivation
Redux-Saga is a great library which allows applications to manage the complex state updates and side effects that happen in many React-Redux applications. It is a crucial part of the current frontend software stack.
However, the library itself is quite complex, which can cause problems in the following ways:
1. Developers onboarding into a Saga-based codebase may need to understand the Saga fork and threading model pretty deeply in order to contribute to the code. This creates cognitive overhead for even the best developers.
2. The effect model can be surprising to unravel. For example, sending a callback to external code becomes a lot more complex as developers need to reason about how to invoke effects from within the callback.
3. The syntax itself can be challenging and unfamiliar, such as `yield` and `yield*`, or why you would want to `yield take` inside of a `while (true)` loop.
4. The code can be very hard to debug, especially in modern compile-to-ES6 toolchains where the generators become obfuscated. Stepping through code can be a chore, and profiling code through many layers of effect realization can be a nightmare.
Tinysaga supports most of the common `put()`, `takeEvery()`, and `take()` workflows from Redux-Saga, leaving only the most complex uses (like debouncing, throttling, and cancellation) to other sophisticated libraries using plain old JavaScript.
## Design
At its core, Tinysaga is really just an event bus that integrates into React-Redux.
- Dispatched Actions from React-Redux (or from other external sources, like a WebSocket or ticking timer) are sent to the Tinysaga `Emitter`.
- The `Emitter` is wired up with handlers for each Action `type` in your application. Those handlers are free to do whatever they want, such as reducing a Store's state, changing any mutable state you have, or dispatching other actions.
There are a set of helpful Effects that Tinysaga exports, such as `take()` and `once()` which allow you to compose the low-level Emitter primitive into more powerful constructs. No generators involved.
## Examples
### Making a network call
```ts
const FetchUser = defineAction<{ userId: string }>("FetchUser");
const FetchUserSuccess = defineAction<{ data: IUserData }>("FetchUserSuccess");
const FetchUserFailed = defineAction<{ message: string }>("FetchUserFailed");
on(emitter, FetchUser.TYPE, async ({ userId }) => {
// Note: `userId` and all of these calls are type-aware! No saga ReturnType shenanigans
try {
const data = await Api.fetchUser(userId);
put(emitter, FetchUserSuccess({ data }));
} catch (e) {
put(emitter, FetchUserFailed({ message: e.message }));
}
});
```
### Closing a popover unless the user mouses into it or its anchor
```ts
const DismissPopover = defineAction("DismissPopover");
const PopoverAnchorEnter = defineAction("PopoverAnchorEnter");
const PopoverEnter = defineAction("PopoverEnter");
function popoverHandler(emitter: IEmitter) {
const debouncedHide = lodash.debounce(() => {
store.setState({ ...store.state, popover: undefined });
}, 500);
on(emitter, DismissPopover.TYPE, () => {
debouncedHide();
});
on(emitter, PopoverAnchorEnter.TYPE, () => {
debouncedHide.cancel();
});
on(emitter, PopoverEnter.TYPE, () => {
debouncedHide.cancel();
});
}
```

@@ -14,3 +14,3 @@ import { IAction, IActionType, IEmitter } from "./types";

public emit({ type, payload }: IAction) {
public put({ type, payload }: IAction) {
const next: IDispatchNode = { type, payload, next: null };

@@ -17,0 +17,0 @@ if (this.end !== null) {

@@ -0,4 +1,5 @@

export { defineAction } from "./defineAction";
export { off, on, once, put, take } from "./effects";
export { Emitter } from "./Emitter";
export { defineAction, off, on, once, take } from "./functions";
export { IAction, IActionDefinition, IActionType, IEmitter, IViewStore } from "./types";
export { ViewStore } from "./ViewStore";
export { Store } from "./Store";
export { IAction, IActionDefinition, IActionType, IEmitter, IStore } from "./types";

@@ -21,3 +21,3 @@ export interface IAction {

export interface IEmitter {
emit(action: IAction): void;
put(action: IAction): void;
on<T>(type: IActionType<T>, handler: (payload: T) => void): void;

@@ -27,3 +27,3 @@ off<T>(type: IActionType<T>, handler: (payload: T) => void): void;

export interface IViewStore<S> {
export interface IStore<S> {
readonly state: S;

@@ -30,0 +30,0 @@

@@ -28,3 +28,7 @@ interface IHandler {

emit(payload: any) {
public emit(payload: any) {
if (this.dispatching) {
throw new Error("emit() when already emitting");
}
this.dispatching = true;

@@ -43,3 +47,3 @@ const chain = this.chain;

add(handler: IHandler) {
public add(handler: IHandler) {
if (this.dispatching) {

@@ -56,3 +60,3 @@ if (this.nextChain === null) {

remove(handler: IHandler) {
public remove(handler: IHandler) {
if (this.dispatching) {

@@ -59,0 +63,0 @@ if (this.nextChain === null) {

@@ -8,4 +8,5 @@ {

"callable-types": false,
"prefer-for-of": false
"prefer-for-of": false,
"member-access": true
}
}
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