Upgrade RxJS to 7 (#129087)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Alejandro Fernández Haro 2022-04-12 21:40:55 +02:00 committed by GitHub
parent 5ee7c3d25a
commit 9d5aca591b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
260 changed files with 11471 additions and 16589 deletions

View file

@ -32,6 +32,7 @@ import {
EuiTabbedContentTab, EuiTabbedContentTab,
} from '@elastic/eui'; } from '@elastic/eui';
import { lastValueFrom } from 'rxjs';
import { CoreStart } from '../../../../src/core/public'; import { CoreStart } from '../../../../src/core/public';
import { mountReactNode } from '../../../../src/core/public/utils'; import { mountReactNode } from '../../../../src/core/public/utils';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public'; import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';
@ -306,9 +307,9 @@ export const SearchExamplesApp = ({
const abortController = new AbortController(); const abortController = new AbortController();
setAbortController(abortController); setAbortController(abortController);
setIsLoading(true); setIsLoading(true);
const { rawResponse: res } = await searchSource const { rawResponse: res } = await lastValueFrom(
.fetch$({ abortSignal: abortController.signal }) searchSource.fetch$({ abortSignal: abortController.signal })
.toPromise(); );
setRawResponse(res); setRawResponse(res);
const message = <EuiText>Searched {res.hits.total} documents.</EuiText>; const message = <EuiText>Searched {res.hits.total} documents.</EuiText>;

View file

@ -30,7 +30,7 @@ import {
EuiTitle, EuiTitle,
} from '@elastic/eui'; } from '@elastic/eui';
import { catchError, map, tap } from 'rxjs/operators'; import { catchError, map, tap } from 'rxjs/operators';
import { of } from 'rxjs'; import { lastValueFrom, of } from 'rxjs';
import { CoreStart } from '../../../../src/core/public'; import { CoreStart } from '../../../../src/core/public';
import { mountReactNode } from '../../../../src/core/public/utils'; import { mountReactNode } from '../../../../src/core/public/utils';
@ -693,9 +693,8 @@ function doSearch(
const startTs = performance.now(); const startTs = performance.now();
// Submit the search request using the `data.search` service. // Submit the search request using the `data.search` service.
return data.search return lastValueFrom(
.search(req, { sessionId }) data.search.search(req, { sessionId }).pipe(
.pipe(
tap((res) => { tap((res) => {
if (isCompleteResponse(res)) { if (isCompleteResponse(res)) {
const avgResult: number | undefined = res.rawResponse.aggregations const avgResult: number | undefined = res.rawResponse.aggregations
@ -724,7 +723,7 @@ function doSearch(
return of({ request: req, response: e }); return of({ request: req, response: e });
}) })
) )
.toPromise(); );
} }
function getNumeric(fields?: DataViewField[]) { function getNumeric(fields?: DataViewField[]) {

View file

@ -383,7 +383,7 @@
"redux-actions": "^2.6.5", "redux-actions": "^2.6.5",
"redux-devtools-extension": "^2.13.8", "redux-devtools-extension": "^2.13.8",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"redux-observable": "^1.2.0", "redux-observable": "2.0.0",
"redux-saga": "^1.1.3", "redux-saga": "^1.1.3",
"redux-thunk": "^2.3.0", "redux-thunk": "^2.3.0",
"redux-thunks": "^1.0.0", "redux-thunks": "^1.0.0",
@ -394,7 +394,7 @@
"reselect": "^4.0.0", "reselect": "^4.0.0",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"rison-node": "1.0.2", "rison-node": "1.0.2",
"rxjs": "^6.5.5", "rxjs": "^7.5.5",
"safe-squel": "^5.12.5", "safe-squel": "^5.12.5",
"seedrandom": "^3.0.5", "seedrandom": "^3.0.5",
"semver": "^7.3.2", "semver": "^7.3.2",

View file

@ -8,7 +8,7 @@
// eslint-disable-next-line max-classes-per-file // eslint-disable-next-line max-classes-per-file
import type { Observable } from 'rxjs'; import type { Observable } from 'rxjs';
import { BehaviorSubject, Subject } from 'rxjs'; import { BehaviorSubject, lastValueFrom, Subject } from 'rxjs';
import type { MockedLogger } from '@kbn/logging-mocks'; import type { MockedLogger } from '@kbn/logging-mocks';
import { loggerMock } from '@kbn/logging-mocks'; import { loggerMock } from '@kbn/logging-mocks';
import { AnalyticsClient } from './analytics_client'; import { AnalyticsClient } from './analytics_client';
@ -113,14 +113,14 @@ describe('AnalyticsClient', () => {
}, },
}); });
const internalQueuePromise = lastValueFrom(
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const internalQueuePromise = analyticsClient['internalEventQueue$'] analyticsClient['internalEventQueue$'].pipe(take(3), toArray())
.pipe(take(3), toArray()) );
.toPromise();
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3), toArray()) analyticsClient.telemetryCounter$.pipe(take(3), toArray())
.toPromise(); );
analyticsClient.reportEvent('testEvent', { a_field: 'a' }); analyticsClient.reportEvent('testEvent', { a_field: 'a' });
analyticsClient.reportEvent('testEvent', { a_field: 'b' }); analyticsClient.reportEvent('testEvent', { a_field: 'b' });
@ -259,7 +259,7 @@ describe('AnalyticsClient', () => {
// Typescript also helps with the config type inference <3 // Typescript also helps with the config type inference <3
analyticsClient.registerShipper(MockedShipper, { telemetryCounter$: mockTelemetryCounter$ }); analyticsClient.registerShipper(MockedShipper, { telemetryCounter$: mockTelemetryCounter$ });
const counterEventPromise = analyticsClient.telemetryCounter$.pipe(take(1)).toPromise(); const counterEventPromise = lastValueFrom(analyticsClient.telemetryCounter$.pipe(take(1)));
const counter: TelemetryCounter = { const counter: TelemetryCounter = {
type: TelemetryCounterType.succeeded, type: TelemetryCounterType.succeeded,
@ -383,7 +383,7 @@ describe('AnalyticsClient', () => {
context$, context$,
}); });
const globalContextPromise = globalContext$.pipe(take(2), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(2), toArray()));
context$.next({ a_field: true }); context$.next({ a_field: true });
await expect(globalContextPromise).resolves.toEqual([ await expect(globalContextPromise).resolves.toEqual([
{}, // Original empty state {}, // Original empty state
@ -392,7 +392,7 @@ describe('AnalyticsClient', () => {
}); });
test('It does not break if context emits `undefined`', async () => { test('It does not break if context emits `undefined`', async () => {
const context$ = new Subject<{ a_field: boolean }>(); const context$ = new Subject<{ a_field: boolean } | undefined | void>();
analyticsClient.registerContextProvider({ analyticsClient.registerContextProvider({
name: 'contextProviderA', name: 'contextProviderA',
schema: { schema: {
@ -406,7 +406,7 @@ describe('AnalyticsClient', () => {
context$, context$,
}); });
const globalContextPromise = globalContext$.pipe(take(3), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(3), toArray()));
context$.next(); context$.next();
context$.next(undefined); context$.next(undefined);
await expect(globalContextPromise).resolves.toEqual([ await expect(globalContextPromise).resolves.toEqual([
@ -431,7 +431,7 @@ describe('AnalyticsClient', () => {
context$, context$,
}); });
const globalContextPromise = globalContext$.pipe(take(1), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(1), toArray()));
await expect(globalContextPromise).resolves.toEqual([ await expect(globalContextPromise).resolves.toEqual([
{ a_field: true }, // No original empty state { a_field: true }, // No original empty state
]); ]);
@ -473,7 +473,7 @@ describe('AnalyticsClient', () => {
context$: contextB$, context$: contextB$,
}); });
const globalContextPromise = globalContext$.pipe(take(6), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(6), toArray()));
contextA$.next({ a_field: true }); contextA$.next({ a_field: true });
contextB$.next({ b_field: 1 }); contextB$.next({ b_field: 1 });
contextB$.next({ a_field: false, b_field: 1 }); contextB$.next({ a_field: false, b_field: 1 });
@ -512,7 +512,7 @@ describe('AnalyticsClient', () => {
context$, context$,
}); });
const globalContextPromise = globalContext$.pipe(take(6), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(6), toArray()));
context$.next({ b_field: 1 }); context$.next({ b_field: 1 });
context$.next({ a_field: false, b_field: 1 }); context$.next({ a_field: false, b_field: 1 });
context$.next({ a_field: true, b_field: 1 }); context$.next({ a_field: true, b_field: 1 });
@ -582,7 +582,7 @@ describe('AnalyticsClient', () => {
context$, context$,
}); });
const globalContextPromise = globalContext$.pipe(take(4), toArray()).toPromise(); const globalContextPromise = lastValueFrom(globalContext$.pipe(take(4), toArray()));
context$.next({ a_field: true }); context$.next({ a_field: true });
// The size of the registry grows on the first emission // The size of the registry grows on the first emission
expect(contextProvidersRegistry.size).toBe(1); expect(contextProvidersRegistry.size).toBe(1);
@ -736,11 +736,11 @@ describe('AnalyticsClient', () => {
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const internalEventQueue$ = analyticsClient['internalEventQueue$']; const internalEventQueue$ = analyticsClient['internalEventQueue$'];
const internalQueuePromise = internalEventQueue$.pipe(take(2), toArray()).toPromise(); const internalQueuePromise = lastValueFrom(internalEventQueue$.pipe(take(2), toArray()));
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(2), toArray()) analyticsClient.telemetryCounter$.pipe(take(2), toArray())
.toPromise(); );
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
analyticsClient.reportEvent('event-type-b', { b_field: 100 }); analyticsClient.reportEvent('event-type-b', { b_field: 100 });
@ -781,9 +781,9 @@ describe('AnalyticsClient', () => {
}); });
test('Sends events from the internal queue when there are shippers and an opt-in response is true', async () => { test('Sends events from the internal queue when there are shippers and an opt-in response is true', async () => {
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events
.toPromise(); );
// Send multiple events of 1 type to test the grouping logic as well // Send multiple events of 1 type to test the grouping logic as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -862,9 +862,9 @@ describe('AnalyticsClient', () => {
}); });
test('Discards events from the internal queue when there are shippers and an opt-in response is false', async () => { test('Discards events from the internal queue when there are shippers and an opt-in response is false', async () => {
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3), toArray()) // Waiting for 3 enqueued analyticsClient.telemetryCounter$.pipe(take(3), toArray()) // Waiting for 3 enqueued
.toPromise(); );
// Send multiple events of 1 type to test the grouping logic as well // Send multiple events of 1 type to test the grouping logic as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -904,9 +904,9 @@ describe('AnalyticsClient', () => {
}); });
test('Discards only one type of the enqueued events based on event_type config', async () => { test('Discards only one type of the enqueued events based on event_type config', async () => {
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events analyticsClient.telemetryCounter$.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events
.toPromise(); );
// Send multiple events of 1 type to test the grouping logic as well // Send multiple events of 1 type to test the grouping logic as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -965,9 +965,9 @@ describe('AnalyticsClient', () => {
}); });
test('Discards the event at the shipper level (for a specific event)', async () => { test('Discards the event at the shipper level (for a specific event)', async () => {
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events
.toPromise(); );
// Send multiple events of 1 type to test the grouping logic as well // Send multiple events of 1 type to test the grouping logic as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -1061,9 +1061,9 @@ describe('AnalyticsClient', () => {
}); });
test('Discards all the events at the shipper level (globally disabled)', async () => { test('Discards all the events at the shipper level (globally disabled)', async () => {
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events
.toPromise(); );
// Send multiple events of 1 type to test the grouping logic as well // Send multiple events of 1 type to test the grouping logic as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -1154,9 +1154,9 @@ describe('AnalyticsClient', () => {
analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); analyticsClient.registerShipper(MockedShipper1, { reportEventsMock });
analyticsClient.optIn({ global: { enabled: false } }); analyticsClient.optIn({ global: { enabled: false } });
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3), toArray()) // Waiting for 3 enqueued analyticsClient.telemetryCounter$.pipe(take(3), toArray()) // Waiting for 3 enqueued
.toPromise(); );
// Send multiple events of 1 type to test the non-grouping logic at this stage as well // Send multiple events of 1 type to test the non-grouping logic at this stage as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
@ -1197,9 +1197,9 @@ describe('AnalyticsClient', () => {
analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); analyticsClient.registerShipper(MockedShipper1, { reportEventsMock });
analyticsClient.optIn({ global: { enabled: true } }); analyticsClient.optIn({ global: { enabled: true } });
const telemetryCounterPromise = analyticsClient.telemetryCounter$ const telemetryCounterPromise = lastValueFrom(
.pipe(take(3 * 2), toArray()) // Waiting for 2 events per each reportEvent call: enqueued and sent_to_shipper analyticsClient.telemetryCounter$.pipe(take(3 * 2), toArray()) // Waiting for 2 events per each reportEvent call: enqueued and sent_to_shipper
.toPromise(); );
// Send multiple events of 1 type to test the non-grouping logic at this stage as well // Send multiple events of 1 type to test the non-grouping logic at this stage as well
analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); analyticsClient.reportEvent('event-type-a', { a_field: 'a' });

View file

@ -6,8 +6,6 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { EventEmitter } from 'events';
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { import {
map, map,
@ -60,9 +58,9 @@ export class DevServer {
this.script = options.script; this.script = options.script;
this.argv = options.argv; this.argv = options.argv;
this.gracefulTimeout = options.gracefulTimeout; this.gracefulTimeout = options.gracefulTimeout;
this.processExit$ = options.processExit$ ?? Rx.fromEvent(process as EventEmitter, 'exit'); this.processExit$ = options.processExit$ ?? Rx.fromEvent<void>(process, 'exit');
this.sigint$ = options.sigint$ ?? Rx.fromEvent(process as EventEmitter, 'SIGINT'); this.sigint$ = options.sigint$ ?? Rx.fromEvent<void>(process, 'SIGINT');
this.sigterm$ = options.sigterm$ ?? Rx.fromEvent(process as EventEmitter, 'SIGTERM'); this.sigterm$ = options.sigterm$ ?? Rx.fromEvent<void>(process, 'SIGTERM');
this.mapLogLine = options.mapLogLine; this.mapLogLine = options.mapLogLine;
} }
@ -117,7 +115,7 @@ export class DevServer {
*/ */
run$ = new Rx.Observable<void>((subscriber) => { run$ = new Rx.Observable<void>((subscriber) => {
// listen for SIGINT and forward to process if it's running, otherwise unsub // listen for SIGINT and forward to process if it's running, otherwise unsub
const gracefulShutdown$ = new Rx.Subject(); const gracefulShutdown$ = new Rx.Subject<void>();
subscriber.add( subscriber.add(
this.sigint$ this.sigint$
.pipe( .pipe(

View file

@ -12,7 +12,6 @@ import * as Rx from 'rxjs';
import { toArray } from 'rxjs/operators'; import { toArray } from 'rxjs/operators';
import { OptimizerUpdate } from '@kbn/optimizer'; import { OptimizerUpdate } from '@kbn/optimizer';
import { observeLines, createReplaceSerializer } from '@kbn/dev-utils'; import { observeLines, createReplaceSerializer } from '@kbn/dev-utils';
import { firstValueFrom } from '@kbn/std';
import { Optimizer, Options } from './optimizer'; import { Optimizer, Options } from './optimizer';
@ -130,7 +129,7 @@ it('uses options to create valid OptimizerConfig', () => {
it('is ready when optimizer phase is success or issue and logs in familiar format', async () => { it('is ready when optimizer phase is success or issue and logs in familiar format', async () => {
const writeLogTo = new PassThrough(); const writeLogTo = new PassThrough();
const linesPromise = firstValueFrom(observeLines(writeLogTo).pipe(toArray())); const linesPromise = Rx.firstValueFrom(observeLines(writeLogTo).pipe(toArray()));
const { update$, optimizer } = setup({ const { update$, optimizer } = setup({
...defaultOptions, ...defaultOptions,

View file

@ -10,7 +10,6 @@ import { EventEmitter } from 'events';
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { materialize, toArray } from 'rxjs/operators'; import { materialize, toArray } from 'rxjs/operators';
import { firstValueFrom } from '@kbn/std';
import { TestLog } from './log'; import { TestLog } from './log';
import { Watcher, Options } from './watcher'; import { Watcher, Options } from './watcher';
@ -112,7 +111,7 @@ it('closes chokidar watcher when unsubscribed', () => {
it('rethrows chokidar errors', async () => { it('rethrows chokidar errors', async () => {
const watcher = new Watcher(defaultOptions); const watcher = new Watcher(defaultOptions);
const promise = firstValueFrom(watcher.run$.pipe(materialize(), toArray())); const promise = Rx.firstValueFrom(watcher.run$.pipe(materialize(), toArray()));
isMock(mockChokidar); isMock(mockChokidar);
mockChokidar.emit('error', new Error('foo bar')); mockChokidar.emit('error', new Error('foo bar'));

View file

@ -9,8 +9,8 @@
import type { PublicMethodsOf } from '@kbn/utility-types'; import type { PublicMethodsOf } from '@kbn/utility-types';
import { Type } from '@kbn/config-schema'; import { Type } from '@kbn/config-schema';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { BehaviorSubject, combineLatest, firstValueFrom, Observable } from 'rxjs';
import { distinctUntilChanged, first, map, shareReplay, take, tap } from 'rxjs/operators'; import { distinctUntilChanged, first, map, shareReplay, tap } from 'rxjs/operators';
import { Logger, LoggerFactory } from '@kbn/logging'; import { Logger, LoggerFactory } from '@kbn/logging';
import { Config, ConfigPath, Env } from '.'; import { Config, ConfigPath, Env } from '.';
@ -170,7 +170,7 @@ export class ConfigService {
const namespace = pathToString(path); const namespace = pathToString(path);
const hasSchema = this.schemas.has(namespace); const hasSchema = this.schemas.has(namespace);
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
if (!hasSchema && config.has(path)) { if (!hasSchema && config.has(path)) {
// Throw if there is no schema, but a config exists at the path. // Throw if there is no schema, but a config exists at the path.
throw new Error(`No validation schema has been defined for [${namespace}]`); throw new Error(`No validation schema has been defined for [${namespace}]`);
@ -195,13 +195,13 @@ export class ConfigService {
} }
public async getUnusedPaths() { public async getUnusedPaths() {
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
const handledPaths = [...this.handledPaths.values()].map(pathToString); const handledPaths = [...this.handledPaths.values()].map(pathToString);
return config.getFlattenedPaths().filter((path) => !isPathHandled(path, handledPaths)); return config.getFlattenedPaths().filter((path) => !isPathHandled(path, handledPaths));
} }
public async getUsedPaths() { public async getUsedPaths() {
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
const handledPaths = [...this.handledPaths.values()].map(pathToString); const handledPaths = [...this.handledPaths.values()].map(pathToString);
return config.getFlattenedPaths().filter((path) => isPathHandled(path, handledPaths)); return config.getFlattenedPaths().filter((path) => isPathHandled(path, handledPaths));
} }
@ -211,8 +211,8 @@ export class ConfigService {
} }
private async logDeprecation() { private async logDeprecation() {
const rawConfig = await this.rawConfigProvider.getConfig$().pipe(take(1)).toPromise(); const rawConfig = await firstValueFrom(this.rawConfigProvider.getConfig$());
const deprecations = await this.deprecations.pipe(take(1)).toPromise(); const deprecations = await firstValueFrom(this.deprecations);
const deprecationMessages: string[] = []; const deprecationMessages: string[] = [];
const createAddDeprecation = (domainId: string) => (context: DeprecatedConfigDetails) => { const createAddDeprecation = (domainId: string) => (context: DeprecatedConfigDetails) => {
if (!context.silent) { if (!context.silent) {

View file

@ -8,7 +8,7 @@
import { mockGetConfigFromFiles } from './raw_config_service.test.mocks'; import { mockGetConfigFromFiles } from './raw_config_service.test.mocks';
import { first } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { RawConfigService } from './raw_config_service'; import { RawConfigService } from './raw_config_service';
const configFile = '/config/kibana.yml'; const configFile = '/config/kibana.yml';
@ -72,7 +72,7 @@ test('returns config at path as observable', async () => {
configService.loadConfig(); configService.loadConfig();
const exampleConfig = await configService.getConfig$().pipe(first()).toPromise(); const exampleConfig = await firstValueFrom(configService.getConfig$());
expect(exampleConfig.key).toEqual('value'); expect(exampleConfig.key).toEqual('value');
expect(Object.keys(exampleConfig)).toEqual(['key']); expect(Object.keys(exampleConfig)).toEqual(['key']);

View file

@ -14,6 +14,7 @@ import { Writer } from './writer';
import { ToolingLogTextWriter } from './tooling_log_text_writer'; import { ToolingLogTextWriter } from './tooling_log_text_writer';
import { ToolingLogCollectingWriter } from './tooling_log_collecting_writer'; import { ToolingLogCollectingWriter } from './tooling_log_collecting_writer';
import { createStripAnsiSerializer } from '../serializers/strip_ansi_serializer'; import { createStripAnsiSerializer } from '../serializers/strip_ansi_serializer';
import { lastValueFrom } from 'rxjs';
expect.addSnapshotSerializer(createStripAnsiSerializer()); expect.addSnapshotSerializer(createStripAnsiSerializer());
@ -146,8 +147,8 @@ describe('#getWritten$()', () => {
const log = new ToolingLog(); const log = new ToolingLog();
log.setWriters(writers); log.setWriters(writers);
const done$ = new Rx.Subject(); const done$ = new Rx.Subject<void>();
const promise = log.getWritten$().pipe(takeUntil(done$), toArray()).toPromise(); const promise = lastValueFrom(log.getWritten$().pipe(takeUntil(done$), toArray()));
log.debug('foo'); log.debug('foo');
log.info('bar'); log.info('bar');

View file

@ -9,7 +9,7 @@
import Path from 'path'; import Path from 'path';
import { REPO_ROOT } from '@kbn/utils'; import { REPO_ROOT } from '@kbn/utils';
import { lastValueFrom } from '@kbn/std'; import { lastValueFrom } from 'rxjs';
import { run, createFlagError, Flags } from '@kbn/dev-utils'; import { run, createFlagError, Flags } from '@kbn/dev-utils';
import { logOptimizerState } from './log_optimizer_state'; import { logOptimizerState } from './log_optimizer_state';

View file

@ -7,8 +7,7 @@
*/ */
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { toArray, map } from 'rxjs/operators'; import { fakeSchedulers } from 'rxjs-marbles/jest';
import { lastValueFrom } from '@kbn/std';
import { pipeClosure, debounceTimeBuffer, maybeMap, maybe } from './rxjs_helpers'; import { pipeClosure, debounceTimeBuffer, maybeMap, maybe } from './rxjs_helpers';
@ -21,26 +20,26 @@ describe('pipeClosure()', () => {
const foo$ = Rx.of(1, 2, 3).pipe( const foo$ = Rx.of(1, 2, 3).pipe(
pipeClosure((source$) => { pipeClosure((source$) => {
const multiplier = ++counter; const multiplier = ++counter;
return source$.pipe(map((i) => i * multiplier)); return source$.pipe(Rx.map((i) => i * multiplier));
}), }),
toArray() Rx.toArray()
); );
await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` await expect(Rx.lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(`
Array [ Array [
1, 1,
2, 2,
3, 3,
] ]
`); `);
await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` await expect(Rx.lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(`
Array [ Array [
2, 2,
4, 4,
6, 6,
] ]
`); `);
await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` await expect(Rx.lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(`
Array [ Array [
3, 3,
6, 6,
@ -52,9 +51,9 @@ describe('pipeClosure()', () => {
describe('maybe()', () => { describe('maybe()', () => {
it('filters out undefined values from the stream', async () => { it('filters out undefined values from the stream', async () => {
const foo$ = Rx.of(1, undefined, 2, undefined, 3).pipe(maybe(), toArray()); const foo$ = Rx.of(1, undefined, 2, undefined, 3).pipe(maybe(), Rx.toArray());
await expect(lastValueFrom(foo$)).resolves.toEqual([1, 2, 3]); await expect(Rx.lastValueFrom(foo$)).resolves.toEqual([1, 2, 3]);
}); });
}); });
@ -62,10 +61,10 @@ describe('maybeMap()', () => {
it('calls map fn and filters out undefined values returned', async () => { it('calls map fn and filters out undefined values returned', async () => {
const foo$ = Rx.of(1, 2, 3, 4, 5).pipe( const foo$ = Rx.of(1, 2, 3, 4, 5).pipe(
maybeMap((i) => (i % 2 ? i : undefined)), maybeMap((i) => (i % 2 ? i : undefined)),
toArray() Rx.toArray()
); );
await expect(lastValueFrom(foo$)).resolves.toEqual([1, 3, 5]); await expect(Rx.lastValueFrom(foo$)).resolves.toEqual([1, 3, 5]);
}); });
}); });
@ -78,31 +77,33 @@ describe('debounceTimeBuffer()', () => {
jest.useRealTimers(); jest.useRealTimers();
}); });
it('buffers items until there is n milliseconds of silence, then flushes buffer to stream', async () => { it(
'buffers items until there is n milliseconds of silence, then flushes buffer to stream',
fakeSchedulers(async (advance) => {
const foo$ = new Rx.Subject<number>(); const foo$ = new Rx.Subject<number>();
const dest = new Rx.BehaviorSubject<number | undefined>(undefined); const dest = new Rx.BehaviorSubject<number | undefined>(undefined);
foo$ foo$
.pipe( .pipe(
debounceTimeBuffer(100), debounceTimeBuffer(100),
map((items) => items.reduce((sum, n) => sum + n)) Rx.map((items) => items.reduce((sum, n) => sum + n))
) )
.subscribe(dest); .subscribe(dest);
foo$.next(1); foo$.next(1);
expect(dest.getValue()).toBe(undefined); expect(dest.getValue()).toBe(undefined);
// only wait 99 milliseconds before sending the next value // only wait 50 milliseconds before sending the next value
jest.advanceTimersByTime(99); advance(50);
foo$.next(1); foo$.next(1);
expect(dest.getValue()).toBe(undefined); expect(dest.getValue()).toBe(undefined);
// only wait 99 milliseconds before sending the next value // only wait 99 milliseconds before sending the next value
jest.advanceTimersByTime(99); advance(99);
foo$.next(1); foo$.next(1);
expect(dest.getValue()).toBe(undefined); expect(dest.getValue()).toBe(undefined);
// send the next value after 100 milliseconds and observe that it was forwarded // send the next value after 100 milliseconds and observe that it was forwarded
jest.advanceTimersByTime(100); advance(500);
foo$.next(1); foo$.next(1);
expect(dest.getValue()).toBe(3); expect(dest.getValue()).toBe(3);
@ -110,7 +111,8 @@ describe('debounceTimeBuffer()', () => {
if (!dest.isStopped) { if (!dest.isStopped) {
throw new Error('Expected destination to stop as soon as the source is completed'); throw new Error('Expected destination to stop as soon as the source is completed');
} }
}); })
);
it('clears queue as soon as source completes if source completes before time is up', () => { it('clears queue as soon as source completes if source completes before time is up', () => {
const foo$ = new Rx.Subject<number>(); const foo$ = new Rx.Subject<number>();
@ -118,7 +120,7 @@ describe('debounceTimeBuffer()', () => {
foo$ foo$
.pipe( .pipe(
debounceTimeBuffer(100), debounceTimeBuffer(100),
map((items) => items.reduce((sum, n) => sum + n)) Rx.map((items) => items.reduce((sum, n) => sum + n))
) )
.subscribe(dest); .subscribe(dest);

View file

@ -7,8 +7,6 @@
*/ */
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { mergeMap, tap, debounceTime, map, toArray } from 'rxjs/operators';
import { firstValueFrom } from '@kbn/std';
type Operator<T1, T2> = (source: Rx.Observable<T1>) => Rx.Observable<T2>; type Operator<T1, T2> = (source: Rx.Observable<T1>) => Rx.Observable<T2>;
type MapFn<T1, T2> = (item: T1, index: number) => T2; type MapFn<T1, T2> = (item: T1, index: number) => T2;
@ -29,7 +27,7 @@ export const pipeClosure = <T1, T2>(fn: Operator<T1, T2>): Operator<T1, T2> => {
* supporting TypeScript * supporting TypeScript
*/ */
export const maybe = <T1>(): Operator<T1 | undefined, T1> => { export const maybe = <T1>(): Operator<T1 | undefined, T1> => {
return mergeMap((item) => (item === undefined ? Rx.EMPTY : [item])); return Rx.mergeMap((item) => (item === undefined ? Rx.EMPTY : [item]));
}; };
/** /**
@ -39,7 +37,7 @@ export const maybe = <T1>(): Operator<T1 | undefined, T1> => {
* the filter. * the filter.
*/ */
export const maybeMap = <T1, T2>(fn: MapFn<T1, undefined | T2>): Operator<T1, T2> => { export const maybeMap = <T1, T2>(fn: MapFn<T1, undefined | T2>): Operator<T1, T2> => {
return mergeMap((item, index) => { return Rx.mergeMap((item, index) => {
const result = fn(item, index); const result = fn(item, index);
return result === undefined ? Rx.EMPTY : [result]; return result === undefined ? Rx.EMPTY : [result];
}); });
@ -54,9 +52,9 @@ export const debounceTimeBuffer = <T>(ms: number) =>
pipeClosure((source$: Rx.Observable<T>) => { pipeClosure((source$: Rx.Observable<T>) => {
const buffer: T[] = []; const buffer: T[] = [];
return source$.pipe( return source$.pipe(
tap((item) => buffer.push(item)), Rx.tap((item) => buffer.push(item)),
debounceTime(ms), Rx.debounceTime(ms),
map(() => { Rx.map(() => {
const items = Array.from(buffer); const items = Array.from(buffer);
buffer.length = 0; buffer.length = 0;
return items; return items;
@ -65,4 +63,4 @@ export const debounceTimeBuffer = <T>(ms: number) =>
}); });
export const allValuesFrom = <T>(observable: Rx.Observable<T>) => export const allValuesFrom = <T>(observable: Rx.Observable<T>) =>
firstValueFrom(observable.pipe(toArray())); Rx.firstValueFrom(observable.pipe(Rx.toArray()));

View file

@ -8,8 +8,8 @@
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { fakeSchedulers } from 'rxjs-marbles/jest';
import ActualWatchpack from 'watchpack'; import ActualWatchpack from 'watchpack';
import { lastValueFrom } from '@kbn/std';
import { Bundle, ascending } from '../common'; import { Bundle, ascending } from '../common';
import { watchBundlesForChanges$ } from '../optimizer/watch_bundles_for_changes'; import { watchBundlesForChanges$ } from '../optimizer/watch_bundles_for_changes';
@ -65,10 +65,12 @@ afterEach(async () => {
jest.useRealTimers(); jest.useRealTimers();
}); });
it('notifies of changes and completes once all bundles have changed', async () => { it(
'notifies of changes and completes once all bundles have changed',
fakeSchedulers(async (advance) => {
expect.assertions(18); expect.assertions(18);
const promise = lastValueFrom( const promise = Rx.lastValueFrom(
watchBundlesForChanges$(bundleCacheEvent$, Date.now()).pipe( watchBundlesForChanges$(bundleCacheEvent$, Date.now()).pipe(
map((event, i) => { map((event, i) => {
// each time we trigger a change event we get a 'changed detected' event // each time we trigger a change event we get a 'changed detected' event
@ -116,18 +118,19 @@ it('notifies of changes and completes once all bundles have changed', async () =
// foo and bar are changes without 1sec so they are batched // foo and bar are changes without 1sec so they are batched
changeListener(bundleEntryPath(FOO_BUNDLE), 'modified'); changeListener(bundleEntryPath(FOO_BUNDLE), 'modified');
jest.advanceTimersByTime(900); advance(900);
changeListener(bundleEntryPath(BAR_BUNDLE), 'modified'); changeListener(bundleEntryPath(BAR_BUNDLE), 'modified');
jest.advanceTimersByTime(1000); advance(1000);
// baz is the only change in 1sec so it is on its own // baz is the only change in 1sec so it is on its own
changeListener(bundleEntryPath(BAZ_BUNDLE), 'modified'); changeListener(bundleEntryPath(BAZ_BUNDLE), 'modified');
jest.advanceTimersByTime(1000); advance(1000);
// finish by changing box and car // finish by changing box and car
changeListener(bundleEntryPath(BOX_BUNDLE), 'deleted'); changeListener(bundleEntryPath(BOX_BUNDLE), 'deleted');
changeListener(bundleEntryPath(CAR_BUNDLE), 'deleted'); changeListener(bundleEntryPath(CAR_BUNDLE), 'deleted');
jest.advanceTimersByTime(1000); advance(1000);
await expect(promise).resolves.toEqual(undefined); await expect(promise).resolves.toEqual(undefined);
}); })
);

View file

@ -159,7 +159,7 @@ export function observeWorker(
let lastMsg: WorkerMsg; let lastMsg: WorkerMsg;
const worker$: Rx.Observable<WorkerMsg | WorkerStatus> = Rx.merge( const worker$: Rx.Observable<WorkerMsg | WorkerStatus> = Rx.merge(
Rx.of({ Rx.of({
type: 'worker started', type: 'worker started' as const,
bundles, bundles,
}), }),
// TypeScript note: As long as the proc stdio[1] is 'pipe', then stdout will not be null // TypeScript note: As long as the proc stdio[1] is 'pipe', then stdout will not be null

View file

@ -27,7 +27,7 @@ const observeCompiler = (
compiler: webpack.Compiler compiler: webpack.Compiler
): Rx.Observable<CompilerMsg> => { ): Rx.Observable<CompilerMsg> => {
const compilerMsgs = new CompilerMsgs(bundle.id); const compilerMsgs = new CompilerMsgs(bundle.id);
const done$ = new Rx.Subject(); const done$ = new Rx.Subject<void>();
const { beforeRun, watchRun, done } = compiler.hooks; const { beforeRun, watchRun, done } = compiler.hooks;
/** /**

File diff suppressed because one or more lines are too long

View file

@ -87,8 +87,8 @@ export function waitUntilWatchIsReady(stream: NodeJS.EventEmitter, opts: IWatchO
stream.once('error', onErrorListener); stream.once('error', onErrorListener);
stream.on('data', onDataListener); stream.on('data', onDataListener);
return Rx.race(getWatchHandlers(buildOutput$, opts)) return Rx.firstValueFrom(
.pipe( Rx.race(getWatchHandlers(buildOutput$, opts)).pipe(
mergeMap((whenReady) => whenReady), mergeMap((whenReady) => whenReady),
finalize(() => { finalize(() => {
stream.removeListener('data', onDataListener); stream.removeListener('data', onDataListener);
@ -98,5 +98,5 @@ export function waitUntilWatchIsReady(stream: NodeJS.EventEmitter, opts: IWatchO
buildOutput$.complete(); buildOutput$.complete();
}) })
) )
.toPromise(); );
} }

View file

@ -4,9 +4,7 @@ exports[`<ExitFullScreenButton /> is rendered 1`] = `
<SharedUxServicesProvider <SharedUxServicesProvider
application={ application={
Object { Object {
"currentAppId$": Observable { "currentAppId$": Observable {},
"_isScalar": false,
},
"navigateToUrl": [Function], "navigateToUrl": [Function],
} }
} }

View file

@ -4,10 +4,9 @@ exports[`ElasticAgentCardComponent props button 1`] = `
<RedirectAppLinks <RedirectAppLinks
currentAppId$={ currentAppId$={
Observable { Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -30,10 +29,9 @@ exports[`ElasticAgentCardComponent props href 1`] = `
<RedirectAppLinks <RedirectAppLinks
currentAppId$={ currentAppId$={
Observable { Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -56,10 +54,9 @@ exports[`ElasticAgentCardComponent renders 1`] = `
<RedirectAppLinks <RedirectAppLinks
currentAppId$={ currentAppId$={
Observable { Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -81,10 +78,9 @@ exports[`ElasticAgentCardComponent renders with canAccessFleet false 1`] = `
<RedirectAppLinks <RedirectAppLinks
currentAppId$={ currentAppId$={
Observable { Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],

View file

@ -4,9 +4,7 @@ exports[`ElasticAgentCard renders 1`] = `
<SharedUxServicesProvider <SharedUxServicesProvider
application={ application={
Object { Object {
"currentAppId$": Observable { "currentAppId$": Observable {},
"_isScalar": false,
},
"navigateToUrl": [Function], "navigateToUrl": [Function],
} }
} }
@ -142,20 +140,12 @@ exports[`ElasticAgentCard renders 1`] = `
<ElasticAgentCard> <ElasticAgentCard>
<ElasticAgentCardComponent <ElasticAgentCardComponent
canAccessFleet={true} canAccessFleet={true}
currentAppId$={ currentAppId$={Observable {}}
Observable {
"_isScalar": false,
}
}
href="/app/integrations/browse" href="/app/integrations/browse"
navigateToUrl={[Function]} navigateToUrl={[Function]}
> >
<RedirectAppLinks <RedirectAppLinks
currentAppId$={ currentAppId$={Observable {}}
Observable {
"_isScalar": false,
}
}
navigateToUrl={[Function]} navigateToUrl={[Function]}
> >
<div> <div>

View file

@ -4,9 +4,7 @@ exports[`<IconButtonGroup /> is rendered 1`] = `
<SharedUxServicesProvider <SharedUxServicesProvider
application={ application={
Object { Object {
"currentAppId$": Observable { "currentAppId$": Observable {},
"_isScalar": false,
},
"navigateToUrl": [Function], "navigateToUrl": [Function],
} }
} }

View file

@ -4,9 +4,7 @@ exports[`<ToolbarButton /> is rendered 1`] = `
<SharedUxServicesProvider <SharedUxServicesProvider
application={ application={
Object { Object {
"currentAppId$": Observable { "currentAppId$": Observable {},
"_isScalar": false,
},
"navigateToUrl": [Function], "navigateToUrl": [Function],
} }
} }

View file

@ -19,7 +19,6 @@ export { isRelativeUrl, modifyUrl, getUrlOrigin } from './url';
export { unset } from './unset'; export { unset } from './unset';
export { getFlattenedObject } from './get_flattened_object'; export { getFlattenedObject } from './get_flattened_object';
export { ensureNoUnsafeProperties } from './ensure_no_unsafe_properties'; export { ensureNoUnsafeProperties } from './ensure_no_unsafe_properties';
export * from './rxjs_7';
export { export {
map$, map$,
mapWithLimit$, mapWithLimit$,

View file

@ -6,9 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { defaultIfEmpty } from 'rxjs/operators'; import { lastValueFrom, defaultIfEmpty } from 'rxjs';
import { lastValueFrom } from '../rxjs_7';
import { mapWithLimit$ } from './observable'; import { mapWithLimit$ } from './observable';
import { IterableInput, AsyncMapFn } from './types'; import { IterableInput, AsyncMapFn } from './types';
@ -21,7 +19,7 @@ import { IterableInput, AsyncMapFn } from './types';
* @param fn Function to call for each item * @param fn Function to call for each item
*/ */
export async function asyncForEach<T>(iterable: IterableInput<T>, fn: AsyncMapFn<T, any>) { export async function asyncForEach<T>(iterable: IterableInput<T>, fn: AsyncMapFn<T, any>) {
await lastValueFrom(mapWithLimit$(iterable, Infinity, fn).pipe(defaultIfEmpty())); await lastValueFrom(mapWithLimit$(iterable, Infinity, fn).pipe(defaultIfEmpty(undefined)));
} }
/** /**
@ -40,5 +38,5 @@ export async function asyncForEachWithLimit<T>(
limit: number, limit: number,
fn: AsyncMapFn<T, any> fn: AsyncMapFn<T, any>
) { ) {
await lastValueFrom(mapWithLimit$(iterable, limit, fn).pipe(defaultIfEmpty())); await lastValueFrom(mapWithLimit$(iterable, limit, fn).pipe(defaultIfEmpty(undefined)));
} }

View file

@ -6,9 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { from } from 'rxjs'; import { from, lastValueFrom } from 'rxjs';
import { toArray } from 'rxjs/operators'; import { toArray } from 'rxjs/operators';
import { lastValueFrom } from '../rxjs_7';
import { IterableInput, AsyncMapFn, AsyncMapResult } from './types'; import { IterableInput, AsyncMapFn, AsyncMapResult } from './types';
import { mapWithLimit$ } from './observable'; import { mapWithLimit$ } from './observable';

View file

@ -8,7 +8,6 @@
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { toArray } from 'rxjs/operators'; import { toArray } from 'rxjs/operators';
import { lastValueFrom } from '../rxjs_7';
import { map$, mapWithLimit$ } from './observable'; import { map$, mapWithLimit$ } from './observable';
import { list, sleep, generator } from './test_helpers'; import { list, sleep, generator } from './test_helpers';
@ -23,7 +22,7 @@ describe('mapWithLimit$', () => {
let active = 0; let active = 0;
const limit = Math.random() > 0.5 ? 20 : 40; const limit = Math.random() > 0.5 ? 20 : 40;
const results = await lastValueFrom( const results = await Rx.lastValueFrom(
mapWithLimit$(list(100), limit, async (n) => { mapWithLimit$(list(100), limit, async (n) => {
active += 1; active += 1;
if (active > maxConcurrency) { if (active > maxConcurrency) {
@ -50,7 +49,7 @@ describe('mapWithLimit$', () => {
['observable', Rx.of(1, 2, 3, 4, 5), [1, 2, 3, 4, 5]] as const, ['observable', Rx.of(1, 2, 3, 4, 5), [1, 2, 3, 4, 5]] as const,
])('works with %p', async (_, iter, expected) => { ])('works with %p', async (_, iter, expected) => {
const mock = jest.fn(async (n) => n); const mock = jest.fn(async (n) => n);
const results = await lastValueFrom(mapWithLimit$(iter, 1, mock).pipe(toArray())); const results = await Rx.lastValueFrom(mapWithLimit$(iter, 1, mock).pipe(toArray()));
expect(results).toEqual(expected); expect(results).toEqual(expected);
}); });
}); });
@ -60,7 +59,7 @@ describe('map$', () => {
let maxConcurrency = 0; let maxConcurrency = 0;
let active = 0; let active = 0;
const results = await lastValueFrom( const results = await Rx.lastValueFrom(
map$(list(100), async (n) => { map$(list(100), async (n) => {
active += 1; active += 1;
if (active > maxConcurrency) { if (active > maxConcurrency) {

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Subscribable } from 'rxjs'; import { ObservableInput } from 'rxjs';
export type IterableInput<T> = Iterable<T> | Subscribable<T>; export type IterableInput<T> = Iterable<T> | ObservableInput<T>;
export type AsyncMapResult<T> = Promise<T> | Subscribable<T>; export type AsyncMapResult<T> = Promise<T> | ObservableInput<T>;
export type AsyncMapFn<T1, T2> = (item: T1, i: number) => AsyncMapResult<T2>; export type AsyncMapFn<T1, T2> = (item: T1, i: number) => AsyncMapResult<T2>;

View file

@ -1,82 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import * as Rx from 'rxjs';
import { firstValueFrom, lastValueFrom } from './rxjs_7';
// create an empty observable that completes with no notifications
// after a delay to ensure helpers aren't checking for the EMPTY constant
function empty() {
return new Rx.Observable<never>((subscriber) => {
setTimeout(() => {
subscriber.complete();
}, 0);
});
}
describe('firstValueFrom()', () => {
it('resolves to the first value from the observable', async () => {
await expect(firstValueFrom(Rx.of(1, 2, 3))).resolves.toBe(1);
});
it('rejects if the observable is empty', async () => {
await expect(firstValueFrom(empty())).rejects.toThrowErrorMatchingInlineSnapshot(
`"no elements in sequence"`
);
});
it('unsubscribes from a source observable that emits synchronously', async () => {
const values = [1, 2, 3, 4];
let unsubscribed = false;
const source = new Rx.Observable<number>((subscriber) => {
while (!subscriber.closed && values.length) {
subscriber.next(values.shift()!);
}
unsubscribed = subscriber.closed;
subscriber.complete();
});
await expect(firstValueFrom(source)).resolves.toMatchInlineSnapshot(`1`);
if (!unsubscribed) {
throw new Error('expected source to be unsubscribed');
}
expect(values).toEqual([2, 3, 4]);
});
it('unsubscribes from the source observable after first async notification', async () => {
const values = [1, 2, 3, 4];
let unsubscribed = false;
const source = new Rx.Observable<number>((subscriber) => {
setTimeout(() => {
while (!subscriber.closed) {
subscriber.next(values.shift()!);
}
unsubscribed = subscriber.closed;
});
});
await expect(firstValueFrom(source)).resolves.toMatchInlineSnapshot(`1`);
if (!unsubscribed) {
throw new Error('expected source to be unsubscribed');
}
expect(values).toEqual([2, 3, 4]);
});
});
describe('lastValueFrom()', () => {
it('resolves to the last value from the observable', async () => {
await expect(lastValueFrom(Rx.of(1, 2, 3))).resolves.toBe(3);
});
it('rejects if the observable is empty', async () => {
await expect(lastValueFrom(empty())).rejects.toThrowErrorMatchingInlineSnapshot(
`"no elements in sequence"`
);
});
});

View file

@ -1,19 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { Observable } from 'rxjs';
import { first, last } from 'rxjs/operators';
export function firstValueFrom<T>(source: Observable<T>) {
// we can't use SafeSubscriber the same way that RxJS 7 does, so instead we
return source.pipe(first()).toPromise();
}
export function lastValueFrom<T>(source: Observable<T>) {
return source.pipe(last()).toPromise();
}

View file

@ -10,7 +10,6 @@ import { inspect } from 'util';
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { mergeMap } from 'rxjs/operators'; import { mergeMap } from 'rxjs/operators';
import { lastValueFrom } from '@kbn/std';
import { ToolingLog, isAxiosResponseError, createFailError } from '@kbn/dev-utils'; import { ToolingLog, isAxiosResponseError, createFailError } from '@kbn/dev-utils';
import { KbnClientRequester, uriencode } from './kbn_client_requester'; import { KbnClientRequester, uriencode } from './kbn_client_requester';
@ -83,7 +82,7 @@ interface DeleteObjectsOptions {
async function concurrently<T>(maxConcurrency: number, arr: T[], fn: (item: T) => Promise<void>) { async function concurrently<T>(maxConcurrency: number, arr: T[], fn: (item: T) => Promise<void>) {
if (arr.length) { if (arr.length) {
await lastValueFrom( await Rx.lastValueFrom(
Rx.from(arr).pipe(mergeMap(async (item) => await fn(item), maxConcurrency)) Rx.from(arr).pipe(mergeMap(async (item) => await fn(item), maxConcurrency))
); );
} }

View file

@ -117,7 +117,7 @@ describe.skip('Server logging configuration', function () {
) )
.toPromise(); .toPromise();
const lastMessage = await message$.pipe(take(1)).toPromise(); const lastMessage = await Rx.firstValueFrom(message$);
expect(containsJsonOnly(lastMessage)).toBe(true); expect(containsJsonOnly(lastMessage)).toBe(true);
createConfigManager(configFilePath).modify((oldConfig) => { createConfigManager(configFilePath).modify((oldConfig) => {

View file

@ -4,15 +4,15 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = `
<AppRouter <AppRouter
appStatuses$={ appStatuses$={
AnonymousSubject { AnonymousSubject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"destination": AnonymousSubject { "destination": AnonymousSubject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"destination": BehaviorSubject { "destination": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": Array [],
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -21,14 +21,11 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = `
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
"operator": MapOperator { "operator": [Function],
"project": [Function],
"thisArg": undefined,
},
"source": BehaviorSubject { "source": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": Array [],
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -41,12 +38,12 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = `
"observers": Array [], "observers": Array [],
"operator": [Function], "operator": [Function],
"source": AnonymousSubject { "source": AnonymousSubject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"destination": BehaviorSubject { "destination": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": Array [],
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -55,14 +52,11 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = `
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
"operator": MapOperator { "operator": [Function],
"project": [Function],
"thisArg": undefined,
},
"source": BehaviorSubject { "source": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": Array [],
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -85,7 +79,6 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = `
setIsMounting={[Function]} setIsMounting={[Function]}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }

View file

@ -13,8 +13,8 @@ import {
} from './application_service.test.mocks'; } from './application_service.test.mocks';
import { createElement } from 'react'; import { createElement } from 'react';
import { BehaviorSubject, Subject } from 'rxjs'; import { BehaviorSubject, firstValueFrom, Subject } from 'rxjs';
import { bufferCount, take, takeUntil } from 'rxjs/operators'; import { bufferCount, takeUntil } from 'rxjs/operators';
import { mount, shallow } from 'enzyme'; import { mount, shallow } from 'enzyme';
import { httpServiceMock } from '../http/http_service.mock'; import { httpServiceMock } from '../http/http_service.mock';
@ -96,7 +96,7 @@ describe('#setup()', () => {
); );
const { applications$ } = await service.start(startDeps); const { applications$ } = await service.start(startDeps);
let applications = await applications$.pipe(take(1)).toPromise(); let applications = await firstValueFrom(applications$);
expect(applications.size).toEqual(2); expect(applications.size).toEqual(2);
expect(applications.get('app1')).toEqual( expect(applications.get('app1')).toEqual(
expect.objectContaining({ expect.objectContaining({
@ -125,7 +125,7 @@ describe('#setup()', () => {
deepLinks: [{ id: 'subapp2', title: 'Subapp 2', path: '/subapp2' }], deepLinks: [{ id: 'subapp2', title: 'Subapp 2', path: '/subapp2' }],
})); }));
applications = await applications$.pipe(take(1)).toPromise(); applications = await firstValueFrom(applications$);
expect(applications.size).toEqual(2); expect(applications.size).toEqual(2);
expect(applications.get('app1')).toEqual( expect(applications.get('app1')).toEqual(
expect.objectContaining({ expect.objectContaining({
@ -205,7 +205,7 @@ describe('#setup()', () => {
}) })
); );
const start = await service.start(startDeps); const start = await service.start(startDeps);
const applications = await start.applications$.pipe(take(1)).toPromise(); const applications = await firstValueFrom(start.applications$);
expect(applications.size).toEqual(2); expect(applications.size).toEqual(2);
expect(applications.get('app1')).toEqual( expect(applications.get('app1')).toEqual(
@ -252,7 +252,7 @@ describe('#setup()', () => {
); );
const { applications$ } = await service.start(startDeps); const { applications$ } = await service.start(startDeps);
const applications = await applications$.pipe(take(1)).toPromise(); const applications = await firstValueFrom(applications$);
expect(applications.size).toEqual(2); expect(applications.size).toEqual(2);
expect(applications.get('app1')).toEqual( expect(applications.get('app1')).toEqual(
@ -295,7 +295,7 @@ describe('#setup()', () => {
); );
const start = await service.start(startDeps); const start = await service.start(startDeps);
const applications = await start.applications$.pipe(take(1)).toPromise(); const applications = await firstValueFrom(start.applications$);
expect(applications.size).toEqual(1); expect(applications.size).toEqual(1);
expect(applications.get('app1')).toEqual( expect(applications.get('app1')).toEqual(
@ -410,7 +410,7 @@ describe('#setup()', () => {
updater$.next((app) => ({ defaultPath: '/foo' })); updater$.next((app) => ({ defaultPath: '/foo' }));
let appInfos = await applications$.pipe(take(1)).toPromise(); let appInfos = await firstValueFrom(applications$);
expect(appInfos.get('app1')!.deepLinks).toEqual([ expect(appInfos.get('app1')!.deepLinks).toEqual([
{ {
@ -445,7 +445,7 @@ describe('#setup()', () => {
], ],
})); }));
appInfos = await applications$.pipe(take(1)).toPromise(); appInfos = await firstValueFrom(applications$);
expect(appInfos.get('app1')!.deepLinks).toEqual([ expect(appInfos.get('app1')!.deepLinks).toEqual([
{ {
@ -496,7 +496,7 @@ describe('#start()', () => {
register(Symbol(), createApp({ id: 'app2' })); register(Symbol(), createApp({ id: 'app2' }));
const { applications$ } = await service.start(startDeps); const { applications$ } = await service.start(startDeps);
const availableApps = await applications$.pipe(take(1)).toPromise(); const availableApps = await firstValueFrom(applications$);
expect(availableApps.size).toEqual(2); expect(availableApps.size).toEqual(2);
expect([...availableApps.keys()]).toEqual(['app1', 'app2']); expect([...availableApps.keys()]).toEqual(['app1', 'app2']);
@ -548,7 +548,7 @@ describe('#start()', () => {
register(Symbol(), createApp({ id: 'app2' })); register(Symbol(), createApp({ id: 'app2' }));
const { applications$ } = await service.start(startDeps); const { applications$ } = await service.start(startDeps);
const availableApps = await applications$.pipe(take(1)).toPromise(); const availableApps = await firstValueFrom(applications$);
expect([...availableApps.keys()]).toEqual(['app1']); expect([...availableApps.keys()]).toEqual(['app1']);
}); });
@ -802,7 +802,7 @@ describe('#start()', () => {
service.setup(setupDeps); service.setup(setupDeps);
const { currentAppId$, navigateToApp } = await service.start(startDeps); const { currentAppId$, navigateToApp } = await service.start(startDeps);
const stop$ = new Subject(); const stop$ = new Subject<void>();
const promise = currentAppId$.pipe(bufferCount(4), takeUntil(stop$)).toPromise(); const promise = currentAppId$.pipe(bufferCount(4), takeUntil(stop$)).toPromise();
await navigateToApp('alpha'); await navigateToApp('alpha');
@ -827,7 +827,7 @@ describe('#start()', () => {
service.setup(setupDeps); service.setup(setupDeps);
const { currentAppId$, navigateToApp } = await service.start(startDeps); const { currentAppId$, navigateToApp } = await service.start(startDeps);
const stop$ = new Subject(); const stop$ = new Subject<void>();
const promise = currentAppId$.pipe(bufferCount(4), takeUntil(stop$)).toPromise(); const promise = currentAppId$.pipe(bufferCount(4), takeUntil(stop$)).toPromise();
await navigateToApp('delta', { openInNewTab: true }); await navigateToApp('delta', { openInNewTab: true });
@ -871,7 +871,7 @@ describe('#start()', () => {
const { navigateToApp, getComponent } = await service.start(startDeps); const { navigateToApp, getComponent } = await service.start(startDeps);
const httpLoadingCount$ = startDeps.http.addLoadingCountSource.mock.calls[0][0]; const httpLoadingCount$ = startDeps.http.addLoadingCountSource.mock.calls[0][0];
const stop$ = new Subject(); const stop$ = new Subject<void>();
const currentLoadingCount$ = new BehaviorSubject(0); const currentLoadingCount$ = new BehaviorSubject(0);
httpLoadingCount$.pipe(takeUntil(stop$)).subscribe(currentLoadingCount$); httpLoadingCount$.pipe(takeUntil(stop$)).subscribe(currentLoadingCount$);
const loadingPromise = httpLoadingCount$.pipe(bufferCount(5), takeUntil(stop$)).toPromise(); const loadingPromise = httpLoadingCount$.pipe(bufferCount(5), takeUntil(stop$)).toPromise();

View file

@ -7,7 +7,7 @@
*/ */
import React from 'react'; import React from 'react';
import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { BehaviorSubject, firstValueFrom, Observable, Subject, Subscription } from 'rxjs';
import { map, shareReplay, takeUntil, distinctUntilChanged, filter, take } from 'rxjs/operators'; import { map, shareReplay, takeUntil, distinctUntilChanged, filter, take } from 'rxjs/operators';
import { createBrowserHistory, History } from 'history'; import { createBrowserHistory, History } from 'history';
@ -99,7 +99,7 @@ export class ApplicationService {
private currentActionMenu$ = new BehaviorSubject<MountPoint | undefined>(undefined); private currentActionMenu$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private readonly statusUpdaters$ = new BehaviorSubject<Map<symbol, AppUpdaterWrapper>>(new Map()); private readonly statusUpdaters$ = new BehaviorSubject<Map<symbol, AppUpdaterWrapper>>(new Map());
private readonly subscriptions: Subscription[] = []; private readonly subscriptions: Subscription[] = [];
private stop$ = new Subject(); private stop$ = new Subject<void>();
private registrationClosed = false; private registrationClosed = false;
private history?: History<any>; private history?: History<any>;
private navigate?: (url: string, state: unknown, replace: boolean) => void; private navigate?: (url: string, state: unknown, replace: boolean) => void;
@ -120,7 +120,7 @@ export class ApplicationService {
createBrowserHistory({ createBrowserHistory({
basename, basename,
getUserConfirmation: getUserConfirmationHandler({ getUserConfirmation: getUserConfirmationHandler({
overlayPromise: this.overlayStart$.pipe(take(1)).toPromise(), overlayPromise: firstValueFrom(this.overlayStart$.pipe(take(1))),
}), }),
}); });

View file

@ -9,7 +9,7 @@
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { take, toArray } from 'rxjs/operators'; import { toArray } from 'rxjs/operators';
import { App, PublicAppInfo } from '../application'; import { App, PublicAppInfo } from '../application';
import { applicationServiceMock } from '../application/application_service.mock'; import { applicationServiceMock } from '../application/application_service.mock';
import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { docLinksServiceMock } from '../doc_links/doc_links_service.mock';
@ -229,7 +229,7 @@ describe('start', () => {
const { chrome, service } = await start({ startDeps }); const { chrome, service } = await start({ startDeps });
const promise = chrome.getIsVisible$().pipe(toArray()).toPromise(); const promise = chrome.getIsVisible$().pipe(toArray()).toPromise();
const availableApps = await applications$.pipe(take(1)).toPromise(); const availableApps = await Rx.firstValueFrom(applications$);
[...availableApps.keys()].forEach((appId) => navigateToApp(appId)); [...availableApps.keys()].forEach((appId) => navigateToApp(appId));
service.stop(); service.stop();

View file

@ -55,7 +55,7 @@ export interface StartDeps {
export class ChromeService { export class ChromeService {
private isVisible$!: Observable<boolean>; private isVisible$!: Observable<boolean>;
private isForceHidden$!: BehaviorSubject<boolean>; private isForceHidden$!: BehaviorSubject<boolean>;
private readonly stop$ = new ReplaySubject(1); private readonly stop$ = new ReplaySubject<void>(1);
private readonly navControls = new NavControlsService(); private readonly navControls = new NavControlsService();
private readonly navLinks = new NavLinksService(); private readonly navLinks = new NavLinksService();
private readonly recentlyAccessed = new RecentlyAccessedService(); private readonly recentlyAccessed = new RecentlyAccessedService();

View file

@ -50,7 +50,7 @@ export interface ChromeNavControls {
/** @internal */ /** @internal */
export class NavControlsService { export class NavControlsService {
private readonly stop$ = new ReplaySubject(1); private readonly stop$ = new ReplaySubject<void>(1);
public start() { public start() {
const navControlsLeft$ = new BehaviorSubject<ReadonlySet<ChromeNavControl>>(new Set()); const navControlsLeft$ = new BehaviorSubject<ReadonlySet<ChromeNavControl>>(new Set());

View file

@ -69,7 +69,7 @@ export interface ChromeNavLinks {
} }
export class NavLinksService { export class NavLinksService {
private readonly stop$ = new ReplaySubject(1); private readonly stop$ = new ReplaySubject<void>(1);
public start({ application, http }: StartDeps): ChromeNavLinks { public start({ application, http }: StartDeps): ChromeNavLinks {
const navLinks$ = new BehaviorSubject<ReadonlyMap<string, NavLinkWrapper>>(new Map()); const navLinks$ = new BehaviorSubject<ReadonlyMap<string, NavLinkWrapper>>(new Map());

View file

@ -90,7 +90,7 @@ describe('RecentlyAccessed#start()', () => {
it('exposes an observable', async () => { it('exposes an observable', async () => {
const { recentlyAccessed } = await getStart(); const { recentlyAccessed } = await getStart();
const stop$ = new Subject(); const stop$ = new Subject<void>();
const observedValues$ = recentlyAccessed const observedValues$ = recentlyAccessed
.get$() .get$()
.pipe(bufferCount(3), takeUntil(stop$)) .pipe(bufferCount(3), takeUntil(stop$))

View file

@ -4,48 +4,32 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
<CollapsibleNav <CollapsibleNav
appId$={ appId$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": "test", "_value": "test",
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -65,7 +49,6 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
closeNav={[Function]} closeNav={[Function]}
customNavLink$={ customNavLink$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Object { "_value": Object {
"baseUrl": "/", "baseUrl": "/",
"category": undefined, "category": undefined,
@ -77,45 +60,30 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
"url": "/", "url": "/",
}, },
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -127,7 +95,6 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
isNavOpen={true} isNavOpen={true}
navLinks$={ navLinks$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [ "_value": Array [
Object { Object {
"baseUrl": "/", "baseUrl": "/",
@ -246,45 +213,30 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
}, },
], ],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -295,7 +247,6 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
onIsLockedUpdate={[Function]} onIsLockedUpdate={[Function]}
recentlyAccessed$={ recentlyAccessed$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [ "_value": Array [
Object { Object {
"id": "recent 1", "id": "recent 1",
@ -309,45 +260,30 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
}, },
], ],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2073,48 +2009,32 @@ exports[`CollapsibleNav renders the default nav 1`] = `
<CollapsibleNav <CollapsibleNav
appId$={ appId$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": "test", "_value": "test",
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2134,48 +2054,32 @@ exports[`CollapsibleNav renders the default nav 1`] = `
closeNav={[Function]} closeNav={[Function]}
customNavLink$={ customNavLink$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": undefined, "_value": undefined,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2187,48 +2091,32 @@ exports[`CollapsibleNav renders the default nav 1`] = `
isNavOpen={false} isNavOpen={false}
navLinks$={ navLinks$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [], "_value": Array [],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2239,48 +2127,32 @@ exports[`CollapsibleNav renders the default nav 1`] = `
onIsLockedUpdate={[Function]} onIsLockedUpdate={[Function]}
recentlyAccessed$={ recentlyAccessed$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [], "_value": Array [],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2321,48 +2193,32 @@ exports[`CollapsibleNav renders the default nav 2`] = `
<CollapsibleNav <CollapsibleNav
appId$={ appId$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": "test", "_value": "test",
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2382,48 +2238,32 @@ exports[`CollapsibleNav renders the default nav 2`] = `
closeNav={[Function]} closeNav={[Function]}
customNavLink$={ customNavLink$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": undefined, "_value": undefined,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2436,48 +2276,32 @@ exports[`CollapsibleNav renders the default nav 2`] = `
isOpen={true} isOpen={true}
navLinks$={ navLinks$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [], "_value": Array [],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,
@ -2488,48 +2312,32 @@ exports[`CollapsibleNav renders the default nav 2`] = `
onIsLockedUpdate={[Function]} onIsLockedUpdate={[Function]}
recentlyAccessed$={ recentlyAccessed$={
BehaviorSubject { BehaviorSubject {
"_isScalar": false,
"_value": Array [], "_value": Array [],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [ "observers": Array [
Subscriber { SafeSubscriber {
"_parentOrParents": null, "_finalizers": Array [
"_subscriptions": Array [ Subscription {
SubjectSubscription { "_finalizers": null,
"_parentOrParents": [Circular], "_parentage": [Circular],
"_subscriptions": null,
"closed": false, "closed": false,
"subject": [Circular], "initialTeardown": [Function],
"subscriber": [Circular],
}, },
], ],
"_parentage": null,
"closed": false, "closed": false,
"destination": SafeSubscriber { "destination": ConsumerObserver {
"_complete": undefined, "partialObserver": Object {
"_context": [Circular], "complete": undefined,
"_error": undefined, "error": undefined,
"_next": [Function],
"_parentOrParents": null,
"_parentSubscriber": [Circular],
"_subscriptions": null,
"closed": false,
"destination": Object {
"closed": true,
"complete": [Function],
"error": [Function],
"next": [Function], "next": [Function],
}, },
"isStopped": false,
"syncErrorThrowable": false,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
"initialTeardown": undefined,
"isStopped": false, "isStopped": false,
"syncErrorThrowable": true,
"syncErrorThrown": false,
"syncErrorValue": null,
}, },
], ],
"thrownError": null, "thrownError": null,

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@ export type LoadingCountStart = LoadingCountSetup;
/** @internal */ /** @internal */
export class LoadingCountService implements CoreService<LoadingCountSetup, LoadingCountStart> { export class LoadingCountService implements CoreService<LoadingCountSetup, LoadingCountStart> {
private readonly stop$ = new Subject(); private readonly stop$ = new Subject<void>();
private readonly loadingCount$ = new BehaviorSubject(0); private readonly loadingCount$ = new BehaviorSubject(0);
public setup({ fatalErrors }: { fatalErrors: FatalErrorsSetup }) { public setup({ fatalErrors }: { fatalErrors: FatalErrorsSetup }) {

View file

@ -12,7 +12,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -22,11 +21,10 @@ Array [
dismissToast={[Function]} dismissToast={[Function]}
toasts$={ toasts$={
Observable { Observable {
"_isScalar": false,
"source": BehaviorSubject { "source": BehaviorSubject {
"_isScalar": false,
"_value": Array [], "_value": Array [],
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { take } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { ToastsApi } from './toasts_api'; import { ToastsApi } from './toasts_api';
@ -14,7 +14,7 @@ import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.moc
import { i18nServiceMock } from '../../i18n/i18n_service.mock'; import { i18nServiceMock } from '../../i18n/i18n_service.mock';
async function getCurrentToasts(toasts: ToastsApi) { async function getCurrentToasts(toasts: ToastsApi) {
return await toasts.get$().pipe(take(1)).toPromise(); return await firstValueFrom(toasts.get$());
} }
function uiSettingsMock() { function uiSettingsMock() {

View file

@ -20,7 +20,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -56,7 +55,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -81,7 +79,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -103,7 +100,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -132,7 +128,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -157,7 +152,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -179,7 +173,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }

View file

@ -22,7 +22,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -47,7 +46,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -69,7 +67,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -108,7 +105,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -131,7 +127,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -159,7 +154,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -180,7 +174,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -205,7 +198,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -241,7 +233,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -264,7 +255,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -290,7 +280,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -315,7 +304,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -336,7 +324,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -360,7 +347,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -382,7 +368,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -411,7 +396,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -434,7 +418,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -460,7 +443,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -485,7 +467,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -506,7 +487,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -530,7 +510,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -552,7 +531,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -586,7 +564,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -609,7 +586,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -635,7 +611,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -660,7 +635,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -681,7 +655,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -705,7 +678,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -727,7 +699,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -756,7 +727,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -779,7 +749,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -805,7 +774,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -830,7 +798,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -851,7 +818,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -875,7 +841,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -897,7 +862,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -929,7 +893,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -965,7 +928,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -990,7 +952,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1012,7 +973,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -1041,7 +1001,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1066,7 +1025,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1088,7 +1046,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -1122,7 +1079,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1147,7 +1103,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1169,7 +1124,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -1198,7 +1152,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1223,7 +1176,6 @@ Array [
globalStyles={false} globalStyles={false}
theme$={ theme$={
Observable { Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
} }
} }
@ -1245,7 +1197,6 @@ Array [
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Subject } from 'rxjs'; import { firstValueFrom, Subject } from 'rxjs';
import { first } from 'rxjs/operators';
import { DiscoveredPlugin, PluginOpaqueId } from '../../server'; import { DiscoveredPlugin, PluginOpaqueId } from '../../server';
import { PluginInitializerContext } from './plugin_context'; import { PluginInitializerContext } from './plugin_context';
import { read } from './plugin_reader'; import { read } from './plugin_reader';
@ -61,7 +60,7 @@ export class PluginWrapper<
private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>; private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>(); private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>();
public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); public readonly startDependencies = firstValueFrom(this.startDependencies$);
constructor( constructor(
public readonly discoveredPlugin: DiscoveredPlugin, public readonly discoveredPlugin: DiscoveredPlugin,

View file

@ -17,7 +17,7 @@ export interface SetupDeps {
export class ThemeService { export class ThemeService {
private theme$?: Observable<CoreTheme>; private theme$?: Observable<CoreTheme>;
private stop$ = new Subject(); private stop$ = new Subject<void>();
public setup({ injectedMetadata }: SetupDeps): ThemeServiceSetup { public setup({ injectedMetadata }: SetupDeps): ThemeServiceSetup {
const theme = injectedMetadata.getTheme(); const theme = injectedMetadata.getTheme();

View file

@ -169,7 +169,7 @@ describe('#getLoadingCount$()', () => {
}); });
const { uiSettingsApi } = setup(); const { uiSettingsApi } = setup();
const done$ = new Rx.Subject(); const done$ = new Rx.Subject<void>();
const promise = uiSettingsApi.getLoadingCount$().pipe(takeUntil(done$), toArray()).toPromise(); const promise = uiSettingsApi.getLoadingCount$().pipe(takeUntil(done$), toArray()).toPromise();
await uiSettingsApi.batchSet('foo', 'bar'); await uiSettingsApi.batchSet('foo', 'bar');
@ -194,7 +194,7 @@ describe('#getLoadingCount$()', () => {
); );
const { uiSettingsApi } = setup(); const { uiSettingsApi } = setup();
const done$ = new Rx.Subject(); const done$ = new Rx.Subject<void>();
const promise = uiSettingsApi.getLoadingCount$().pipe(takeUntil(done$), toArray()).toPromise(); const promise = uiSettingsApi.getLoadingCount$().pipe(takeUntil(done$), toArray()).toPromise();
await uiSettingsApi.batchSet('foo', 'bar'); await uiSettingsApi.batchSet('foo', 'bar');

View file

@ -34,7 +34,10 @@ describe('#stop', () => {
service.stop(); service.stop();
await expect( await expect(
Rx.combineLatest(client.getUpdate$(), client.getUpdateErrors$(), loadingCount$!).toPromise() Rx.lastValueFrom(
Rx.combineLatest([client.getUpdate$(), client.getUpdateErrors$(), loadingCount$!]),
{ defaultValue: undefined }
)
).resolves.toBe(undefined); ).resolves.toBe(undefined);
}); });
}); });

View file

@ -8,9 +8,11 @@
import type { ConfigPath } from '@kbn/config'; import type { ConfigPath } from '@kbn/config';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { HotObservable } from 'rxjs/internal/testing/HotObservable';
import { TestScheduler } from 'rxjs/testing'; import { TestScheduler } from 'rxjs/testing';
// eslint-disable-next-line @kbn/imports/no_unresolved_imports
import { HotObservable } from 'rxjs/internal/testing/HotObservable';
import { configServiceMock } from '../config/mocks'; import { configServiceMock } from '../config/mocks';
import { mockCoreContext } from '../core_context.mock'; import { mockCoreContext } from '../core_context.mock';

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Subject, Observable } from 'rxjs'; import { Subject, Observable, firstValueFrom } from 'rxjs';
import { takeUntil, first } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { get } from 'lodash'; import { get } from 'lodash';
import { hasConfigPathIntersection, ChangedDeprecatedPaths } from '@kbn/config'; import { hasConfigPathIntersection, ChangedDeprecatedPaths } from '@kbn/config';
@ -100,7 +100,7 @@ export class CoreUsageDataService
constructor(core: CoreContext) { constructor(core: CoreContext) {
this.logger = core.logger.get('core-usage-stats-service'); this.logger = core.logger.get('core-usage-stats-service');
this.configService = core.configService; this.configService = core.configService;
this.stop$ = new Subject(); this.stop$ = new Subject<void>();
} }
private async getSavedObjectUsageData( private async getSavedObjectUsageData(
@ -383,7 +383,7 @@ export class CoreUsageDataService
private async getNonDefaultKibanaConfigs( private async getNonDefaultKibanaConfigs(
exposedConfigsToUsage: ExposedConfigsToUsage exposedConfigsToUsage: ExposedConfigsToUsage
): Promise<ConfigUsageData> { ): Promise<ConfigUsageData> {
const config = await this.configService.getConfig$().pipe(first()).toPromise(); const config = await firstValueFrom(this.configService.getConfig$());
const nonDefaultConfigs = config.toRaw(); const nonDefaultConfigs = config.toRaw();
const usedPaths = await this.configService.getUsedPaths(); const usedPaths = await this.configService.getUsedPaths();
const exposedConfigsKeys = [...exposedConfigsToUsage.keys()]; const exposedConfigsKeys = [...exposedConfigsToUsage.keys()];

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { take } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { DeprecationsFactory } from './deprecations_factory'; import { DeprecationsFactory } from './deprecations_factory';
import { DomainDeprecationDetails, RegisterDeprecationsConfig } from './types'; import { DomainDeprecationDetails, RegisterDeprecationsConfig } from './types';
@ -144,10 +144,9 @@ export class DeprecationsService
public async setup({ http }: DeprecationsSetupDeps): Promise<InternalDeprecationsServiceSetup> { public async setup({ http }: DeprecationsSetupDeps): Promise<InternalDeprecationsServiceSetup> {
this.logger.debug('Setting up Deprecations service'); this.logger.debug('Setting up Deprecations service');
const config = await this.configService const config = await firstValueFrom(
.atPath<DeprecationConfigType>(deprecationConfig.path) this.configService.atPath<DeprecationConfigType>(deprecationConfig.path)
.pipe(take(1)) );
.toPromise();
this.deprecationsFactory = new DeprecationsFactory({ this.deprecationsFactory = new DeprecationsFactory({
logger: this.logger, logger: this.logger,

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable, Subject } from 'rxjs'; import { firstValueFrom, Observable, Subject } from 'rxjs';
import { first, map, shareReplay, takeUntil } from 'rxjs/operators'; import { map, shareReplay, takeUntil } from 'rxjs/operators';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
import { CoreContext } from '../core_context'; import { CoreContext } from '../core_context';
@ -41,7 +41,7 @@ export class ElasticsearchService
{ {
private readonly log: Logger; private readonly log: Logger;
private readonly config$: Observable<ElasticsearchConfig>; private readonly config$: Observable<ElasticsearchConfig>;
private stop$ = new Subject(); private stop$ = new Subject<void>();
private kibanaVersion: string; private kibanaVersion: string;
private authHeaders?: IAuthHeadersStorage; private authHeaders?: IAuthHeadersStorage;
private executionContextClient?: IExecutionContext; private executionContextClient?: IExecutionContext;
@ -60,7 +60,7 @@ export class ElasticsearchService
public async preboot(): Promise<InternalElasticsearchServicePreboot> { public async preboot(): Promise<InternalElasticsearchServicePreboot> {
this.log.debug('Prebooting elasticsearch service'); this.log.debug('Prebooting elasticsearch service');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
return { return {
config: { config: {
hosts: config.hosts, hosts: config.hosts,
@ -76,7 +76,7 @@ export class ElasticsearchService
public async setup(deps: SetupDeps): Promise<InternalElasticsearchServiceSetup> { public async setup(deps: SetupDeps): Promise<InternalElasticsearchServiceSetup> {
this.log.debug('Setting up elasticsearch service'); this.log.debug('Setting up elasticsearch service');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
this.authHeaders = deps.http.authRequestHeaders; this.authHeaders = deps.http.authRequestHeaders;
this.executionContextClient = deps.executionContext; this.executionContextClient = deps.executionContext;
@ -112,7 +112,7 @@ export class ElasticsearchService
throw new Error('ElasticsearchService needs to be setup before calling start'); throw new Error('ElasticsearchService needs to be setup before calling start');
} }
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
// Log every error we may encounter in the connection to Elasticsearch // Log every error we may encounter in the connection to Elasticsearch
this.esNodesCompatibility$.subscribe(({ isCompatible, message }) => { this.esNodesCompatibility$.subscribe(({ isCompatible, message }) => {

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { take } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { PathConfigType, config as pathConfigDef } from '@kbn/utils'; import { PathConfigType, config as pathConfigDef } from '@kbn/utils';
import { CoreContext } from '../core_context'; import { CoreContext } from '../core_context';
import { Logger } from '../logging'; import { Logger } from '../logging';
@ -49,9 +49,9 @@ export class EnvironmentService {
// IMPORTANT: This code is based on the assumption that none of the configuration values used // IMPORTANT: This code is based on the assumption that none of the configuration values used
// here is supposed to change during preboot phase and it's safe to read them only once. // here is supposed to change during preboot phase and it's safe to read them only once.
const [pathConfig, serverConfig, pidConfig] = await Promise.all([ const [pathConfig, serverConfig, pidConfig] = await Promise.all([
this.configService.atPath<PathConfigType>(pathConfigDef.path).pipe(take(1)).toPromise(), firstValueFrom(this.configService.atPath<PathConfigType>(pathConfigDef.path)),
this.configService.atPath<HttpConfigType>(httpConfigDef.path).pipe(take(1)).toPromise(), firstValueFrom(this.configService.atPath<HttpConfigType>(httpConfigDef.path)),
this.configService.atPath<PidConfigType>(pidConfigDef.path).pipe(take(1)).toPromise(), firstValueFrom(this.configService.atPath<PidConfigType>(pidConfigDef.path)),
]); ]);
// Log unhandled rejections so that we can fix them in preparation for https://github.com/elastic/kibana/issues/77469 // Log unhandled rejections so that we can fix them in preparation for https://github.com/elastic/kibana/issues/77469

View file

@ -19,7 +19,7 @@ import {
import agent from 'elastic-apm-node'; import agent from 'elastic-apm-node';
import type { Duration } from 'moment'; import type { Duration } from 'moment';
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import apm from 'elastic-apm-node'; import apm from 'elastic-apm-node';
import { Logger, LoggerFactory } from '../logging'; import { Logger, LoggerFactory } from '../logging';
@ -223,7 +223,7 @@ export class HttpServer {
if (hasStarted) { if (hasStarted) {
this.log.debug('stopping http server'); this.log.debug('stopping http server');
const shutdownTimeout = await this.shutdownTimeout$.pipe(take(1)).toPromise(); const shutdownTimeout = await firstValueFrom(this.shutdownTimeout$.pipe(take(1)));
await this.server.stop({ timeout: shutdownTimeout.asMilliseconds() }); await this.server.stop({ timeout: shutdownTimeout.asMilliseconds() });
this.log.debug(`http server stopped`); this.log.debug(`http server stopped`);

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable, Subscription, combineLatest } from 'rxjs'; import { Observable, Subscription, combineLatest, firstValueFrom } from 'rxjs';
import { first, map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { pick } from '@kbn/std'; import { pick } from '@kbn/std';
import type { RequestHandlerContext } from 'src/core/server'; import type { RequestHandlerContext } from 'src/core/server';
@ -84,7 +84,7 @@ export class HttpService
public async preboot(deps: PrebootDeps): Promise<InternalHttpServicePreboot> { public async preboot(deps: PrebootDeps): Promise<InternalHttpServicePreboot> {
this.log.debug('setting up preboot server'); this.log.debug('setting up preboot server');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
const prebootSetup = await this.prebootServer.setup(config); const prebootSetup = await this.prebootServer.setup(config);
prebootSetup.server.route({ prebootSetup.server.route({
@ -147,7 +147,7 @@ export class HttpService
} }
}); });
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
const { registerRouter, ...serverContract } = await this.httpServer.setup( const { registerRouter, ...serverContract } = await this.httpServer.setup(
config, config,
@ -196,7 +196,7 @@ export class HttpService
} }
public async start() { public async start() {
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
if (this.shouldListen(config)) { if (this.shouldListen(config)) {
this.log.debug('stopping preboot server'); this.log.debug('stopping preboot server');
await this.prebootServer.stop(); await this.prebootServer.stop();

View file

@ -9,7 +9,7 @@
import { URL } from 'url'; import { URL } from 'url';
import uuid from 'uuid'; import uuid from 'uuid';
import { Request, RouteOptionsApp, RequestApplicationState, RouteOptions } from '@hapi/hapi'; import { Request, RouteOptionsApp, RequestApplicationState, RouteOptions } from '@hapi/hapi';
import { Observable, fromEvent } from 'rxjs'; import { Observable, fromEvent, NEVER } from 'rxjs';
import { shareReplay, first, filter } from 'rxjs/operators'; import { shareReplay, first, filter } from 'rxjs/operators';
import { RecursiveReadonly } from '@kbn/utility-types'; import { RecursiveReadonly } from '@kbn/utility-types';
import { deepFreeze } from '@kbn/std'; import { deepFreeze } from '@kbn/std';
@ -216,6 +216,13 @@ export class KibanaRequest<
} }
private getEvents(request: Request): KibanaRequestEvents { private getEvents(request: Request): KibanaRequestEvents {
if (!request.raw.res) {
return {
aborted$: NEVER,
completed$: NEVER,
};
}
const completed$ = fromEvent<void>(request.raw.res, 'close').pipe(shareReplay(1), first()); const completed$ = fromEvent<void>(request.raw.res, 'close').pipe(shareReplay(1), first());
// the response's underlying connection was terminated prematurely // the response's underlying connection was terminated prematurely
const aborted$ = completed$.pipe(filter(() => !isCompleted(request))); const aborted$ = completed$.pipe(filter(() => !isCompleted(request)));

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { take } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { Logger } from '../logging'; import { Logger } from '../logging';
import { IConfigService } from '../config'; import { IConfigService } from '../config';
import { CoreContext } from '../core_context'; import { CoreContext } from '../core_context';
@ -68,10 +68,9 @@ export class I18nService {
} }
private async initTranslations(pluginPaths: string[]) { private async initTranslations(pluginPaths: string[]) {
const i18nConfig = await this.configService const i18nConfig = await firstValueFrom(
.atPath<I18nConfigType>(i18nConfigDef.path) this.configService.atPath<I18nConfigType>(i18nConfigDef.path)
.pipe(take(1)) );
.toPromise();
const locale = i18nConfig.locale; const locale = i18nConfig.locale;
this.log.debug(`Using locale: ${locale}`); this.log.debug(`Using locale: ${locale}`);

View file

@ -76,8 +76,8 @@ describe('ServerMetricsCollector', () => {
it('collect disconnects requests infos', async () => { it('collect disconnects requests infos', async () => {
const never = new Promise((resolve) => undefined); const never = new Promise((resolve) => undefined);
const disconnectRequested$ = new Subject(); // Controls the number of requests in the /disconnect endpoint const disconnectRequested$ = new Subject<void>(); // Controls the number of requests in the /disconnect endpoint
const disconnectAborted$ = new Subject(); // Controls the abort event in the /disconnect endpoint const disconnectAborted$ = new Subject<void>(); // Controls the abort event in the /disconnect endpoint
router.get({ path: '/', validate: false }, async (ctx, req, res) => { router.get({ path: '/', validate: false }, async (ctx, req, res) => {
return res.ok({ body: '' }); return res.ok({ body: '' });

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { ReplaySubject } from 'rxjs'; import { firstValueFrom, ReplaySubject } from 'rxjs';
import { first } from 'rxjs/operators';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
import { CoreContext } from '../core_context'; import { CoreContext } from '../core_context';
import { Logger } from '../logging'; import { Logger } from '../logging';
@ -38,10 +37,9 @@ export class MetricsService
} }
public async setup({ http }: MetricsServiceSetupDeps): Promise<InternalMetricsServiceSetup> { public async setup({ http }: MetricsServiceSetupDeps): Promise<InternalMetricsServiceSetup> {
const config = await this.coreContext.configService const config = await firstValueFrom(
.atPath<OpsConfigType>(opsConfig.path) this.coreContext.configService.atPath<OpsConfigType>(opsConfig.path)
.pipe(first()) );
.toPromise();
this.metricsCollector = new OpsMetricsCollector(http.server, { this.metricsCollector = new OpsMetricsCollector(http.server, {
logger: this.logger, logger: this.logger,

View file

@ -13,8 +13,8 @@ import mockFs from 'mock-fs';
import { loggingSystemMock } from '../../logging/logging_system.mock'; import { loggingSystemMock } from '../../logging/logging_system.mock';
import { getEnvOptions, rawConfigServiceMock } from '../../config/mocks'; import { getEnvOptions, rawConfigServiceMock } from '../../config/mocks';
import { from } from 'rxjs'; import { firstValueFrom, from } from 'rxjs';
import { first, map, toArray } from 'rxjs/operators'; import { map, toArray } from 'rxjs/operators';
import { resolve } from 'path'; import { resolve } from 'path';
import { ConfigService, Env } from '../../config'; import { ConfigService, Env } from '../../config';
import { PluginsConfig, PluginsConfigType, config } from '../plugins_config'; import { PluginsConfig, PluginsConfigType, config } from '../plugins_config';
@ -163,10 +163,7 @@ describe('plugins discovery system', () => {
logger, logger,
}; };
pluginConfig = await configService pluginConfig = await firstValueFrom(configService.atPath<PluginsConfigType>('plugins'));
.atPath<PluginsConfigType>('plugins')
.pipe(first())
.toPromise();
// jest relies on the filesystem to get sourcemaps when using console.log // jest relies on the filesystem to get sourcemaps when using console.log
// which breaks with the mocked FS, see https://github.com/tschaub/mock-fs/issues/234 // which breaks with the mocked FS, see https://github.com/tschaub/mock-fs/issues/234
@ -195,7 +192,7 @@ describe('plugins discovery system', () => {
{ createCwd: false } { createCwd: false }
); );
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
const pluginNames = plugins.map((plugin) => plugin.name); const pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(4); expect(pluginNames).toHaveLength(4);
@ -362,7 +359,7 @@ describe('plugins discovery system', () => {
{ createCwd: false } { createCwd: false }
); );
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
const pluginNames = plugins.map((plugin) => plugin.name); const pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(4); expect(pluginNames).toHaveLength(4);
@ -401,7 +398,7 @@ describe('plugins discovery system', () => {
{ createCwd: false } { createCwd: false }
); );
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
const pluginNames = plugins.map((plugin) => plugin.name); const pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toEqual(['pluginA']); expect(pluginNames).toEqual(['pluginA']);
@ -423,7 +420,7 @@ describe('plugins discovery system', () => {
{ createCwd: false } { createCwd: false }
); );
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
const pluginNames = plugins.map((plugin) => plugin.name); const pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(5); expect(pluginNames).toHaveLength(5);
@ -451,7 +448,7 @@ describe('plugins discovery system', () => {
{ createCwd: false } { createCwd: false }
); );
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
const pluginNames = plugins.map((plugin) => plugin.name); const pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(3); expect(pluginNames).toHaveLength(3);
@ -536,7 +533,7 @@ describe('plugins discovery system', () => {
let { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo); let { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo);
expect(scanPluginSearchPathsMock).toHaveBeenCalledTimes(1); expect(scanPluginSearchPathsMock).toHaveBeenCalledTimes(1);
let plugins = await plugin$.pipe(toArray()).toPromise(); let plugins = await firstValueFrom(plugin$.pipe(toArray()));
let pluginNames = plugins.map((plugin) => plugin.name); let pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(3); expect(pluginNames).toHaveLength(3);
@ -555,7 +552,7 @@ describe('plugins discovery system', () => {
plugin$ = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo).plugin$; plugin$ = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo).plugin$;
expect(scanPluginSearchPathsMock).toHaveBeenCalledTimes(2); expect(scanPluginSearchPathsMock).toHaveBeenCalledTimes(2);
plugins = await plugin$.pipe(toArray()).toPromise(); plugins = await firstValueFrom(plugin$.pipe(toArray()));
pluginNames = plugins.map((plugin) => plugin.name); pluginNames = plugins.map((plugin) => plugin.name);
expect(pluginNames).toHaveLength(3); expect(pluginNames).toHaveLength(3);

View file

@ -12,6 +12,7 @@ import { toArray } from 'rxjs/operators';
import { resolve } from 'path'; import { resolve } from 'path';
import { scanPluginSearchPaths } from './scan_plugin_search_paths'; import { scanPluginSearchPaths } from './scan_plugin_search_paths';
import { PluginDiscoveryError } from './plugin_discovery_error'; import { PluginDiscoveryError } from './plugin_discovery_error';
import { firstValueFrom } from 'rxjs';
const KIBANA_ROOT = process.cwd(); const KIBANA_ROOT = process.cwd();
@ -82,7 +83,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths(scanPaths, logger); const pluginOrErrors$ = scanPluginSearchPaths(scanPaths, logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(paths).toHaveLength(3); expect(paths).toHaveLength(3);
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
@ -106,7 +107,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(paths).toHaveLength(1); expect(paths).toHaveLength(1);
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
@ -128,7 +129,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(paths).toHaveLength(0); expect(paths).toHaveLength(0);
expect(errors).toHaveLength(1); expect(errors).toHaveLength(1);
@ -153,7 +154,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
expect(paths).toHaveLength(4); expect(paths).toHaveLength(4);
@ -180,7 +181,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
expect(paths).toHaveLength(1); expect(paths).toHaveLength(1);
@ -203,7 +204,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/src/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
expect(paths).toHaveLength(5); expect(paths).toHaveLength(5);
@ -236,7 +237,7 @@ describe('scanPluginSearchPaths', () => {
); );
const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/plugins`], logger); const pluginOrErrors$ = scanPluginSearchPaths([`${KIBANA_ROOT}/plugins`], logger);
const { paths, errors } = extract(await pluginOrErrors$.pipe(toArray()).toPromise()); const { paths, errors } = extract(await firstValueFrom(pluginOrErrors$.pipe(toArray())));
expect(errors).toHaveLength(0); expect(errors).toHaveLength(0);
expect(paths).toHaveLength(2); expect(paths).toHaveLength(2);

View file

@ -13,8 +13,8 @@ import { catchError, mergeMap } from 'rxjs/operators';
import { Logger } from '../../logging'; import { Logger } from '../../logging';
import { PluginDiscoveryError } from './plugin_discovery_error'; import { PluginDiscoveryError } from './plugin_discovery_error';
const fsReadDir$ = bindNodeCallback<string, string[]>(readdir); const fsReadDir$ = bindNodeCallback<[string], [string[]]>(readdir);
const fsStat$ = bindNodeCallback<PathLike, Stats>(stat); const fsStat$ = bindNodeCallback<[PathLike], [Stats]>(stat);
const maxScanDepth = 5; const maxScanDepth = 5;

View file

@ -8,8 +8,7 @@
import { join } from 'path'; import { join } from 'path';
import typeDetect from 'type-detect'; import typeDetect from 'type-detect';
import { Subject } from 'rxjs'; import { firstValueFrom, Subject } from 'rxjs';
import { first } from 'rxjs/operators';
import { isPromise } from '@kbn/std'; import { isPromise } from '@kbn/std';
import { isConfigSchema } from '@kbn/config-schema'; import { isConfigSchema } from '@kbn/config-schema';
@ -63,7 +62,7 @@ export class PluginWrapper<
| AsyncPlugin<TSetup, TStart, TPluginsSetup, TPluginsStart>; | AsyncPlugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>(); private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>();
public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); public readonly startDependencies = firstValueFrom(this.startDependencies$);
constructor( constructor(
public readonly params: { public readonly params: {

View file

@ -7,8 +7,8 @@
*/ */
import Path from 'path'; import Path from 'path';
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { filter, first, map, tap, toArray } from 'rxjs/operators'; import { filter, map, tap, toArray } from 'rxjs/operators';
import { getFlattenedObject } from '@kbn/std'; import { getFlattenedObject } from '@kbn/std';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
@ -111,7 +111,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
} }
public async discover({ environment }: PluginsServiceDiscoverDeps): Promise<DiscoveredPlugins> { public async discover({ environment }: PluginsServiceDiscoverDeps): Promise<DiscoveredPlugins> {
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
const { error$, plugin$ } = discover(config, this.coreContext, { const { error$, plugin$ } = discover(config, this.coreContext, {
uuid: environment.instanceUuid, uuid: environment.instanceUuid,
@ -151,7 +151,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
public async preboot(deps: PluginsServicePrebootSetupDeps) { public async preboot(deps: PluginsServicePrebootSetupDeps) {
this.log.debug('Prebooting plugins service'); this.log.debug('Prebooting plugins service');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
if (config.initialize) { if (config.initialize) {
await this.prebootPluginsSystem.setupPlugins(deps); await this.prebootPluginsSystem.setupPlugins(deps);
this.registerPluginStaticDirs(deps, this.prebootUiPluginInternalInfo); this.registerPluginStaticDirs(deps, this.prebootUiPluginInternalInfo);
@ -165,7 +165,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
public async setup(deps: PluginsServiceSetupDeps) { public async setup(deps: PluginsServiceSetupDeps) {
this.log.debug('Setting up plugins service'); this.log.debug('Setting up plugins service');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
let contracts = new Map<PluginName, unknown>(); let contracts = new Map<PluginName, unknown>();
if (config.initialize) { if (config.initialize) {
@ -186,7 +186,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
public async start(deps: PluginsServiceStartDeps) { public async start(deps: PluginsServiceStartDeps) {
this.log.debug('Plugins service starts plugins'); this.log.debug('Plugins service starts plugins');
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
if (!config.initialize) { if (!config.initialize) {
this.log.info( this.log.info(
'Skipping `start` for `standard` plugins since plugin initialization is disabled.' 'Skipping `start` for `standard` plugins since plugin initialization is disabled.'
@ -246,13 +246,13 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
PluginDiscoveryErrorType.InvalidManifest, PluginDiscoveryErrorType.InvalidManifest,
]; ];
const errors = await error$ const errors = await firstValueFrom(
.pipe( error$.pipe(
filter((error) => errorTypesToReport.includes(error.type)), filter((error) => errorTypesToReport.includes(error.type)),
tap((pluginError) => this.log.error(pluginError)), tap((pluginError) => this.log.error(pluginError)),
toArray() toArray()
) )
.toPromise(); );
if (errors.length > 0) { if (errors.length > 0) {
throw new Error( throw new Error(
`Failed to initialize plugins:${errors.map((err) => `\n\t${err.message}`).join('')}` `Failed to initialize plugins:${errors.map((err) => `\n\t${err.message}`).join('')}`
@ -265,7 +265,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
PluginName, PluginName,
{ plugin: PluginWrapper; isEnabled: boolean } { plugin: PluginWrapper; isEnabled: boolean }
>(); >();
const plugins = await plugin$.pipe(toArray()).toPromise(); const plugins = await firstValueFrom(plugin$.pipe(toArray()));
// Register config descriptors and deprecations // Register config descriptors and deprecations
for (const plugin of plugins) { for (const plugin of plugins) {

View file

@ -16,6 +16,7 @@ import { SavedObjectTypeRegistry } from '../saved_objects_type_registry';
import { SavedObjectsType } from '../types'; import { SavedObjectsType } from '../types';
import { DocumentMigrator } from './core/document_migrator'; import { DocumentMigrator } from './core/document_migrator';
import { ByteSizeValue } from '@kbn/config-schema'; import { ByteSizeValue } from '@kbn/config-schema';
import { lastValueFrom } from 'rxjs';
jest.mock('./core/document_migrator', () => { jest.mock('./core/document_migrator', () => {
return { return {
@ -134,7 +135,7 @@ describe('KibanaMigrator', () => {
it('emits results on getMigratorResult$()', async () => { it('emits results on getMigratorResult$()', async () => {
const options = mockV2MigrationOptions(); const options = mockV2MigrationOptions();
const migrator = new KibanaMigrator(options); const migrator = new KibanaMigrator(options);
const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise(); const migratorStatus = lastValueFrom(migrator.getStatus$().pipe(take(3)));
migrator.prepareMigrations(); migrator.prepareMigrations();
await migrator.runMigrations(); await migrator.runMigrations();

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Subject, Observable } from 'rxjs'; import { Subject, Observable, firstValueFrom } from 'rxjs';
import { first, filter, take, switchMap } from 'rxjs/operators'; import { filter, take, switchMap } from 'rxjs/operators';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
import { import {
SavedObjectsClient, SavedObjectsClient,
@ -314,14 +314,12 @@ export class SavedObjectsService
this.setupDeps = setupDeps; this.setupDeps = setupDeps;
const { http, elasticsearch, coreUsageData, deprecations } = setupDeps; const { http, elasticsearch, coreUsageData, deprecations } = setupDeps;
const savedObjectsConfig = await this.coreContext.configService const savedObjectsConfig = await firstValueFrom(
.atPath<SavedObjectsConfigType>('savedObjects') this.coreContext.configService.atPath<SavedObjectsConfigType>('savedObjects')
.pipe(first()) );
.toPromise(); const savedObjectsMigrationConfig = await firstValueFrom(
const savedObjectsMigrationConfig = await this.coreContext.configService this.coreContext.configService.atPath<SavedObjectsMigrationConfigType>('migrations')
.atPath<SavedObjectsMigrationConfigType>('migrations') );
.pipe(first())
.toPromise();
this.config = new SavedObjectConfig(savedObjectsConfig, savedObjectsMigrationConfig); this.config = new SavedObjectConfig(savedObjectsConfig, savedObjectsMigrationConfig);
deprecations.getRegistry('savedObjects').registerDeprecations( deprecations.getRegistry('savedObjects').registerDeprecations(
@ -340,7 +338,7 @@ export class SavedObjectsService
coreUsageData, coreUsageData,
logger: this.logger, logger: this.logger,
config: this.config, config: this.config,
migratorPromise: this.migrator$.pipe(first()).toPromise(), migratorPromise: firstValueFrom(this.migrator$),
kibanaIndex, kibanaIndex,
kibanaVersion: this.kibanaVersion, kibanaVersion: this.kibanaVersion,
}); });

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { first } from 'rxjs/operators';
import supertest from 'supertest'; import supertest from 'supertest';
import { omit } from 'lodash'; import { omit } from 'lodash';
@ -144,7 +143,7 @@ describe('GET /api/status', () => {
build_number: 1234, build_number: 1234,
build_snapshot: true, build_snapshot: true,
}); });
const metricsMockValue = await metrics.getOpsMetrics$().pipe(first()).toPromise(); const metricsMockValue = await firstValueFrom(metrics.getOpsMetrics$());
expect(result.body.metrics).toEqual({ expect(result.body.metrics).toEqual({
last_updated: expect.any(String), last_updated: expect.any(String),
collection_interval_in_millis: metrics.collectionInterval, collection_interval_in_millis: metrics.collectionInterval,

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable, combineLatest, ReplaySubject } from 'rxjs'; import { Observable, combineLatest, ReplaySubject, firstValueFrom } from 'rxjs';
import { first } from 'rxjs/operators';
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { IRouter } from '../../http'; import { IRouter } from '../../http';
@ -92,7 +91,7 @@ export const registerStatusRoute = ({
async (context, req, res) => { async (context, req, res) => {
const { version, buildSha, buildNum } = config.packageInfo; const { version, buildSha, buildNum } = config.packageInfo;
const versionWithoutSnapshot = version.replace(SNAPSHOT_POSTFIX, ''); const versionWithoutSnapshot = version.replace(SNAPSHOT_POSTFIX, '');
const [overall, coreOverall, core, plugins] = await combinedStatus$.pipe(first()).toPromise(); const [overall, coreOverall, core, plugins] = await firstValueFrom(combinedStatus$);
const { v8format = true, v7format = false } = req.query ?? {}; const { v8format = true, v7format = false } = req.query ?? {};
@ -113,7 +112,7 @@ export const registerStatusRoute = ({
}); });
} }
const lastMetrics = await metrics.getOpsMetrics$().pipe(first()).toPromise(); const lastMetrics = await firstValueFrom(metrics.getOpsMetrics$());
const body: StatusHttpBody = { const body: StatusHttpBody = {
name: config.serverName, name: config.serverName,

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable, combineLatest, Subscription, Subject } from 'rxjs'; import { Observable, combineLatest, Subscription, Subject, firstValueFrom } from 'rxjs';
import { map, distinctUntilChanged, shareReplay, take, debounceTime } from 'rxjs/operators'; import { map, distinctUntilChanged, shareReplay, debounceTime } from 'rxjs/operators';
import { isDeepStrictEqual } from 'util'; import { isDeepStrictEqual } from 'util';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
@ -65,7 +65,7 @@ export class StatusService implements CoreService<InternalStatusServiceSetup> {
environment, environment,
coreUsageData, coreUsageData,
}: SetupDeps) { }: SetupDeps) {
const statusConfig = await this.config$.pipe(take(1)).toPromise(); const statusConfig = await firstValueFrom(this.config$);
const core$ = this.setupCoreStatus({ elasticsearch, savedObjects }); const core$ = this.setupCoreStatus({ elasticsearch, savedObjects });
this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies }); this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies });

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { first } from 'rxjs/operators';
import { mapToObject } from '@kbn/std'; import { mapToObject } from '@kbn/std';
import { CoreService } from '../../types'; import { CoreService } from '../../types';
@ -53,7 +52,7 @@ export class UiSettingsService
public async preboot(): Promise<InternalUiSettingsServicePreboot> { public async preboot(): Promise<InternalUiSettingsServicePreboot> {
this.log.debug('Prebooting ui settings service'); this.log.debug('Prebooting ui settings service');
const { overrides } = await this.config$.pipe(first()).toPromise(); const { overrides } = await firstValueFrom(this.config$);
this.overrides = overrides; this.overrides = overrides;
this.register(getCoreSettings({ isDist: this.isDist })); this.register(getCoreSettings({ isDist: this.isDist }));
@ -74,7 +73,7 @@ export class UiSettingsService
savedObjects.registerType(uiSettingsType); savedObjects.registerType(uiSettingsType);
registerRoutes(http.createRouter('')); registerRoutes(http.createRouter(''));
const config = await this.config$.pipe(first()).toPromise(); const config = await firstValueFrom(this.config$);
this.overrides = config.overrides; this.overrides = config.overrides;
return { return {

View file

@ -15,8 +15,8 @@ import { map, mergeAll, mergeMap } from 'rxjs/operators';
// @ts-ignore // @ts-ignore
import { assertAbsolute } from './fs'; import { assertAbsolute } from './fs';
const getStat$ = Rx.bindNodeCallback(Fs.stat) as (path: string) => Rx.Observable<Fs.Stats>; const getStat$ = Rx.bindNodeCallback<[string], [Fs.Stats]>(Fs.stat);
const getReadDir$ = Rx.bindNodeCallback(Fs.readdir) as (path: string) => Rx.Observable<string[]>; const getReadDir$ = Rx.bindNodeCallback<[string], [string[]]>(Fs.readdir);
/** /**
* Return an observable of all files in a directory, starting with the * Return an observable of all files in a directory, starting with the

View file

@ -16,8 +16,8 @@ import { count, map, mergeAll, mergeMap } from 'rxjs/operators';
// @ts-ignore // @ts-ignore
import { assertAbsolute } from './fs'; import { assertAbsolute } from './fs';
const getStat$ = Rx.bindNodeCallback<Fs.PathLike, Fs.Stats>(Fs.stat); const getStat$ = Rx.bindNodeCallback<[Fs.PathLike], [Fs.Stats]>(Fs.stat);
const getReadDir$ = Rx.bindNodeCallback<string, string[]>(Fs.readdir); const getReadDir$ = Rx.bindNodeCallback<[string], [string[]]>(Fs.readdir);
interface Options { interface Options {
directory: string; directory: string;

View file

@ -9,7 +9,7 @@
import Path from 'path'; import Path from 'path';
import { REPO_ROOT } from '@kbn/utils'; import { REPO_ROOT } from '@kbn/utils';
import { lastValueFrom } from '@kbn/std'; import { lastValueFrom } from 'rxjs';
import { CiStatsMetric } from '@kbn/dev-utils'; import { CiStatsMetric } from '@kbn/dev-utils';
import { import {
runOptimizer, runOptimizer,

View file

@ -16,7 +16,6 @@ import { mergeMap, reduce } from 'rxjs/operators';
import { supportsColor } from 'chalk'; import { supportsColor } from 'chalk';
import { run, createFailError } from '@kbn/dev-utils'; import { run, createFailError } from '@kbn/dev-utils';
import { REPO_ROOT } from '@kbn/utils'; import { REPO_ROOT } from '@kbn/utils';
import { lastValueFrom } from '@kbn/std';
import { PROJECTS } from '../typescript/projects'; import { PROJECTS } from '../typescript/projects';
import { Project } from '../typescript/project'; import { Project } from '../typescript/project';
@ -61,7 +60,7 @@ export function runEslintWithTypes() {
const concurrency = Math.max(1, Math.round((Os.cpus() || []).length / 2) || 1) || 1; const concurrency = Math.max(1, Math.round((Os.cpus() || []).length / 2) || 1) || 1;
log.info(`Linting ${projects.length} projects, ${concurrency} at a time`); log.info(`Linting ${projects.length} projects, ${concurrency} at a time`);
const failures = await lastValueFrom( const failures = await Rx.lastValueFrom(
Rx.from(projects).pipe( Rx.from(projects).pipe(
mergeMap(async (project) => { mergeMap(async (project) => {
const configFilePath = Path.resolve(project.directory, 'types.eslint.config.js'); const configFilePath = Path.resolve(project.directory, 'types.eslint.config.js');

View file

@ -8,7 +8,6 @@
import * as Rx from 'rxjs'; import * as Rx from 'rxjs';
import { mergeMap, toArray, map } from 'rxjs/operators'; import { mergeMap, toArray, map } from 'rxjs/operators';
import { lastValueFrom } from '@kbn/std';
export async function concurrentMap<T, T2>( export async function concurrentMap<T, T2>(
concurrency: number, concurrency: number,
@ -19,7 +18,7 @@ export async function concurrentMap<T, T2>(
return []; return [];
} }
return await lastValueFrom( return await Rx.lastValueFrom(
Rx.from(arr).pipe( Rx.from(arr).pipe(
// execute items in parallel based on concurrency // execute items in parallel based on concurrency
mergeMap(async (item, index) => ({ index, result: await fn(item, index) }), concurrency), mergeMap(async (item, index) => ({ index, result: await fn(item, index) }), concurrency),

View file

@ -13,7 +13,6 @@ import * as Rx from 'rxjs';
import { mergeMap, reduce } from 'rxjs/operators'; import { mergeMap, reduce } from 'rxjs/operators';
import execa from 'execa'; import execa from 'execa';
import { run, createFailError } from '@kbn/dev-utils'; import { run, createFailError } from '@kbn/dev-utils';
import { lastValueFrom } from '@kbn/std';
import { PROJECTS } from './projects'; import { PROJECTS } from './projects';
import { buildTsRefs } from './build_ts_refs'; import { buildTsRefs } from './build_ts_refs';
@ -65,7 +64,7 @@ export async function runTypeCheckCli() {
: ['--skipLibCheck', 'false']), : ['--skipLibCheck', 'false']),
]; ];
const failureCount = await lastValueFrom( const failureCount = await Rx.lastValueFrom(
Rx.from(projects).pipe( Rx.from(projects).pipe(
mergeMap(async (p) => { mergeMap(async (p) => {
const relativePath = Path.relative(process.cwd(), p.tsConfigPath); const relativePath = Path.relative(process.cwd(), p.tsConfigPath);

View file

@ -22,8 +22,8 @@ describe('ActiveCursor', () => {
expect(activeCursor.activeCursor$).toMatchInlineSnapshot(` expect(activeCursor.activeCursor$).toMatchInlineSnapshot(`
Subject { Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],

View file

@ -6,8 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable, Subscription } from 'rxjs'; import { firstValueFrom, Observable, Subscription } from 'rxjs';
import { first } from 'rxjs/operators';
import { ElasticsearchConfig } from 'kibana/server'; import { ElasticsearchConfig } from 'kibana/server';
export class EsLegacyConfigService { export class EsLegacyConfigService {
@ -45,7 +44,7 @@ export class EsLegacyConfigService {
} }
if (!this.config) { if (!this.config) {
return this.config$.pipe(first()).toPromise(); return firstValueFrom(this.config$);
} }
return this.config; return this.config;

View file

@ -59,7 +59,7 @@ export const ControlGroupChainingSystems: {
onChildChange: ({ childOutputChangedId, childOrder, recalculateFilters$, getChild }) => { onChildChange: ({ childOutputChangedId, childOrder, recalculateFilters$, getChild }) => {
if (childOutputChangedId === childOrder.lastChildId) { if (childOutputChangedId === childOrder.lastChildId) {
// the last control's output has updated, recalculate filters // the last control's output has updated, recalculate filters
recalculateFilters$.next(); recalculateFilters$.next(null);
return; return;
} }
@ -75,6 +75,6 @@ export const ControlGroupChainingSystems: {
NONE: { NONE: {
getContainerSettings: () => undefined, getContainerSettings: () => undefined,
getPrecedingFilters: () => undefined, getPrecedingFilters: () => undefined,
onChildChange: ({ recalculateFilters$ }) => recalculateFilters$.next(), onChildChange: ({ recalculateFilters$ }) => recalculateFilters$.next(null),
}, },
}; };

View file

@ -151,7 +151,7 @@ export class TimeSliderControlEmbeddable extends Embeddable<
const min = value ? value[0] : null; const min = value ? value[0] : null;
const max = value ? value[1] : null; const max = value ? value[1] : null;
const hasRange = const hasRange =
this.componentState.range!.max !== undefined && this.componentState.range!.min !== undefined; this.componentState.range?.max !== undefined && this.componentState.range?.min !== undefined;
this.getCurrentDataView$().subscribe((dataView) => { this.getCurrentDataView$().subscribe((dataView) => {
const range: RangeFilterParams = {}; const range: RangeFilterParams = {};

View file

@ -310,7 +310,7 @@ export const useDashboardAppState = ({
* the last saved state on save. * the last saved state on save.
*/ */
setLastSavedState(savedDashboardState); setLastSavedState(savedDashboardState);
dashboardBuildContext.$checkForUnsavedChanges.next(); dashboardBuildContext.$checkForUnsavedChanges.next(undefined);
const updateLastSavedState = () => { const updateLastSavedState = () => {
setLastSavedState( setLastSavedState(
savedObjectToDashboardState({ savedObjectToDashboardState({

View file

@ -60,7 +60,7 @@ export const syncDashboardContainerInput = (
.getInput$() .getInput$()
.subscribe(() => applyContainerChangesToState(syncDashboardContainerProps)) .subscribe(() => applyContainerChangesToState(syncDashboardContainerProps))
); );
subscriptions.add($onDashboardStateChange.subscribe(() => $triggerDashboardRefresh.next())); subscriptions.add($onDashboardStateChange.subscribe(() => $triggerDashboardRefresh.next({})));
subscriptions.add( subscriptions.add(
getSessionURLObservable(history).subscribe(() => { getSessionURLObservable(history).subscribe(() => {
$triggerDashboardRefresh.next({ force: true }); $triggerDashboardRefresh.next({ force: true });

View file

@ -103,13 +103,14 @@ export const syncDashboardFilterState = ({
.subscribe(() => applyFilters(queryString.getQuery(), filterManager.getFilters())); .subscribe(() => applyFilters(queryString.getQuery(), filterManager.getFilters()));
const timeRefreshSubscription = merge( const timeRefreshSubscription = merge(
...[timefilterService.getRefreshIntervalUpdate$(), timefilterService.getTimeUpdate$()] timefilterService.getRefreshIntervalUpdate$(),
timefilterService.getTimeUpdate$()
).subscribe(() => { ).subscribe(() => {
$triggerDashboardRefresh.next(); $triggerDashboardRefresh.next({});
// manually check for unsaved changes here because the time range is not stored on the dashboardState, // manually check for unsaved changes here because the time range is not stored on the dashboardState,
// but it could trigger the unsaved changes badge. // but it could trigger the unsaved changes badge.
$checkForUnsavedChanges.next(); $checkForUnsavedChanges.next(undefined);
}); });
const forceRefreshSubscription = timefilterService const forceRefreshSubscription = timefilterService

View file

@ -25,9 +25,9 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -39,10 +39,9 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -129,7 +128,6 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -175,9 +173,9 @@ exports[`after fetch initialFilter 1`] = `
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -189,10 +187,9 @@ exports[`after fetch initialFilter 1`] = `
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -279,7 +276,6 @@ exports[`after fetch initialFilter 1`] = `
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -324,9 +320,9 @@ exports[`after fetch renders all table rows 1`] = `
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -338,10 +334,9 @@ exports[`after fetch renders all table rows 1`] = `
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -428,7 +423,6 @@ exports[`after fetch renders all table rows 1`] = `
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -473,9 +467,9 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -487,10 +481,9 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -577,7 +570,6 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -622,9 +614,9 @@ exports[`after fetch renders call to action with continue when no dashboards exi
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -636,10 +628,9 @@ exports[`after fetch renders call to action with continue when no dashboards exi
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -737,7 +728,6 @@ exports[`after fetch renders call to action with continue when no dashboards exi
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -782,9 +772,9 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -796,10 +786,9 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -886,7 +875,6 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }
@ -931,9 +919,9 @@ exports[`after fetch showWriteControls 1`] = `
application={ application={
Object { Object {
"applications$": BehaviorSubject { "applications$": BehaviorSubject {
"_isScalar": false,
"_value": Map {}, "_value": Map {},
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -945,10 +933,9 @@ exports[`after fetch showWriteControls 1`] = `
"navLinks": Object {}, "navLinks": Object {},
}, },
"currentAppId$": Observable { "currentAppId$": Observable {
"_isScalar": false,
"source": Subject { "source": Subject {
"_isScalar": false,
"closed": false, "closed": false,
"currentObservers": null,
"hasError": false, "hasError": false,
"isStopped": false, "isStopped": false,
"observers": Array [], "observers": Array [],
@ -1005,7 +992,6 @@ exports[`after fetch showWriteControls 1`] = `
theme={ theme={
Object { Object {
"theme$": Observable { "theme$": Observable {
"_isScalar": false,
"_subscribe": [Function], "_subscribe": [Function],
}, },
} }

View file

@ -15,6 +15,7 @@ import {
buildQueryFromFilters, buildQueryFromFilters,
Filter, Filter,
} from '@kbn/es-query'; } from '@kbn/es-query';
import { lastValueFrom } from 'rxjs';
import { AggGroupNames } from '../agg_groups'; import { AggGroupNames } from '../agg_groups';
import { IAggConfigs } from '../agg_configs'; import { IAggConfigs } from '../agg_configs';
import { IAggType } from '../agg_type'; import { IAggType } from '../agg_type';
@ -342,8 +343,8 @@ export const createOtherBucketPostFlightRequest = (
nestedSearchSource.setField('aggs', filterAgg); nestedSearchSource.setField('aggs', filterAgg);
const { rawResponse: response } = await nestedSearchSource const { rawResponse: response } = await lastValueFrom(
.fetch$({ nestedSearchSource.fetch$({
abortSignal, abortSignal,
sessionId: searchSessionId, sessionId: searchSessionId,
inspector: { inspector: {
@ -358,7 +359,7 @@ export const createOtherBucketPostFlightRequest = (
}), }),
}, },
}) })
.toPromise(); );
resp = mergeOtherBucketAggResponse( resp = mergeOtherBucketAggResponse(
aggConfigs, aggConfigs,

View file

@ -11,6 +11,7 @@ import { buildEsQuery } from '@kbn/es-query';
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { EqlSearchRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EqlSearchRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { lastValueFrom } from 'rxjs';
import { RequestStatistics, RequestAdapter } from '../../../../inspector/common'; import { RequestStatistics, RequestAdapter } from '../../../../inspector/common';
import { import {
ISearchGeneric, ISearchGeneric,
@ -143,7 +144,8 @@ export const getEqlFn = ({
}); });
try { try {
const response = await search<EqlSearchStrategyRequest, EqlSearchStrategyResponse>( const response = await lastValueFrom(
search<EqlSearchStrategyRequest, EqlSearchStrategyResponse>(
{ {
params: { params: {
index: args.index, index: args.index,
@ -151,7 +153,8 @@ export const getEqlFn = ({
}, },
}, },
{ abortSignal, strategy: EQL_SEARCH_STRATEGY } { abortSignal, strategy: EQL_SEARCH_STRATEGY }
).toPromise(); )
);
const stats: RequestStatistics = {}; const stats: RequestStatistics = {};

View file

@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
import { buildEsQuery } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query';
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { lastValueFrom } from 'rxjs';
import { EsRawResponse } from './es_raw_response'; import { EsRawResponse } from './es_raw_response';
import { RequestStatistics, RequestAdapter } from '../../../../inspector/common'; import { RequestStatistics, RequestAdapter } from '../../../../inspector/common';
import { ISearchGeneric, KibanaContext } from '..'; import { ISearchGeneric, KibanaContext } from '..';
@ -125,7 +126,8 @@ export const getEsdslFn = ({
}); });
try { try {
const { rawResponse } = await search( const { rawResponse } = await lastValueFrom(
search(
{ {
params: { params: {
index: args.index, index: args.index,
@ -134,7 +136,8 @@ export const getEsdslFn = ({
}, },
}, },
{ abortSignal } { abortSignal }
).toPromise(); )
);
const stats: RequestStatistics = {}; const stats: RequestStatistics = {};

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { IndexPattern } from '../..'; import { IndexPattern } from '../..';
import { SearchSource, SearchSourceDependencies, SortDirection } from './'; import { SearchSource, SearchSourceDependencies, SortDirection } from './';
import { AggConfigs, AggTypesRegistryStart } from '../../'; import { AggConfigs, AggTypesRegistryStart } from '../../';
@ -1240,7 +1240,7 @@ describe('SearchSource', () => {
const fetch$ = searchSource.fetch$({}); const fetch$ = searchSource.fetch$({});
fetch$.subscribe(fetchSub); fetch$.subscribe(fetchSub);
const resp = await fetch$.toPromise(); const resp = await lastValueFrom(fetch$);
expect(fetchSub.next).toHaveBeenCalledTimes(3); expect(fetchSub.next).toHaveBeenCalledTimes(3);
expect(fetchSub.complete).toHaveBeenCalledTimes(1); expect(fetchSub.complete).toHaveBeenCalledTimes(1);

View file

@ -70,7 +70,7 @@ import {
switchMap, switchMap,
tap, tap,
} from 'rxjs/operators'; } from 'rxjs/operators';
import { defer, EMPTY, from, Observable } from 'rxjs'; import { defer, EMPTY, from, lastValueFrom, Observable } from 'rxjs';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { buildEsQuery, Filter } from '@kbn/es-query'; import { buildEsQuery, Filter } from '@kbn/es-query';
import { normalizeSortRequest } from './normalize_sort_request'; import { normalizeSortRequest } from './normalize_sort_request';
@ -325,9 +325,7 @@ export class SearchSource {
* @removeBy 8.1 * @removeBy 8.1
*/ */
fetch(options: ISearchOptions = {}) { fetch(options: ISearchOptions = {}) {
return this.fetch$(options) return lastValueFrom(this.fetch$(options)).then((r) => {
.toPromise()
.then((r) => {
return r.rawResponse as estypes.SearchResponse<any>; return r.rawResponse as estypes.SearchResponse<any>;
}); });
} }

View file

@ -32,10 +32,10 @@ export class Timefilter {
// Fired when isTimeRangeSelectorEnabled \ isAutoRefreshSelectorEnabled are toggled // Fired when isTimeRangeSelectorEnabled \ isAutoRefreshSelectorEnabled are toggled
private enabledUpdated$ = new BehaviorSubject(false); private enabledUpdated$ = new BehaviorSubject(false);
// Fired when a user changes the timerange // Fired when a user changes the timerange
private timeUpdate$ = new Subject(); private timeUpdate$ = new Subject<void>();
// Fired when a user changes the the autorefresh settings // Fired when a user changes the the autorefresh settings
private refreshIntervalUpdate$ = new Subject(); private refreshIntervalUpdate$ = new Subject<void>();
private fetch$ = new Subject(); private fetch$ = new Subject<void>();
private _time: TimeRange; private _time: TimeRange;
// Denotes whether setTime has been called, can be used to determine if the constructor defaults are being used. // Denotes whether setTime has been called, can be used to determine if the constructor defaults are being used.

View file

@ -23,7 +23,7 @@ const createSetupContractMock = () => {
getTimeUpdate$: jest.fn(), getTimeUpdate$: jest.fn(),
getRefreshIntervalUpdate$: jest.fn(), getRefreshIntervalUpdate$: jest.fn(),
getAutoRefreshFetch$: jest.fn(() => new Observable<() => void>()), getAutoRefreshFetch$: jest.fn(() => new Observable<() => void>()),
getFetch$: jest.fn(() => new Observable<() => void>()), getFetch$: jest.fn().mockImplementation(() => new Observable<() => void>()),
getTime: jest.fn(), getTime: jest.fn(),
setTime: jest.fn(), setTime: jest.fn(),
setRefreshInterval: jest.fn(), setRefreshInterval: jest.fn(),

View file

@ -9,6 +9,7 @@
import { waitUntilNextSessionCompletes$ } from './session_helpers'; import { waitUntilNextSessionCompletes$ } from './session_helpers';
import { ISessionService, SessionService } from './session_service'; import { ISessionService, SessionService } from './session_service';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { fakeSchedulers } from 'rxjs-marbles/jest';
import { SearchSessionState } from './search_session_state'; import { SearchSessionState } from './search_session_state';
import { NowProviderInternalContract } from '../../now_provider'; import { NowProviderInternalContract } from '../../now_provider';
import { coreMock } from '../../../../../core/public/mocks'; import { coreMock } from '../../../../../core/public/mocks';
@ -62,7 +63,9 @@ describe('waitUntilNextSessionCompletes$', () => {
afterEach(() => { afterEach(() => {
jest.useRealTimers(); jest.useRealTimers();
}); });
test('emits when next session starts', () => { test(
'emits when next session starts',
fakeSchedulers((advance) => {
sessionService.start(); sessionService.start();
let untrackSearch = sessionService.trackSearch({ abort: () => {} }); let untrackSearch = sessionService.trackSearch({ abort: () => {} });
untrackSearch(); untrackSearch();
@ -79,10 +82,11 @@ describe('waitUntilNextSessionCompletes$', () => {
untrackSearch(); untrackSearch();
expect(next).not.toBeCalled(); expect(next).not.toBeCalled();
jest.advanceTimersByTime(500); advance(500);
expect(next).not.toBeCalled(); expect(next).not.toBeCalled();
jest.advanceTimersByTime(1000); advance(1000);
expect(next).toBeCalledTimes(1); expect(next).toBeCalledTimes(1);
expect(complete).toBeCalled(); expect(complete).toBeCalled();
}); })
);
}); });

View file

@ -8,8 +8,7 @@
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { IRouter } from 'kibana/server'; import { IRouter } from 'kibana/server';
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { first } from 'rxjs/operators';
import { getRequestAbortedSignal } from '../lib'; import { getRequestAbortedSignal } from '../lib';
import { getKbnServerError, reportServerError } from '../../../kibana_utils/server'; import { getKbnServerError, reportServerError } from '../../../kibana_utils/server';
import type { ConfigSchema } from '../../config'; import type { ConfigSchema } from '../../config';
@ -42,7 +41,7 @@ export function registerValueSuggestionsRoute(router: IRouter, config$: Observab
}, },
}, },
async (context, request, response) => { async (context, request, response) => {
const config = await config$.pipe(first()).toPromise(); const config = await firstValueFrom(config$);
const { field: fieldName, query, filters, fieldMeta, method } = request.body; const { field: fieldName, query, filters, fieldMeta, method } = request.body;
const { index } = request.params; const { index } = request.params;
const abortSignal = getRequestAbortedSignal(request.events.aborted$); const abortSignal = getRequestAbortedSignal(request.events.aborted$);

View file

@ -6,7 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { catchError, first } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { BfetchServerSetup } from 'src/plugins/bfetch/server'; import { BfetchServerSetup } from 'src/plugins/bfetch/server';
import type { ExecutionContextSetup } from 'src/core/server'; import type { ExecutionContextSetup } from 'src/core/server';
import apm from 'elastic-apm-node'; import apm from 'elastic-apm-node';
@ -37,10 +38,8 @@ export function registerBsearchRoute(
return executionContextService.withContext(executionContext, () => { return executionContextService.withContext(executionContext, () => {
apm.addLabels(executionContextService.getAsLabels()); apm.addLabels(executionContextService.getAsLabels());
return search return firstValueFrom(
.search(requestData, restOptions) search.search(requestData, restOptions).pipe(
.pipe(
first(),
catchError((err) => { catchError((err) => {
// Re-throw as object, to get attributes passed to the client // Re-throw as object, to get attributes passed to the client
// eslint-disable-next-line no-throw-literal // eslint-disable-next-line no-throw-literal
@ -51,7 +50,7 @@ export function registerBsearchRoute(
}; };
}) })
) )
.toPromise(); );
}); });
}, },
}; };

View file

@ -16,7 +16,7 @@ import { createIndexPatternsStartMock } from '../data_views/mocks';
import { SearchService, SearchServiceSetupDependencies } from './search_service'; import { SearchService, SearchServiceSetupDependencies } from './search_service';
import { bfetchPluginMock } from '../../../bfetch/server/mocks'; import { bfetchPluginMock } from '../../../bfetch/server/mocks';
import { of } from 'rxjs'; import { lastValueFrom, of } from 'rxjs';
import type { import type {
IEsSearchRequest, IEsSearchRequest,
IEsSearchResponse, IEsSearchResponse,
@ -182,7 +182,7 @@ describe('Search service', () => {
throw new NoSearchIdInSessionError(); throw new NoSearchIdInSessionError();
}); });
const res = await mockScopedClient.search(searchRequest, options).toPromise(); const res = await lastValueFrom(mockScopedClient.search(searchRequest, options));
const [request, callOptions] = mockStrategy.search.mock.calls[0]; const [request, callOptions] = mockStrategy.search.mock.calls[0];
expect(callOptions).toBe(options); expect(callOptions).toBe(options);

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { from, Observable, throwError } from 'rxjs'; import { firstValueFrom, from, Observable, throwError } from 'rxjs';
import { pick } from 'lodash'; import { pick } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import { import {
@ -19,7 +19,7 @@ import {
SharedGlobalConfig, SharedGlobalConfig,
StartServicesAccessor, StartServicesAccessor,
} from 'src/core/server'; } from 'src/core/server';
import { first, map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; import { map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { BfetchServerSetup } from 'src/plugins/bfetch/server'; import { BfetchServerSetup } from 'src/plugins/bfetch/server';
import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; import { ExpressionsServerSetup } from 'src/plugins/expressions/server';
import type { import type {
@ -221,11 +221,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
const aggs = this.aggsService.setup({ registerFunction: expressions.registerFunction }); const aggs = this.aggsService.setup({ registerFunction: expressions.registerFunction });
this.initializerContext.config firstValueFrom(this.initializerContext.config.create<ConfigSchema>()).then((value) => {
.create<ConfigSchema>()
.pipe(first())
.toPromise()
.then((value) => {
if (value.search.aggs.shardDelay.enabled) { if (value.search.aggs.shardDelay.enabled) {
aggs.types.registerBucket(SHARD_DELAY_AGG_NAME, getShardDelayBucketAgg); aggs.types.registerBucket(SHARD_DELAY_AGG_NAME, getShardDelayBucketAgg);
expressions.registerFunction(aggShardDelay); expressions.registerFunction(aggShardDelay);

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { from, Observable } from 'rxjs'; import { firstValueFrom, from, Observable } from 'rxjs';
import { first, tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import type { Logger, SharedGlobalConfig } from 'kibana/server'; import type { Logger, SharedGlobalConfig } from 'kibana/server';
import type { ISearchStrategy } from '../../types'; import type { ISearchStrategy } from '../../types';
import type { SearchUsage } from '../../collectors'; import type { SearchUsage } from '../../collectors';
@ -37,7 +37,7 @@ export const esSearchStrategyProvider = (
const search = async () => { const search = async () => {
try { try {
const config = await config$.pipe(first()).toPromise(); const config = await firstValueFrom(config$);
// @ts-expect-error params fall back to any, but should be valid SearchRequest params // @ts-expect-error params fall back to any, but should be valid SearchRequest params
const { terminateAfter, ...requestParams } = request.params ?? {}; const { terminateAfter, ...requestParams } = request.params ?? {};
const params = { const params = {

Some files were not shown because too many files have changed in this diff Show more