@openctx/client
Advanced tools
Comparing version 0.0.28 to 0.0.29
import { Observable, filter, map } from 'observable-fns'; | ||
import { catchError, combineLatest, defer, distinctUntilChanged, mergeMap, promiseOrObservableToObservable, startWith, tap, } from './misc/observable.js'; | ||
import { catchError, combineLatest, defer, distinctUntilChanged, promiseOrObservableToObservable, startWith, switchMap, tap, } from './misc/observable.js'; | ||
function observeProviderCall(providerClients, fn, { emitPartial, errorHook, logger }) { | ||
@@ -11,3 +11,3 @@ // This sentinel value lets us avoid emitting a "fake" partial result when `emitPartial` is | ||
const EMIT_PARTIAL_SENTINEL = {}; | ||
return providerClients.pipe(mergeMap(providerClients => providerClients && providerClients.length > 0 | ||
return providerClients.pipe(switchMap(providerClients => providerClients && providerClients.length > 0 | ||
? combineLatest(providerClients.map(({ uri, providerClient, settings }) => defer(() => fn({ uri, providerClient, settings })) | ||
@@ -14,0 +14,0 @@ .pipe(emitPartial ? startWith(EMIT_PARTIAL_SENTINEL) : tap(), catchError(error => { |
@@ -5,3 +5,3 @@ import { LRUCache } from 'lru-cache'; | ||
import { configurationFromUserInput, } from '../configuration.js'; | ||
import { catchError, combineLatest, concatMap, distinctUntilChanged, firstValueFrom, mergeMap, promiseOrObservableToObservable, shareReplay, take, timer, } from '../misc/observable.js'; | ||
import { catchError, combineLatest, concatMap, distinctUntilChanged, firstValueFrom, promiseOrObservableToObservable, shareReplay, switchMap, take, timer, } from '../misc/observable.js'; | ||
import { createProviderClient } from '../providerClient/createProviderClient.js'; | ||
@@ -39,3 +39,3 @@ /** | ||
})) | ||
.pipe(mergeMap(([configuration, providers]) => configuration.providers.length > 0 | ||
.pipe(switchMap(([configuration, providers]) => configuration.providers.length > 0 | ||
? combineLatest(configuration.providers.map(({ providerUri, settings }) => (env.authInfo | ||
@@ -42,0 +42,0 @@ ? promiseOrObservableToObservable(env.authInfo(providerUri)) |
@@ -1,3 +0,5 @@ | ||
import type { Observable } from 'rxjs'; | ||
import { Observable } from 'rxjs'; | ||
export declare function observableToAsyncGenerator<T>(observable: Observable<T>, signal?: AbortSignal): AsyncGenerator<T>; | ||
export declare function asyncGeneratorToObservable<T>(asyncGenerator: AsyncGenerator<T, void>): Observable<T>; | ||
export declare function isAsyncGenerator(value: any): value is AsyncGenerator<any, any, any>; | ||
//# sourceMappingURL=util.d.ts.map |
@@ -0,1 +1,2 @@ | ||
import { Observable } from 'rxjs'; | ||
export async function* observableToAsyncGenerator(observable, signal) { | ||
@@ -60,2 +61,34 @@ const queue = []; | ||
} | ||
export function asyncGeneratorToObservable(asyncGenerator) { | ||
return new Observable(observer => { | ||
; | ||
(async () => { | ||
try { | ||
for await (const value of asyncGenerator) { | ||
observer.next(value); | ||
} | ||
observer.complete(); | ||
} | ||
catch (error) { | ||
observer.error(error); | ||
} | ||
})(); | ||
return () => { | ||
// If the AsyncGenerator has a return method, call it to clean up | ||
if (asyncGenerator.return) { | ||
asyncGenerator.return(); | ||
} | ||
}; | ||
}); | ||
} | ||
export function isAsyncGenerator(value) { | ||
if (value === null || typeof value !== 'object') { | ||
return false; | ||
} | ||
return (typeof value.next === 'function' && | ||
typeof value.throw === 'function' && | ||
typeof value.return === 'function' && | ||
typeof value[Symbol.asyncIterator] === 'function' && | ||
value[Symbol.asyncIterator]() === value); | ||
} | ||
//# sourceMappingURL=util.js.map |
@@ -90,2 +90,6 @@ import { Observable, type ObservableLike } from 'observable-fns'; | ||
export declare function distinctUntilChanged<T>(isEqualFn?: (a: T, b: T) => boolean): (observable: ObservableLike<T>) => Observable<T>; | ||
/** | ||
* Whether {@link value} is equivalent to {@link other} in terms of JSON serialization. | ||
*/ | ||
export declare function isEqualJSON<T>(value: T, other: T): boolean; | ||
interface Observer<T> { | ||
@@ -98,2 +102,3 @@ next: (value: T) => void; | ||
export declare function mergeMap<T, R>(project: (value: T, index: number) => ObservableLike<R>): (observable: ObservableLike<T>) => Observable<R>; | ||
export declare function switchMap<T, R>(project: (value: T, index: number) => ObservableLike<R>): (source: ObservableLike<T>) => Observable<R>; | ||
export declare function defer<R>(observableFactory: () => ObservableLike<R>): Observable<R>; | ||
@@ -100,0 +105,0 @@ export declare function startWith<T, R>(value: R): (source: ObservableLike<T>) => Observable<R | T>; |
@@ -348,2 +348,29 @@ import { Observable, Subject, map, unsubscribe, } from 'observable-fns'; | ||
} | ||
/** | ||
* Whether {@link value} is equivalent to {@link other} in terms of JSON serialization. | ||
*/ | ||
export function isEqualJSON(value, other) { | ||
if (value === other) { | ||
return true; | ||
} | ||
if (value == null || other == null || typeof value !== 'object' || typeof other !== 'object') { | ||
return false; | ||
} | ||
const isValueArray = Array.isArray(value); | ||
const isOtherArray = Array.isArray(other); | ||
if (isValueArray !== isOtherArray) { | ||
return false; | ||
} | ||
if (isValueArray && isOtherArray) { | ||
return (value.length === other.length && | ||
value.every((value, index) => isEqualJSON(value, other[index]))); | ||
} | ||
const allKeys = new Set([...Object.keys(value), ...Object.keys(other)]); | ||
for (const key of allKeys) { | ||
if (!isEqualJSON(value[key], other[key])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
export function tap(observerOrNext) { | ||
@@ -375,5 +402,2 @@ return (input) => new Observable(observer => { | ||
const NO_VALUES_YET = {}; | ||
function isEqualJSON(a, b) { | ||
return JSON.stringify(a) === JSON.stringify(b); | ||
} | ||
export function mergeMap(project) { | ||
@@ -426,2 +450,50 @@ return (observable) => { | ||
} | ||
export function switchMap(project) { | ||
return (source) => { | ||
return new Observable(observer => { | ||
let index = 0; | ||
let innerSubscription = null; | ||
let outerCompleted = false; | ||
const checkComplete = () => { | ||
if (outerCompleted && !innerSubscription) { | ||
observer.complete(); | ||
} | ||
}; | ||
const outerSubscription = source.subscribe({ | ||
next(value) { | ||
if (innerSubscription) { | ||
unsubscribe(innerSubscription); | ||
innerSubscription = null; | ||
} | ||
const innerObservable = project(value, index++); | ||
innerSubscription = innerObservable.subscribe({ | ||
next(innerValue) { | ||
observer.next(innerValue); | ||
}, | ||
error(err) { | ||
observer.error(err); | ||
}, | ||
complete() { | ||
innerSubscription = null; | ||
checkComplete(); | ||
}, | ||
}); | ||
}, | ||
error(err) { | ||
observer.error(err); | ||
}, | ||
complete() { | ||
outerCompleted = true; | ||
checkComplete(); | ||
}, | ||
}); | ||
return () => { | ||
unsubscribe(outerSubscription); | ||
if (innerSubscription) { | ||
unsubscribe(innerSubscription); | ||
} | ||
}; | ||
}); | ||
}; | ||
} | ||
export function defer(observableFactory) { | ||
@@ -428,0 +500,0 @@ return new Observable(observer => { |
{ | ||
"name": "@openctx/client", | ||
"version": "0.0.28", | ||
"version": "0.0.29", | ||
"description": "OpenCtx client library", | ||
@@ -39,5 +39,5 @@ "license": "Apache-2.0", | ||
"picomatch": "^3.0.1", | ||
"@openctx/provider": "0.0.18", | ||
"@openctx/protocol": "0.0.19", | ||
"@openctx/schema": "0.0.15", | ||
"@openctx/protocol": "0.0.19" | ||
"@openctx/provider": "0.0.18" | ||
}, | ||
@@ -44,0 +44,0 @@ "devDependencies": { |
@@ -19,5 +19,5 @@ import type { | ||
distinctUntilChanged, | ||
mergeMap, | ||
promiseOrObservableToObservable, | ||
startWith, | ||
switchMap, | ||
tap, | ||
@@ -82,3 +82,3 @@ } from './misc/observable.js' | ||
return providerClients.pipe( | ||
mergeMap(providerClients => | ||
switchMap(providerClients => | ||
providerClients && providerClients.length > 0 | ||
@@ -85,0 +85,0 @@ ? combineLatest( |
@@ -38,5 +38,5 @@ import type { | ||
firstValueFrom, | ||
mergeMap, | ||
promiseOrObservableToObservable, | ||
shareReplay, | ||
switchMap, | ||
take, | ||
@@ -292,3 +292,3 @@ timer, | ||
.pipe( | ||
mergeMap(([configuration, providers]) => | ||
switchMap(([configuration, providers]) => | ||
configuration.providers.length > 0 | ||
@@ -295,0 +295,0 @@ ? combineLatest( |
@@ -455,2 +455,36 @@ import { | ||
/** | ||
* Whether {@link value} is equivalent to {@link other} in terms of JSON serialization. | ||
*/ | ||
export function isEqualJSON<T>(value: T, other: T): boolean { | ||
if (value === other) { | ||
return true | ||
} | ||
if (value == null || other == null || typeof value !== 'object' || typeof other !== 'object') { | ||
return false | ||
} | ||
const isValueArray = Array.isArray(value) | ||
const isOtherArray = Array.isArray(other) | ||
if (isValueArray !== isOtherArray) { | ||
return false | ||
} | ||
if (isValueArray && isOtherArray) { | ||
return ( | ||
value.length === other.length && | ||
value.every((value, index) => isEqualJSON(value, other[index])) | ||
) | ||
} | ||
const allKeys = new Set([...Object.keys(value), ...Object.keys(other)]) | ||
for (const key of allKeys) { | ||
if (!isEqualJSON((value as any)[key], (other as any)[key])) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
interface Observer<T> { | ||
@@ -494,6 +528,2 @@ next: (value: T) => void | ||
function isEqualJSON(a: unknown, b: unknown): boolean { | ||
return JSON.stringify(a) === JSON.stringify(b) | ||
} | ||
export function mergeMap<T, R>( | ||
@@ -552,2 +582,57 @@ project: (value: T, index: number) => ObservableLike<R>, | ||
export function switchMap<T, R>( | ||
project: (value: T, index: number) => ObservableLike<R>, | ||
): (source: ObservableLike<T>) => Observable<R> { | ||
return (source: ObservableLike<T>): Observable<R> => { | ||
return new Observable<R>(observer => { | ||
let index = 0 | ||
let innerSubscription: UnsubscribableLike | null = null | ||
let outerCompleted = false | ||
const checkComplete = () => { | ||
if (outerCompleted && !innerSubscription) { | ||
observer.complete() | ||
} | ||
} | ||
const outerSubscription = source.subscribe({ | ||
next(value) { | ||
if (innerSubscription) { | ||
unsubscribe(innerSubscription) | ||
innerSubscription = null | ||
} | ||
const innerObservable = project(value, index++) | ||
innerSubscription = innerObservable.subscribe({ | ||
next(innerValue) { | ||
observer.next(innerValue) | ||
}, | ||
error(err) { | ||
observer.error(err) | ||
}, | ||
complete() { | ||
innerSubscription = null | ||
checkComplete() | ||
}, | ||
}) | ||
}, | ||
error(err) { | ||
observer.error(err) | ||
}, | ||
complete() { | ||
outerCompleted = true | ||
checkComplete() | ||
}, | ||
}) | ||
return () => { | ||
unsubscribe(outerSubscription) | ||
if (innerSubscription) { | ||
unsubscribe(innerSubscription) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
export function defer<R>(observableFactory: () => ObservableLike<R>): Observable<R> { | ||
@@ -554,0 +639,0 @@ return new Observable<R>(observer => { |
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
231962
4019