@equinor/fusion-observable
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -1,20 +0,17 @@ | ||
import { from, fromEvent, Observable, of, timer } from 'rxjs'; | ||
import { catchError, map, switchMap, withLatestFrom } from 'rxjs/operators'; | ||
import { EMPTY, from, fromEvent, Observable, of, timer } from 'rxjs'; | ||
import { catchError, map, mergeMap, switchMap, withLatestFrom } from 'rxjs/operators'; | ||
import { ActionError } from '../..'; | ||
import { filterAction } from '../../operators'; | ||
const requestProcessor = (action$, state$) => (action, cb) => { | ||
const requestProcessor = (action$) => (request, cb) => { | ||
return new Observable((subscriber) => { | ||
const { controller, transaction } = action.meta; | ||
const { meta: { controller, transaction }, } = request; | ||
if (controller.signal.aborted) { | ||
subscriber.next({ | ||
type: 'cancel', | ||
payload: `request [${transaction}] was aborted!`, | ||
meta: { request: action }, | ||
payload: { transaction, reason: `request [${transaction}] was aborted!` }, | ||
}); | ||
return subscriber.complete(); | ||
} | ||
subscriber.add(action$ | ||
.pipe(filterAction('cancel'), withLatestFrom(state$)) | ||
.subscribe(([action, state]) => { | ||
if (!action.payload || action.payload === state.transaction) { | ||
subscriber.add(action$.pipe(filterAction('cancel')).subscribe((action) => { | ||
if (action.payload.transaction === transaction) { | ||
if (!controller.signal.aborted) { | ||
@@ -29,4 +26,6 @@ controller.abort(); | ||
type: 'cancel', | ||
payload: `request [${transaction}] was aborted!`, | ||
meta: { request: action }, | ||
payload: { | ||
transaction, | ||
reason: `request [${transaction}] was aborted!`, | ||
}, | ||
}); | ||
@@ -43,6 +42,16 @@ subscriber.complete(); | ||
return (action$, state$) => { | ||
const process = requestProcessor(action$, state$); | ||
const process = requestProcessor(action$); | ||
return action$.pipe(filterAction('failure'), withLatestFrom(state$), switchMap(([action, state]) => { | ||
const { retryCount = 0 } = state; | ||
const request = Object.assign({}, action.payload.action); | ||
var _a, _b; | ||
const { request } = action.meta; | ||
const { transaction } = request.meta; | ||
const entry = state[transaction]; | ||
if (!entry) { | ||
return EMPTY; | ||
} | ||
const retryCount = (_b = (_a = entry.retry) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; | ||
const retryAction = { | ||
type: 'retry', | ||
payload: action.meta.request, | ||
}; | ||
const retry = Object.assign({}, config, request.meta.retry); | ||
@@ -65,5 +74,5 @@ return process(request, (subscriber) => { | ||
return delay$ | ||
.pipe(map(() => request), catchError((err) => of({ | ||
.pipe(map(() => retryAction), catchError((err) => of({ | ||
type: 'error', | ||
payload: new ActionError(request, err, 'failed to resolve delay'), | ||
payload: new ActionError(retryAction, err, 'failed to resolve delay'), | ||
meta: { request }, | ||
@@ -76,15 +85,16 @@ }))) | ||
}; | ||
export const handleRequests = (fetch) => (action$, state$) => { | ||
const process = requestProcessor(action$, state$); | ||
return action$.pipe(filterAction('request'), switchMap((action) => { | ||
return process(action, (subscriber) => { | ||
from(fetch(action.payload, action.meta.controller.signal)) | ||
export const handleRequests = (fetch) => (action$) => { | ||
const process = requestProcessor(action$); | ||
return action$.pipe(filterAction('request', 'retry'), mergeMap((action) => { | ||
const request = action.type === 'request' ? action : action.payload; | ||
return process(request, (subscriber) => { | ||
from(fetch(request.payload, request.meta.controller.signal)) | ||
.pipe(map((result) => ({ | ||
type: 'success', | ||
payload: result, | ||
meta: { request: action }, | ||
meta: { request }, | ||
})), catchError((err) => of({ | ||
type: 'failure', | ||
payload: new ActionError(action, err, 'failed to execute request'), | ||
meta: { request: action }, | ||
meta: { request }, | ||
}))) | ||
@@ -91,0 +101,0 @@ .subscribe(subscriber); |
export { QueryClientError } from './QueryClientError'; | ||
export { default, QueryClient } from './QueryClient'; | ||
export * from './types'; | ||
export * as operators from './operators'; | ||
//# sourceMappingURL=index.js.map |
@@ -21,9 +21,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
var _QueryClient_state$, _QueryClient_subscription; | ||
import { asyncScheduler, firstValueFrom, Observable, Subscription } from 'rxjs'; | ||
import { map, observeOn } from 'rxjs/operators'; | ||
import { v4 as uuid } from 'uuid'; | ||
var _QueryClient_state, _QueryClient_subscription; | ||
import { firstValueFrom, Observable, ReplaySubject, Subscription } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
import * as uuid from 'uuid'; | ||
import { ReactiveObservable } from '../..'; | ||
import { filterAction } from '../../operators'; | ||
import { handleRequests, handleFailures } from './epics'; | ||
import { filterQueryTaskComplete } from './operators'; | ||
import { QueryClientError } from './QueryClientError'; | ||
@@ -34,62 +35,56 @@ import { createReducer } from './reducer'; | ||
super((subscriber) => { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").subscribe(subscriber); | ||
return __classPrivateFieldGet(this, _QueryClient_state, "f").subscribe(subscriber); | ||
}); | ||
_QueryClient_state$.set(this, void 0); | ||
_QueryClient_state.set(this, void 0); | ||
_QueryClient_subscription.set(this, void 0); | ||
__classPrivateFieldSet(this, _QueryClient_state$, new ReactiveObservable(createReducer(), { status: 'idle' }), "f"); | ||
__classPrivateFieldSet(this, _QueryClient_subscription, new Subscription(() => __classPrivateFieldGet(this, _QueryClient_state$, "f").complete()), "f"); | ||
__classPrivateFieldGet(this, _QueryClient_subscription, "f").add(__classPrivateFieldGet(this, _QueryClient_state$, "f").addEpic(handleRequests(queryFn))); | ||
__classPrivateFieldSet(this, _QueryClient_state, new ReactiveObservable(createReducer(), {}), "f"); | ||
__classPrivateFieldSet(this, _QueryClient_subscription, new Subscription(() => __classPrivateFieldGet(this, _QueryClient_state, "f").complete()), "f"); | ||
__classPrivateFieldGet(this, _QueryClient_subscription, "f").add(__classPrivateFieldGet(this, _QueryClient_state, "f").addEpic(handleRequests(queryFn))); | ||
const retry = Object.assign({ count: 0, delay: 0 }, options === null || options === void 0 ? void 0 : options.retry); | ||
__classPrivateFieldGet(this, _QueryClient_subscription, "f").add(__classPrivateFieldGet(this, _QueryClient_state$, "f").addEpic(handleFailures(retry))); | ||
__classPrivateFieldGet(this, _QueryClient_subscription, "f").add(__classPrivateFieldGet(this, _QueryClient_state, "f").addEpic(handleFailures(retry))); | ||
} | ||
get value() { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").value; | ||
} | ||
get action$() { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").action$; | ||
return __classPrivateFieldGet(this, _QueryClient_state, "f").action$; | ||
} | ||
get closed() { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").closed; | ||
return __classPrivateFieldGet(this, _QueryClient_state, "f").closed; | ||
} | ||
get status() { | ||
return this.value.status; | ||
get success$() { | ||
return this.action$.pipe(filterAction('success'), map(({ payload }) => payload)); | ||
} | ||
get error() { | ||
return this.value.error; | ||
get error$() { | ||
return this.action$.pipe(filterAction('error'), map(({ payload }) => new QueryClientError('error', 'failed to execute request', payload))); | ||
} | ||
next(args, opt) { | ||
const action = this._next(args, opt); | ||
return action.meta.transaction; | ||
return this._next(args, opt).meta; | ||
} | ||
nextAsync(args, opt) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this._next(args, opt); | ||
const complete$ = __classPrivateFieldGet(this, _QueryClient_state$, "f").action$.pipe(filterAction('success', 'error', 'cancel'), map((action) => { | ||
const { payload, type } = action; | ||
switch (type) { | ||
case 'error': | ||
throw new QueryClientError('error', 'failed to execute request', payload); | ||
case 'cancel': | ||
throw new QueryClientError('abort', 'request was canceled', new Error(String(payload))); | ||
} | ||
return payload; | ||
}), observeOn(asyncScheduler)); | ||
return firstValueFrom(complete$); | ||
return firstValueFrom(this.next(args, opt).task.pipe(filterQueryTaskComplete())); | ||
}); | ||
} | ||
getTaskByTransaction(transaction) { | ||
const entry = __classPrivateFieldGet(this, _QueryClient_state, "f").value[transaction]; | ||
return entry && entry.task; | ||
} | ||
getTaskByRef(ref) { | ||
const entry = Object.values(__classPrivateFieldGet(this, _QueryClient_state, "f").value).find((x) => x.ref === ref); | ||
return entry && entry.task; | ||
} | ||
cancel(transaction, reason) { | ||
if (this.value.status !== 'canceled') { | ||
reason !== null && reason !== void 0 ? reason : (reason = `request [${transaction || this.value.transaction}] was canceled!`); | ||
__classPrivateFieldGet(this, _QueryClient_state$, "f").next({ | ||
if (transaction && __classPrivateFieldGet(this, _QueryClient_state, "f").value[transaction]) { | ||
reason !== null && reason !== void 0 ? reason : (reason = `[${transaction}]: transaction canceled`); | ||
__classPrivateFieldGet(this, _QueryClient_state, "f").next({ | ||
type: 'cancel', | ||
payload: transaction, | ||
meta: { | ||
request: undefined, | ||
reason, | ||
}, | ||
payload: { transaction, reason }, | ||
}); | ||
} | ||
else { | ||
for (const key of Object.keys(__classPrivateFieldGet(this, _QueryClient_state, "f").value)) { | ||
this.cancel(key, `[${transaction}]: all transactions canceled`); | ||
} | ||
} | ||
} | ||
on(type, cb) { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").addEffect(type, (action) => { | ||
return __classPrivateFieldGet(this, _QueryClient_state, "f").addEffect(type, (action) => { | ||
cb(action, this); | ||
@@ -102,7 +97,10 @@ }); | ||
asObservable() { | ||
return __classPrivateFieldGet(this, _QueryClient_state$, "f").asObservable(); | ||
return __classPrivateFieldGet(this, _QueryClient_state, "f").asObservable(); | ||
} | ||
_next(args, opt) { | ||
const { controller = new AbortController(), transaction = uuid() } = opt !== null && opt !== void 0 ? opt : {}; | ||
const meta = Object.assign(Object.assign({}, opt), { controller, transaction }); | ||
const meta = Object.assign({ | ||
transaction: uuid.v4(), | ||
controller: new AbortController(), | ||
task: new ReplaySubject(), | ||
}, opt !== null && opt !== void 0 ? opt : {}); | ||
const action = { | ||
@@ -113,8 +111,8 @@ type: 'request', | ||
}; | ||
__classPrivateFieldGet(this, _QueryClient_state$, "f").next(action); | ||
__classPrivateFieldGet(this, _QueryClient_state, "f").next(action); | ||
return action; | ||
} | ||
} | ||
_QueryClient_state$ = new WeakMap(), _QueryClient_subscription = new WeakMap(); | ||
_QueryClient_state = new WeakMap(), _QueryClient_subscription = new WeakMap(); | ||
export default QueryClient; | ||
//# sourceMappingURL=QueryClient.js.map |
@@ -0,32 +1,81 @@ | ||
import { QueryClientError } from './QueryClientError'; | ||
export const createReducer = () => (state, action) => { | ||
switch (action.type) { | ||
case 'request': { | ||
const { transaction } = action.meta; | ||
if (state.transaction === transaction) { | ||
return Object.assign(Object.assign({}, state), { status: 'active', retryCount: (state.retryCount || 0) + 1 }); | ||
const { transaction, task, ref } = action.meta; | ||
return Object.assign({}, state, { | ||
[transaction]: { | ||
transaction, | ||
task, | ||
ref, | ||
created: Date.now(), | ||
}, | ||
}); | ||
} | ||
case 'retry': { | ||
const { transaction } = action.payload.meta; | ||
const entry = Object.assign({}, state[transaction]); | ||
if (entry) { | ||
entry.retry = entry.retry ? [...entry.retry, Date.now()] : []; | ||
return Object.assign({}, state, { [transaction]: entry }); | ||
} | ||
return { | ||
transaction, | ||
status: 'active', | ||
initiated: Date.now(), | ||
retryCount: 0, | ||
}; | ||
break; | ||
} | ||
case 'success': { | ||
return Object.assign(Object.assign({}, state), { status: 'idle', completed: Date.now() }); | ||
} | ||
case 'failure': { | ||
return Object.assign(Object.assign({}, state), { status: 'failed' }); | ||
const { transaction } = action.meta.request.meta; | ||
const entry = Object.assign({}, state[transaction]); | ||
if (entry) { | ||
entry.errors = entry.errors ? [...entry.errors, action.payload] : []; | ||
return Object.assign({}, state, { [transaction]: entry }); | ||
} | ||
break; | ||
} | ||
case 'cancel': { | ||
const { transaction, reason } = action.payload; | ||
const entry = state[transaction]; | ||
if (entry) { | ||
entry.task.error(new QueryClientError('abort', 'request was canceled', new Error(reason))); | ||
const next = Object.assign({}, state); | ||
delete next[transaction]; | ||
return next; | ||
} | ||
break; | ||
} | ||
case 'error': { | ||
return Object.assign(Object.assign({}, state), { status: 'failed', error: action.payload }); | ||
const { transaction } = action.meta.request.meta; | ||
const entry = state[transaction]; | ||
if (entry) { | ||
entry.task.error(new QueryClientError('error', 'failed to execute request', action.payload)); | ||
const next = Object.assign({}, state); | ||
delete next[transaction]; | ||
return next; | ||
} | ||
break; | ||
} | ||
case 'cancel': { | ||
return state.status === 'canceled' | ||
? state | ||
: Object.assign(Object.assign({}, state), { status: 'canceled' }); | ||
case 'success': { | ||
const { request } = action.meta; | ||
const { transaction, ref } = request.meta; | ||
const entry = state[transaction]; | ||
if (entry) { | ||
const taskNext = { | ||
status: 'complete', | ||
transaction, | ||
ref, | ||
value: action.payload, | ||
args: request.payload, | ||
created: entry.created, | ||
completed: Date.now(), | ||
}; | ||
entry.task.next(taskNext); | ||
entry.task.complete(); | ||
const next = Object.assign({}, state); | ||
delete next[transaction]; | ||
return next; | ||
} | ||
break; | ||
} | ||
} | ||
return state; | ||
}; | ||
export default createReducer; | ||
//# sourceMappingURL=reducer.js.map |
@@ -1,4 +0,4 @@ | ||
import { map } from 'rxjs'; | ||
export * from './types'; | ||
export * as operators from './operators'; | ||
export { default, Query } from './Query'; | ||
export const queryValue = (stream) => stream.pipe(map((entry) => entry.value)); | ||
//# sourceMappingURL=index.js.map |
@@ -23,9 +23,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
}; | ||
var _Query_subscription, _Query_client, _Query_cache, _Query_queryQueue$, _Query_generateCacheKey, _Query_validateCacheEntry; | ||
import { firstValueFrom, lastValueFrom, Observable, race, Subject, Subscription, } from 'rxjs'; | ||
import { filter, map, take, takeWhile, tap } from 'rxjs/operators'; | ||
import { v4 as uuid } from 'uuid'; | ||
import { filterAction } from '../operators'; | ||
import { QueryClient } from './client'; | ||
var _Query_subscription, _Query_client, _Query_cache, _Query_queryQueue$, _Query_generateCacheKey, _Query_validateCacheEntry, _Query_namespace; | ||
import { firstValueFrom, lastValueFrom, Observable, ReplaySubject, Subject, Subscription, } from 'rxjs'; | ||
import { map, takeWhile } from 'rxjs/operators'; | ||
import * as uuid from 'uuid'; | ||
import { QueryClient, } from './client'; | ||
import { QueryCache } from './cache'; | ||
import { filterQueryTaskComplete } from './client/operators'; | ||
import { queryValue, switchQueue } from './operators'; | ||
const defaultCacheValidator = (expires = 0) => (entry) => { var _a; return ((_a = entry.updated) !== null && _a !== void 0 ? _a : 0) + expires > Date.now(); }; | ||
@@ -42,3 +43,6 @@ export class Query extends Observable { | ||
_Query_validateCacheEntry.set(this, void 0); | ||
__classPrivateFieldSet(this, _Query_generateCacheKey, options.key, "f"); | ||
_Query_namespace.set(this, uuid.v4()); | ||
__classPrivateFieldSet(this, _Query_generateCacheKey, (args) => { | ||
return uuid.v5(options.key(args), __classPrivateFieldGet(this, _Query_namespace, "f")); | ||
}, "f"); | ||
__classPrivateFieldSet(this, _Query_validateCacheEntry, (_a = options === null || options === void 0 ? void 0 : options.validate) !== null && _a !== void 0 ? _a : defaultCacheValidator(options === null || options === void 0 ? void 0 : options.expire), "f"); | ||
@@ -59,16 +63,21 @@ if (options.client instanceof QueryClient) { | ||
} | ||
const queueOperator = (_b = options.queueOperator) !== null && _b !== void 0 ? _b : (() => ($) => $); | ||
__classPrivateFieldGet(this, _Query_subscription, "f").add(__classPrivateFieldGet(this, _Query_client, "f").on('success', (action) => { | ||
const { payload: value, meta: { request }, } = action; | ||
const key = __classPrivateFieldGet(this, _Query_generateCacheKey, "f").call(this, request.payload); | ||
const queueOperator = (_b = options.queueOperator) !== null && _b !== void 0 ? _b : switchQueue; | ||
__classPrivateFieldGet(this, _Query_subscription, "f").add(() => __classPrivateFieldGet(this, _Query_queryQueue$, "f").complete()); | ||
__classPrivateFieldGet(this, _Query_subscription, "f").add(__classPrivateFieldGet(this, _Query_queryQueue$, "f") | ||
.pipe(queueOperator(({ args, options }) => new Observable((subscriber) => { | ||
const { task, transaction } = __classPrivateFieldGet(this, _Query_client, "f").next(args, options); | ||
subscriber.add(task.subscribe(subscriber)); | ||
subscriber.add(() => { | ||
__classPrivateFieldGet(this, _Query_client, "f").cancel(transaction); | ||
}); | ||
})), filterQueryTaskComplete(), takeWhile(() => !__classPrivateFieldGet(this, _Query_client, "f").closed)) | ||
.subscribe((task) => { | ||
const { args, value, transaction, ref } = task; | ||
const key = ref !== null && ref !== void 0 ? ref : __classPrivateFieldGet(this, _Query_generateCacheKey, "f").call(this, args); | ||
__classPrivateFieldGet(this, _Query_cache, "f").setItem(key, { | ||
value, | ||
args: request.payload, | ||
transaction: request.meta.transaction, | ||
args, | ||
transaction, | ||
}); | ||
})); | ||
__classPrivateFieldGet(this, _Query_subscription, "f").add(() => __classPrivateFieldGet(this, _Query_queryQueue$, "f").complete()); | ||
__classPrivateFieldGet(this, _Query_subscription, "f").add(__classPrivateFieldGet(this, _Query_queryQueue$, "f") | ||
.pipe(queueOperator(__classPrivateFieldGet(this, _Query_cache, "f").value), takeWhile(() => !__classPrivateFieldGet(this, _Query_client, "f").closed)) | ||
.subscribe(({ args, options }) => __classPrivateFieldGet(this, _Query_client, "f").next(args, options))); | ||
} | ||
@@ -85,30 +94,6 @@ get client() { | ||
query(args, options) { | ||
var _a, _b, _c; | ||
const cacheKey = ((_b = (_a = options === null || options === void 0 ? void 0 : options.cache) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : __classPrivateFieldGet(this, _Query_generateCacheKey, "f"))(args); | ||
const validateCache = ((_c = options === null || options === void 0 ? void 0 : options.cache) === null || _c === void 0 ? void 0 : _c.validate) || __classPrivateFieldGet(this, _Query_validateCacheEntry, "f"); | ||
const cacheEntry = __classPrivateFieldGet(this, _Query_cache, "f").getItem(cacheKey); | ||
const refresh = !cacheEntry || !validateCache(cacheEntry, args); | ||
const clientOptions = Object.assign({ transaction: uuid() }, options === null || options === void 0 ? void 0 : options.client); | ||
if (refresh) { | ||
(options === null || options === void 0 ? void 0 : options.skipQueue) | ||
? __classPrivateFieldGet(this, _Query_client, "f").next(args, clientOptions) | ||
: this.next(args, clientOptions); | ||
} | ||
const cancel$ = __classPrivateFieldGet(this, _Query_client, "f").action$.pipe(filterAction('cancel'), filter((x) => { var _a; return ((_a = x.meta.request) === null || _a === void 0 ? void 0 : _a.meta.transaction) === clientOptions.transaction; }), map((cause) => { | ||
throw new Error('query was canceled', { cause }); | ||
})); | ||
const complete$ = __classPrivateFieldGet(this, _Query_cache, "f").action$.pipe(filterAction('set'), filter((action) => action.payload.value.transaction === clientOptions.transaction), map((action) => action.payload.value), take(1)); | ||
return new Observable((observer) => { | ||
cacheEntry && observer.next(cacheEntry); | ||
if (refresh) { | ||
const cancelTransaction = () => __classPrivateFieldGet(this, _Query_client, "f").cancel(clientOptions.transaction); | ||
observer.add(cancelTransaction); | ||
race(complete$, cancel$) | ||
.pipe(tap(() => observer.remove(cancelTransaction))) | ||
.subscribe(observer); | ||
} | ||
else { | ||
observer.complete(); | ||
} | ||
}); | ||
var _a; | ||
const ref = __classPrivateFieldGet(this, _Query_generateCacheKey, "f").call(this, args); | ||
const task = (_a = __classPrivateFieldGet(this, _Query_client, "f").getTaskByRef(ref)) !== null && _a !== void 0 ? _a : this._createTask(ref, args, options); | ||
return task; | ||
} | ||
@@ -118,3 +103,3 @@ queryAsync(payload, opt) { | ||
const fn = awaitResolve ? lastValueFrom : firstValueFrom; | ||
return fn(this.query(payload, args)); | ||
return fn(this._query(payload, args)); | ||
} | ||
@@ -124,5 +109,39 @@ complete() { | ||
} | ||
_query(args, options) { | ||
var _a; | ||
const ref = __classPrivateFieldGet(this, _Query_generateCacheKey, "f").call(this, args); | ||
const task = (_a = __classPrivateFieldGet(this, _Query_client, "f").getTaskByRef(ref)) !== null && _a !== void 0 ? _a : this._createTask(ref, args, options); | ||
return task; | ||
} | ||
_createTask(ref, args, options) { | ||
var _a; | ||
const task = new ReplaySubject(); | ||
const cacheEntry = __classPrivateFieldGet(this, _Query_cache, "f").getItem(ref); | ||
if (cacheEntry) { | ||
const { value, args, created, updated, updates, transaction } = cacheEntry; | ||
const taskEntry = { | ||
status: 'cache', | ||
value, | ||
args, | ||
created, | ||
updated, | ||
updates, | ||
transaction, | ||
}; | ||
task.next(taskEntry); | ||
} | ||
const validateCache = ((_a = options === null || options === void 0 ? void 0 : options.cache) === null || _a === void 0 ? void 0 : _a.validate) || __classPrivateFieldGet(this, _Query_validateCacheEntry, "f"); | ||
const validCacheEntry = cacheEntry && validateCache(cacheEntry, args); | ||
if (!validCacheEntry) { | ||
__classPrivateFieldGet(this, _Query_queryQueue$, "f").next({ args, options: { ref, task } }); | ||
} | ||
else { | ||
task.complete(); | ||
} | ||
return task.asObservable(); | ||
} | ||
} | ||
_Query_subscription = new WeakMap(), _Query_client = new WeakMap(), _Query_cache = new WeakMap(), _Query_queryQueue$ = new WeakMap(), _Query_generateCacheKey = new WeakMap(), _Query_validateCacheEntry = new WeakMap(); | ||
_Query_subscription = new WeakMap(), _Query_client = new WeakMap(), _Query_cache = new WeakMap(), _Query_queryQueue$ = new WeakMap(), _Query_generateCacheKey = new WeakMap(), _Query_validateCacheEntry = new WeakMap(), _Query_namespace = new WeakMap(); | ||
Query.extractQueryValue = queryValue; | ||
export default Query; | ||
//# sourceMappingURL=Query.js.map |
@@ -10,2 +10,3 @@ export * from './useObservable'; | ||
export * from './useObservableInput'; | ||
export * from './useDebounceQuery'; | ||
//# sourceMappingURL=index.js.map |
@@ -12,3 +12,3 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
}; | ||
var _ReactiveObservable_action$, _ReactiveObservable_state$; | ||
var _ReactiveObservable_action, _ReactiveObservable_state; | ||
import { asyncScheduler, BehaviorSubject, EMPTY, from, Observable, Subject, } from 'rxjs'; | ||
@@ -20,23 +20,21 @@ import { catchError, distinctUntilChanged, filter, mergeMap, observeOn, scan, } from 'rxjs/operators'; | ||
super((subscriber) => { | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state$, "f").subscribe(subscriber); | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state, "f").subscribe(subscriber); | ||
}); | ||
this.__initial = __initial; | ||
_ReactiveObservable_action$.set(this, new Subject()); | ||
_ReactiveObservable_state$.set(this, void 0); | ||
__classPrivateFieldSet(this, _ReactiveObservable_state$, new BehaviorSubject(__initial), "f"); | ||
__classPrivateFieldGet(this, _ReactiveObservable_action$, "f") | ||
.pipe(scan(reducer, __initial), distinctUntilChanged()) | ||
.subscribe(__classPrivateFieldGet(this, _ReactiveObservable_state$, "f")); | ||
_ReactiveObservable_action.set(this, new Subject()); | ||
_ReactiveObservable_state.set(this, void 0); | ||
__classPrivateFieldSet(this, _ReactiveObservable_state, new BehaviorSubject(__initial), "f"); | ||
__classPrivateFieldGet(this, _ReactiveObservable_action, "f").pipe(scan(reducer, __initial), distinctUntilChanged()).subscribe(__classPrivateFieldGet(this, _ReactiveObservable_state, "f")); | ||
} | ||
get action$() { | ||
return __classPrivateFieldGet(this, _ReactiveObservable_action$, "f").asObservable(); | ||
return __classPrivateFieldGet(this, _ReactiveObservable_action, "f").asObservable(); | ||
} | ||
get value() { | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state$, "f").value; | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state, "f").value; | ||
} | ||
get closed() { | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state$, "f").closed || __classPrivateFieldGet(this, _ReactiveObservable_action$, "f").closed; | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state, "f").closed || __classPrivateFieldGet(this, _ReactiveObservable_action, "f").closed; | ||
} | ||
next(action) { | ||
__classPrivateFieldGet(this, _ReactiveObservable_action$, "f").next(action); | ||
__classPrivateFieldGet(this, _ReactiveObservable_action, "f").next(action); | ||
} | ||
@@ -60,3 +58,3 @@ addEffect(actionTypeOrFn, fn) { | ||
}))), filter((x) => !!x), observeOn(asyncScheduler)) | ||
.subscribe(__classPrivateFieldGet(this, _ReactiveObservable_action$, "f")); | ||
.subscribe(__classPrivateFieldGet(this, _ReactiveObservable_action, "f")); | ||
} | ||
@@ -73,21 +71,21 @@ addEpic(fn) { | ||
}), observeOn(asyncScheduler)) | ||
.subscribe(__classPrivateFieldGet(this, _ReactiveObservable_action$, "f")); | ||
.subscribe(__classPrivateFieldGet(this, _ReactiveObservable_action, "f")); | ||
} | ||
reset() { | ||
__classPrivateFieldGet(this, _ReactiveObservable_state$, "f").next(this.__initial); | ||
__classPrivateFieldGet(this, _ReactiveObservable_state, "f").next(this.__initial); | ||
} | ||
unsubscribe() { | ||
__classPrivateFieldGet(this, _ReactiveObservable_action$, "f").unsubscribe(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_state$, "f").unsubscribe(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_action, "f").unsubscribe(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_state, "f").unsubscribe(); | ||
} | ||
complete() { | ||
__classPrivateFieldGet(this, _ReactiveObservable_action$, "f").complete(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_state$, "f").complete(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_action, "f").complete(); | ||
__classPrivateFieldGet(this, _ReactiveObservable_state, "f").complete(); | ||
} | ||
asObservable() { | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state$, "f").asObservable(); | ||
return __classPrivateFieldGet(this, _ReactiveObservable_state, "f").asObservable(); | ||
} | ||
} | ||
_ReactiveObservable_action$ = new WeakMap(), _ReactiveObservable_state$ = new WeakMap(); | ||
_ReactiveObservable_action = new WeakMap(), _ReactiveObservable_state = new WeakMap(); | ||
export default ReactiveObservable; | ||
//# sourceMappingURL=ReactiveObservable.js.map |
@@ -6,3 +6,8 @@ import type { PayloadAction } from '../..'; | ||
key: string; | ||
value: QueryCacheRecord<TType, TArgs>; | ||
value: { | ||
value: TType; | ||
args: TArgs; | ||
transaction: string; | ||
created?: number; | ||
}; | ||
}>; | ||
@@ -9,0 +14,0 @@ clear: PayloadAction<'clear', { |
export declare type QueryCacheRecord<TType = unknown, TArgs = unknown> = { | ||
value: TType; | ||
args?: TArgs; | ||
transaction?: string; | ||
created?: number; | ||
args: TArgs; | ||
transaction: string; | ||
created: number; | ||
updated?: number; | ||
@@ -7,0 +7,0 @@ updates?: number; |
import { ActionError } from '../..'; | ||
import type { Action, PayloadMetaAction } from '../..'; | ||
import type { RetryOptions } from './types'; | ||
export declare type RequestAction<TArgs = unknown> = PayloadMetaAction<'request', TArgs, { | ||
import type { Action, PayloadAction, PayloadMetaAction } from '../..'; | ||
import type { QueryTaskValue, RetryOptions } from './types'; | ||
import { Subject } from 'rxjs'; | ||
export declare type RequestAction<TArgs = unknown, TResponse = unknown> = PayloadMetaAction<'request', TArgs, { | ||
transaction: string; | ||
controller: AbortController; | ||
task: Subject<QueryTaskValue<TResponse, TArgs>>; | ||
retry?: Partial<RetryOptions>; | ||
ref?: string; | ||
transaction: string; | ||
}>; | ||
export declare type SuccessAction<TArgs, TResponse = Response> = PayloadMetaAction<'success', TResponse, { | ||
request: RequestAction<TArgs>; | ||
export declare type RetryAction<TArgs = unknown, TResponse = unknown> = PayloadAction<'retry', RequestAction<TArgs, TResponse>>; | ||
export declare type SuccessAction<TArgs = unknown, TResponse = unknown> = PayloadMetaAction<'success', TResponse, { | ||
request: RequestAction<TArgs, TResponse>; | ||
}>; | ||
export declare type CancelAction<TArgs, TTransaction = string | undefined> = PayloadMetaAction<'cancel', TTransaction, { | ||
request?: RequestAction<TArgs>; | ||
export declare type CancelAction = PayloadAction<'cancel', { | ||
transaction: string; | ||
reason?: string; | ||
}>; | ||
export declare type FailureAction<TArgs, TType extends Error = Error> = PayloadMetaAction<'failure', ActionError<Action, TType>, { | ||
request: RequestAction<TArgs>; | ||
export declare type FailureAction<TArgs = unknown, TResponse = unknown, TError extends Error = Error> = PayloadMetaAction<'failure', ActionError<Action, TError>, { | ||
request: RequestAction<TArgs, TResponse>; | ||
}>; | ||
export declare type ErrorAction<TArgs, TType extends Error = Error> = PayloadMetaAction<'error', ActionError<Action, TType>, { | ||
request: RequestAction<TArgs>; | ||
export declare type ErrorAction<TArgs = unknown, TResponse = unknown, TError extends Error = Error> = PayloadMetaAction<'error', ActionError<Action, TError>, { | ||
request: RequestAction<TArgs, TResponse>; | ||
}>; | ||
export declare type ActionTypes<TType = unknown, TArgs = unknown, TFailure extends Error = Error, TError extends Error = Error> = RequestAction<TArgs> | SuccessAction<TArgs, TType> | FailureAction<TArgs, TFailure> | ErrorAction<TArgs, TError> | CancelAction<TArgs>; | ||
export declare type ActionTypes<TType = unknown, TArgs = unknown, TFailure extends Error = Error, TError extends Error = Error> = CancelAction | ErrorAction<TArgs, TType, TError> | FailureAction<TArgs, TType, TFailure> | RequestAction<TArgs, TType> | RetryAction<TArgs, TType> | SuccessAction<TArgs, TType>; |
import { Epic } from '../..'; | ||
import { ActionTypes } from './actions'; | ||
import { QueryFn, RetryOptions, State } from './types'; | ||
export declare const handleFailures: <TType, TArgs>(config?: Partial<RetryOptions>) => Epic<ActionTypes<TType, TArgs, Error, Error>, State>; | ||
export declare const handleRequests: <TType, TArgs>(fetch: QueryFn<TType, TArgs>) => Epic<ActionTypes<TType, TArgs, Error, Error>, State>; | ||
export declare const handleFailures: <TType, TArgs>(config?: Partial<RetryOptions>) => Epic<ActionTypes<TType, TArgs, Error, Error>, State<TType, TArgs>>; | ||
export declare const handleRequests: <TType, TArgs>(fetch: QueryFn<TType, TArgs>) => Epic<ActionTypes<TType, TArgs, Error, Error>, State<TType, TArgs>>; |
export { ActionTypes as QueryClientActions } from './actions'; | ||
export { State as QueryClientState, Status as QueryClientStatus, QueryFn as QueryClientFn, RetryOptions as QueryClientRetryOptions, } from './types'; | ||
export { QueryClientError } from './QueryClientError'; | ||
export { default, QueryClient, QueryClientOptions, QueryClientCtorOptions } from './QueryClient'; | ||
export * from './types'; | ||
export * as operators from './operators'; |
@@ -1,9 +0,11 @@ | ||
import { Observable, Subscription } from 'rxjs'; | ||
import { ActionType, ExtractAction } from '../..'; | ||
import { Observable, Subject, Subscription } from 'rxjs'; | ||
import { ActionMeta, ActionType, ExtractAction } from '../..'; | ||
import { ActionTypes, RequestAction } from './actions'; | ||
import { State, RetryOptions, QueryFn } from './types'; | ||
export declare type QueryClientOptions = { | ||
import { QueryClientError } from './QueryClientError'; | ||
import { State, RetryOptions, QueryFn, QueryTaskCompleted, QueryTaskValue } from './types'; | ||
export declare type QueryClientOptions<TType = unknown, TArgs = unknown> = { | ||
controller: AbortController; | ||
retry: Partial<RetryOptions>; | ||
transaction?: string; | ||
ref?: string; | ||
task?: Subject<QueryTaskValue<TType, TArgs>>; | ||
}; | ||
@@ -13,18 +15,19 @@ export declare type QueryClientCtorOptions = { | ||
}; | ||
export declare class QueryClient<TType, TArgs> extends Observable<State> { | ||
export declare class QueryClient<TType, TArgs> extends Observable<State<TType, TArgs>> { | ||
#private; | ||
get value(): State; | ||
get action$(): Observable<ActionTypes<TType, TArgs>>; | ||
get closed(): boolean; | ||
get status(): import("./types").Status; | ||
get error(): unknown; | ||
get success$(): Observable<TType>; | ||
get error$(): Observable<QueryClientError>; | ||
constructor(queryFn: QueryFn<TType, TArgs>, options?: QueryClientCtorOptions); | ||
next(args?: TArgs, opt?: Partial<QueryClientOptions>): string; | ||
nextAsync(args?: TArgs, opt?: Partial<QueryClientOptions>): Promise<TType | Error>; | ||
next(args?: TArgs, opt?: Partial<QueryClientOptions<TType, TArgs>>): ActionMeta<RequestAction<TArgs, TType>>; | ||
nextAsync(args?: TArgs, opt?: Partial<QueryClientOptions<TType, TArgs>>): Promise<QueryTaskCompleted<TType, TArgs>>; | ||
getTaskByTransaction(transaction: string): Subject<QueryTaskValue<TType, TArgs>> | undefined; | ||
getTaskByRef(ref: string): Subject<QueryTaskValue<TType, TArgs>> | undefined; | ||
cancel(transaction?: string, reason?: string): void; | ||
on<TAction extends ActionType<ActionTypes>>(type: TAction, cb: (action: ExtractAction<ActionTypes<TType, TArgs>, TAction>, subject: QueryClient<TType, TArgs>) => void): Subscription; | ||
complete(): void; | ||
asObservable(): Observable<State>; | ||
protected _next(args?: TArgs, opt?: Partial<QueryClientOptions>): RequestAction<TArgs>; | ||
asObservable(): Observable<State<TType, TArgs>>; | ||
protected _next(args?: TArgs, opt?: Partial<QueryClientOptions<TType, TArgs>>): RequestAction<TArgs, TType>; | ||
} | ||
export default QueryClient; |
import type { Reducer } from '../..'; | ||
import { ActionTypes } from './actions'; | ||
import { State } from './types'; | ||
export declare const createReducer: <TType, TArgs>() => Reducer<State, ActionTypes<TType, TArgs, Error, Error>>; | ||
export declare const createReducer: <TType, TArgs>() => Reducer<State<TType, TArgs>, ActionTypes<TType, TArgs, Error, Error>>; | ||
export default createReducer; |
@@ -1,11 +0,24 @@ | ||
import type { ObservableInput } from 'rxjs'; | ||
export declare type Status = 'idle' | 'active' | 'failed' | 'canceled'; | ||
export declare type State = { | ||
status: Status; | ||
transaction?: string; | ||
initiated?: number; | ||
retryCount?: number; | ||
completed?: number; | ||
error?: unknown; | ||
import { ObservableInput, Subject } from 'rxjs'; | ||
export declare type QueryTaskValue<TValue = unknown, TArgs = unknown> = { | ||
status: string; | ||
transaction: string; | ||
created: number; | ||
args: TArgs; | ||
value: TValue; | ||
}; | ||
export declare type QueryTaskCompleted<TValue, TArgs = unknown> = QueryTaskValue<TValue, TArgs> & { | ||
status: 'complete'; | ||
ref?: string; | ||
completed: number; | ||
}; | ||
export declare type QueryTask<TValue, TArgs = unknown> = Subject<QueryTaskValue<TValue, TArgs>>; | ||
export declare type QueueItem<TType = unknown, TArgs = unknown> = { | ||
transaction: string; | ||
task: QueryTask<TType, TArgs>; | ||
created: number; | ||
retry?: Array<number>; | ||
errors?: Array<Error>; | ||
ref?: string; | ||
}; | ||
export declare type State<TType = unknown, TArgs = unknown> = Record<string, QueueItem<TType, TArgs>>; | ||
export declare type RetryOptions = { | ||
@@ -15,2 +28,2 @@ count: number; | ||
}; | ||
export declare type QueryFn<TType, TArgs> = (args: TArgs, signal?: AbortSignal) => ObservableInput<TType>; | ||
export declare type QueryFn<TType = unknown, TArgs = unknown> = (args: TArgs, signal?: AbortSignal) => ObservableInput<TType>; |
@@ -1,4 +0,3 @@ | ||
import { Observable } from 'rxjs'; | ||
import Query from './Query'; | ||
export { default, Query, QueryCtorOptions, QueryOptions } from './Query'; | ||
export declare const queryValue: <TType, TArgs>(stream: Observable<import("./cache").QueryCacheRecord<TType, TArgs>>) => Observable<TType>; | ||
export * from './types'; | ||
export * as operators from './operators'; | ||
export { default, Query, QueryCtorOptions } from './Query'; |
@@ -1,19 +0,6 @@ | ||
import { MonoTypeOperatorFunction, Observable } from 'rxjs'; | ||
import { QueryClient, QueryClientCtorOptions, QueryClientOptions } from './client'; | ||
import { QueryCache, QueryCacheRecord, QueryCacheState, QueryCacheStateData } from './cache'; | ||
import { QueryFn } from './types'; | ||
import { Observable } from 'rxjs'; | ||
import { QueryClient, QueryClientCtorOptions, QueryClientOptions, QueryTaskCompleted, QueryTaskValue } from './client'; | ||
import { QueryCache, QueryCacheStateData } from './cache'; | ||
import { CacheOptions, QueryFn, QueryOptions, QueryQueueFn, QueryTaskCached } from './types'; | ||
import { QueryCacheCtorArgs } from './cache/QueryCache'; | ||
declare type CacheOptions<TType, TArgs> = { | ||
key: (query: TArgs) => string; | ||
validate: CacheValidator<TType, TArgs>; | ||
}; | ||
declare type QueryQueueItem<TArgs> = { | ||
args: TArgs; | ||
options?: Partial<QueryClientOptions>; | ||
}; | ||
export declare type QueryOptions<TType, TArgs = unknown> = { | ||
client?: Partial<QueryClientOptions>; | ||
cache?: Partial<CacheOptions<TType, TArgs>>; | ||
skipQueue?: boolean; | ||
}; | ||
export declare type QueryCtorOptions<TType, TArgs> = { | ||
@@ -28,17 +15,19 @@ client: QueryClient<TType, TArgs> | { | ||
expire?: number; | ||
queueOperator?: (state: QueryCacheState<TType, TArgs>) => MonoTypeOperatorFunction<QueryQueueItem<TArgs>>; | ||
queueOperator?: QueryQueueFn<TArgs, TType>; | ||
}; | ||
declare type CacheValidator<TType, TArgs> = (entry: QueryCacheRecord<TType, TArgs>, args: TArgs) => boolean; | ||
export declare class Query<TType, TArgs> extends Observable<QueryCacheStateData<TType, TArgs>> { | ||
#private; | ||
static extractQueryValue: <TType_1, TArgs_1>(source$: Observable<QueryTaskCached<TType_1, TArgs_1> | QueryTaskCompleted<TType_1, TArgs_1>>) => Observable<TType_1>; | ||
get client(): QueryClient<TType, TArgs>; | ||
get state$(): QueryCache<TType, TArgs>; | ||
constructor(options: QueryCtorOptions<TType, TArgs>); | ||
next(args: TArgs, options?: Partial<QueryClientOptions>): void; | ||
query(args: TArgs, options?: QueryOptions<TType, TArgs>): Observable<QueryCacheRecord<TType, TArgs>>; | ||
next(args: TArgs, options?: Partial<QueryClientOptions<TType, TArgs>>): void; | ||
query(args: TArgs, options?: QueryOptions<TType, TArgs>): Observable<QueryTaskCached<TType, TArgs> | QueryTaskCompleted<TType, TArgs>>; | ||
queryAsync(payload: TArgs, opt?: QueryOptions<TType, TArgs> & { | ||
awaitResolve: boolean; | ||
}): Promise<QueryCacheRecord<TType, TArgs>>; | ||
}): Promise<QueryTaskValue<TType, TArgs>>; | ||
complete(): void; | ||
protected _query(args: TArgs, options?: QueryOptions<TType, TArgs>): Observable<QueryTaskCached<TType, TArgs> | QueryTaskCompleted<TType, TArgs>>; | ||
protected _createTask(ref: string, args: TArgs, options?: QueryOptions<TType, TArgs>): Observable<QueryTaskValue<TType, TArgs>>; | ||
} | ||
export default Query; |
@@ -1,2 +0,4 @@ | ||
import type { ObservableInput } from 'rxjs'; | ||
import type { Observable, ObservableInput, OperatorFunction } from 'rxjs'; | ||
import type { QueryCacheRecord } from './cache'; | ||
import type { QueryClientOptions, QueryTaskValue } from './client'; | ||
export declare type QueryState = { | ||
@@ -16,2 +18,23 @@ status: QueryStatus; | ||
} | ||
export declare type CacheValidator<TType, TArgs> = (entry: QueryCacheRecord<TType, TArgs>, args: TArgs) => boolean; | ||
export declare type CacheOptions<TType, TArgs> = { | ||
key: (query: TArgs) => string; | ||
validate: CacheValidator<TType, TArgs>; | ||
}; | ||
export declare type QueryOptions<TType, TArgs = unknown> = { | ||
client?: Partial<QueryClientOptions>; | ||
cache?: { | ||
suppressInvalid: boolean; | ||
validate?: CacheValidator<TType, TArgs>; | ||
}; | ||
}; | ||
export declare type QueryTaskCached<TValue, TArgs> = QueryTaskValue<TValue, TArgs> & { | ||
status: 'cache'; | ||
updated?: number; | ||
updates?: number; | ||
}; | ||
export declare type QueryQueueItem<TArgs, TType> = { | ||
args: TArgs; | ||
options?: Partial<QueryClientOptions<TType, TArgs>>; | ||
}; | ||
export declare type RetryOpt = { | ||
@@ -22,1 +45,2 @@ count: number; | ||
export declare type QueryFn<TType, TArgs> = (args: TArgs, signal?: AbortSignal) => ObservableInput<TType>; | ||
export declare type QueryQueueFn<TArgs = unknown, TType = unknown> = (fn: (args: QueryQueueItem<TArgs, TType>) => Observable<QueryTaskValue<TType, TArgs>>) => OperatorFunction<QueryQueueItem<TArgs, TType>, QueryTaskValue<TType, TArgs>>; |
@@ -10,1 +10,2 @@ export * from './useObservable'; | ||
export * from './useObservableInput'; | ||
export * from './useDebounceQuery'; |
{ | ||
"name": "@equinor/fusion-observable", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "WIP", | ||
@@ -97,3 +97,3 @@ "private": false, | ||
}, | ||
"gitHead": "07b75f05b0f7c01cfeb240dc1dfd1e64fbaa2267" | ||
"gitHead": "8d6faac0a36f2e1792e4112e362c6ce3cf98371e" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
176134
112
1170