diff --git a/package.json b/package.json index cae25e40ccf07..871e467394e52 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "**/react-syntax-highlighter": "^15.3.1", "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", "**/trim": "1.0.1", - "**/typescript": "4.3.5", + "**/typescript": "4.5.3", "**/underscore": "^1.13.1", "globby/fast-glob": "3.2.7" }, @@ -555,7 +555,7 @@ "@types/js-levenshtein": "^1.1.0", "@types/js-search": "^1.4.0", "@types/js-yaml": "^3.11.1", - "@types/jsdom": "^16.2.3", + "@types/jsdom": "^16.2.13", "@types/json-stable-stringify": "^1.0.32", "@types/json5": "^0.0.30", "@types/kbn__ace": "link:bazel-bin/packages/kbn-ace/npm_module_types", @@ -836,7 +836,7 @@ "ts-loader": "^7.0.5", "ts-morph": "^11.0.0", "tsd": "^0.13.1", - "typescript": "4.3.5", + "typescript": "4.5.3", "unlazy-loader": "^0.1.3", "url-loader": "^2.2.0", "val-loader": "^1.1.1", diff --git a/packages/kbn-test/src/jest/utils/enzyme_helpers.tsx b/packages/kbn-test/src/jest/utils/enzyme_helpers.tsx index ee5e06ebf6947..696a1d1b63163 100644 --- a/packages/kbn-test/src/jest/utils/enzyme_helpers.tsx +++ b/packages/kbn-test/src/jest/utils/enzyme_helpers.tsx @@ -46,7 +46,11 @@ function getOptions(context = {}, childContextTypes = {}, props = {}) { /** * When using @kbn/i18n `injectI18n` on components, props.intl is required. */ -function nodeWithIntlProp(node: ReactElement): ReactElement { +// This function is exported solely to fix the types output in TS 4.5.2, likely a bug +// Otherwise, InjectedIntl is missing from the output +export function nodeWithIntlProp( + node: ReactElement +): ReactElement { return React.cloneElement(node, { intl }); } 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 10b4f510d4afa..bcf58b7a40ab1 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 @@ -44,11 +44,9 @@ describe('RecentlyAccessed#start()', () => { let originalLocalStorage: Storage; beforeAll(() => { originalLocalStorage = window.localStorage; - // @ts-expect-error window.localStorage = new LocalStorageMock(); }); beforeEach(() => localStorage.clear()); - // @ts-expect-error afterAll(() => (window.localStorage = originalLocalStorage)); const getStart = async () => { diff --git a/src/dev/build/lib/fs.ts b/src/dev/build/lib/fs.ts index a47fb64c5e563..47b98c9cc398a 100644 --- a/src/dev/build/lib/fs.ts +++ b/src/dev/build/lib/fs.ts @@ -117,10 +117,10 @@ export async function deleteEmptyFolders( // Delete empty is used to gather all the empty folders and // then we use del to actually delete them - const emptyFoldersList = await deleteEmpty(rootFolderPath, { + const emptyFoldersList = (await deleteEmpty(rootFolderPath, { // @ts-expect-error DT package has incorrect types https://github.com/jonschlinkert/delete-empty/blob/6ae34547663e6845c3c98b184c606fa90ef79c0a/index.js#L160 dryRun: true, - }); + })) as unknown as string[]; // DT package has incorrect types const foldersToDelete = emptyFoldersList.filter((folderToDelete) => { return !foldersToKeep.some((folderToKeep) => folderToDelete.includes(folderToKeep)); diff --git a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx index effbf8ce980d7..44b1aec226fd6 100644 --- a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx +++ b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx @@ -86,6 +86,7 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => { const factories = embeddable ? Array.from(embeddable.getEmbeddableFactories()).filter( ({ type, isEditable, canCreateNew, isContainerType }) => + // @ts-expect-error ts 4.5 upgrade isEditable() && !isContainerType && canCreateNew() && type !== 'visualization' ) : []; diff --git a/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx index 9a575a9446a01..e7a9127f17040 100644 --- a/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx +++ b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx @@ -164,7 +164,10 @@ export class AttributeService< try { const newAttributes = { ...(input as ValType)[ATTRIBUTE_SERVICE_KEY] }; newAttributes.title = props.newTitle; - const wrappedInput = (await this.wrapAttributes(newAttributes, true)) as RefType; + const wrappedInput = (await this.wrapAttributes( + newAttributes, + true + )) as unknown as RefType; // Remove unneeded attributes from the original input. const newInput = omit(input, ATTRIBUTE_SERVICE_KEY); diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx index a392502251039..624d5cc56288a 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx @@ -130,6 +130,7 @@ export class AddPanelFlyout extends React.Component { private getCreateMenuItems(): ReactElement[] { return [...this.props.getAllFactories()] .filter( + // @ts-expect-error ts 4.5 upgrade (factory) => factory.isEditable() && !factory.isContainerType && factory.canCreateNew() ) .map((factory) => ( diff --git a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts index 3f1966901544a..83f33a894b903 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts @@ -41,8 +41,6 @@ export function handleKibanaStats( const { kibana, kibana_stats: kibanaStats, ...plugins } = response; const os = { - platform: 'unknown', - platformRelease: 'unknown', ...kibanaStats.os, }; const formattedOsStats = Object.entries(os).reduce((acc, [key, value]) => { diff --git a/tsconfig.base.json b/tsconfig.base.json index ae06e39f7a274..71d686e09d162 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -7,23 +7,21 @@ "node_modules/@kbn/*", "bazel-out/darwin-fastbuild/bin/packages/kbn-*", "bazel-out/k8-fastbuild/bin/packages/kbn-*", - "bazel-out/x64_windows-fastbuild/bin/packages/kbn-*", + "bazel-out/x64_windows-fastbuild/bin/packages/kbn-*" ], // Allows for importing from `kibana` package for the exported types. "kibana": ["./kibana"], "kibana/public": ["src/core/public"], "kibana/server": ["src/core/server"], - "@emotion/core": [ - "typings/@emotion" - ], - "resize-observer-polyfill": [ - "typings/resize-observer-polyfill" - ] + "@emotion/core": ["typings/@emotion"], + "resize-observer-polyfill": ["typings/resize-observer-polyfill"] }, // Support .tsx files and transform JSX into calls to React.createElement "jsx": "react", // Enables all strict type checking options. "strict": true, + // for now, don't use unknown in catch + "useUnknownInCatchVariables": false, // All TS projects should be composite and only include the files they select, and ref the files outside of the project "composite": true, // save information about the project graph on disk diff --git a/x-pack/plugins/apm/public/application/uxApp.tsx b/x-pack/plugins/apm/public/application/uxApp.tsx index f7a8f7030d4f9..cfb1a5c354c2d 100644 --- a/x-pack/plugins/apm/public/application/uxApp.tsx +++ b/x-pack/plugins/apm/public/application/uxApp.tsx @@ -130,7 +130,6 @@ export function UXAppRoot({ services={{ ...core, ...plugins, embeddable, data }} > - {/* @ts-expect-error Type instantiation is excessively deep */} diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts index 228add10184ba..d0fa24913a214 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts @@ -43,7 +43,7 @@ export async function getServicesDetailedStatistics({ getServiceTransactionDetailedStatistics(commonProps), offset ? getServiceTransactionDetailedStatistics({ ...commonProps, offset }) - : {}, + : Promise.resolve({}), ]); return { currentPeriod, previousPeriod }; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx index dad34e6983c5d..a6bb98e9aba9b 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx @@ -91,7 +91,7 @@ export const EditorMenu: FC = ({ addElement }) => { if (embeddableInput) { const config = encode(embeddableInput); const expression = `embeddable config="${config}" - type="${factory.type}" + type="${factory.type}" | render`; addElement({ expression }); @@ -123,6 +123,7 @@ export const EditorMenu: FC = ({ addElement }) => { const factories = embeddablesService ? Array.from(embeddablesService.getEmbeddableFactories()).filter( ({ type, isEditable, canCreateNew, isContainerType }) => + // @ts-expect-error ts 4.5 upgrade isEditable() && !isContainerType && canCreateNew() && diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts index 79f34c13d511c..2cdbc76504fb4 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts @@ -230,7 +230,7 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon type: string, id: string, attributes: Partial, - options?: SavedObjectsUpdateOptions + options?: SavedObjectsUpdateOptions ) { if (!this.options.service.isRegistered(type)) { return await this.options.baseClient.update(type, id, attributes, options); diff --git a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts index e84f959c02df9..57a9290d00a00 100644 --- a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts @@ -23,7 +23,6 @@ import type { DeleteAgentPolicyRequestSchema, GetFullAgentPolicyRequestSchema, } from '../../types'; -import type { AgentPolicy, NewPackagePolicy } from '../../types'; import { FLEET_SYSTEM_PACKAGE } from '../../../common'; import type { GetAgentPoliciesResponse, @@ -112,10 +111,7 @@ export const createAgentPolicyHandler: RequestHandler< try { // eslint-disable-next-line prefer-const - let [agentPolicy, newSysPackagePolicy] = await Promise.all< - AgentPolicy, - NewPackagePolicy | undefined - >([ + let [agentPolicy, newSysPackagePolicy] = await Promise.all([ agentPolicyService.create(soClient, esClient, request.body, { user, }), diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/attribution_control.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/attribution_control.tsx index 3955db278777a..4b42bc482a702 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/attribution_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/attribution_control/attribution_control.tsx @@ -53,7 +53,7 @@ export class AttributionControl extends Component { return; } - const uniqueAttributions = []; + const uniqueAttributions: Attribution[] = []; for (let i = 0; i < attributions.length; i++) { for (let j = 0; j < attributions[i].length; j++) { const testAttr = attributions[i][j]; diff --git a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx index b55b7e636472c..380857f1bffd2 100644 --- a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx +++ b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx @@ -147,7 +147,9 @@ export class ReportingCsvPanelAction implements ActionDefinition const blob = new Blob([rawResponse as BlobPart], { type: 'text/csv;charset=utf-8;' }); // Hack for IE11 Support + // @ts-expect-error if (window.navigator.msSaveOrOpenBlob) { + // @ts-expect-error return window.navigator.msSaveOrOpenBlob(blob, download); } diff --git a/x-pack/plugins/security_solution/public/common/components/auto_download/auto_download.tsx b/x-pack/plugins/security_solution/public/common/components/auto_download/auto_download.tsx index f7e863a648bc6..c9f36bfbe7681 100644 --- a/x-pack/plugins/security_solution/public/common/components/auto_download/auto_download.tsx +++ b/x-pack/plugins/security_solution/public/common/components/auto_download/auto_download.tsx @@ -23,7 +23,9 @@ export const AutoDownload: React.FC = ({ blob, name, onDownlo useEffect(() => { if (blob && anchorRef?.current) { + // @ts-expect-error if (typeof window.navigator.msSaveOrOpenBlob === 'function') { + // @ts-expect-error window.navigator.msSaveBlob(blob); } else { const objectURL = window.URL.createObjectURL(blob); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_host_table.tsx b/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_host_table.tsx index 49a4f22ef0a75..b4db5f6798860 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_host_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_host_table.tsx @@ -81,7 +81,6 @@ const AnomaliesHostTableComponent: React.FC = ({ type is not as specific as EUI's... columns={columns} - // @ts-expect-error ...which leads to `networks` not "matching" the columns items={hosts} pagination={pagination} sorting={sorting} diff --git a/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_network_table.tsx b/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_network_table.tsx index 24fe1c06aef4c..51561c9bf0d63 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_network_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/tables/anomalies_network_table.tsx @@ -71,7 +71,6 @@ const AnomaliesNetworkTableComponent: React.FC = ({ type is not as specific as EUI's... columns={columns} - // @ts-expect-error ...which leads to `networks` not "matching" the columns items={networks} pagination={pagination} sorting={sorting} diff --git a/x-pack/plugins/security_solution/public/common/lib/helpers/scheduler.ts b/x-pack/plugins/security_solution/public/common/lib/helpers/scheduler.ts index 248f0a2a0f65b..89c51757e420f 100644 --- a/x-pack/plugins/security_solution/public/common/lib/helpers/scheduler.ts +++ b/x-pack/plugins/security_solution/public/common/lib/helpers/scheduler.ts @@ -7,35 +7,11 @@ import { scaleLog } from 'd3-scale'; -// Types are from: https://github.com/Microsoft/TypeScript/issues/21309 -// TODO: Once this is no longer an experimental web API, remove these below -// as they should be Typed by TypeScript -type RequestIdleCallbackHandle = number; -interface RequestIdleCallbackOptions { - timeout: number; -} -interface RequestIdleCallbackDeadline { - readonly didTimeout: boolean; - timeRemaining: () => number; -} - -declare global { - interface Window { - requestIdleCallback: ( - callback: (deadline: RequestIdleCallbackDeadline) => void, - opts?: RequestIdleCallbackOptions - ) => RequestIdleCallbackHandle; - cancelIdleCallback: (handle: RequestIdleCallbackHandle) => void; - } -} - /** * Polyfill is from: https://developers.google.com/web/updates/2015/08/using-requestidlecallback * This is for Safari 12.1.2 and IE-11 */ -export const polyFillRequestIdleCallback = ( - callback: (deadline: RequestIdleCallbackDeadline) => void -) => { +export const polyFillRequestIdleCallback = (callback: IdleRequestCallback) => { const start = Date.now(); return setTimeout(() => { callback({ @@ -59,8 +35,8 @@ export const polyFillRequestIdleCallback = ( * this and all usages. Otherwise, just remove this note */ export const requestIdleCallbackViaScheduler = ( - callback: (deadline: RequestIdleCallbackDeadline) => void, - opts?: RequestIdleCallbackOptions + callback: IdleRequestCallback, + opts?: IdleRequestOptions ) => { if ('requestIdleCallback' in window) { window.requestIdleCallback(callback, opts); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts index 0045f69968b2a..1fc9017125696 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts @@ -496,6 +496,7 @@ describe('Detections Rules API', () => { name: 'fileToImport', size: 89, type: 'json', + webkitRelativePath: '/webkitRelativePath', arrayBuffer: jest.fn(), slice: jest.fn(), stream: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts index 1630d63aee5c6..e8a647c257b01 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts @@ -371,6 +371,7 @@ const fetchAllPoliciesIfNeeded = async ( dispatch({ type: 'policyDetailsListOfAllPoliciesStateChanged', + // @ts-expect-error ts 4.5 upgrade payload: createLoadingResourceState(asStaleResourceState(currentPoliciesState)), }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_messages_pane.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_messages_pane.tsx index 3f8b0549c219b..ce03d5989bc15 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_messages_pane.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_messages_pane.tsx @@ -128,7 +128,6 @@ export const ExpandedRowMessagesPane: React.FC = ({ transformId }) => { page = { index: 0, size: 10 }, }: { page?: { index: number; size: number }; - sort?: { field: string; direction: string }; }) => { const { index, size } = page; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details_route.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details_route.tsx index b530df986c277..e9a49d62d8923 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details_route.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details_route.tsx @@ -138,7 +138,7 @@ export async function getRuleData( const loadedRule: ResolvedRule = await resolveRule(ruleId); setAlert(loadedRule); - const [loadedAlertType, loadedActionTypes] = await Promise.all([ + const [loadedAlertType, loadedActionTypes] = await Promise.all([ loadAlertTypes() .then((types) => types.find((type) => type.id === loadedRule.alertTypeId)) .then(throwIfAbsent(`Invalid Rule Type: ${loadedRule.alertTypeId}`)), diff --git a/yarn.lock b/yarn.lock index fbeab26149b3f..edfc532366ce4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5765,10 +5765,10 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656" integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA== -"@types/jsdom@^16.2.3": - version "16.2.3" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.3.tgz#c6feadfe0836389b27f9c911cde82cd32e91c537" - integrity sha512-BREatezSn74rmLIDksuqGNFUTi9HNAWWQXYpFBFLK9U6wlMCO4M0QCa8CMpDsZQuqxSO9XifVLT5Q1P0vgKLqw== +"@types/jsdom@^16.2.13": + version "16.2.13" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.13.tgz#126c8b7441b159d6234610a48de77b6066f1823f" + integrity sha512-8JQCjdeAidptSsOcRWk2iTm9wCcwn9l+kRG6k5bzUacrnm1ezV4forq0kWjUih/tumAeoG+OspOvQEbbRucBTw== dependencies: "@types/node" "*" "@types/parse5" "*" @@ -27757,10 +27757,10 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@4.3.5, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.3.5, typescript@~4.4.2: - version "4.3.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" - integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== +typescript@4.5.3, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.3.5, typescript@~4.4.2: + version "4.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c" + integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ== ua-parser-js@^0.7.18: version "0.7.24"