UNPKG

redux-observable

Version:

RxJS based middleware for Redux. Compose and cancel async actions and more.

1 lines 11.5 kB
{"version":3,"sources":["../src/StateObservable.ts","../src/combineEpics.ts","../src/createEpicMiddleware.ts","../src/utils/console.ts","../src/operators.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\n\nexport class StateObservable<S> extends Observable<S> {\n value: S;\n private __notifier = new Subject<S>();\n\n constructor(input$: Observable<S>, initialState: S) {\n super((subscriber) => {\n const subscription = this.__notifier.subscribe(subscriber);\n if (subscription && !subscription.closed) {\n subscriber.next(this.value);\n }\n return subscription;\n });\n\n this.value = initialState;\n input$.subscribe((value) => {\n // We only want to update state$ if it has actually changed since\n // redux requires reducers use immutability patterns.\n // This is basically what distinctUntilChanged() does but it's so simple\n // we don't need to pull that code in\n if (value !== this.value) {\n this.value = value;\n this.__notifier.next(value);\n }\n });\n }\n}\n","import { merge } from 'rxjs';\nimport type { Epic } from './epic';\n\n/**\n Merges all epics into a single one.\n */\nexport function combineEpics<\n Input = unknown,\n Output extends Input = Input,\n State = void,\n Dependencies = any\n>(\n ...epics: Epic<Input, Output, State, Dependencies>[]\n): Epic<Input, Output, State, Dependencies> {\n const merger: Epic<Input, Output, State, Dependencies> = (...args) =>\n merge(\n ...epics.map((epic) => {\n const output$ = epic(...args);\n if (!output$) {\n throw new TypeError(\n `combineEpics: one of the provided Epics \"${\n epic.name || '<anonymous>'\n }\" does not return a stream. Double check you're not missing a return statement!`\n );\n }\n return output$;\n })\n );\n\n // Technically the `name` property on Function's are supposed to be read-only.\n // While some JS runtimes allow it anyway (so this is useful in debugging)\n // some actually throw an exception when you attempt to do so.\n try {\n Object.defineProperty(merger, 'name', {\n value: `combineEpics(${epics\n .map((epic) => epic.name || '<anonymous>')\n .join(', ')})`,\n });\n } catch (e) {\n // noop\n }\n\n return merger;\n}\n","import type { Dispatch, Middleware, MiddlewareAPI } from 'redux';\nimport { Subject, from, queueScheduler } from 'rxjs';\nimport { map, mergeMap, observeOn, subscribeOn } from 'rxjs/operators';\nimport { StateObservable } from './StateObservable';\nimport type { Epic } from './epic';\nimport { warn } from './utils/console';\n\ninterface Options<D = any> {\n dependencies?: D;\n}\n\nexport interface EpicMiddleware<\n Input = unknown,\n Output extends Input = Input,\n State = void,\n Dependencies = any\n // eslint-disable-next-line @typescript-eslint/ban-types\n> extends Middleware<{}, State> {\n run(rootEpic: Epic<Input, Output, State, Dependencies>): void;\n}\n\nexport function createEpicMiddleware<\n Input = unknown,\n Output extends Input = Input,\n State = void,\n Dependencies = any\n>(\n options: Options<Dependencies> = {}\n): EpicMiddleware<Input, Output, State, Dependencies> {\n // This isn't great. RxJS doesn't publicly export the constructor for\n // QueueScheduler nor QueueAction, so we reach in. We need to do this because\n // we don't want our internal queuing mechanism to be on the same queue as any\n // other RxJS code outside of redux-observable internals.\n const QueueScheduler: any = queueScheduler.constructor;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call\n const uniqueQueueScheduler: typeof queueScheduler = new QueueScheduler(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n (queueScheduler as any).schedulerActionCtor\n );\n\n if (process.env.NODE_ENV !== 'production' && typeof options === 'function') {\n throw new TypeError(\n 'Providing your root Epic to `createEpicMiddleware(rootEpic)` is no longer supported, instead use `epicMiddleware.run(rootEpic)`\\n\\nLearn more: https://redux-observable.js.org/MIGRATION.html#setting-up-the-middleware'\n );\n }\n\n const epic$ = new Subject<Epic<Input, Output, State, Dependencies>>();\n let store: MiddlewareAPI<Dispatch<any>, State>;\n\n const epicMiddleware: EpicMiddleware<Input, Output, State, Dependencies> = (\n _store\n ) => {\n if (process.env.NODE_ENV !== 'production' && store) {\n // https://github.com/redux-observable/redux-observable/issues/389\n warn(\n 'this middleware is already associated with a store. createEpicMiddleware should be called for every store.\\n\\nLearn more: https://goo.gl/2GQ7Da'\n );\n }\n store = _store;\n const actionSubject$ = new Subject<Input>();\n const stateSubject$ = new Subject<State>();\n const action$ = actionSubject$\n .asObservable()\n .pipe(observeOn(uniqueQueueScheduler));\n const state$ = new StateObservable(\n stateSubject$.pipe(observeOn(uniqueQueueScheduler)),\n store.getState()\n );\n\n const result$ = epic$.pipe(\n map((epic) => {\n const output$ = epic(action$, state$, options.dependencies!);\n\n if (!output$) {\n throw new TypeError(\n `Your root Epic \"${\n epic.name || '<anonymous>'\n }\" does not return a stream. Double check you're not missing a return statement!`\n );\n }\n\n return output$;\n }),\n mergeMap((output$) =>\n from(output$).pipe(\n subscribeOn(uniqueQueueScheduler),\n observeOn(uniqueQueueScheduler)\n )\n )\n );\n\n result$.subscribe(store.dispatch);\n\n return (next) => {\n return (action) => {\n // Downstream middleware gets the action first,\n // which includes their reducers, so state is\n // updated before epics receive the action\n const result = next(action);\n\n // It's important to update the state$ before we emit\n // the action because otherwise it would be stale\n stateSubject$.next(store.getState());\n actionSubject$.next(action as Input);\n\n return result;\n };\n };\n };\n\n epicMiddleware.run = (rootEpic) => {\n if (process.env.NODE_ENV !== 'production' && !store) {\n warn(\n 'epicMiddleware.run(rootEpic) called before the middleware has been setup by redux. Provide the epicMiddleware instance to createStore() first.'\n );\n }\n epic$.next(rootEpic);\n };\n\n return epicMiddleware;\n}\n","let deprecationsSeen: { [key: string]: boolean } = {};\nexport const resetDeprecationsSeen = (): void => {\n deprecationsSeen = {};\n};\n\nconst consoleWarn =\n typeof console === 'object' && typeof console.warn === 'function'\n ? console.warn.bind(console)\n : () => {};\n\nexport const deprecate = (msg: string): void => {\n if (!deprecationsSeen[msg]) {\n deprecationsSeen[msg] = true;\n consoleWarn(`redux-observable | DEPRECATION: ${msg}`);\n }\n};\n\nexport const warn = (msg: string): void => {\n consoleWarn(`redux-observable | WARNING: ${msg}`);\n};\n","import { isAction, type Action } from 'redux';\nimport type { OperatorFunction } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { warn } from './utils/console';\n\n/**\n * Inferring the types of this is a bit challenging, and only works in newer\n * versions of TypeScript.\n *\n * @param ...types One or more Redux action types you want to filter for, variadic.\n */\nexport function ofType<\n // All possible actions your app can dispatch\n Input,\n // The types you want to filter for\n Type extends string,\n // The resulting actions that match the above types\n Output extends Input = Extract<Input, Action<Type>>\n>(...types: [Type, ...Type[]]): OperatorFunction<Input, Output> {\n const len = types.length;\n\n if (process.env.NODE_ENV !== 'production') {\n if (len === 0) {\n warn('ofType was called without any types!');\n }\n if (types.some((key) => key === null || key === undefined)) {\n warn('ofType was called with one or more undefined or null values!');\n }\n }\n\n return filter(\n len === 1\n ? (action): action is Output => isAction(action) && action.type === types[0]\n : (action): action is Output => {\n if (isAction(action)) {\n for (let i = 0; i < len; i++) {\n if (action.type === types[i]) {\n return true;\n }\n }\n }\n\n return false;\n }\n );\n}\n"],"mappings":"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","names":["Observable","Subject","StateObservable","input$","initialState","subscriber","subscription","value","merge","combineEpics","epics","merger","args","epic","output$","Subject","from","queueScheduler","map","mergeMap","observeOn","subscribeOn","deprecationsSeen","resetDeprecationsSeen","consoleWarn","createEpicMiddleware","options","QueueScheduler","queueScheduler","uniqueQueueScheduler","epic$","Subject","store","epicMiddleware","_store","actionSubject$","stateSubject$","action$","observeOn","state$","StateObservable","map","epic","output$","mergeMap","from","subscribeOn","next","action","result","rootEpic","isAction","filter","ofType","types","len","filter","action","isAction","i"]}