saga-toolkit 2.2.3 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +28 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/effects.ts +17 -36
- package/src/types.ts +3 -1
- package/src/utils.ts +27 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AsyncThunk, AsyncThunkAction } from '@reduxjs/toolkit';
|
|
2
2
|
import * as redux_saga_effects from 'redux-saga/effects';
|
|
3
3
|
import { ActionPattern, PutEffect } from 'redux-saga/effects';
|
|
4
|
-
import { Channel } from 'redux-saga';
|
|
4
|
+
import { Channel, Task } from 'redux-saga';
|
|
5
5
|
import { Action } from 'redux';
|
|
6
6
|
|
|
7
7
|
type SagaWorker = (...args: unknown[]) => unknown;
|
|
@@ -13,13 +13,19 @@ interface Deferred<T = unknown> {
|
|
|
13
13
|
interface Request {
|
|
14
14
|
requestId?: string;
|
|
15
15
|
deferred?: Deferred;
|
|
16
|
-
onAdd?: (request: Request) => void;
|
|
17
16
|
abort?: () => void;
|
|
17
|
+
task?: any;
|
|
18
|
+
onAdd?: (request: Request) => void;
|
|
19
|
+
handled?: boolean;
|
|
18
20
|
}
|
|
19
21
|
type SagaAction<Returned, ThunkArg = void> = AsyncThunk<Returned, ThunkArg, object>;
|
|
20
22
|
|
|
21
23
|
declare function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<never>;
|
|
22
|
-
declare function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<Generator<unknown,
|
|
24
|
+
declare function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<Generator<Generator<unknown, Request, unknown> | redux_saga_effects.TakeEffect | redux_saga_effects.ForkEffect<unknown> | redux_saga_effects.CancelEffect, never, {
|
|
25
|
+
meta: {
|
|
26
|
+
requestId: string;
|
|
27
|
+
};
|
|
28
|
+
} & Request & Task<any>>>;
|
|
23
29
|
declare function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<never>;
|
|
24
30
|
declare function putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown>;
|
|
25
31
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AsyncThunk, AsyncThunkAction } from '@reduxjs/toolkit';
|
|
2
2
|
import * as redux_saga_effects from 'redux-saga/effects';
|
|
3
3
|
import { ActionPattern, PutEffect } from 'redux-saga/effects';
|
|
4
|
-
import { Channel } from 'redux-saga';
|
|
4
|
+
import { Channel, Task } from 'redux-saga';
|
|
5
5
|
import { Action } from 'redux';
|
|
6
6
|
|
|
7
7
|
type SagaWorker = (...args: unknown[]) => unknown;
|
|
@@ -13,13 +13,19 @@ interface Deferred<T = unknown> {
|
|
|
13
13
|
interface Request {
|
|
14
14
|
requestId?: string;
|
|
15
15
|
deferred?: Deferred;
|
|
16
|
-
onAdd?: (request: Request) => void;
|
|
17
16
|
abort?: () => void;
|
|
17
|
+
task?: any;
|
|
18
|
+
onAdd?: (request: Request) => void;
|
|
19
|
+
handled?: boolean;
|
|
18
20
|
}
|
|
19
21
|
type SagaAction<Returned, ThunkArg = void> = AsyncThunk<Returned, ThunkArg, object>;
|
|
20
22
|
|
|
21
23
|
declare function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<never>;
|
|
22
|
-
declare function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<Generator<unknown,
|
|
24
|
+
declare function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<Generator<Generator<unknown, Request, unknown> | redux_saga_effects.TakeEffect | redux_saga_effects.ForkEffect<unknown> | redux_saga_effects.CancelEffect, never, {
|
|
25
|
+
meta: {
|
|
26
|
+
requestId: string;
|
|
27
|
+
};
|
|
28
|
+
} & Request & Task<any>>>;
|
|
23
29
|
declare function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]): redux_saga_effects.ForkEffect<never>;
|
|
24
30
|
declare function putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown>;
|
|
25
31
|
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,8 @@ var addRequest = (requestId) => {
|
|
|
46
46
|
const request = {
|
|
47
47
|
...requests[requestId],
|
|
48
48
|
requestId,
|
|
49
|
-
deferred: deferred2
|
|
49
|
+
deferred: deferred2,
|
|
50
|
+
handled: false
|
|
50
51
|
};
|
|
51
52
|
if (requests[requestId]) {
|
|
52
53
|
requests[requestId].deferred = deferred2;
|
|
@@ -56,6 +57,11 @@ var addRequest = (requestId) => {
|
|
|
56
57
|
} else {
|
|
57
58
|
requests[requestId] = request;
|
|
58
59
|
}
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
if (requests[requestId] && !requests[requestId].handled) {
|
|
62
|
+
delete requests[requestId];
|
|
63
|
+
}
|
|
64
|
+
}, 3e4);
|
|
59
65
|
return deferred2.promise;
|
|
60
66
|
};
|
|
61
67
|
var cleanup = (requestId) => {
|
|
@@ -68,10 +74,14 @@ var setRequestAbort = (requestId, abort) => {
|
|
|
68
74
|
};
|
|
69
75
|
function* getRequest(requestId) {
|
|
70
76
|
const request = requests[requestId];
|
|
77
|
+
if (request) {
|
|
78
|
+
request.handled = true;
|
|
79
|
+
}
|
|
71
80
|
if (!request) {
|
|
72
81
|
const result = yield new Promise((onAdd) => {
|
|
73
82
|
requests[requestId] = {
|
|
74
|
-
onAdd: (req) => onAdd(req)
|
|
83
|
+
onAdd: (req) => onAdd(req),
|
|
84
|
+
handled: true
|
|
75
85
|
};
|
|
76
86
|
});
|
|
77
87
|
return result;
|
|
@@ -116,37 +126,26 @@ function takeEveryAsync(pattern, saga, ...args) {
|
|
|
116
126
|
return takeEveryHelper(pattern, wrap(saga), ...args);
|
|
117
127
|
}
|
|
118
128
|
function takeLatestAsync(pattern, saga, ...args) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (deferred2) {
|
|
123
|
-
const lastRequestId = yield deferred2.promise;
|
|
124
|
-
const request = yield getRequest(lastRequestId);
|
|
125
|
-
if (request.abort) {
|
|
126
|
-
request.abort();
|
|
127
|
-
}
|
|
128
|
-
const task = yield tasks[lastRequestId].promise;
|
|
129
|
-
yield (0, import_effects.cancel)(task);
|
|
130
|
-
}
|
|
131
|
-
deferred2 = deferred();
|
|
132
|
-
const { requestId } = action.meta;
|
|
133
|
-
yield getRequest(requestId);
|
|
134
|
-
if (deferred2) {
|
|
135
|
-
deferred2.resolve(requestId);
|
|
136
|
-
}
|
|
137
|
-
yield wrap(saga)(action, ...rest);
|
|
138
|
-
deferred2 = null;
|
|
139
|
-
}
|
|
140
|
-
const customTakeEvery = (patternOrChannel, saga2, ...args2) => (0, import_effects.fork)(function* () {
|
|
129
|
+
return (0, import_effects.fork)(function* () {
|
|
130
|
+
let lastTask = null;
|
|
131
|
+
let lastRequestId = null;
|
|
141
132
|
while (true) {
|
|
142
|
-
const action = yield (0, import_effects.take)(
|
|
133
|
+
const action = yield (0, import_effects.take)(pattern);
|
|
143
134
|
const { requestId } = action.meta;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
135
|
+
if (lastTask) {
|
|
136
|
+
if (lastRequestId) {
|
|
137
|
+
const lastRequest = yield getRequest(lastRequestId);
|
|
138
|
+
if (lastRequest.abort) {
|
|
139
|
+
lastRequest.abort();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
yield (0, import_effects.cancel)(lastTask);
|
|
143
|
+
}
|
|
144
|
+
lastRequestId = requestId;
|
|
145
|
+
const worker = wrap(saga);
|
|
146
|
+
lastTask = yield (0, import_effects.fork)(worker, ...args.concat(action));
|
|
147
147
|
}
|
|
148
148
|
});
|
|
149
|
-
return customTakeEvery(pattern, wrapper, ...args);
|
|
150
149
|
}
|
|
151
150
|
function takeAggregateAsync(pattern, saga, ...args) {
|
|
152
151
|
let deferred2;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/@redux-saga/deferred/dist/redux-saga-deferred.esm.js","../src/utils.ts","../src/effects.ts"],"sourcesContent":["import { createAsyncThunk } from '@reduxjs/toolkit'\nimport type { ThunkDispatch } from '@reduxjs/toolkit'\nimport type { Action } from 'redux'\nimport { addRequest, setRequestAbort } from './utils'\nimport { SagaAction } from './types'\n\nexport * from './types'\nexport * from './effects'\n\nexport const createSagaAction = <Returned, ThunkArg = void>(type: string): SagaAction<Returned, ThunkArg> => {\n const thunk = createAsyncThunk<Returned, ThunkArg>(type, (_, { requestId }) => addRequest(requestId) as Promise<Returned>)\n\n function actionCreator(arg: ThunkArg) {\n const originalActionCreator = thunk(arg)\n\n return (dispatch: ThunkDispatch<unknown, unknown, Action>, getState: () => unknown, extra: unknown) => {\n const promise = originalActionCreator(dispatch, getState, extra)\n if (promise.requestId) {\n setRequestAbort(promise.requestId, promise.abort)\n }\n\n return promise\n }\n }\n\n Object.assign(actionCreator, {\n pending: thunk.pending,\n rejected: thunk.rejected,\n fulfilled: thunk.fulfilled,\n typePrefix: thunk.typePrefix,\n type: (thunk.pending as unknown as { type: string }).type,\n })\n\n return actionCreator as unknown as SagaAction<Returned, ThunkArg>\n}\n","function deferred() {\n var def = {};\n def.promise = new Promise(function (resolve, reject) {\n def.resolve = resolve;\n def.reject = reject;\n });\n return def;\n}\nfunction arrayOfDeferred(length) {\n var arr = [];\n for (var i = 0; i < length; i++) {\n arr.push(deferred());\n }\n return arr;\n}\n\nexport { arrayOfDeferred, deferred as default };\n","import createDeferred from '@redux-saga/deferred'\nimport { Request, SagaWorker } from './types'\n\nconst requests: Record<string, Request> = {}\n\nexport const addRequest = (requestId: string) => {\n const deferred = createDeferred()\n const request: Request = {\n ...requests[requestId],\n requestId,\n deferred,\n }\n\n if (requests[requestId]) {\n requests[requestId].deferred = deferred\n if (requests[requestId].onAdd) {\n requests[requestId].onAdd(request)\n }\n } else {\n requests[requestId] = request\n }\n\n return deferred.promise\n}\n\nexport const cleanup = (requestId: string) => {\n delete requests[requestId]\n}\n\nexport const setRequestAbort = (requestId: string, abort: () => void) => {\n if (requests[requestId]) {\n requests[requestId].abort = abort\n }\n}\n\nexport function* getRequest(requestId: string): Generator<unknown, Request, unknown> {\n const request = requests[requestId]\n\n if (!request) {\n const result = yield (new Promise(onAdd => {\n requests[requestId] = {\n onAdd: (req: Request) => onAdd(req)\n }\n }))\n return result as Request\n }\n\n return request\n}\n\nexport const wrap = (saga: SagaWorker) => function* (action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n const request = (yield getRequest(requestId)) as Request\n\n if (!request.deferred) return\n\n const deferred = request.deferred\n let isFinished = false\n\n try {\n const result = yield saga(action, ...rest)\n deferred.resolve(result)\n isFinished = true\n } catch (error) {\n deferred.reject(error)\n isFinished = true\n } finally {\n if (!isFinished) {\n deferred.reject(new Error('Aborted'))\n const currentRequest = requests[requestId]\n if (currentRequest && currentRequest.abort) {\n currentRequest.abort()\n }\n }\n cleanup(requestId)\n }\n}\n","import { put, take, fork, cancel } from 'redux-saga/effects'\nimport type { PutEffect, ActionPattern } from 'redux-saga/effects'\nimport type { Task, Channel } from 'redux-saga'\nimport type { Action } from 'redux'\nimport createDeferred from '@redux-saga/deferred'\nimport { AsyncThunkAction, unwrapResult } from '@reduxjs/toolkit'\nimport { SagaWorker, Deferred, Request } from './types'\nimport { wrap, getRequest, cleanup } from './utils'\n\n// Helper to avoid 'takeEvery' overload issues with spread arguments\nconst takeEveryHelper = (patternOrChannel: ActionPattern | Channel<Action>, worker: SagaWorker, ...args: unknown[]) => fork(function* () {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as Action\n yield fork(worker, ...args.concat(action))\n }\n})\n\nexport function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrap(saga as unknown as SagaWorker), ...args)\n}\n\nexport function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n const tasks: Record<string, Deferred> = {}\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n if (deferred) {\n const lastRequestId = (yield deferred.promise) as string\n const request = (yield getRequest(lastRequestId)) as Request\n\n if (request.abort) {\n request.abort()\n }\n\n const task = (yield tasks[lastRequestId].promise) as Task\n\n yield cancel(task)\n }\n\n deferred = createDeferred()\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n yield getRequest(requestId) // Ensure request is registered/ready if needed\n\n if (deferred) {\n deferred.resolve(requestId)\n }\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n deferred = null\n }\n\n const customTakeEvery = (patternOrChannel: ActionPattern | Channel<Action>, saga: SagaWorker, ...args: unknown[]) => fork(function* (): Generator<unknown, void, unknown> {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as { meta: { requestId: string } }\n const { requestId } = action.meta\n tasks[requestId] = createDeferred()\n const task = (yield fork(saga, ...args.concat(action))) as Task\n tasks[requestId].resolve(task)\n }\n })\n\n return customTakeEvery(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n if (deferred) {\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { resolve, reject } = request.deferred\n const { promise } = (yield deferred.promise) as { promise: Promise<unknown> }\n\n promise\n .then(resolve, reject)\n .finally(() => cleanup(requestId))\n .catch(() => { })\n }\n } else {\n deferred = createDeferred()\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { promise } = request.deferred\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n if (deferred) {\n deferred.resolve({ promise })\n }\n deferred = null\n }\n }\n }\n\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function* putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown> {\n const promise = yield put(action as Action)\n const result = yield (promise as Promise<unknown>)\n return unwrapResult(result as { payload: unknown, error?: unknown, meta?: unknown })\n}\n"],"mappings":"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","names":["import_toolkit","deferred","deferred","saga","args"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/@redux-saga/deferred/dist/redux-saga-deferred.esm.js","../src/utils.ts","../src/effects.ts"],"sourcesContent":["import { createAsyncThunk } from '@reduxjs/toolkit'\nimport type { ThunkDispatch } from '@reduxjs/toolkit'\nimport type { Action } from 'redux'\nimport { addRequest, setRequestAbort } from './utils'\nimport { SagaAction } from './types'\n\nexport * from './types'\nexport * from './effects'\n\nexport const createSagaAction = <Returned, ThunkArg = void>(type: string): SagaAction<Returned, ThunkArg> => {\n const thunk = createAsyncThunk<Returned, ThunkArg>(type, (_, { requestId }) => addRequest(requestId) as Promise<Returned>)\n\n function actionCreator(arg: ThunkArg) {\n const originalActionCreator = thunk(arg)\n\n return (dispatch: ThunkDispatch<unknown, unknown, Action>, getState: () => unknown, extra: unknown) => {\n const promise = originalActionCreator(dispatch, getState, extra)\n if (promise.requestId) {\n setRequestAbort(promise.requestId, promise.abort)\n }\n\n return promise\n }\n }\n\n Object.assign(actionCreator, {\n pending: thunk.pending,\n rejected: thunk.rejected,\n fulfilled: thunk.fulfilled,\n typePrefix: thunk.typePrefix,\n type: (thunk.pending as unknown as { type: string }).type,\n })\n\n return actionCreator as unknown as SagaAction<Returned, ThunkArg>\n}\n","function deferred() {\n var def = {};\n def.promise = new Promise(function (resolve, reject) {\n def.resolve = resolve;\n def.reject = reject;\n });\n return def;\n}\nfunction arrayOfDeferred(length) {\n var arr = [];\n for (var i = 0; i < length; i++) {\n arr.push(deferred());\n }\n return arr;\n}\n\nexport { arrayOfDeferred, deferred as default };\n","import createDeferred from '@redux-saga/deferred'\nimport { Request, SagaWorker } from './types'\n\nconst requests: Record<string, Request> = {}\n\nexport const addRequest = (requestId: string) => {\n const deferred = createDeferred()\n const request: Request = {\n ...requests[requestId],\n requestId,\n deferred,\n handled: false\n }\n\n if (requests[requestId]) {\n requests[requestId].deferred = deferred\n if (requests[requestId].onAdd) {\n requests[requestId].onAdd(request)\n }\n } else {\n requests[requestId] = request\n }\n\n // Auto-cleanup if not picked up by a saga within 30 seconds\n setTimeout(() => {\n if (requests[requestId] && !requests[requestId].handled) {\n delete requests[requestId]\n }\n }, 30000)\n\n return deferred.promise\n}\n\nexport const cleanup = (requestId: string) => {\n delete requests[requestId]\n}\n\n/** @internal */\nexport const _clearInternalState = () => {\n for (const key in requests) {\n delete requests[key]\n }\n}\n\nexport const setRequestAbort = (requestId: string, abort: () => void) => {\n if (requests[requestId]) {\n requests[requestId].abort = abort\n }\n}\n\nexport function* getRequest(requestId: string): Generator<unknown, Request, unknown> {\n const request = requests[requestId]\n\n if (request) {\n request.handled = true\n }\n\n if (!request) {\n const result = yield (new Promise(onAdd => {\n requests[requestId] = {\n onAdd: (req: Request) => onAdd(req),\n handled: true\n }\n }))\n return result as Request\n }\n\n return request\n}\n\nexport const wrap = (saga: SagaWorker) => function* (action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n const request = (yield getRequest(requestId)) as Request\n\n if (!request.deferred) return\n\n const deferred = request.deferred\n let isFinished = false\n\n try {\n const result = yield saga(action, ...rest)\n deferred.resolve(result)\n isFinished = true\n } catch (error) {\n deferred.reject(error)\n isFinished = true\n } finally {\n if (!isFinished) {\n deferred.reject(new Error('Aborted'))\n const currentRequest = requests[requestId]\n if (currentRequest && currentRequest.abort) {\n currentRequest.abort()\n }\n }\n cleanup(requestId)\n }\n}\n\n/** @internal */\nexport const _getInternalState = () => ({\n requests,\n size: Object.keys(requests).length\n})\n","import { put, take, fork, cancel } from 'redux-saga/effects'\nimport type { PutEffect, ActionPattern } from 'redux-saga/effects'\nimport type { Task, Channel } from 'redux-saga'\nimport type { Action } from 'redux'\nimport createDeferred from '@redux-saga/deferred'\nimport { AsyncThunkAction, unwrapResult } from '@reduxjs/toolkit'\nimport { SagaWorker, Deferred, Request } from './types'\nimport { wrap, getRequest, cleanup } from './utils'\n\n// Helper to avoid 'takeEvery' overload issues with spread arguments\nconst takeEveryHelper = (patternOrChannel: ActionPattern | Channel<Action>, worker: SagaWorker, ...args: unknown[]) => fork(function* () {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as Action\n yield fork(worker, ...args.concat(action))\n }\n})\n\nexport function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrap(saga as unknown as SagaWorker), ...args)\n}\n\nexport function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return fork(function* () {\n let lastTask: Task | null = null\n let lastRequestId: string | null = null\n\n while (true) {\n const action = (yield take(pattern as unknown as ActionPattern)) as { meta: { requestId: string } }\n const { requestId } = action.meta\n\n if (lastTask) {\n if (lastRequestId) {\n const lastRequest = (yield getRequest(lastRequestId)) as Request\n if (lastRequest.abort) {\n lastRequest.abort()\n }\n }\n yield cancel(lastTask)\n }\n\n lastRequestId = requestId\n const worker = wrap(saga as unknown as SagaWorker)\n lastTask = (yield fork(worker as any, ...args.concat(action))) as Task\n }\n })\n}\n\nexport function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n if (deferred) {\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { resolve, reject } = request.deferred\n const { promise } = (yield deferred.promise) as { promise: Promise<unknown> }\n\n promise\n .then(resolve, reject)\n .finally(() => cleanup(requestId))\n .catch(() => { })\n }\n } else {\n deferred = createDeferred()\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { promise } = request.deferred\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n if (deferred) {\n deferred.resolve({ promise })\n }\n deferred = null\n }\n }\n }\n\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function* putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown> {\n const promise = yield put(action as Action)\n const result = yield (promise as Promise<unknown>)\n return unwrapResult(result as { payload: unknown, error?: unknown, meta?: unknown })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,kBAAiC;;;ACAjC,SAAS,WAAW;AAClB,MAAI,MAAM,CAAC;AACX,MAAI,UAAU,IAAI,QAAQ,SAAU,SAAS,QAAQ;AACnD,QAAI,UAAU;AACd,QAAI,SAAS;AAAA,EACf,CAAC;AACD,SAAO;AACT;;;ACJA,IAAM,WAAoC,CAAC;AAEpC,IAAM,aAAa,CAAC,cAAsB;AAC7C,QAAMC,YAAW,SAAe;AAChC,QAAM,UAAmB;AAAA,IACrB,GAAG,SAAS,SAAS;AAAA,IACrB;AAAA,IACA,UAAAA;AAAA,IACA,SAAS;AAAA,EACb;AAEA,MAAI,SAAS,SAAS,GAAG;AACrB,aAAS,SAAS,EAAE,WAAWA;AAC/B,QAAI,SAAS,SAAS,EAAE,OAAO;AAC3B,eAAS,SAAS,EAAE,MAAM,OAAO;AAAA,IACrC;AAAA,EACJ,OAAO;AACH,aAAS,SAAS,IAAI;AAAA,EAC1B;AAGA,aAAW,MAAM;AACb,QAAI,SAAS,SAAS,KAAK,CAAC,SAAS,SAAS,EAAE,SAAS;AACrD,aAAO,SAAS,SAAS;AAAA,IAC7B;AAAA,EACJ,GAAG,GAAK;AAER,SAAOA,UAAS;AACpB;AAEO,IAAM,UAAU,CAAC,cAAsB;AAC1C,SAAO,SAAS,SAAS;AAC7B;AASO,IAAM,kBAAkB,CAAC,WAAmB,UAAsB;AACrE,MAAI,SAAS,SAAS,GAAG;AACrB,aAAS,SAAS,EAAE,QAAQ;AAAA,EAChC;AACJ;AAEO,UAAU,WAAW,WAAyD;AACjF,QAAM,UAAU,SAAS,SAAS;AAElC,MAAI,SAAS;AACT,YAAQ,UAAU;AAAA,EACtB;AAEA,MAAI,CAAC,SAAS;AACV,UAAM,SAAS,MAAO,IAAI,QAAQ,WAAS;AACvC,eAAS,SAAS,IAAI;AAAA,QAClB,OAAO,CAAC,QAAiB,MAAM,GAAG;AAAA,QAClC,SAAS;AAAA,MACb;AAAA,IACJ,CAAC;AACD,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAEO,IAAM,OAAO,CAAC,SAAqB,WAAW,WAAoB,MAAoD;AACzH,QAAM,EAAE,UAAU,IAAK,OAA2C;AAClE,QAAM,UAAW,MAAM,WAAW,SAAS;AAE3C,MAAI,CAAC,QAAQ,SAAU;AAEvB,QAAMC,YAAW,QAAQ;AACzB,MAAI,aAAa;AAEjB,MAAI;AACA,UAAM,SAAS,MAAM,KAAK,QAAQ,GAAG,IAAI;AACzC,IAAAA,UAAS,QAAQ,MAAM;AACvB,iBAAa;AAAA,EACjB,SAAS,OAAO;AACZ,IAAAA,UAAS,OAAO,KAAK;AACrB,iBAAa;AAAA,EACjB,UAAE;AACE,QAAI,CAAC,YAAY;AACb,MAAAA,UAAS,OAAO,IAAI,MAAM,SAAS,CAAC;AACpC,YAAM,iBAAiB,SAAS,SAAS;AACzC,UAAI,kBAAkB,eAAe,OAAO;AACxC,uBAAe,MAAM;AAAA,MACzB;AAAA,IACJ;AACA,YAAQ,SAAS;AAAA,EACrB;AACJ;;;AChGA,qBAAwC;AAKxC,qBAA+C;AAK/C,IAAM,kBAAkB,CAAC,kBAAmD,WAAuB,aAAoB,qBAAK,aAAa;AACrI,SAAO,MAAM;AACT,UAAM,SAAU,UAAM,qBAAK,gBAA4C;AACvE,cAAM,qBAAK,QAAQ,GAAG,KAAK,OAAO,MAAM,CAAC;AAAA,EAC7C;AACJ,CAAC;AAEM,SAAS,eAA0C,SAAwC,SAAqD,MAAiB;AACpK,SAAO,gBAAgB,SAA4C,KAAK,IAA6B,GAAG,GAAG,IAAI;AACnH;AAEO,SAAS,gBAA2C,SAAwC,SAAqD,MAAiB;AACrK,aAAO,qBAAK,aAAa;AACrB,QAAI,WAAwB;AAC5B,QAAI,gBAA+B;AAEnC,WAAO,MAAM;AACT,YAAM,SAAU,UAAM,qBAAK,OAAmC;AAC9D,YAAM,EAAE,UAAU,IAAI,OAAO;AAE7B,UAAI,UAAU;AACV,YAAI,eAAe;AACf,gBAAM,cAAe,MAAM,WAAW,aAAa;AACnD,cAAI,YAAY,OAAO;AACnB,wBAAY,MAAM;AAAA,UACtB;AAAA,QACJ;AACA,kBAAM,uBAAO,QAAQ;AAAA,MACzB;AAEA,sBAAgB;AAChB,YAAM,SAAS,KAAK,IAA6B;AACjD,iBAAY,UAAM,qBAAK,QAAe,GAAG,KAAK,OAAO,MAAM,CAAC;AAAA,IAChE;AAAA,EACJ,CAAC;AACL;AAEO,SAAS,mBAA8C,SAAwC,SAAqD,MAAiB;AACxK,MAAIC;AAEJ,YAAU,QAAQ,WAAoB,MAAoD;AACtF,UAAM,EAAE,UAAU,IAAK,OAA2C;AAElE,QAAIA,WAAU;AACV,YAAM,UAAW,MAAM,WAAW,SAAS;AAC3C,UAAI,QAAQ,UAAU;AAClB,cAAM,EAAE,SAAS,OAAO,IAAI,QAAQ;AACpC,cAAM,EAAE,QAAQ,IAAK,MAAMA,UAAS;AAEpC,gBACK,KAAK,SAAS,MAAM,EACpB,QAAQ,MAAM,QAAQ,SAAS,CAAC,EAChC,MAAM,MAAM;AAAA,QAAE,CAAC;AAAA,MACxB;AAAA,IACJ,OAAO;AACH,MAAAA,YAAW,SAAe;AAC1B,YAAM,UAAW,MAAM,WAAW,SAAS;AAC3C,UAAI,QAAQ,UAAU;AAClB,cAAM,EAAE,QAAQ,IAAI,QAAQ;AAE5B,cAAM,KAAK,IAA6B,EAAE,QAAQ,GAAG,IAAI;AAEzD,YAAIA,WAAU;AACV,UAAAA,UAAS,QAAQ,EAAE,QAAQ,CAAC;AAAA,QAChC;AACA,QAAAA,YAAW;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,gBAAgB,SAA4C,SAAS,GAAG,IAAI;AACvF;AAEO,UAAU,SAAS,QAAoI;AAC1J,QAAM,UAAU,UAAM,oBAAI,MAAgB;AAC1C,QAAM,SAAS,MAAO;AACtB,aAAO,6BAAa,MAA+D;AACvF;;;AH9EO,IAAM,mBAAmB,CAA4B,SAAiD;AACzG,QAAM,YAAQ,kCAAqC,MAAM,CAAC,GAAG,EAAE,UAAU,MAAM,WAAW,SAAS,CAAsB;AAEzH,WAAS,cAAc,KAAe;AAClC,UAAM,wBAAwB,MAAM,GAAG;AAEvC,WAAO,CAAC,UAAmD,UAAyB,UAAmB;AACnG,YAAM,UAAU,sBAAsB,UAAU,UAAU,KAAK;AAC/D,UAAI,QAAQ,WAAW;AACnB,wBAAgB,QAAQ,WAAW,QAAQ,KAAK;AAAA,MACpD;AAEA,aAAO;AAAA,IACX;AAAA,EACJ;AAEA,SAAO,OAAO,eAAe;AAAA,IACzB,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,YAAY,MAAM;AAAA,IAClB,MAAO,MAAM,QAAwC;AAAA,EACzD,CAAC;AAED,SAAO;AACX;","names":["import_toolkit","deferred","deferred","deferred"]}
|
package/dist/index.mjs
CHANGED
|
@@ -18,7 +18,8 @@ var addRequest = (requestId) => {
|
|
|
18
18
|
const request = {
|
|
19
19
|
...requests[requestId],
|
|
20
20
|
requestId,
|
|
21
|
-
deferred: deferred2
|
|
21
|
+
deferred: deferred2,
|
|
22
|
+
handled: false
|
|
22
23
|
};
|
|
23
24
|
if (requests[requestId]) {
|
|
24
25
|
requests[requestId].deferred = deferred2;
|
|
@@ -28,6 +29,11 @@ var addRequest = (requestId) => {
|
|
|
28
29
|
} else {
|
|
29
30
|
requests[requestId] = request;
|
|
30
31
|
}
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
if (requests[requestId] && !requests[requestId].handled) {
|
|
34
|
+
delete requests[requestId];
|
|
35
|
+
}
|
|
36
|
+
}, 3e4);
|
|
31
37
|
return deferred2.promise;
|
|
32
38
|
};
|
|
33
39
|
var cleanup = (requestId) => {
|
|
@@ -40,10 +46,14 @@ var setRequestAbort = (requestId, abort) => {
|
|
|
40
46
|
};
|
|
41
47
|
function* getRequest(requestId) {
|
|
42
48
|
const request = requests[requestId];
|
|
49
|
+
if (request) {
|
|
50
|
+
request.handled = true;
|
|
51
|
+
}
|
|
43
52
|
if (!request) {
|
|
44
53
|
const result = yield new Promise((onAdd) => {
|
|
45
54
|
requests[requestId] = {
|
|
46
|
-
onAdd: (req) => onAdd(req)
|
|
55
|
+
onAdd: (req) => onAdd(req),
|
|
56
|
+
handled: true
|
|
47
57
|
};
|
|
48
58
|
});
|
|
49
59
|
return result;
|
|
@@ -88,37 +98,26 @@ function takeEveryAsync(pattern, saga, ...args) {
|
|
|
88
98
|
return takeEveryHelper(pattern, wrap(saga), ...args);
|
|
89
99
|
}
|
|
90
100
|
function takeLatestAsync(pattern, saga, ...args) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (deferred2) {
|
|
95
|
-
const lastRequestId = yield deferred2.promise;
|
|
96
|
-
const request = yield getRequest(lastRequestId);
|
|
97
|
-
if (request.abort) {
|
|
98
|
-
request.abort();
|
|
99
|
-
}
|
|
100
|
-
const task = yield tasks[lastRequestId].promise;
|
|
101
|
-
yield cancel(task);
|
|
102
|
-
}
|
|
103
|
-
deferred2 = deferred();
|
|
104
|
-
const { requestId } = action.meta;
|
|
105
|
-
yield getRequest(requestId);
|
|
106
|
-
if (deferred2) {
|
|
107
|
-
deferred2.resolve(requestId);
|
|
108
|
-
}
|
|
109
|
-
yield wrap(saga)(action, ...rest);
|
|
110
|
-
deferred2 = null;
|
|
111
|
-
}
|
|
112
|
-
const customTakeEvery = (patternOrChannel, saga2, ...args2) => fork(function* () {
|
|
101
|
+
return fork(function* () {
|
|
102
|
+
let lastTask = null;
|
|
103
|
+
let lastRequestId = null;
|
|
113
104
|
while (true) {
|
|
114
|
-
const action = yield take(
|
|
105
|
+
const action = yield take(pattern);
|
|
115
106
|
const { requestId } = action.meta;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
107
|
+
if (lastTask) {
|
|
108
|
+
if (lastRequestId) {
|
|
109
|
+
const lastRequest = yield getRequest(lastRequestId);
|
|
110
|
+
if (lastRequest.abort) {
|
|
111
|
+
lastRequest.abort();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
yield cancel(lastTask);
|
|
115
|
+
}
|
|
116
|
+
lastRequestId = requestId;
|
|
117
|
+
const worker = wrap(saga);
|
|
118
|
+
lastTask = yield fork(worker, ...args.concat(action));
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
|
-
return customTakeEvery(pattern, wrapper, ...args);
|
|
122
121
|
}
|
|
123
122
|
function takeAggregateAsync(pattern, saga, ...args) {
|
|
124
123
|
let deferred2;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/@redux-saga/deferred/dist/redux-saga-deferred.esm.js","../src/utils.ts","../src/effects.ts"],"sourcesContent":["import { createAsyncThunk } from '@reduxjs/toolkit'\nimport type { ThunkDispatch } from '@reduxjs/toolkit'\nimport type { Action } from 'redux'\nimport { addRequest, setRequestAbort } from './utils'\nimport { SagaAction } from './types'\n\nexport * from './types'\nexport * from './effects'\n\nexport const createSagaAction = <Returned, ThunkArg = void>(type: string): SagaAction<Returned, ThunkArg> => {\n const thunk = createAsyncThunk<Returned, ThunkArg>(type, (_, { requestId }) => addRequest(requestId) as Promise<Returned>)\n\n function actionCreator(arg: ThunkArg) {\n const originalActionCreator = thunk(arg)\n\n return (dispatch: ThunkDispatch<unknown, unknown, Action>, getState: () => unknown, extra: unknown) => {\n const promise = originalActionCreator(dispatch, getState, extra)\n if (promise.requestId) {\n setRequestAbort(promise.requestId, promise.abort)\n }\n\n return promise\n }\n }\n\n Object.assign(actionCreator, {\n pending: thunk.pending,\n rejected: thunk.rejected,\n fulfilled: thunk.fulfilled,\n typePrefix: thunk.typePrefix,\n type: (thunk.pending as unknown as { type: string }).type,\n })\n\n return actionCreator as unknown as SagaAction<Returned, ThunkArg>\n}\n","function deferred() {\n var def = {};\n def.promise = new Promise(function (resolve, reject) {\n def.resolve = resolve;\n def.reject = reject;\n });\n return def;\n}\nfunction arrayOfDeferred(length) {\n var arr = [];\n for (var i = 0; i < length; i++) {\n arr.push(deferred());\n }\n return arr;\n}\n\nexport { arrayOfDeferred, deferred as default };\n","import createDeferred from '@redux-saga/deferred'\nimport { Request, SagaWorker } from './types'\n\nconst requests: Record<string, Request> = {}\n\nexport const addRequest = (requestId: string) => {\n const deferred = createDeferred()\n const request: Request = {\n ...requests[requestId],\n requestId,\n deferred,\n }\n\n if (requests[requestId]) {\n requests[requestId].deferred = deferred\n if (requests[requestId].onAdd) {\n requests[requestId].onAdd(request)\n }\n } else {\n requests[requestId] = request\n }\n\n return deferred.promise\n}\n\nexport const cleanup = (requestId: string) => {\n delete requests[requestId]\n}\n\nexport const setRequestAbort = (requestId: string, abort: () => void) => {\n if (requests[requestId]) {\n requests[requestId].abort = abort\n }\n}\n\nexport function* getRequest(requestId: string): Generator<unknown, Request, unknown> {\n const request = requests[requestId]\n\n if (!request) {\n const result = yield (new Promise(onAdd => {\n requests[requestId] = {\n onAdd: (req: Request) => onAdd(req)\n }\n }))\n return result as Request\n }\n\n return request\n}\n\nexport const wrap = (saga: SagaWorker) => function* (action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n const request = (yield getRequest(requestId)) as Request\n\n if (!request.deferred) return\n\n const deferred = request.deferred\n let isFinished = false\n\n try {\n const result = yield saga(action, ...rest)\n deferred.resolve(result)\n isFinished = true\n } catch (error) {\n deferred.reject(error)\n isFinished = true\n } finally {\n if (!isFinished) {\n deferred.reject(new Error('Aborted'))\n const currentRequest = requests[requestId]\n if (currentRequest && currentRequest.abort) {\n currentRequest.abort()\n }\n }\n cleanup(requestId)\n }\n}\n","import { put, take, fork, cancel } from 'redux-saga/effects'\nimport type { PutEffect, ActionPattern } from 'redux-saga/effects'\nimport type { Task, Channel } from 'redux-saga'\nimport type { Action } from 'redux'\nimport createDeferred from '@redux-saga/deferred'\nimport { AsyncThunkAction, unwrapResult } from '@reduxjs/toolkit'\nimport { SagaWorker, Deferred, Request } from './types'\nimport { wrap, getRequest, cleanup } from './utils'\n\n// Helper to avoid 'takeEvery' overload issues with spread arguments\nconst takeEveryHelper = (patternOrChannel: ActionPattern | Channel<Action>, worker: SagaWorker, ...args: unknown[]) => fork(function* () {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as Action\n yield fork(worker, ...args.concat(action))\n }\n})\n\nexport function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrap(saga as unknown as SagaWorker), ...args)\n}\n\nexport function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n const tasks: Record<string, Deferred> = {}\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n if (deferred) {\n const lastRequestId = (yield deferred.promise) as string\n const request = (yield getRequest(lastRequestId)) as Request\n\n if (request.abort) {\n request.abort()\n }\n\n const task = (yield tasks[lastRequestId].promise) as Task\n\n yield cancel(task)\n }\n\n deferred = createDeferred()\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n yield getRequest(requestId) // Ensure request is registered/ready if needed\n\n if (deferred) {\n deferred.resolve(requestId)\n }\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n deferred = null\n }\n\n const customTakeEvery = (patternOrChannel: ActionPattern | Channel<Action>, saga: SagaWorker, ...args: unknown[]) => fork(function* (): Generator<unknown, void, unknown> {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as { meta: { requestId: string } }\n const { requestId } = action.meta\n tasks[requestId] = createDeferred()\n const task = (yield fork(saga, ...args.concat(action))) as Task\n tasks[requestId].resolve(task)\n }\n })\n\n return customTakeEvery(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n if (deferred) {\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { resolve, reject } = request.deferred\n const { promise } = (yield deferred.promise) as { promise: Promise<unknown> }\n\n promise\n .then(resolve, reject)\n .finally(() => cleanup(requestId))\n .catch(() => { })\n }\n } else {\n deferred = createDeferred()\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { promise } = request.deferred\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n if (deferred) {\n deferred.resolve({ promise })\n }\n deferred = null\n }\n }\n }\n\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function* putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown> {\n const promise = yield put(action as Action)\n const result = yield (promise as Promise<unknown>)\n return unwrapResult(result as { payload: unknown, error?: unknown, meta?: unknown })\n}\n"],"mappings":"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","names":["deferred","deferred","saga","args"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/@redux-saga/deferred/dist/redux-saga-deferred.esm.js","../src/utils.ts","../src/effects.ts"],"sourcesContent":["import { createAsyncThunk } from '@reduxjs/toolkit'\nimport type { ThunkDispatch } from '@reduxjs/toolkit'\nimport type { Action } from 'redux'\nimport { addRequest, setRequestAbort } from './utils'\nimport { SagaAction } from './types'\n\nexport * from './types'\nexport * from './effects'\n\nexport const createSagaAction = <Returned, ThunkArg = void>(type: string): SagaAction<Returned, ThunkArg> => {\n const thunk = createAsyncThunk<Returned, ThunkArg>(type, (_, { requestId }) => addRequest(requestId) as Promise<Returned>)\n\n function actionCreator(arg: ThunkArg) {\n const originalActionCreator = thunk(arg)\n\n return (dispatch: ThunkDispatch<unknown, unknown, Action>, getState: () => unknown, extra: unknown) => {\n const promise = originalActionCreator(dispatch, getState, extra)\n if (promise.requestId) {\n setRequestAbort(promise.requestId, promise.abort)\n }\n\n return promise\n }\n }\n\n Object.assign(actionCreator, {\n pending: thunk.pending,\n rejected: thunk.rejected,\n fulfilled: thunk.fulfilled,\n typePrefix: thunk.typePrefix,\n type: (thunk.pending as unknown as { type: string }).type,\n })\n\n return actionCreator as unknown as SagaAction<Returned, ThunkArg>\n}\n","function deferred() {\n var def = {};\n def.promise = new Promise(function (resolve, reject) {\n def.resolve = resolve;\n def.reject = reject;\n });\n return def;\n}\nfunction arrayOfDeferred(length) {\n var arr = [];\n for (var i = 0; i < length; i++) {\n arr.push(deferred());\n }\n return arr;\n}\n\nexport { arrayOfDeferred, deferred as default };\n","import createDeferred from '@redux-saga/deferred'\nimport { Request, SagaWorker } from './types'\n\nconst requests: Record<string, Request> = {}\n\nexport const addRequest = (requestId: string) => {\n const deferred = createDeferred()\n const request: Request = {\n ...requests[requestId],\n requestId,\n deferred,\n handled: false\n }\n\n if (requests[requestId]) {\n requests[requestId].deferred = deferred\n if (requests[requestId].onAdd) {\n requests[requestId].onAdd(request)\n }\n } else {\n requests[requestId] = request\n }\n\n // Auto-cleanup if not picked up by a saga within 30 seconds\n setTimeout(() => {\n if (requests[requestId] && !requests[requestId].handled) {\n delete requests[requestId]\n }\n }, 30000)\n\n return deferred.promise\n}\n\nexport const cleanup = (requestId: string) => {\n delete requests[requestId]\n}\n\n/** @internal */\nexport const _clearInternalState = () => {\n for (const key in requests) {\n delete requests[key]\n }\n}\n\nexport const setRequestAbort = (requestId: string, abort: () => void) => {\n if (requests[requestId]) {\n requests[requestId].abort = abort\n }\n}\n\nexport function* getRequest(requestId: string): Generator<unknown, Request, unknown> {\n const request = requests[requestId]\n\n if (request) {\n request.handled = true\n }\n\n if (!request) {\n const result = yield (new Promise(onAdd => {\n requests[requestId] = {\n onAdd: (req: Request) => onAdd(req),\n handled: true\n }\n }))\n return result as Request\n }\n\n return request\n}\n\nexport const wrap = (saga: SagaWorker) => function* (action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n const request = (yield getRequest(requestId)) as Request\n\n if (!request.deferred) return\n\n const deferred = request.deferred\n let isFinished = false\n\n try {\n const result = yield saga(action, ...rest)\n deferred.resolve(result)\n isFinished = true\n } catch (error) {\n deferred.reject(error)\n isFinished = true\n } finally {\n if (!isFinished) {\n deferred.reject(new Error('Aborted'))\n const currentRequest = requests[requestId]\n if (currentRequest && currentRequest.abort) {\n currentRequest.abort()\n }\n }\n cleanup(requestId)\n }\n}\n\n/** @internal */\nexport const _getInternalState = () => ({\n requests,\n size: Object.keys(requests).length\n})\n","import { put, take, fork, cancel } from 'redux-saga/effects'\nimport type { PutEffect, ActionPattern } from 'redux-saga/effects'\nimport type { Task, Channel } from 'redux-saga'\nimport type { Action } from 'redux'\nimport createDeferred from '@redux-saga/deferred'\nimport { AsyncThunkAction, unwrapResult } from '@reduxjs/toolkit'\nimport { SagaWorker, Deferred, Request } from './types'\nimport { wrap, getRequest, cleanup } from './utils'\n\n// Helper to avoid 'takeEvery' overload issues with spread arguments\nconst takeEveryHelper = (patternOrChannel: ActionPattern | Channel<Action>, worker: SagaWorker, ...args: unknown[]) => fork(function* () {\n while (true) {\n const action = (yield take(patternOrChannel as unknown as ActionPattern)) as Action\n yield fork(worker, ...args.concat(action))\n }\n})\n\nexport function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrap(saga as unknown as SagaWorker), ...args)\n}\n\nexport function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n return fork(function* () {\n let lastTask: Task | null = null\n let lastRequestId: string | null = null\n\n while (true) {\n const action = (yield take(pattern as unknown as ActionPattern)) as { meta: { requestId: string } }\n const { requestId } = action.meta\n\n if (lastTask) {\n if (lastRequestId) {\n const lastRequest = (yield getRequest(lastRequestId)) as Request\n if (lastRequest.abort) {\n lastRequest.abort()\n }\n }\n yield cancel(lastTask)\n }\n\n lastRequestId = requestId\n const worker = wrap(saga as unknown as SagaWorker)\n lastTask = (yield fork(worker as any, ...args.concat(action))) as Task\n }\n })\n}\n\nexport function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {\n let deferred: Deferred | null\n\n function* wrapper(action: unknown, ...rest: unknown[]): Generator<unknown, void, unknown> {\n const { requestId } = (action as { meta: { requestId: string } }).meta\n\n if (deferred) {\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { resolve, reject } = request.deferred\n const { promise } = (yield deferred.promise) as { promise: Promise<unknown> }\n\n promise\n .then(resolve, reject)\n .finally(() => cleanup(requestId))\n .catch(() => { })\n }\n } else {\n deferred = createDeferred()\n const request = (yield getRequest(requestId)) as Request\n if (request.deferred) {\n const { promise } = request.deferred\n\n yield wrap(saga as unknown as SagaWorker)(action, ...rest)\n\n if (deferred) {\n deferred.resolve({ promise })\n }\n deferred = null\n }\n }\n }\n\n return takeEveryHelper(pattern as ActionPattern | Channel<Action>, wrapper, ...args)\n}\n\nexport function* putAsync(action: Action | PutEffect | AsyncThunkAction<unknown, unknown, object>): Generator<PutEffect | Promise<unknown>, unknown, unknown> {\n const promise = yield put(action as Action)\n const result = yield (promise as Promise<unknown>)\n return unwrapResult(result as { payload: unknown, error?: unknown, meta?: unknown })\n}\n"],"mappings":"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","names":["deferred","deferred","deferred"]}
|
package/package.json
CHANGED
package/src/effects.ts
CHANGED
|
@@ -20,48 +20,29 @@ export function takeEveryAsync<A extends Action = Action>(pattern: ActionPattern
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function takeLatestAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
return fork(function* () {
|
|
24
|
+
let lastTask: Task | null = null
|
|
25
|
+
let lastRequestId: string | null = null
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const request = (yield getRequest(lastRequestId)) as Request
|
|
27
|
+
while (true) {
|
|
28
|
+
const action = (yield take(pattern as unknown as ActionPattern)) as { meta: { requestId: string } }
|
|
29
|
+
const { requestId } = action.meta
|
|
30
30
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
31
|
+
if (lastTask) {
|
|
32
|
+
if (lastRequestId) {
|
|
33
|
+
const lastRequest = (yield getRequest(lastRequestId)) as Request
|
|
34
|
+
if (lastRequest.abort) {
|
|
35
|
+
lastRequest.abort()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
yield cancel(lastTask)
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
yield
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
deferred = createDeferred()
|
|
41
|
-
const { requestId } = (action as { meta: { requestId: string } }).meta
|
|
42
|
-
|
|
43
|
-
yield getRequest(requestId) // Ensure request is registered/ready if needed
|
|
44
|
-
|
|
45
|
-
if (deferred) {
|
|
46
|
-
deferred.resolve(requestId)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
yield wrap(saga as unknown as SagaWorker)(action, ...rest)
|
|
50
|
-
|
|
51
|
-
deferred = null
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const customTakeEvery = (patternOrChannel: ActionPattern | Channel<Action>, saga: SagaWorker, ...args: unknown[]) => fork(function* (): Generator<unknown, void, unknown> {
|
|
55
|
-
while (true) {
|
|
56
|
-
const action = (yield take(patternOrChannel as unknown as ActionPattern)) as { meta: { requestId: string } }
|
|
57
|
-
const { requestId } = action.meta
|
|
58
|
-
tasks[requestId] = createDeferred()
|
|
59
|
-
const task = (yield fork(saga, ...args.concat(action))) as Task
|
|
60
|
-
tasks[requestId].resolve(task)
|
|
41
|
+
lastRequestId = requestId
|
|
42
|
+
const worker = wrap(saga as unknown as SagaWorker)
|
|
43
|
+
lastTask = (yield fork(worker as any, ...args.concat(action))) as Task
|
|
61
44
|
}
|
|
62
45
|
})
|
|
63
|
-
|
|
64
|
-
return customTakeEvery(pattern as ActionPattern | Channel<Action>, wrapper, ...args)
|
|
65
46
|
}
|
|
66
47
|
|
|
67
48
|
export function takeAggregateAsync<A extends Action = Action>(pattern: ActionPattern<A> | Channel<A>, saga: (action: A, ...args: unknown[]) => unknown, ...args: unknown[]) {
|
package/src/types.ts
CHANGED
|
@@ -11,8 +11,10 @@ export interface Deferred<T = unknown> {
|
|
|
11
11
|
export interface Request {
|
|
12
12
|
requestId?: string
|
|
13
13
|
deferred?: Deferred
|
|
14
|
-
onAdd?: (request: Request) => void
|
|
15
14
|
abort?: () => void
|
|
15
|
+
task?: any // Using any to avoid circular dependency with Task from redux-saga
|
|
16
|
+
onAdd?: (request: Request) => void
|
|
17
|
+
handled?: boolean
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export type SagaAction<Returned, ThunkArg = void> = AsyncThunk<Returned, ThunkArg, object>
|
package/src/utils.ts
CHANGED
|
@@ -9,6 +9,7 @@ export const addRequest = (requestId: string) => {
|
|
|
9
9
|
...requests[requestId],
|
|
10
10
|
requestId,
|
|
11
11
|
deferred,
|
|
12
|
+
handled: false
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
if (requests[requestId]) {
|
|
@@ -20,6 +21,13 @@ export const addRequest = (requestId: string) => {
|
|
|
20
21
|
requests[requestId] = request
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
// Auto-cleanup if not picked up by a saga within 30 seconds
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
if (requests[requestId] && !requests[requestId].handled) {
|
|
27
|
+
delete requests[requestId]
|
|
28
|
+
}
|
|
29
|
+
}, 30000)
|
|
30
|
+
|
|
23
31
|
return deferred.promise
|
|
24
32
|
}
|
|
25
33
|
|
|
@@ -27,6 +35,13 @@ export const cleanup = (requestId: string) => {
|
|
|
27
35
|
delete requests[requestId]
|
|
28
36
|
}
|
|
29
37
|
|
|
38
|
+
/** @internal */
|
|
39
|
+
export const _clearInternalState = () => {
|
|
40
|
+
for (const key in requests) {
|
|
41
|
+
delete requests[key]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
export const setRequestAbort = (requestId: string, abort: () => void) => {
|
|
31
46
|
if (requests[requestId]) {
|
|
32
47
|
requests[requestId].abort = abort
|
|
@@ -36,10 +51,15 @@ export const setRequestAbort = (requestId: string, abort: () => void) => {
|
|
|
36
51
|
export function* getRequest(requestId: string): Generator<unknown, Request, unknown> {
|
|
37
52
|
const request = requests[requestId]
|
|
38
53
|
|
|
54
|
+
if (request) {
|
|
55
|
+
request.handled = true
|
|
56
|
+
}
|
|
57
|
+
|
|
39
58
|
if (!request) {
|
|
40
59
|
const result = yield (new Promise(onAdd => {
|
|
41
60
|
requests[requestId] = {
|
|
42
|
-
onAdd: (req: Request) => onAdd(req)
|
|
61
|
+
onAdd: (req: Request) => onAdd(req),
|
|
62
|
+
handled: true
|
|
43
63
|
}
|
|
44
64
|
}))
|
|
45
65
|
return result as Request
|
|
@@ -75,3 +95,9 @@ export const wrap = (saga: SagaWorker) => function* (action: unknown, ...rest: u
|
|
|
75
95
|
cleanup(requestId)
|
|
76
96
|
}
|
|
77
97
|
}
|
|
98
|
+
|
|
99
|
+
/** @internal */
|
|
100
|
+
export const _getInternalState = () => ({
|
|
101
|
+
requests,
|
|
102
|
+
size: Object.keys(requests).length
|
|
103
|
+
})
|