UNPKG

core-native

Version:

A lightweight framework based on React Native + Redux + Redux Saga, in strict TypeScript.

153 lines 4.54 kB
import { put } from "redux-saga/effects"; import { app } from "./app"; import { loadingAction } from "./reducer"; import { stringifyWithMask } from "./util/json"; /** * A helper for ActionHandler functions (Saga) */ export function createActionHandlerDecorator(interceptor) { return (target) => { const descriptor = target.descriptor; const fn = descriptor.value; descriptor.value = function* (...args) { const rootState = app.store.getState(); yield* interceptor(fn.bind(this, ...args), rootState); }; return target; }; } /** * A helper for regular functions */ export function createRegularDecorator(interceptor) { return (target) => { const descriptor = target.descriptor; const fn = descriptor.value; descriptor.value = function (...args) { const rootState = app.store.getState(); interceptor(fn.bind(this, ...args), rootState); }; return target; }; } /** * To mark state.loading[identifier] during Saga execution */ export function Loading(identifier = "global") { return createActionHandlerDecorator(function* (handler) { try { yield put(loadingAction(true, identifier)); yield* handler(); } finally { yield put(loadingAction(false, identifier)); } }); } /** * To log (Result=OK) this action, including action name and parameters (masked) */ export function Log() { return (target) => { const descriptor = target.descriptor; const fn = descriptor.value; descriptor.value = function* (...args) { if (app.loggerConfig) { // Do not use fn directly, it is a different object const params = stringifyWithMask(app.loggerConfig.maskedKeywords || [], "***", ...args); const logTypeName = descriptor.value.actionName; const context = params ? { params } : {}; const onLogEnd = app.logger.info(logTypeName, context); try { yield* fn.bind(this)(...args); } finally { onLogEnd(); } } else { yield* fn.bind(this)(...args); } }; return target; }; } /** * Required decorator when using lifecycle actions, including onRender/onDestroy/... */ export function Lifecycle() { return (target) => { const descriptor = target.descriptor; descriptor.value.isLifecycle = true; return target; }; } /** * Used for onTick action, to specify to tick interval in second */ export function Interval(second) { return (target) => { const descriptor = target.descriptor; descriptor.value.tickInterval = second; return target; }; } /** * If specified, the Saga action cannot be entered by other threads during execution * Useful for error handler action */ export function Mutex() { let isLocked = false; return createActionHandlerDecorator(function* (handler) { if (!isLocked) { try { isLocked = true; yield* handler(); } finally { isLocked = false; } } }); } /** * For Regular function ONLY * * Throttle the execution of a regular function */ export function Throttle(millisecond) { let hasCalled = false; return createRegularDecorator(handler => { if (!hasCalled) { handler(); hasCalled = true; setTimeout(() => { hasCalled = false; }, millisecond); } }); } /** * For Regular function ONLY * * Memoize the last computed result, and return the same value if given the same input * Input equality is based on JSON.stringify by default * Only used for pure functions */ const defaultMemoKeyGenerator = (args) => JSON.stringify(args); export function Memo(memoKeyGenerator = defaultMemoKeyGenerator) { return (target) => { const descriptor = target.descriptor; const fn = descriptor.value; const cache = {}; descriptor.value = (...args) => { const paramKey = memoKeyGenerator(args); if (!cache[paramKey]) { cache[paramKey] = fn(...args); } return cache[paramKey]; }; return target; }; } //# sourceMappingURL=decorator.js.map