From 78fe96dacffee27c9b9667eae10ebcd81c3ceab6 Mon Sep 17 00:00:00 2001 From: Graham Langford <30706330+grahamlangford@users.noreply.github.com> Date: Mon, 29 Apr 2024 19:11:27 -0500 Subject: [PATCH] Further strict null checks (#8371) * getToken/refreshToken * src/background/requests.ts * src/contentScript/pageEditor/elementPicker.ts * src/background/partnerIntegrations.ts * whoops * cleanup * fix widget and getScopeAndId * auto-add * src/extensionConsole/pages/mods/GetStartedView.tsx * src/mods/useModViewItems.tsx * test memo compare dependencies * fix scopeAndId tests * autosuggest * src/background/backgroundPlatform.ts * src/background/restrictUnauthenticatedUrlAccess.ts * src/bricks/effects/insertHtml.ts * ./bricks/effects/runSubTour.ts * ./bricks/effects/scrollIntoView.ts * src/bricks/transformers/controlFlow/WithAsyncModVariable.ts * mod state / variable context * src/bricks/transformers/RunMetadataTransformer.ts * src/bricks/transformers/splitText.ts * src/components/fields/schemaFields/widgets/varPopup/useTreeRow.ts * src/components/walkthroughModal/WalkthroughModalApp.tsx * src/extensionConsole/pages/brickEditor/BrickHistory.tsx * fix test * src/extensionConsole/pages/mods/utils/exportBlueprint.ts * src/extensionConsole/pages/mods/utils/exportBlueprint.ts * src/pageScript/elementInfo.ts * src/sidebar/LoginPanel.tsx * src/testUtils/factories/authFactories.ts * src/bricks/effects/attachAutocomplete.ts * more bricks * fix test * src/components/fields/schemaFields/fieldTestUtils.ts * add a bunch more * the rest * cleanup * fix lint * wip * remove file * remove logs * fix factory * update counts * extensionPagePlatform * partnerIntegrations * update counts * finding cycles * documenting cycle * move starterbricks into separate folders * extract shared types from contextmenu * migrate shared types for menuItemExtension * migrate panel types; migrate more contextMenu types * migrate more menuitem types * migrate quickbar types * migrate quickbar provider types * migrate sidebar types * migrate tour types * update file paths * auto-add * fix types * auto-add * cleanup * more contentScript messenger migrations * selectElement * insertPanel * insertButton * move insertButton to strict registration * eliminate cycle * auto-add * migrate more registration methods * auto-add * update counts * remove comments * address pr comments --------- Co-authored-by: Ben Loe --- src/background/messenger/api.ts | 13 --- src/background/messenger/registration.ts | 27 +------ src/background/messenger/strict/api.ts | 12 +++ .../messenger/strict/registration.ts | 19 +++++ .../transformers/extensionDiagnostics.ts | 2 +- src/contentScript/contentScriptCore.ts | 2 +- src/contentScript/messenger/api.ts | 3 - src/contentScript/messenger/registration.ts | 14 +--- src/contentScript/messenger/strict/api.ts | 3 + .../messenger/strict/registration.ts | 6 ++ src/contentScript/pageEditor/insertButton.tsx | 13 ++- src/contentScript/pageEditor/insertPanel.tsx | 4 + src/contentScript/performanceMonitoring.ts | 2 +- src/extensionConsole/options.tsx | 2 +- .../pages/mods/ModsPageContent.tsx | 8 +- .../pages/mods/gridView/GridView.tsx | 2 +- .../pages/mods/listView/ListView.tsx | 2 +- .../pages/mods/modsPageTypes.ts | 25 ++++++ src/pageEditor/starterBricks/menuItem.ts | 2 +- src/pageEditor/starterBricks/panel.ts | 2 +- .../pipelineTests/deploymentAlert.test.ts | 2 +- src/runtime/reducePipeline.ts | 3 +- src/tsconfig.strictNullChecks.json | 11 ++- src/utils/inference/markupInference.ts | 81 ++++++++++++------- 24 files changed, 158 insertions(+), 102 deletions(-) create mode 100644 src/extensionConsole/pages/mods/modsPageTypes.ts diff --git a/src/background/messenger/api.ts b/src/background/messenger/api.ts index b4bc3b069c..1ea5bd88dd 100644 --- a/src/background/messenger/api.ts +++ b/src/background/messenger/api.ts @@ -52,22 +52,9 @@ export const contextMenus = { preload: getMethod("PRELOAD_CONTEXT_MENUS", bg), }; -// Use this instead: `import reportError from "@/telemetry/reportError"` -// export const recordError = getNotifier("RECORD_ERROR", bg); - -export const initTelemetry = getNotifier("INIT_TELEMETRY", bg); -export const sendDeploymentAlert = getNotifier("SEND_DEPLOYMENT_ALERT", bg); - export const getUserData = getMethod("GET_USER_DATA", bg); export const installStarterBlueprints = getMethod( "INSTALL_STARTER_BLUEPRINTS", bg, ); - -export const ping = getMethod("PING", bg); - -export const collectPerformanceDiagnostics = getMethod( - "COLLECT_PERFORMANCE_DIAGNOSTICS", - bg, -); diff --git a/src/background/messenger/registration.ts b/src/background/messenger/registration.ts index 77b9c5ebcf..da03082d72 100644 --- a/src/background/messenger/registration.ts +++ b/src/background/messenger/registration.ts @@ -28,7 +28,7 @@ import { ensureContextMenu, preloadContextMenus, uninstallContextMenu, -} from "@/background/contextMenus"; // 205 strictNullCheck errors +} from "@/background/contextMenus"; // 201 strictNullCheck errors import { requestRunInAllFrames, requestRunInOtherTabs, @@ -36,15 +36,8 @@ import { requestRunInTarget, requestRunInTop, } from "@/background/executor"; // Depends on contentScript/messenger to pass strictNullCheck -import { removeExtensionForEveryTab } from "@/background/removeExtensionForEveryTab"; // 207 strictNullCheck errors -import { debouncedActivateStarterMods as installStarterBlueprints } from "@/background/starterMods"; // 211 strictNullCheck errors -import { - collectPerformanceDiagnostics, - initTelemetry, - pong, - recordEvent, - sendDeploymentAlert, -} from "@/background/telemetry"; // Depends on contentScript/messenger to pass strictNullCheck +import { removeExtensionForEveryTab } from "@/background/removeExtensionForEveryTab"; // 203 strictNullCheck errors +import { debouncedActivateStarterMods as installStarterBlueprints } from "@/background/starterMods"; // 209 strictNullCheck errors import { setCopilotProcessData } from "@/background/partnerHandlers"; // Depends on contentScript/messenger to pass strictNullCheck @@ -60,9 +53,6 @@ declare global { INSTALL_STARTER_BLUEPRINTS: typeof installStarterBlueprints; - PING: typeof pong; - COLLECT_PERFORMANCE_DIAGNOSTICS: typeof collectPerformanceDiagnostics; - REMOVE_EXTENSION_EVERY_TAB: typeof removeExtensionForEveryTab; REQUEST_RUN_IN_OPENER: typeof requestRunInOpener; @@ -70,10 +60,6 @@ declare global { REQUEST_RUN_IN_TOP: typeof requestRunInTop; REQUEST_RUN_IN_OTHER_TABS: typeof requestRunInOtherTabs; REQUEST_RUN_IN_ALL_FRAMES: typeof requestRunInAllFrames; - - RECORD_EVENT: typeof recordEvent; - INIT_TELEMETRY: typeof initTelemetry; - SEND_DEPLOYMENT_ALERT: typeof sendDeploymentAlert; } } @@ -87,9 +73,6 @@ export default function registerMessenger(): void { UNINSTALL_CONTEXT_MENU: uninstallContextMenu, ENSURE_CONTEXT_MENU: ensureContextMenu, - PING: pong, - COLLECT_PERFORMANCE_DIAGNOSTICS: collectPerformanceDiagnostics, - REMOVE_EXTENSION_EVERY_TAB: removeExtensionForEveryTab, REQUEST_RUN_IN_OPENER: requestRunInOpener, @@ -97,9 +80,5 @@ export default function registerMessenger(): void { REQUEST_RUN_IN_TOP: requestRunInTop, REQUEST_RUN_IN_OTHER_TABS: requestRunInOtherTabs, REQUEST_RUN_IN_ALL_FRAMES: requestRunInAllFrames, - - RECORD_EVENT: recordEvent, - INIT_TELEMETRY: initTelemetry, - SEND_DEPLOYMENT_ALERT: sendDeploymentAlert, }); } diff --git a/src/background/messenger/strict/api.ts b/src/background/messenger/strict/api.ts index 67c4724699..43ca08887b 100644 --- a/src/background/messenger/strict/api.ts +++ b/src/background/messenger/strict/api.ts @@ -111,3 +111,15 @@ export const performConfiguredRequestInBackground = getMethod( export const getPartnerPrincipals = getMethod("GET_PARTNER_PRINCIPALS", bg); export const launchAuthIntegration = getMethod("LAUNCH_AUTH_INTEGRATION", bg); + +export const ping = getMethod("PING", bg); +export const collectPerformanceDiagnostics = getMethod( + "COLLECT_PERFORMANCE_DIAGNOSTICS", + bg, +); + +// Use this instead: `import reportError from "@/telemetry/reportError"` +// export const recordError = getNotifier("RECORD_ERROR", bg); + +export const initTelemetry = getNotifier("INIT_TELEMETRY", bg); +export const sendDeploymentAlert = getNotifier("SEND_DEPLOYMENT_ALERT", bg); diff --git a/src/background/messenger/strict/registration.ts b/src/background/messenger/strict/registration.ts index add812bf6e..6c15f69831 100644 --- a/src/background/messenger/strict/registration.ts +++ b/src/background/messenger/strict/registration.ts @@ -57,6 +57,13 @@ import { launchAuthIntegration, } from "@/background/partnerIntegrations"; import { getAvailableVersion } from "@/background/installer"; +import { + collectPerformanceDiagnostics, + initTelemetry, + pong, + recordEvent, + sendDeploymentAlert, +} from "@/background/telemetry"; expectContext("background"); @@ -110,6 +117,12 @@ declare global { LAUNCH_AUTH_INTEGRATION: typeof launchAuthIntegration; GET_AVAILABLE_VERSION: typeof getAvailableVersion; + + PING: typeof pong; + COLLECT_PERFORMANCE_DIAGNOSTICS: typeof collectPerformanceDiagnostics; + RECORD_EVENT: typeof recordEvent; + INIT_TELEMETRY: typeof initTelemetry; + SEND_DEPLOYMENT_ALERT: typeof sendDeploymentAlert; } } @@ -163,5 +176,11 @@ export default function registerMessenger(): void { LAUNCH_AUTH_INTEGRATION: launchAuthIntegration, GET_AVAILABLE_VERSION: getAvailableVersion, + + PING: pong, + COLLECT_PERFORMANCE_DIAGNOSTICS: collectPerformanceDiagnostics, + RECORD_EVENT: recordEvent, + INIT_TELEMETRY: initTelemetry, + SEND_DEPLOYMENT_ALERT: sendDeploymentAlert, }); } diff --git a/src/bricks/transformers/extensionDiagnostics.ts b/src/bricks/transformers/extensionDiagnostics.ts index e313d6b551..2686403ee4 100644 --- a/src/bricks/transformers/extensionDiagnostics.ts +++ b/src/bricks/transformers/extensionDiagnostics.ts @@ -18,7 +18,7 @@ import { TransformerABC } from "@/types/bricks/transformerTypes"; import { type Schema } from "@/types/schemaTypes"; import { getDiagnostics as collectFrameDiagnostics } from "@/contentScript/performanceMonitoring"; -import { collectPerformanceDiagnostics as collectExtensionDiagnostics } from "@/background/messenger/api"; +import { collectPerformanceDiagnostics as collectExtensionDiagnostics } from "@/background/messenger/strict/api"; import { propertiesToSchema } from "@/utils/schemaUtils"; class ExtensionDiagnostics extends TransformerABC { diff --git a/src/contentScript/contentScriptCore.ts b/src/contentScript/contentScriptCore.ts index f5fc557de9..610caa7cc5 100644 --- a/src/contentScript/contentScriptCore.ts +++ b/src/contentScript/contentScriptCore.ts @@ -28,7 +28,7 @@ import registerBuiltinBricks from "@/bricks/registerBuiltinBricks"; import registerContribBlocks from "@/contrib/registerContribBlocks"; import brickRegistry from "@/bricks/registry"; import { initNavigation } from "@/contentScript/lifecycle"; -import { initTelemetry } from "@/background/messenger/api"; +import { initTelemetry } from "@/background/messenger/strict/api"; import { initToaster } from "@/utils/notify"; import { initPartnerIntegrations } from "@/contentScript/partnerIntegrations"; import { diff --git a/src/contentScript/messenger/api.ts b/src/contentScript/messenger/api.ts index 2fa80b01fc..f854cf8724 100644 --- a/src/contentScript/messenger/api.ts +++ b/src/contentScript/messenger/api.ts @@ -42,9 +42,6 @@ export const removeInstalledExtension = getNotifier( export const resetTab = getNotifier("RESET_TAB"); export const toggleQuickBar = getMethod("TOGGLE_QUICK_BAR"); -export const insertPanel = getMethod("INSERT_PANEL"); -export const insertButton = getMethod("INSERT_BUTTON"); - export const runBlock = getMethod("RUN_SINGLE_BLOCK"); export const runRendererBlock = getMethod("RUN_RENDERER_BLOCK"); diff --git a/src/contentScript/messenger/registration.ts b/src/contentScript/messenger/registration.ts index 56f15ce671..5747e61237 100644 --- a/src/contentScript/messenger/registration.ts +++ b/src/contentScript/messenger/registration.ts @@ -30,21 +30,19 @@ import { queueReactivateTab, reactivateTab, removePersistedExtension, -} from "@/contentScript/lifecycle"; // 203 strictNullCheck errors -import { insertPanel } from "@/contentScript/pageEditor/insertPanel"; // 31 strictNullCheck errors -import { insertButton } from "@/contentScript/pageEditor/insertButton"; // 37 strictNullCheck errors +} from "@/contentScript/lifecycle"; // 202 strictNullCheck errors import { clearDynamicElements, disableOverlay, enableOverlay, runExtensionPointReader, updateDynamicElement, -} from "@/contentScript/pageEditor/dynamic"; // 206 strictNullCheck errors +} from "@/contentScript/pageEditor/dynamic"; // 205 strictNullCheck errors import { runBlockPreview, resetTab, runRendererBlock, -} from "@/contentScript/pageEditor"; // 208 strictNullCheck errors +} from "@/contentScript/pageEditor"; // 207 strictNullCheck errors import { runBrick } from "@/contentScript/executor"; // Depends on background/messenger to pass strictNullCheck import { runHeadlessPipeline, @@ -63,9 +61,6 @@ declare global { REMOVE_INSTALLED_EXTENSION: typeof removePersistedExtension; RESET_TAB: typeof resetTab; - INSERT_PANEL: typeof insertPanel; - INSERT_BUTTON: typeof insertButton; - RUN_SINGLE_BLOCK: typeof runBlockPreview; RUN_RENDERER_BLOCK: typeof runRendererBlock; @@ -96,9 +91,6 @@ export default function registerMessenger(): void { REMOVE_INSTALLED_EXTENSION: removePersistedExtension, RESET_TAB: resetTab, - INSERT_PANEL: insertPanel, - INSERT_BUTTON: insertButton, - RUN_SINGLE_BLOCK: runBlockPreview, RUN_RENDERER_BLOCK: runRendererBlock, diff --git a/src/contentScript/messenger/strict/api.ts b/src/contentScript/messenger/strict/api.ts index c4b6379827..d730063f4d 100644 --- a/src/contentScript/messenger/strict/api.ts +++ b/src/contentScript/messenger/strict/api.ts @@ -61,3 +61,6 @@ export const reloadMarketplaceEnhancements = getMethod( ); export const getAttributeExamples = getMethod("GET_ATTRIBUTE_EXAMPLES"); export const selectElement = getMethod("SELECT_ELEMENT"); + +export const insertPanel = getMethod("INSERT_PANEL"); +export const insertButton = getMethod("INSERT_BUTTON"); diff --git a/src/contentScript/messenger/strict/registration.ts b/src/contentScript/messenger/strict/registration.ts index 7553470eac..b03edd3e38 100644 --- a/src/contentScript/messenger/strict/registration.ts +++ b/src/contentScript/messenger/strict/registration.ts @@ -49,6 +49,8 @@ import { cancelSelect } from "@/contentScript/pageEditor/elementPicker"; import { reloadActivationEnhancements } from "@/contentScript/loadActivationEnhancementsCore"; import { getAttributeExamples } from "@/contentScript/pageEditor/elementInformation"; import selectElement from "@/contentScript/pageEditor/selectElement"; +import { insertPanel } from "@/contentScript/pageEditor/insertPanel"; +import { insertButton } from "@/contentScript/pageEditor/insertButton"; declare global { interface MessengerMethods { @@ -81,6 +83,8 @@ declare global { RELOAD_MARKETPLACE_ENHANCEMENTS: typeof reloadActivationEnhancements; GET_ATTRIBUTE_EXAMPLES: typeof getAttributeExamples; SELECT_ELEMENT: typeof selectElement; + INSERT_PANEL: typeof insertPanel; + INSERT_BUTTON: typeof insertButton; } } export default function registerMessenger(): void { @@ -114,5 +118,7 @@ export default function registerMessenger(): void { RELOAD_MARKETPLACE_ENHANCEMENTS: reloadActivationEnhancements, GET_ATTRIBUTE_EXAMPLES: getAttributeExamples, SELECT_ELEMENT: selectElement, + INSERT_PANEL: insertPanel, + INSERT_BUTTON: insertButton, }); } diff --git a/src/contentScript/pageEditor/insertButton.tsx b/src/contentScript/pageEditor/insertButton.tsx index 9ea7dce263..feb15b6291 100644 --- a/src/contentScript/pageEditor/insertButton.tsx +++ b/src/contentScript/pageEditor/insertButton.tsx @@ -36,7 +36,7 @@ export async function insertButton( "./beautify" ); - let selected; + let selected: HTMLElement[]; if (useNewFilter) { const { elements } = await userSelectElement({ filter: `:is(a, button):not(${PRIVATE_ATTRIBUTES_SELECTOR})`, @@ -52,14 +52,20 @@ export async function insertButton( // if the parent is BUTTON, the user probably just selected the wrong thing if ( selected.length === 1 && - ["A", "BUTTON"].includes(selected[0].parentElement?.tagName) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check + ["A", "BUTTON"].includes(selected[0]!.parentElement?.tagName ?? "") ) { - selected = [selected[0].parentElement]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- verified above + selected = [selected[0]!.parentElement!]; } } const { container, selectors: containerSelectors } = findContainer(selected); + if (!containerSelectors[0]) { + throw new Error("No selector found for the button"); + } + console.debug("insertButton", { container, selected }); const element: ButtonSelectionResult = { @@ -75,7 +81,6 @@ export async function insertButton( wrap_line_length: 80, wrap_attributes: "force", }), - shadowDOM: null, position: "append", }, containerInfo: await pageScript.getElementInfo({ diff --git a/src/contentScript/pageEditor/insertPanel.tsx b/src/contentScript/pageEditor/insertPanel.tsx index 41c6c93075..6602525605 100644 --- a/src/contentScript/pageEditor/insertPanel.tsx +++ b/src/contentScript/pageEditor/insertPanel.tsx @@ -36,6 +36,10 @@ export async function insertPanel(): Promise { const { elements: selected } = await userSelectElement(); const { container, selectors } = findContainer(selected); + if (!selectors[0]) { + throw new Error("No selector found for the panel"); + } + return { uuid: uuidv4(), panel: { diff --git a/src/contentScript/performanceMonitoring.ts b/src/contentScript/performanceMonitoring.ts index 3313536497..f61c024a42 100644 --- a/src/contentScript/performanceMonitoring.ts +++ b/src/contentScript/performanceMonitoring.ts @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -import { ping } from "@/background/messenger/api"; +import { ping } from "@/background/messenger/strict/api"; import { isContextInvalidatedError } from "@/errors/contextInvalidated"; import { isLoadedInIframe } from "@/utils/iframeUtils"; import { getSettingsState } from "@/store/settings/settingsStorage"; diff --git a/src/extensionConsole/options.tsx b/src/extensionConsole/options.tsx index 69dfdd1067..572a603441 100644 --- a/src/extensionConsole/options.tsx +++ b/src/extensionConsole/options.tsx @@ -27,7 +27,7 @@ import { render } from "react-dom"; import React from "react"; import App from "@/extensionConsole/App"; import { initToaster } from "@/utils/notify"; -import { initTelemetry } from "@/background/messenger/api"; +import { initTelemetry } from "@/background/messenger/strict/api"; import { initMessengerLogging } from "@/development/messengerLogging"; import { initPerformanceMonitoring } from "@/telemetry/performance"; import { initRuntimeLogging } from "@/development/runtimeLogging"; diff --git a/src/extensionConsole/pages/mods/ModsPageContent.tsx b/src/extensionConsole/pages/mods/ModsPageContent.tsx index e8557c6991..085189afcd 100644 --- a/src/extensionConsole/pages/mods/ModsPageContent.tsx +++ b/src/extensionConsole/pages/mods/ModsPageContent.tsx @@ -27,14 +27,8 @@ import OnboardingView from "@/extensionConsole/pages/mods/onboardingView/Onboard import EmptyView from "@/extensionConsole/pages/mods/emptyView/EmptyView"; import GetStartedView from "@/extensionConsole/pages/mods/GetStartedView"; import useOnboarding from "@/extensionConsole/pages/mods/onboardingView/useOnboarding"; -import { type TableInstance } from "react-table"; -import { type ModViewItem } from "@/types/modTypes"; +import { type ModsPageContentProps } from "@/extensionConsole/pages/mods/modsPageTypes"; -export type ModsPageContentProps = { - tableInstance: TableInstance; - width: number; - height: number; -}; const ModsPageContent: React.VoidFunctionComponent = ({ tableInstance, width, diff --git a/src/extensionConsole/pages/mods/gridView/GridView.tsx b/src/extensionConsole/pages/mods/gridView/GridView.tsx index f596f4eca2..32764ae687 100644 --- a/src/extensionConsole/pages/mods/gridView/GridView.tsx +++ b/src/extensionConsole/pages/mods/gridView/GridView.tsx @@ -32,7 +32,7 @@ import ListGroupHeader from "@/extensionConsole/pages/mods/listView/ListGroupHea import { uuidv4 } from "@/types/helpers"; import { getUniqueId } from "@/utils/modUtils"; import GridCardErrorBoundary from "@/extensionConsole/pages/mods/gridView/GridCardErrorBoundary"; -import { type ModsPageContentProps } from "@/extensionConsole/pages/mods/ModsPageContent"; +import { type ModsPageContentProps } from "@/extensionConsole/pages/mods/modsPageTypes"; /** * Expands `react-table` rows recursively in chunks of diff --git a/src/extensionConsole/pages/mods/listView/ListView.tsx b/src/extensionConsole/pages/mods/listView/ListView.tsx index 2cf883f04d..1c25dcd424 100644 --- a/src/extensionConsole/pages/mods/listView/ListView.tsx +++ b/src/extensionConsole/pages/mods/listView/ListView.tsx @@ -22,7 +22,7 @@ import { VariableSizeList as List } from "react-window"; import ListGroupHeader from "@/extensionConsole/pages/mods/listView/ListGroupHeader"; import { uuidv4 } from "@/types/helpers"; import ListItemErrorBoundary from "@/extensionConsole/pages/mods/listView/ListItemErrorBoundary"; -import { type ModsPageContentProps } from "@/extensionConsole/pages/mods/ModsPageContent"; +import { type ModsPageContentProps } from "@/extensionConsole/pages/mods/modsPageTypes"; const ROW_HEIGHT_PX = 90; const HEADER_ROW_HEIGHT_PX = 43; diff --git a/src/extensionConsole/pages/mods/modsPageTypes.ts b/src/extensionConsole/pages/mods/modsPageTypes.ts new file mode 100644 index 0000000000..9a85ddd44a --- /dev/null +++ b/src/extensionConsole/pages/mods/modsPageTypes.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 PixieBrix, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { type ModViewItem } from "@/types/modTypes"; +import { type TableInstance } from "react-table"; + +export type ModsPageContentProps = { + tableInstance: TableInstance; + width: number; + height: number; +}; diff --git a/src/pageEditor/starterBricks/menuItem.ts b/src/pageEditor/starterBricks/menuItem.ts index f9aec3c088..542687f761 100644 --- a/src/pageEditor/starterBricks/menuItem.ts +++ b/src/pageEditor/starterBricks/menuItem.ts @@ -38,7 +38,7 @@ import { getDomain } from "@/permissions/patterns"; import { faMousePointer } from "@fortawesome/free-solid-svg-icons"; import { type ElementConfig } from "@/pageEditor/starterBricks/elementConfig"; import MenuItemConfiguration from "@/pageEditor/tabs/menuItem/MenuItemConfiguration"; -import { insertButton } from "@/contentScript/messenger/api"; +import { insertButton } from "@/contentScript/messenger/strict/api"; import { type ButtonDefinition, type ButtonSelectionResult, diff --git a/src/pageEditor/starterBricks/panel.ts b/src/pageEditor/starterBricks/panel.ts index e74c445312..477c46d3e7 100644 --- a/src/pageEditor/starterBricks/panel.ts +++ b/src/pageEditor/starterBricks/panel.ts @@ -37,7 +37,7 @@ import { getDomain } from "@/permissions/patterns"; import { faWindowMaximize } from "@fortawesome/free-solid-svg-icons"; import { type ElementConfig } from "@/pageEditor/starterBricks/elementConfig"; import PanelConfiguration from "@/pageEditor/tabs/panel/PanelConfiguration"; -import { insertPanel } from "@/contentScript/messenger/api"; +import { insertPanel } from "@/contentScript/messenger/strict/api"; import { type DynamicDefinition, type PanelSelectionResult, diff --git a/src/runtime/pipelineTests/deploymentAlert.test.ts b/src/runtime/pipelineTests/deploymentAlert.test.ts index b0ec110bbc..a86a235092 100644 --- a/src/runtime/pipelineTests/deploymentAlert.test.ts +++ b/src/runtime/pipelineTests/deploymentAlert.test.ts @@ -24,7 +24,7 @@ import { testOptions, throwBrick, } from "./pipelineTestHelpers"; -import { sendDeploymentAlert } from "@/background/messenger/api"; +import { sendDeploymentAlert } from "@/background/messenger/strict/api"; import { type ApiVersion } from "@/types/runtimeTypes"; import { uuidv4 } from "@/types/helpers"; import ConsoleLogger from "@/utils/ConsoleLogger"; diff --git a/src/runtime/reducePipeline.ts b/src/runtime/reducePipeline.ts index 45821f908c..e6fd44ef58 100644 --- a/src/runtime/reducePipeline.ts +++ b/src/runtime/reducePipeline.ts @@ -17,7 +17,7 @@ import { type Logger } from "@/types/loggerTypes"; import { castArray, isPlainObject, once } from "lodash"; -import { requestRun, sendDeploymentAlert } from "@/background/messenger/api"; +import { requestRun } from "@/background/messenger/api"; import { hideNotification, showNotification } from "@/utils/notify"; import { serializeError } from "serialize-error"; import { HeadlessModeError } from "@/bricks/errors"; @@ -73,6 +73,7 @@ import type { RegistryId, RegistryProtocol } from "@/types/registryTypes"; import type { Brick } from "@/types/brickTypes"; import getType from "@/runtime/getType"; import { getPlatform } from "@/platform/platformContext"; +import { sendDeploymentAlert } from "@/background/messenger/strict/api"; // Introduce a layer of indirection to avoid cyclical dependency between runtime and registry // eslint-disable-next-line local-rules/persistBackgroundData -- Static diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index cc38bdf21b..e07f159464 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -78,7 +78,7 @@ "./background/dataStore.ts", "./background/externalProtocol.ts", "./background/initTheme.ts", - "./background/installer", + "./background/installer.ts", "./background/locator.ts", "./background/messenger/strict/api.ts", "./background/messenger/strict/registration.ts", @@ -94,6 +94,7 @@ "./background/setToolbarIconFromTheme.ts", "./background/sidePanel.ts", "./background/tabs.ts", + "./background/telemetry.ts", "./background/toolbarBadge.ts", "./background/walkthroughModalTrigger.ts", "./bricks/available.ts", @@ -188,6 +189,7 @@ "./bricks/transformers/encode.ts", "./bricks/transformers/ephemeralForm/EphemeralFormContent.tsx", "./bricks/transformers/ephemeralForm/formTransformer.ts", + "./bricks/transformers/extensionDiagnostics.ts", "./bricks/transformers/httpGet.ts", "./bricks/transformers/javascript.ts", "./bricks/transformers/jq.ts", @@ -392,8 +394,12 @@ "./contentScript/pageEditor/beautify.ts", "./contentScript/pageEditor/elementInformation.ts", "./contentScript/pageEditor/elementPicker.ts", + "./contentScript/pageEditor/insertButton", + "./contentScript/pageEditor/insertPanel", + "./contentScript/pageEditor/selectElement.ts", "./contentScript/pageEditor/types.ts", "./contentScript/partnerIntegrations.ts", + "./contentScript/performanceMonitoring.ts", "./contentScript/popoverDom.ts", "./contentScript/ready.ts", "./contentScript/setExtensionIdInApp.ts", @@ -503,6 +509,7 @@ "./extensionConsole/Navbar.tsx", "./extensionConsole/Sidebar.tsx", "./extensionConsole/SidebarLink.tsx", + "./extensionConsole/components/IDBErrorDisplay.tsx", "./extensionConsole/components/ServiceFieldError.tsx", "./extensionConsole/pages/InvitationBanner.tsx", "./extensionConsole/pages/UpdateBanner.tsx", @@ -537,6 +544,7 @@ "./extensionConsole/pages/mods/modals/shareModals/useSortOrganizations.ts", "./extensionConsole/pages/mods/modsPageSelectors.ts", "./extensionConsole/pages/mods/modsPageSlice.ts", + "./extensionConsole/pages/mods/modsPageTypes.ts", "./extensionConsole/pages/mods/utils/exportBlueprint.ts", "./extensionConsole/pages/onboarding/DefaultSetupCard.tsx", "./extensionConsole/pages/onboarding/partner/partnerOnboardingUtils.ts", @@ -545,6 +553,7 @@ "./extensionConsole/pages/settings/LoggingSettings.tsx", "./extensionConsole/pages/settings/PrivacySettings.tsx", "./extensionConsole/pages/settings/SettingToggle.tsx", + "./extensionConsole/pages/settings/StorageSettings.tsx", "./extensionConsole/pages/useRegistryIdParam.ts", "./extensionConsole/pages/workshop/workshopTypes.ts", "./extensionConsole/pages/workshop/workshopUtils.ts", diff --git a/src/utils/inference/markupInference.ts b/src/utils/inference/markupInference.ts index 0118ee8770..e0d6c4a0ac 100644 --- a/src/utils/inference/markupInference.ts +++ b/src/utils/inference/markupInference.ts @@ -21,10 +21,11 @@ import { PIXIEBRIX_DATA_ATTR, } from "@/domConstants"; import { BUTTON_TAGS, UNIQUE_ATTRIBUTES } from "./selectorInference"; -import { intersection, unary, uniq } from "lodash"; +import { compact, intersection, unary, uniq } from "lodash"; import { BusinessError } from "@/errors/businessErrors"; import { isNullOrBlank, matchesAnyPattern } from "@/utils/stringUtils"; import { mostCommonElement } from "@/utils/arrayUtils"; +import { assertNotNullish } from "@/utils/nullishUtils"; const BUTTON_SELECTORS: string[] = ["[role='button']"]; const ICON_TAGS = ["svg", "img"]; @@ -111,7 +112,8 @@ function commonAttribute(items: Element[], attribute: string) { const classNames = attributeValues.map((x) => (x ? x.split(" ") : [])); unfiltered = intersection(...classNames); } else if (uniq(attributeValues).length === 1) { - unfiltered = attributeValues[0].split(" "); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check above + unfiltered = attributeValues[0]!.split(" "); } else { // Single attribute doesn't match return null; @@ -127,7 +129,8 @@ function commonAttribute(items: Element[], attribute: string) { } function setCommonAttributes(common: Element, items: Element[]) { - const { attributes } = items[0]; + const { attributes } = items[0] ?? {}; + assertNotNullish(attributes, "No attributes found"); // Find the common attributes between the elements for (const { name } of attributes) { @@ -155,7 +158,8 @@ function setCommonAttributes(common: Element, items: Element[]) { function ignoreDivChildNode(node: Node): boolean { return ( NON_RENDERED_NODES.includes(node.nodeType) || - (node.nodeType === Node.TEXT_NODE && node.textContent.trim() === "") + (node.nodeType === Node.TEXT_NODE && + (node.textContent == null || node.textContent.trim() === "")) ); } @@ -175,7 +179,8 @@ function removeUnstyledLayout(node: Node): Node | null { isNullOrBlank(element.className) && nonEmptyChildren.length === 1 ) { - return removeUnstyledLayout(nonEmptyChildren[0]); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check above + return removeUnstyledLayout(nonEmptyChildren[0]!); } const clone = node.cloneNode(false) as Element; @@ -205,6 +210,7 @@ function commonButtonStructure( let currentCaptioned = captioned; const proto = items[0]; + assertNotNullish(proto, "No elements provided"); if (ICON_TAGS.includes(proto.tagName.toLowerCase())) { // TODO: need to provide a way of adding additional classes to the button. E.g. some classes @@ -244,10 +250,11 @@ function commonButtonStructure( } else if ( protoChild.nodeType === Node.ELEMENT_NODE && items.every((x) => elementIndex < x.children.length) && - uniq(items.map((x) => x.children.item(elementIndex).tagName)).length === 1 + uniq(items.map((x) => x.children.item(elementIndex)?.tagName)).length === + 1 ) { - const children = items.map((element) => - element.children.item(elementIndex), + const children = compact( + items.map((element) => element.children.item(elementIndex)), ); const [child, childCaptioned] = commonButtonStructure( @@ -297,6 +304,8 @@ function commonPanelStructure( }: PanelStructureState = {} as PanelStructureState, ): [Element | string, PanelStructureState] { const proto = $items.get(0); + assertNotNullish(proto, "No elements provided"); + inHeader ||= HEADER_TAGS.includes(proto.tagName.toLowerCase()); const common = newElement(proto.tagName); @@ -304,16 +313,16 @@ function commonPanelStructure( setCommonAttributes(common, $items.get()); // Heuristic that assumes tag matches from the beginning - for (let i = 0; i < proto.children.length; i++) { + for (let i = 0; i < (proto.children.length ?? 0); i++) { const protoChild = proto.children.item(i) as HTMLElement; const $protoChild = $(protoChild); if ( $items.toArray().every((x) => i < x.children.length) && - uniq($items.toArray().map((x) => x.children.item(i).tagName)).length === + uniq($items.toArray().map((x) => x.children.item(i)?.tagName)).length === 1 && (!headingInserted || - LAYOUT_TAGS.includes(proto.children.item(i).tagName.toLowerCase())) + LAYOUT_TAGS.includes(protoChild.tagName.toLowerCase())) ) { const $children = $items.map(function () { return this.children.item(i) as HTMLElement; @@ -336,7 +345,7 @@ function commonPanelStructure( } else if ( !inHeader && !bodyInserted && - !LAYOUT_TAGS.includes(proto.children.item(i).tagName.toLowerCase()) + !LAYOUT_TAGS.includes(protoChild.tagName.toLowerCase()) ) { common.append("{{{ body }}}"); bodyInserted = true; @@ -438,7 +447,9 @@ function commonButtonHTML(tag: string, items: Element[]): string { const elements = items .map(unary(removeUnstyledLayout)) - .filter((x): x is Element => x && x.nodeType === Node.ELEMENT_NODE); + .filter( + (x): x is Element => Boolean(x) && x?.nodeType === Node.ELEMENT_NODE, + ); const [common] = commonButtonStructure(elements); @@ -470,6 +481,9 @@ function inferSinglePanelHTML( ): string { const $container = $(container); const child = containerChildren($container, [selected])[0]; + + assertNotNullish(child, "Unable to find direct children of the container"); + const [$panel] = buildSinglePanelElement(child); return outerHTML($panel); } @@ -478,14 +492,20 @@ export function inferPanelHTML( container: HTMLElement, selected: HTMLElement[], ): string { + if (selected.length === 0) { + throw new Error("No selected element"); + } + const $container = $(container); if (selected.length > 1) { const children = containerChildren($container, selected); - return commonPanelHTML(selected[0].tagName, $(children)); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check above + return commonPanelHTML(selected[0]!.tagName, $(children)); } - return inferSinglePanelHTML(container, selected[0]); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check above + return inferSinglePanelHTML(container, selected[0]!); } export function inferButtonHTML( @@ -507,7 +527,8 @@ export function inferButtonHTML( return commonButtonHTML(tag, children); } - const element = selected[0]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion -- length check above + const element = selected[0]!; for (const buttonTag of [...BUTTON_SELECTORS, ...BUTTON_TAGS]) { const $items = $container.children(buttonTag); if ( @@ -540,21 +561,23 @@ function containerChildren( $container: JQuery, selected: HTMLElement[], ): HTMLElement[] { - return selected.map((element) => { - const exactMatch = $container.children().filter(function () { - return this === element; - }); + return compact( + selected.map((element) => { + const exactMatch = $container.children().filter(function () { + return this === element; + }); - if (exactMatch.length > 0) { - return exactMatch.get(0); - } + if (exactMatch.length > 0) { + return exactMatch.get(0); + } - const match = $container.children().has(element); + const match = $container.children().has(element); - if (match.length === 0) { - throw new Error("element not found in container"); - } + if (match.length === 0) { + throw new Error("element not found in container"); + } - return match.get(0); - }); + return match.get(0); + }), + ); }