From 2a133d18019de33582da9652fe3a4607b51c9cb8 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 30 Jun 2020 08:37:42 +0300 Subject: [PATCH] Use ts-expect-error in platform code (#69883) * ts-ignore --> ts-expect-error * fix error with mutable array * fix errors in consumers code * update SOM * fix FeatureConfig & Feature compatibility * do not re-export from code. it breaks built version * update docs * add eslint rule for platform team code * remove test. this is covered by ts-expect-error in unit tests Co-authored-by: Elastic Machine --- .eslintrc.js | 17 +++++++ .../core/public/kibana-plugin-core-public.md | 1 - ...na-plugin-core-public.recursivereadonly.md | 14 ------ .../core/server/kibana-plugin-core-server.md | 1 - ...na-plugin-core-server.recursivereadonly.md | 14 ------ ...in-plugins-data-public.querystringinput.md | 2 +- packages/kbn-utility-types/index.ts | 3 +- .../capabilities/capabilities_service.test.ts | 4 +- .../capabilities/capabilities_service.tsx | 3 +- src/core/public/application/types.ts | 2 +- .../recently_accessed/persisted_log.test.ts | 2 +- .../recently_accessed_service.test.ts | 4 +- .../chrome/ui/header/header_help_menu.tsx | 1 - .../public/chrome/ui/header/recent_links.tsx | 1 - src/core/public/http/fetch.test.ts | 4 +- src/core/public/http/http_service.test.ts | 2 +- src/core/public/index.ts | 1 - .../injected_metadata_service.test.ts | 7 ++- .../integrations/styles/styles_service.ts | 2 +- src/core/public/kbn_bootstrap.ts | 1 - src/core/public/public.api.md | 8 +-- .../saved_objects_client.test.ts | 2 +- .../ui_settings/ui_settings_api.test.ts | 2 +- .../legacy/retry_call_cluster.ts | 2 +- .../server/http/cookie_session_storage.ts | 2 +- src/core/server/http/router/request.ts | 5 +- src/core/server/index.ts | 1 - .../legacy/config/get_unused_config_keys.ts | 2 +- src/core/server/legacy/legacy_service.test.ts | 1 - .../legacy/logging/legacy_logging_server.ts | 4 +- .../plugins/find_legacy_plugin_specs.ts | 2 +- src/core/server/plugins/types.ts | 2 +- .../service/lib/decorate_es_error.ts | 6 +-- src/core/server/server.api.md | 13 ++--- src/core/utils/deep_freeze.test.ts | 11 ++-- src/core/utils/deep_freeze.ts | 15 +----- .../frozen_object_mutation/index.ts | 44 ---------------- .../frozen_object_mutation/tsconfig.json | 12 ----- .../integration_tests/deep_freeze.test.ts | 40 --------------- src/plugins/data/public/public.api.md | 3 +- src/plugins/data/server/server.api.md | 2 +- .../object_view/components/field.tsx | 9 +--- .../objects_table/components/flyout.tsx | 1 - .../objects_table/components/table.test.tsx | 2 +- .../objects_table/components/table.tsx | 1 - .../objects_table/saved_objects_table.tsx | 2 +- .../vis_type_timelion/server/plugin.ts | 8 ++- .../lib/adapters/framework/adapter_types.ts | 4 +- .../lib/adapters/framework/adapter_types.ts | 2 +- ...dashboard_mode_request_interceptor.test.ts | 4 +- x-pack/plugins/features/common/feature.ts | 14 +++--- .../common/feature_kibana_privileges.ts | 14 +++--- x-pack/plugins/features/common/sub_feature.ts | 4 +- .../plugins/features/server/feature_schema.ts | 6 +-- x-pack/plugins/features/server/plugin.ts | 3 +- .../embeddable/embeddable_factory.ts | 8 +-- x-pack/plugins/security/common/model/user.ts | 2 +- .../role_combo_box/role_combo_box.tsx | 2 +- .../users/edit_user/edit_user_page.tsx | 2 +- .../authorization/app_authorization.test.ts | 9 ++-- .../feature_privilege_iterator.ts | 2 +- x-pack/plugins/security/server/index.ts | 2 +- .../management/lib/feature_utils.test.ts | 4 +- .../on_post_auth_interceptor.test.ts | 50 +++++++++---------- 64 files changed, 134 insertions(+), 286 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md delete mode 100644 src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts delete mode 100644 src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json delete mode 100644 src/core/utils/integration_tests/deep_freeze.test.ts diff --git a/.eslintrc.js b/.eslintrc.js index ffc49a60d5bca..32f59c4d6b3db 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1039,5 +1039,22 @@ module.exports = { ...require('eslint-config-prettier/@typescript-eslint').rules, }, }, + + { + files: [ + // platform-team owned code + 'src/core/**', + 'x-pack/plugins/features/**', + 'x-pack/plugins/licensing/**', + 'x-pack/plugins/global_search/**', + 'x-pack/plugins/cloud/**', + 'packages/kbn-config-schema', + 'src/plugins/status_page/**', + 'src/plugins/saved_objects_management/**', + ], + rules: { + '@typescript-eslint/prefer-ts-expect-error': 'error', + }, + }, ], }; diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index b0612ff4d5b65..8f2bde3856019 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -172,7 +172,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PublicAppInfo](./kibana-plugin-core-public.publicappinfo.md) | Public information about a registered [application](./kibana-plugin-core-public.app.md) | | [PublicLegacyAppInfo](./kibana-plugin-core-public.publiclegacyappinfo.md) | Information about a registered [legacy application](./kibana-plugin-core-public.legacyapp.md) | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) | | | [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | | [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | | [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md b/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md deleted file mode 100644 index 2f47ef1086d71..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 7e777d51f147f..f73595ea0a8ff 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -257,7 +257,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginName](./kibana-plugin-core-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | | [PluginOpaqueId](./kibana-plugin-core-server.pluginopaqueid.md) | | | [PublicUiSettingsParams](./kibana-plugin-core-server.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) | | | [RedirectResponseOptions](./kibana-plugin-core-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | | [RequestHandler](./kibana-plugin-core-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) functions. | | [RequestHandlerContextContainer](./kibana-plugin-core-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | diff --git a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md b/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md deleted file mode 100644 index bc9cd4680b17d..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index 85eb4825bc2e3..a25f4a0c373b2 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 9a8a81460f410..6ccfeb8ab052c 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -61,7 +61,8 @@ export type Ensure = T extends X ? T : never; // If we define this inside RecursiveReadonly TypeScript complains. // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} +export interface RecursiveReadonlyArray extends ReadonlyArray> {} + export type RecursiveReadonly = T extends (...args: any) => any ? T : T extends any[] diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index dfbb449b4d58e..286a93fdc2398 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -48,7 +48,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); @@ -59,7 +59,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); }); diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index d602422c14634..7304a8e5a66bc 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -16,9 +16,10 @@ * specific language governing permissions and limitations * under the License. */ +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index cd2dd99c30c11..0fe97431b1569 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -19,6 +19,7 @@ import { Observable } from 'rxjs'; import { History } from 'history'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from './capabilities'; import { ChromeStart } from '../chrome'; @@ -30,7 +31,6 @@ import { NotificationsStart } from '../notifications'; import { OverlayStart } from '../overlays'; import { PluginOpaqueId } from '../plugins'; import { IUiSettingsClient } from '../ui_settings'; -import { RecursiveReadonly } from '../../utils'; import { SavedObjectsStart } from '../saved_objects'; import { AppCategory } from '../../types'; import { ScopedHistory } from './scoped_history'; diff --git a/src/core/public/chrome/recently_accessed/persisted_log.test.ts b/src/core/public/chrome/recently_accessed/persisted_log.test.ts index 9b307a2d25faf..4229efdf7ca9d 100644 --- a/src/core/public/chrome/recently_accessed/persisted_log.test.ts +++ b/src/core/public/chrome/recently_accessed/persisted_log.test.ts @@ -59,7 +59,7 @@ describe('PersistedLog', () => { describe('internal functionality', () => { test('reads from storage', () => { - // @ts-ignore + // @ts-expect-error const log = new PersistedLog(historyName, { maxLength: 10 }, storage); expect(storage.getItem).toHaveBeenCalledTimes(1); diff --git a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts index 3c9713a93144a..14c3c581f9f17 100644 --- a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts +++ b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts @@ -55,11 +55,11 @@ describe('RecentlyAccessed#start()', () => { let originalLocalStorage: Storage; beforeAll(() => { originalLocalStorage = window.localStorage; - // @ts-ignore + // @ts-expect-error window.localStorage = new LocalStorageMock(); }); beforeEach(() => localStorage.clear()); - // @ts-ignore + // @ts-expect-error afterAll(() => (window.localStorage = originalLocalStorage)); const getStart = async () => { diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx index 1023a561a0fe3..6d2938e3345a6 100644 --- a/src/core/public/chrome/ui/header/header_help_menu.tsx +++ b/src/core/public/chrome/ui/header/header_help_menu.tsx @@ -312,7 +312,6 @@ class HeaderHelpMenuUI extends Component { ); return ( - // @ts-ignore repositionOnScroll doesn't exist in EuiPopover { fetchMock.get('*', {}); await expect( fetchInstance.fetch( - // @ts-ignore + // @ts-expect-error { path: '/', headers: { hello: 'world' } }, { headers: { hello: 'mars' } } ) diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts index 78220af9cc83b..0afea5aaa506a 100644 --- a/src/core/public/http/http_service.test.ts +++ b/src/core/public/http/http_service.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import { loadingServiceMock } from './http_service.test.mocks'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 41af0f1b8395f..3e4e70fb99508 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -81,7 +81,6 @@ import { export { CoreContext, CoreSystem } from './core_system'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, diff --git a/src/core/public/injected_metadata/injected_metadata_service.test.ts b/src/core/public/injected_metadata/injected_metadata_service.test.ts index cf4b72114d5ac..1a8b4d14ee249 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.test.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.test.ts @@ -58,7 +58,6 @@ describe('setup.getCspConfig()', () => { const csp = injectedMetadata.setup().getCspConfig(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible csp.warnLegacyBrowsers = false; }).toThrowError(); }); @@ -100,11 +99,11 @@ describe('setup.getPlugins()', () => { plugins.push({ id: 'new-plugin', plugin: {} as DiscoveredPlugin }); }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].name = 'changed'; }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].newProp = 'changed'; }).toThrowError(); }); @@ -136,7 +135,7 @@ describe('setup.getLegacyMetadata()', () => { foo: true, }); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible legacyMetadata.foo = false; }).toThrowError(); }); diff --git a/src/core/public/integrations/styles/styles_service.ts b/src/core/public/integrations/styles/styles_service.ts index 41fc861d6cb39..d1d7f2170fde3 100644 --- a/src/core/public/integrations/styles/styles_service.ts +++ b/src/core/public/integrations/styles/styles_service.ts @@ -21,7 +21,7 @@ import { Subscription } from 'rxjs'; import { IUiSettingsClient } from '../../ui_settings'; import { CoreService } from '../../../types'; -// @ts-ignore +// @ts-expect-error import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; interface StartDeps { diff --git a/src/core/public/kbn_bootstrap.ts b/src/core/public/kbn_bootstrap.ts index 0f86061816701..a108b5aaa47ec 100644 --- a/src/core/public/kbn_bootstrap.ts +++ b/src/core/public/kbn_bootstrap.ts @@ -42,7 +42,6 @@ export function __kbnBootstrap__() { const APM_ENABLED = process.env.IS_KIBANA_DISTRIBUTABLE !== 'true' && apmConfig != null; if (APM_ENABLED) { - // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-var-requires const { init, apm } = require('@elastic/apm-rum'); if (apmConfig.globalLabels) { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a65b9dd9d242a..86e281a49b744 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -116,6 +116,7 @@ import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/ser import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import React from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -1158,13 +1159,6 @@ export type PublicLegacyAppInfo = Omit & { // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index 0c34a16c68e99..20824af38af0f 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -432,7 +432,7 @@ describe('SavedObjectsClient', () => { sortOrder: 'sort', // Not currently supported by API }; - // @ts-ignore + // @ts-expect-error savedObjectsClient.find(options); expect(http.fetch.mock.calls).toMatchInlineSnapshot(` Array [ diff --git a/src/core/public/ui_settings/ui_settings_api.test.ts b/src/core/public/ui_settings/ui_settings_api.test.ts index bab7081509d53..14791407d2550 100644 --- a/src/core/public/ui_settings/ui_settings_api.test.ts +++ b/src/core/public/ui_settings/ui_settings_api.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import * as Rx from 'rxjs'; import { takeUntil, toArray } from 'rxjs/operators'; diff --git a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts index b12ecc889eb2d..475a76d406017 100644 --- a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts @@ -67,7 +67,7 @@ export function migrationsRetryCallCluster( error instanceof esErrors.RequestTimeout || error instanceof esErrors.AuthenticationException || error instanceof esErrors.AuthorizationException || - // @ts-ignore + // @ts-expect-error error instanceof esErrors.Gone || error?.body?.error?.type === 'snapshot_in_progress_exception' ); diff --git a/src/core/server/http/cookie_session_storage.ts b/src/core/server/http/cookie_session_storage.ts index 13f498233f695..5ca70045f81db 100644 --- a/src/core/server/http/cookie_session_storage.ts +++ b/src/core/server/http/cookie_session_storage.ts @@ -19,7 +19,7 @@ import { Request, Server } from 'hapi'; import hapiAuthCookie from 'hapi-auth-cookie'; -// @ts-ignore no TS definitions +// @ts-expect-error no TS definitions import Statehood from 'statehood'; import { KibanaRequest, ensureRawRequest } from './router'; diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index f266677c1a172..fefd75ad9710e 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -21,8 +21,9 @@ import { Url } from 'url'; import { Request, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; @@ -156,7 +157,7 @@ export class KibanaRequest< public readonly params: Params, public readonly query: Query, public readonly body: Body, - // @ts-ignore we will use this flag as soon as http request proxy is supported in the core + // @ts-expect-error we will use this flag as soon as http request proxy is supported in the core // until that time we have to expose all the headers private readonly withoutSecretHeaders: boolean ) { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 91c33fac41646..35aabab4a0b26 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -307,7 +307,6 @@ export { } from './metrics'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index 6cd193d896109..8e53178142180 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,7 +18,7 @@ */ import { difference, get, set } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { getTransform } from '../../../../legacy/deprecation/index'; import { unset } from '../../../../legacy/utils'; import { getFlattenedObject } from '../../../utils'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index ccadae757fe54..ffe3b2375bc90 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -29,7 +29,6 @@ import { import { BehaviorSubject, throwError } from 'rxjs'; -// @ts-ignore: implicit any for JS file import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; diff --git a/src/core/server/legacy/logging/legacy_logging_server.ts b/src/core/server/legacy/logging/legacy_logging_server.ts index 85a8686b4eded..4a7fea87cf69f 100644 --- a/src/core/server/legacy/logging/legacy_logging_server.ts +++ b/src/core/server/legacy/logging/legacy_logging_server.ts @@ -19,9 +19,9 @@ import { ServerExtType } from 'hapi'; import Podium from 'podium'; -// @ts-ignore: implicit any for JS file +// @ts-expect-error: implicit any for JS file import { Config } from '../../../../legacy/server/config'; -// @ts-ignore: implicit any for JS file +// @ts-expect-error: implicit any for JS file import { setupLogging } from '../../../../legacy/server/logging'; import { LogLevel } from '../../logging/log_level'; import { LogRecord } from '../../logging/log_record'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 5039b3a55cc58..f3ec2ed8335c5 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -23,7 +23,7 @@ import { toArray, tap, distinct, map } from 'rxjs/operators'; import { findPluginSpecs, defaultConfig, - // @ts-ignore + // @ts-expect-error } from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 2ca5c9f6ed3c5..9e86ee22c607b 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -19,8 +19,8 @@ import { Observable } from 'rxjs'; import { Type } from '@kbn/config-schema'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { RecursiveReadonly } from 'kibana/public'; import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } from '../config'; import { LoggerFactory } from '../logging'; import { KibanaConfigType } from '../kibana_config'; diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.ts index e57f08aa7a527..7d1575798c357 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.ts @@ -26,11 +26,11 @@ const { NoConnections, RequestTimeout, Conflict, - // @ts-ignore + // @ts-expect-error 401: NotAuthorized, - // @ts-ignore + // @ts-expect-error 403: Forbidden, - // @ts-ignore + // @ts-expect-error 413: RequestEntityTooLarge, NotFound, BadRequest, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 5973e300e098e..9cc5a8a386b0b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -108,7 +108,7 @@ import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import { Readable } from 'stream'; -import { RecursiveReadonly as RecursiveReadonly_2 } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -299,7 +299,7 @@ export const config: { startupTimeout: import("@kbn/config-schema").Type; logQueries: import("@kbn/config-schema").Type; ssl: import("@kbn/config-schema").ObjectType<{ - verificationMode: import("@kbn/config-schema").Type<"none" | "full" | "certificate">; + verificationMode: import("@kbn/config-schema").Type<"none" | "certificate" | "full">; certificateAuthorities: import("@kbn/config-schema").Type; certificate: import("@kbn/config-schema").Type; key: import("@kbn/config-schema").Type; @@ -1663,13 +1663,6 @@ export interface PluginsServiceStart { // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // @public export type RedirectResponseOptions = HttpResponseOptions & { headers: { @@ -2550,7 +2543,7 @@ export interface SessionStorageFactory { } // @public (undocumented) -export type SharedGlobalConfig = RecursiveReadonly_2<{ +export type SharedGlobalConfig = RecursiveReadonly<{ kibana: Pick; elasticsearch: Pick; path: Pick; diff --git a/src/core/utils/deep_freeze.test.ts b/src/core/utils/deep_freeze.test.ts index b4531d80d0252..58aa9c9b8c92b 100644 --- a/src/core/utils/deep_freeze.test.ts +++ b/src/core/utils/deep_freeze.test.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { deepFreeze } from './deep_freeze'; it('returns the first argument with all original references', () => { @@ -33,7 +32,7 @@ it('returns the first argument with all original references', () => { it('prevents adding properties to argument', () => { const frozen = deepFreeze({}); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`object is not extensible`); }); @@ -41,7 +40,7 @@ it('prevents adding properties to argument', () => { it('prevents changing properties on argument', () => { const frozen = deepFreeze({ foo: false }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`read only property 'foo'`); }); @@ -49,7 +48,7 @@ it('prevents changing properties on argument', () => { it('prevents changing properties on nested children of argument', () => { const frozen = deepFreeze({ foo: { bar: { baz: { box: 1 } } } }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.bar.baz.box = 2; }).toThrowError(`read only property 'box'`); }); @@ -57,7 +56,7 @@ it('prevents changing properties on nested children of argument', () => { it('prevents adding items to a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.push(2); }).toThrowError(`object is not extensible`); }); @@ -65,7 +64,7 @@ it('prevents adding items to a frozen array', () => { it('prevents reassigning items in a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo[0] = 2; }).toThrowError(`read only property '0'`); }); diff --git a/src/core/utils/deep_freeze.ts b/src/core/utils/deep_freeze.ts index b0f283c60d0fc..fbc35acb45b0f 100644 --- a/src/core/utils/deep_freeze.ts +++ b/src/core/utils/deep_freeze.ts @@ -16,19 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -// if we define this inside RecursiveReadonly TypeScript complains -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} - -/** @public */ -export type RecursiveReadonly = T extends (...args: any[]) => any - ? T - : T extends any[] - ? RecursiveReadonlyArray - : T extends object - ? Readonly<{ [K in keyof T]: RecursiveReadonly }> - : T; +import { RecursiveReadonly } from '@kbn/utility-types'; /** @public */ export type Freezable = { [k: string]: any } | any[]; @@ -47,6 +35,5 @@ export function deepFreeze(object: T) { deepFreeze(value); } } - return Object.freeze(object) as RecursiveReadonly; } diff --git a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts b/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts deleted file mode 100644 index d4f001a914d34..0000000000000 --- a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { deepFreeze } from '../../../../utils/deep_freeze'; - -deepFreeze({ - foo: { - bar: { - baz: 1, - }, - }, -}).foo.bar.baz = 2; - -deepFreeze({ - foo: [ - { - bar: 1, - }, - ], -}).foo[0].bar = 2; - -deepFreeze({ - foo: [1], -}).foo[0] = 2; - -deepFreeze({ - foo: [1], -}).foo.push(2); diff --git a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json b/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json deleted file mode 100644 index 12307c46b95fa..0000000000000 --- a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "skipLibCheck": true, - "lib": [ - "es2018" - ] - }, - "files": [ - "index.ts" - ] -} diff --git a/src/core/utils/integration_tests/deep_freeze.test.ts b/src/core/utils/integration_tests/deep_freeze.test.ts deleted file mode 100644 index f58e298fecfbf..0000000000000 --- a/src/core/utils/integration_tests/deep_freeze.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; - -import execa from 'execa'; - -const MINUTE = 60 * 1000; - -it( - 'types return values to prevent mutations in typescript', - async () => { - await expect( - execa('tsc', ['--noEmit'], { - cwd: resolve(__dirname, '__fixtures__/frozen_object_mutation'), - preferLocal: true, - }).catch((err) => err.stdout) - ).resolves.toMatchInlineSnapshot(` - "index.ts(28,12): error TS2540: Cannot assign to 'baz' because it is a read-only property. - index.ts(36,11): error TS2540: Cannot assign to 'bar' because it is a read-only property." - `); - }, - MINUTE -); diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index b12ad94017fbb..0bb3fc3a3bf16 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -142,6 +142,7 @@ import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import React from 'react'; import * as React_2 from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -1531,7 +1532,7 @@ export interface QueryState { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 1eaab2550645f..24ce42e2c20ae 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -109,7 +109,7 @@ import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; -import { RecursiveReadonly } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; diff --git a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx index fd7967f4128c3..50358c17e058c 100644 --- a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx @@ -18,14 +18,7 @@ */ import React, { PureComponent } from 'react'; -import { - EuiFieldNumber, - EuiFieldText, - EuiFormRow, - EuiSwitch, - // @ts-ignore - EuiCodeEditor, -} from '@elastic/eui'; +import { EuiFieldNumber, EuiFieldText, EuiFormRow, EuiSwitch, EuiCodeEditor } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { FieldState, FieldType } from '../../types'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index 6e7397d1058bf..aac799da6ea67 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -31,7 +31,6 @@ import { EuiForm, EuiFormRow, EuiSwitch, - // @ts-ignore EuiFilePicker, EuiInMemoryTable, EuiSelect, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 6b25a1b0c1f25..6b209a62e1b98 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; -// @ts-ignore +// @ts-expect-error import { findTestSubject } from '@elastic/eui/lib/test'; import { keyCodes } from '@elastic/eui'; import { httpServiceMock } from '../../../../../../core/public/mocks'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 51e7525d0e00a..719729cee2602 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -20,7 +20,6 @@ import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; import { - // @ts-ignore EuiSearchBar, EuiBasicTable, EuiButton, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 54bc649c33b60..340c0e3237f91 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -19,7 +19,7 @@ import React, { Component } from 'react'; import { debounce } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { saveAs } from '@elastic/filesaver'; import { EuiSpacer, diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 435ec9027eef2..605c6be0a85df 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -20,11 +20,9 @@ import { i18n } from '@kbn/i18n'; import { first } from 'rxjs/operators'; import { TypeOf } from '@kbn/config-schema'; -import { - CoreSetup, - PluginInitializerContext, - RecursiveReadonly, -} from '../../../../src/core/server'; +import { RecursiveReadonly } from '@kbn/utility-types'; + +import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; diff --git a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts index e2703cb5786dd..85a8618be5d18 100644 --- a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts @@ -126,7 +126,7 @@ export interface KibanaServerRequest extends t.TypeOf { kind: 'authenticated'; [internalAuthData]: AuthDataType; username: string; - roles: string[]; + roles: readonly string[]; full_name: string | null; email: string | null; enabled: boolean; diff --git a/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts index a5904d687b37e..ce663650409fa 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts @@ -43,7 +43,7 @@ export interface FrameworkInfo extends t.TypeOf {} export const RuntimeFrameworkUser = t.interface( { username: t.string, - roles: t.array(t.string), + roles: t.readonlyArray(t.string), full_name: t.union([t.null, t.string]), email: t.union([t.null, t.string]), enabled: t.boolean, diff --git a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts index 2978c48af7414..67fc1a98ad4d1 100644 --- a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts +++ b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts @@ -85,9 +85,9 @@ describe('DashboardOnlyModeRequestInterceptor', () => { security.authc.getCurrentUser = jest.fn( (r: KibanaRequest) => - ({ + (({ roles: [DASHBOARD_ONLY_MODE_ROLE], - } as AuthenticatedUser) + } as unknown) as AuthenticatedUser) ); uiSettingsMock = [DASHBOARD_ONLY_MODE_ROLE]; diff --git a/x-pack/plugins/features/common/feature.ts b/x-pack/plugins/features/common/feature.ts index 1b405094d9eda..4a293e0c962cc 100644 --- a/x-pack/plugins/features/common/feature.ts +++ b/x-pack/plugins/features/common/feature.ts @@ -49,7 +49,9 @@ export interface FeatureConfig { * This does not restrict access to your feature based on license. * Its only purpose is to inform the space and roles UIs on which features to display. */ - validLicenses?: Array<'basic' | 'standard' | 'gold' | 'platinum' | 'enterprise' | 'trial'>; + validLicenses?: ReadonlyArray< + 'basic' | 'standard' | 'gold' | 'platinum' | 'enterprise' | 'trial' + >; /** * An optional EUI Icon to be used when displaying your feature. @@ -66,7 +68,7 @@ export interface FeatureConfig { * An array of app ids that are enabled when this feature is enabled. * Apps specified here will automatically cascade to the privileges defined below, unless specified differently there. */ - app: string[]; + app: readonly string[]; /** * If this feature includes management sections, you can specify them here to control visibility of those @@ -83,14 +85,14 @@ export interface FeatureConfig { * ``` */ management?: { - [sectionId: string]: string[]; + [sectionId: string]: readonly string[]; }; /** * If this feature includes a catalogue entry, you can specify them here to control visibility based on the current space. * * Items specified here will automatically cascade to the privileges defined below, unless specified differently there. */ - catalogue?: string[]; + catalogue?: readonly string[]; /** * Feature privilege definition. @@ -112,7 +114,7 @@ export interface FeatureConfig { /** * Optional sub-feature privilege definitions. This can only be specified if `privileges` are are also defined. */ - subFeatures?: SubFeatureConfig[]; + subFeatures?: readonly SubFeatureConfig[]; /** * Optional message to display on the Role Management screen when configuring permissions for this feature. @@ -124,7 +126,7 @@ export interface FeatureConfig { */ reserved?: { description: string; - privileges: ReservedKibanaPrivilege[]; + privileges: readonly ReservedKibanaPrivilege[]; }; } diff --git a/x-pack/plugins/features/common/feature_kibana_privileges.ts b/x-pack/plugins/features/common/feature_kibana_privileges.ts index 768c8c6ae1088..a9ba38e36f20b 100644 --- a/x-pack/plugins/features/common/feature_kibana_privileges.ts +++ b/x-pack/plugins/features/common/feature_kibana_privileges.ts @@ -26,13 +26,13 @@ export interface FeatureKibanaPrivileges { * ``` */ management?: { - [sectionId: string]: string[]; + [sectionId: string]: readonly string[]; }; /** * If this feature includes a catalogue entry, you can specify them here to control visibility based on user permissions. */ - catalogue?: string[]; + catalogue?: readonly string[]; /** * If your feature includes server-side APIs, you can tag those routes to secure access based on user permissions. @@ -60,7 +60,7 @@ export interface FeatureKibanaPrivileges { * A generic tag name like "access:read" could be used elsewhere, and access to that API endpoint would also * extend to any routes you have also tagged with that name. */ - api?: string[]; + api?: readonly string[]; /** * If your feature exposes a client-side application (most of them do!), then you can control access to them here. @@ -73,7 +73,7 @@ export interface FeatureKibanaPrivileges { * ``` * */ - app?: string[]; + app?: readonly string[]; /** * If your feature requires access to specific saved objects, then specify your access needs here. @@ -88,7 +88,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all: string[]; + all: readonly string[]; /** * List of saved object types which users should have read-only access to when granted this privilege. @@ -99,7 +99,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read: string[]; + read: readonly string[]; }; /** * A list of UI Capabilities that should be granted to users with this privilege. @@ -121,5 +121,5 @@ export interface FeatureKibanaPrivileges { * * @see UICapabilities */ - ui: string[]; + ui: readonly string[]; } diff --git a/x-pack/plugins/features/common/sub_feature.ts b/x-pack/plugins/features/common/sub_feature.ts index 121bb8514c8a2..0651bad883ea5 100644 --- a/x-pack/plugins/features/common/sub_feature.ts +++ b/x-pack/plugins/features/common/sub_feature.ts @@ -15,7 +15,7 @@ export interface SubFeatureConfig { name: string; /** Collection of privilege groups */ - privilegeGroups: SubFeaturePrivilegeGroupConfig[]; + privilegeGroups: readonly SubFeaturePrivilegeGroupConfig[]; } /** @@ -45,7 +45,7 @@ export interface SubFeaturePrivilegeGroupConfig { /** * The privileges which belong to this group. */ - privileges: SubFeaturePrivilegeConfig[]; + privileges: readonly SubFeaturePrivilegeConfig[]; } /** diff --git a/x-pack/plugins/features/server/feature_schema.ts b/x-pack/plugins/features/server/feature_schema.ts index 7497548cf8904..c45788b511cde 100644 --- a/x-pack/plugins/features/server/feature_schema.ts +++ b/x-pack/plugins/features/server/feature_schema.ts @@ -126,7 +126,7 @@ export function validateFeature(feature: FeatureConfig) { const unseenCatalogue = new Set(catalogue); - function validateAppEntry(privilegeId: string, entry: string[] = []) { + function validateAppEntry(privilegeId: string, entry: readonly string[] = []) { entry.forEach((privilegeApp) => unseenApps.delete(privilegeApp)); const unknownAppEntries = difference(entry, app); @@ -139,7 +139,7 @@ export function validateFeature(feature: FeatureConfig) { } } - function validateCatalogueEntry(privilegeId: string, entry: string[] = []) { + function validateCatalogueEntry(privilegeId: string, entry: readonly string[] = []) { entry.forEach((privilegeCatalogue) => unseenCatalogue.delete(privilegeCatalogue)); const unknownCatalogueEntries = difference(entry || [], catalogue); @@ -154,7 +154,7 @@ export function validateFeature(feature: FeatureConfig) { function validateManagementEntry( privilegeId: string, - managementEntry: Record = {} + managementEntry: Record = {} ) { Object.entries(managementEntry).forEach(([managementSectionId, managementSectionEntry]) => { if (unseenManagement.has(managementSectionId)) { diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index bfae416471c2f..149c1acfb5086 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -3,14 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { RecursiveReadonly } from '@kbn/utility-types'; import { CoreSetup, CoreStart, SavedObjectsServiceStart, Logger, PluginInitializerContext, - RecursiveReadonly, } from '../../../../src/core/server'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/server'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts index c23d44aa8e4b6..f9685dac32e23 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts @@ -4,13 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Capabilities, - HttpSetup, - RecursiveReadonly, - SavedObjectsClientContract, -} from 'kibana/public'; +import { Capabilities, HttpSetup, SavedObjectsClientContract } from 'kibana/public'; import { i18n } from '@kbn/i18n'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { IndexPatternsContract, IndexPattern, diff --git a/x-pack/plugins/security/common/model/user.ts b/x-pack/plugins/security/common/model/user.ts index 5c852e7a8f03d..ae6de7f4c5fbc 100644 --- a/x-pack/plugins/security/common/model/user.ts +++ b/x-pack/plugins/security/common/model/user.ts @@ -8,7 +8,7 @@ export interface User { username: string; email: string; full_name: string; - roles: string[]; + roles: readonly string[]; enabled: boolean; metadata?: { _reserved: boolean; diff --git a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx index 689830e2845ce..5b24b296b299f 100644 --- a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx +++ b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx @@ -12,7 +12,7 @@ import { RoleComboBoxOption } from './role_combo_box_option'; interface Props { availableRoles: Role[]; - selectedRoleNames: string[]; + selectedRoleNames: readonly string[]; onChange: (selectedRoleNames: string[]) => void; placeholder?: string; isLoading?: boolean; diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index eea7edd62fbfa..9eb2616cebb18 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -57,7 +57,7 @@ interface State { showDeleteConfirmation: boolean; user: EditUser; roles: Role[]; - selectedRoles: string[]; + selectedRoles: readonly string[]; formError: UserValidationResult | null; } diff --git a/x-pack/plugins/security/server/authorization/app_authorization.test.ts b/x-pack/plugins/security/server/authorization/app_authorization.test.ts index 2d3a981fb3247..1dc072ab2e6e9 100644 --- a/x-pack/plugins/security/server/authorization/app_authorization.test.ts +++ b/x-pack/plugins/security/server/authorization/app_authorization.test.ts @@ -5,6 +5,7 @@ */ import { PluginSetupContract as FeaturesSetupContract } from '../../../features/server'; +import { featuresPluginMock } from '../../../features/server/mocks'; import { initAppAuthorization } from './app_authorization'; import { @@ -16,9 +17,11 @@ import { import { authorizationMock } from './index.mock'; const createFeaturesSetupContractMock = (): FeaturesSetupContract => { - return { - getFeatures: () => [{ id: 'foo', name: 'Foo', app: ['foo'], privileges: {} }], - } as FeaturesSetupContract; + const mock = featuresPluginMock.createSetup(); + mock.getFeatures.mockReturnValue([ + { id: 'foo', name: 'Foo', app: ['foo'], privileges: {} } as any, + ]); + return mock; }; describe('initAppAuthorization', () => { diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts index e239a6e280aec..029b2e77f7812 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts @@ -76,7 +76,7 @@ function mergeWithSubFeatures( return mergedConfig; } -function mergeArrays(input1: string[] | undefined, input2: string[] | undefined) { +function mergeArrays(input1: readonly string[] | undefined, input2: readonly string[] | undefined) { const first = input1 ?? []; const second = input2 ?? []; return Array.from(new Set([...first, ...second])); diff --git a/x-pack/plugins/security/server/index.ts b/x-pack/plugins/security/server/index.ts index a0a06b537213d..d357519c5ccce 100644 --- a/x-pack/plugins/security/server/index.ts +++ b/x-pack/plugins/security/server/index.ts @@ -5,11 +5,11 @@ */ import { TypeOf } from '@kbn/config-schema'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { PluginConfigDescriptor, PluginInitializer, PluginInitializerContext, - RecursiveReadonly, } from '../../../../src/core/server'; import { ConfigSchema } from './config'; import { Plugin, SecurityPluginSetup, PluginSetupDependencies } from './plugin'; diff --git a/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts b/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts index a3360969fb3f2..20d419e5c90e4 100644 --- a/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts +++ b/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts @@ -5,7 +5,7 @@ */ import { getEnabledFeatures } from './feature_utils'; -import { Feature } from '../../../../features/public'; +import { FeatureConfig } from '../../../../features/public'; const buildFeatures = () => [ @@ -25,7 +25,7 @@ const buildFeatures = () => id: 'feature4', name: 'feature 4', }, - ] as Feature[]; + ] as FeatureConfig[]; const buildSpace = (disabledFeatures = [] as string[]) => ({ id: 'space', diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts index 17a1fbcca73bd..8375296d869e6 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts @@ -21,7 +21,6 @@ import { coreMock, } from '../../../../../../src/core/server/mocks'; import * as kbnTestServer from '../../../../../../src/test_utils/kbn_server'; -import { PluginsSetup } from '../../plugin'; import { SpacesService } from '../../spaces_service'; import { SpacesAuditLogger } from '../audit_logger'; import { convertSavedObjectToSpace } from '../../routes/lib'; @@ -29,6 +28,7 @@ import { initSpacesOnPostAuthRequestInterceptor } from './on_post_auth_intercept import { Feature } from '../../../../features/server'; import { spacesConfig } from '../__fixtures__'; import { securityMock } from '../../../../security/server/mocks'; +import { featuresPluginMock } from '../../../../features/server/mocks'; // FLAKY: https://github.com/elastic/kibana/issues/55953 describe.skip('onPostAuthInterceptor', () => { @@ -123,31 +123,29 @@ describe.skip('onPostAuthInterceptor', () => { const loggingMock = loggingSystemMock.create().asLoggerFactory().get('xpack', 'spaces'); - const featuresPlugin = { - getFeatures: () => - [ - { - id: 'feature-1', - name: 'feature 1', - app: ['app-1'], - }, - { - id: 'feature-2', - name: 'feature 2', - app: ['app-2'], - }, - { - id: 'feature-4', - name: 'feature 4', - app: ['app-1', 'app-4'], - }, - { - id: 'feature-5', - name: 'feature 4', - app: ['kibana'], - }, - ] as Feature[], - } as PluginsSetup['features']; + const featuresPlugin = featuresPluginMock.createSetup(); + featuresPlugin.getFeatures.mockReturnValue(([ + { + id: 'feature-1', + name: 'feature 1', + app: ['app-1'], + }, + { + id: 'feature-2', + name: 'feature 2', + app: ['app-2'], + }, + { + id: 'feature-4', + name: 'feature 4', + app: ['app-1', 'app-4'], + }, + { + id: 'feature-5', + name: 'feature 4', + app: ['kibana'], + }, + ] as unknown) as Feature[]); const mockRepository = jest.fn().mockImplementation(() => { return {