@equinor/fusion-observable
Advanced tools
Comparing version 0.3.2 to 0.3.3
export class ActionError extends Error { | ||
action; | ||
cause; | ||
constructor(action, cause, msg) { | ||
super(msg ?? cause.message); | ||
super(msg !== null && msg !== void 0 ? msg : cause.message); | ||
this.action = action; | ||
@@ -7,0 +5,0 @@ this.cause = cause; |
@@ -42,3 +42,3 @@ import { from, fromEvent, Observable, of, timer } from 'rxjs'; | ||
const { retryCount = 0 } = state; | ||
const request = { ...action.payload.action }; | ||
const request = Object.assign({}, action.payload.action); | ||
const retry = Object.assign({}, config, request.meta.retry); | ||
@@ -45,0 +45,0 @@ return process(request, (subscriber) => { |
@@ -7,5 +7,2 @@ var RequestErrorType; | ||
export class QueryError extends Error { | ||
type; | ||
cause; | ||
static TYPE = RequestErrorType; | ||
constructor(type, message, cause) { | ||
@@ -17,2 +14,3 @@ super(message); | ||
} | ||
QueryError.TYPE = RequestErrorType; | ||
//# sourceMappingURL=errors.js.map |
@@ -0,1 +1,10 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import { asyncScheduler, firstValueFrom, Observable, Subscription } from 'rxjs'; | ||
@@ -12,4 +21,12 @@ import { map, observeOn } from 'rxjs/operators'; | ||
export class Query extends Observable { | ||
__state$; | ||
__subscription; | ||
constructor(queryFn, config) { | ||
super((subscriber) => { | ||
return this.__state$.subscribe(subscriber); | ||
}); | ||
this.__state$ = new ReactiveObservable(createReducer(), { status: QueryStatus.IDLE }); | ||
this.__subscription = new Subscription(() => this.__state$.complete()); | ||
this.__subscription.add(this.__state$.addEpic(handleRequests(queryFn))); | ||
const retry = Object.assign({ count: 0, delay: 0 }, config === null || config === void 0 ? void 0 : config.retry); | ||
this.__subscription.add(this.__state$.addEpic(handleFailures(retry))); | ||
} | ||
get value() { | ||
@@ -30,28 +47,20 @@ return this.__state$.value; | ||
} | ||
constructor(queryFn, config) { | ||
super((subscriber) => { | ||
return this.__state$.subscribe(subscriber); | ||
}); | ||
this.__state$ = new ReactiveObservable(createReducer(), { status: QueryStatus.IDLE }); | ||
this.__subscription = new Subscription(() => this.__state$.complete()); | ||
this.__subscription.add(this.__state$.addEpic(handleRequests(queryFn))); | ||
const retry = Object.assign({ count: 0, delay: 0 }, config?.retry); | ||
this.__subscription.add(this.__state$.addEpic(handleFailures(retry))); | ||
} | ||
next(args, opt) { | ||
return this._next(args, opt).transaction; | ||
} | ||
async nextAsync(args, opt) { | ||
this._next(args, opt); | ||
const complete$ = this.__state$.action$.pipe(filterAction(ActionType.SUCCESS, ActionType.ERROR, ActionType.CANCEL), map((action) => { | ||
const { payload, type } = action; | ||
switch (type) { | ||
case ActionType.ERROR: | ||
throw new QueryError(QueryError.TYPE.ERROR, 'failed to execute request', payload); | ||
case ActionType.CANCEL: | ||
throw new QueryError(QueryError.TYPE.ABORT, 'request was canceled', new Error(String(payload))); | ||
} | ||
return payload; | ||
}), observeOn(asyncScheduler)); | ||
return firstValueFrom(complete$); | ||
nextAsync(args, opt) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this._next(args, opt); | ||
const complete$ = this.__state$.action$.pipe(filterAction(ActionType.SUCCESS, ActionType.ERROR, ActionType.CANCEL), map((action) => { | ||
const { payload, type } = action; | ||
switch (type) { | ||
case ActionType.ERROR: | ||
throw new QueryError(QueryError.TYPE.ERROR, 'failed to execute request', payload); | ||
case ActionType.CANCEL: | ||
throw new QueryError(QueryError.TYPE.ABORT, 'request was canceled', new Error(String(payload))); | ||
} | ||
return payload; | ||
}), observeOn(asyncScheduler)); | ||
return firstValueFrom(complete$); | ||
}); | ||
} | ||
@@ -79,4 +88,4 @@ cancel(reason) { | ||
_next(args, opt) { | ||
const { controller = new AbortController() } = opt ?? {}; | ||
const meta = { ...opt, controller }; | ||
const { controller = new AbortController() } = opt !== null && opt !== void 0 ? opt : {}; | ||
const meta = Object.assign(Object.assign({}, opt), { controller }); | ||
const action = { | ||
@@ -83,0 +92,0 @@ transaction: uuid(), |
import { BehaviorSubject, Observable, Subscription } from 'rxjs'; | ||
import { ActionType } from './actions'; | ||
export class QueryCache extends Observable { | ||
__state$; | ||
__subscription = new Subscription(); | ||
constructor(client, initial) { | ||
@@ -10,2 +8,3 @@ super((subscriber) => { | ||
}); | ||
this.__subscription = new Subscription(); | ||
this.__state$ = new BehaviorSubject({ data: initial, updates: 0 }); | ||
@@ -12,0 +11,0 @@ this.__subscription.add(() => this.__state$.complete()); |
@@ -6,20 +6,12 @@ import { interval, Observable, Subject } from 'rxjs'; | ||
export class QueryClient extends Observable { | ||
__client$; | ||
__state$; | ||
__queries$ = new Subject(); | ||
get data() { | ||
return this.__state$.value.data; | ||
} | ||
get query() { | ||
return this.__client$; | ||
} | ||
constructor(queryFn, options) { | ||
super((subscriber) => this.__state$.pipe(map((x) => x.data)).subscribe(subscriber)); | ||
this.__queries$ = new Subject(); | ||
this.__client$ = new Query(queryFn, { | ||
retry: options?.retry, | ||
retry: options === null || options === void 0 ? void 0 : options.retry, | ||
}); | ||
this.__state$ = new QueryCache(this.__client$, options?.initial); | ||
const debounceFn = typeof options?.debounce === 'function' | ||
this.__state$ = new QueryCache(this.__client$, options === null || options === void 0 ? void 0 : options.initial); | ||
const debounceFn = typeof (options === null || options === void 0 ? void 0 : options.debounce) === 'function' | ||
? options.debounce | ||
: () => interval(Number(options?.debounce)); | ||
: () => interval(Number(options === null || options === void 0 ? void 0 : options.debounce)); | ||
this.__queries$ | ||
@@ -29,2 +21,8 @@ .pipe(withLatestFrom(this.__state$), debounce(([value, state]) => debounceFn(value, state)), map(([value]) => value), filter(() => !this.__client$.closed)) | ||
} | ||
get data() { | ||
return this.__state$.value.data; | ||
} | ||
get query() { | ||
return this.__client$; | ||
} | ||
refresh() { | ||
@@ -31,0 +29,0 @@ this.next(this.__state$.value.args); |
@@ -8,7 +8,3 @@ import { ActionType } from './actions'; | ||
if (state.transaction === transaction) { | ||
return { | ||
...state, | ||
status: QueryStatus.ACTIVE, | ||
retryCount: (state.retryCount || 0) + 1, | ||
}; | ||
return Object.assign(Object.assign({}, state), { status: QueryStatus.ACTIVE, retryCount: (state.retryCount || 0) + 1 }); | ||
} | ||
@@ -23,20 +19,9 @@ return { | ||
case ActionType.SUCCESS: { | ||
return { | ||
...state, | ||
status: QueryStatus.IDLE, | ||
completed: Date.now(), | ||
}; | ||
return Object.assign(Object.assign({}, state), { status: QueryStatus.IDLE, completed: Date.now() }); | ||
} | ||
case ActionType.FAILURE: { | ||
return { | ||
...state, | ||
status: QueryStatus.FAILED, | ||
}; | ||
return Object.assign(Object.assign({}, state), { status: QueryStatus.FAILED }); | ||
} | ||
case ActionType.ERROR: { | ||
return { | ||
...state, | ||
status: QueryStatus.FAILED, | ||
error: action.payload, | ||
}; | ||
return Object.assign(Object.assign({}, state), { status: QueryStatus.FAILED, error: action.payload }); | ||
} | ||
@@ -46,6 +31,3 @@ case ActionType.CANCEL: { | ||
? state | ||
: { | ||
...state, | ||
status: QueryStatus.CANCELED, | ||
}; | ||
: Object.assign(Object.assign({}, state), { status: QueryStatus.CANCELED }); | ||
} | ||
@@ -52,0 +34,0 @@ } |
import { useLayoutEffect, useState } from 'react'; | ||
export const useObservableEffect = (subject, effectOrType, effect) => { | ||
const [type] = useState(() => (typeof effectOrType === 'string' ? effectOrType : undefined)); | ||
const [fn] = useState(() => effect ?? effectOrType); | ||
const [fn] = useState(() => effect !== null && effect !== void 0 ? effect : effectOrType); | ||
useLayoutEffect(() => { | ||
@@ -6,0 +6,0 @@ const subscription = type |
import { useCallback, useRef } from 'react'; | ||
import { useObservableLayoutSubscription } from './useObservableSubscription'; | ||
export const useObservableRef = (subject, initial) => { | ||
initial ??= subject.value; | ||
initial !== null && initial !== void 0 ? initial : (initial = subject.value); | ||
const ref = useRef(initial); | ||
@@ -6,0 +6,0 @@ useObservableLayoutSubscription(subject, useCallback((x) => (ref.current = x), [])); |
import { useState } from 'react'; | ||
import { useObservableLayoutSubscription } from './useObservableSubscription'; | ||
export const useObservableState = (subject, initial) => { | ||
initial ??= subject.value; | ||
initial !== null && initial !== void 0 ? initial : (initial = subject.value); | ||
const [state, setState] = useState(initial); | ||
@@ -6,0 +6,0 @@ useObservableLayoutSubscription(subject, setState); |
@@ -0,1 +1,12 @@ | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
import { useEffect, useMemo, useState } from 'react'; | ||
@@ -15,5 +26,6 @@ import { share, Subject } from 'rxjs'; | ||
export const useQueryClientStreamResult = (result) => { | ||
const { data$, status$, ...obj } = result; | ||
var _a; | ||
const { data$, status$ } = result, obj = __rest(result, ["data$", "status$"]); | ||
const data = useObservableState(data$); | ||
const status = useObservableState(status$) ?? QueryStatus.IDLE; | ||
const status = (_a = useObservableState(status$)) !== null && _a !== void 0 ? _a : QueryStatus.IDLE; | ||
const isLoading = useMemo(() => status === QueryStatus.ACTIVE, [status]); | ||
@@ -20,0 +32,0 @@ return Object.assign(obj, { data, status, isLoading }); |
@@ -5,14 +5,2 @@ import { asyncScheduler, BehaviorSubject, EMPTY, from, Observable, Subject, } from 'rxjs'; | ||
export class ReactiveObservable extends Observable { | ||
__initial; | ||
__action$ = new Subject(); | ||
__state$; | ||
get action$() { | ||
return this.__action$.asObservable(); | ||
} | ||
get value() { | ||
return this.__state$.value; | ||
} | ||
get closed() { | ||
return this.__state$.closed || this.__action$.closed; | ||
} | ||
constructor(reducer, __initial) { | ||
@@ -23,2 +11,3 @@ super((subscriber) => { | ||
this.__initial = __initial; | ||
this.__action$ = new Subject(); | ||
this.__state$ = new BehaviorSubject(__initial); | ||
@@ -29,2 +18,11 @@ this.__action$ | ||
} | ||
get action$() { | ||
return this.__action$.asObservable(); | ||
} | ||
get value() { | ||
return this.__state$.value; | ||
} | ||
get closed() { | ||
return this.__state$.closed || this.__action$.closed; | ||
} | ||
next(action) { | ||
@@ -31,0 +29,0 @@ this.__action$.next(action); |
{ | ||
"name": "@equinor/fusion-observable", | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"description": "WIP", | ||
@@ -73,3 +73,3 @@ "private": false, | ||
"ts-jest": "^27.1.4", | ||
"typescript": "^4.8.2" | ||
"typescript": "^4.8.4" | ||
}, | ||
@@ -85,3 +85,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "512e05eab757da7a9836199dd28a1bc0dbf5b492" | ||
"gitHead": "573a97b7b0938a4cfad7063480ad88b5adab6ba1" | ||
} |
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
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
131022
814