diff --git a/package-lock.json b/package-lock.json index 7121734c3..70781d861 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35398,7 +35398,7 @@ "@deephaven/iris-grid": "^0.68.0", "@deephaven/jsapi-bootstrap": "^0.68.0", "@deephaven/jsapi-components": "^0.68.0", - "@deephaven/jsapi-types": "^0.67.0", + "@deephaven/jsapi-types": "1.0.0-dev0.33.2", "@deephaven/log": "^0.68.0", "@deephaven/plugin": "^0.68.0", "@deephaven/react-hooks": "^0.68.0", @@ -35796,12 +35796,9 @@ "integrity": "sha512-1f0ZsR7zpXGQFs6vyRovBUECUPg7tNYrzCuHA0iJCrTlJ0FfFDVcDg8uZxsH+11cERcAEs5xdSHXqpo/fM6dKQ==" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-types": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-0.67.0.tgz", - "integrity": "sha512-KOI6tI7NeFSDi3RbW2u75qH5qFoH81AJREOsZqVs0nSdoHuPXqvbwy/cpuh2bJdPLFAJ5fgzcuAw4nB8HQ1MkA==", - "engines": { - "node": ">=16" - } + "version": "1.0.0-dev0.33.2", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.33.2.tgz", + "integrity": "sha512-lTUlZtoPvvwMU5X4UFdtXIQKkKdarnBTJh9QdsMwP+WHa2IigsyMTS3lQhGrX9A8h8f6LCjfuCuChAUJS7d0Kg==" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-utils": { "version": "0.68.0", @@ -39767,7 +39764,7 @@ "@deephaven/iris-grid": "^0.68.0", "@deephaven/jsapi-bootstrap": "^0.68.0", "@deephaven/jsapi-components": "^0.68.0", - "@deephaven/jsapi-types": "^0.67.0", + "@deephaven/jsapi-types": "1.0.0-dev0.33.2", "@deephaven/log": "^0.68.0", "@deephaven/plugin": "^0.68.0", "@deephaven/react-hooks": "^0.68.0", @@ -40092,9 +40089,9 @@ } }, "@deephaven/jsapi-types": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-0.67.0.tgz", - "integrity": "sha512-KOI6tI7NeFSDi3RbW2u75qH5qFoH81AJREOsZqVs0nSdoHuPXqvbwy/cpuh2bJdPLFAJ5fgzcuAw4nB8HQ1MkA==" + "version": "1.0.0-dev0.33.2", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.33.2.tgz", + "integrity": "sha512-lTUlZtoPvvwMU5X4UFdtXIQKkKdarnBTJh9QdsMwP+WHa2IigsyMTS3lQhGrX9A8h8f6LCjfuCuChAUJS7d0Kg==" }, "@deephaven/jsapi-utils": { "version": "0.68.0", diff --git a/package.json b/package.json index dacf6f0b5..6a9b1dbdc 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "docker": "docker compose up deephaven-plugins --build", "start": "run-p \"start:packages -- {@}\" serve:plugins --", "build": "lerna run build --stream", + "watch:types": "tsc -p . --watch --emitDeclarationOnly false --noEmit", "serve:plugins": "vite", "start:packages": "lerna run start --stream", "test": "jest --watch --changedSince origin/main", diff --git a/plugins/ui/src/js/package.json b/plugins/ui/src/js/package.json index dc27083dd..6adb2b675 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -51,7 +51,7 @@ "@deephaven/iris-grid": "^0.68.0", "@deephaven/jsapi-bootstrap": "^0.68.0", "@deephaven/jsapi-components": "^0.68.0", - "@deephaven/jsapi-types": "^0.67.0", + "@deephaven/jsapi-types": "1.0.0-dev0.33.2", "@deephaven/log": "^0.68.0", "@deephaven/plugin": "^0.68.0", "@deephaven/react-hooks": "^0.68.0", diff --git a/plugins/ui/src/js/src/DashboardPlugin.tsx b/plugins/ui/src/js/src/DashboardPlugin.tsx index 33cad703e..c67ba4225 100644 --- a/plugins/ui/src/js/src/DashboardPlugin.tsx +++ b/plugins/ui/src/js/src/DashboardPlugin.tsx @@ -18,7 +18,7 @@ import { DeferredApiBootstrap, useObjectFetcher, } from '@deephaven/jsapi-bootstrap'; -import { Widget } from '@deephaven/jsapi-types'; +import { dh } from '@deephaven/jsapi-types'; import { ErrorBoundary } from '@deephaven/components'; import { useDebouncedCallback } from '@deephaven/react-hooks'; import styles from './styles.scss?inline'; @@ -89,7 +89,7 @@ export function DashboardPlugin( widgetId = shortid.generate(), widget, }: { - fetch: () => Promise; + fetch: () => Promise; widgetId: string; widget: WidgetDescriptor; }) => { @@ -115,11 +115,11 @@ export function DashboardPlugin( widget: WidgetDescriptor; dashboardId: string; }) => { - const { name: title = 'Untitled' } = widget; + const { name: title } = widget; log.debug('Emitting create dashboard event for', dashboardId, widget); emitCreateDashboard(layout.eventHub, { pluginId: PLUGIN_NAME, - title, + title: title ?? 'Untitled', data: { openWidgets: { [dashboardId]: { descriptor: widget } } }, }); }, @@ -131,7 +131,7 @@ export function DashboardPlugin( fetch, panelId: widgetId = shortid.generate(), widget, - }: PanelOpenEventDetail) => { + }: PanelOpenEventDetail) => { const { type } = widget; switch (type) { diff --git a/plugins/ui/src/js/src/elements/ElementUtils.test.tsx b/plugins/ui/src/js/src/elements/ElementUtils.test.tsx index 14223a112..fd9ce8416 100644 --- a/plugins/ui/src/js/src/elements/ElementUtils.test.tsx +++ b/plugins/ui/src/js/src/elements/ElementUtils.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Text } from '@adobe/react-spectrum'; -import type { WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import { TestUtils } from '@deephaven/utils'; import { ELEMENT_KEY, isPrimitive, wrapElementChildren } from './ElementUtils'; import ObjectView from './ObjectView'; @@ -25,13 +25,13 @@ describe('isPrimitive', () => { describe('wrapElementChildren', () => { const mock = { - exportedA1: createMockProxy({ + exportedA1: createMockProxy({ type: 'mock.exported.a', }), - exportedA2: createMockProxy({ + exportedA2: createMockProxy({ type: 'mock.exported.a', }), - exportedB1: createMockProxy({ + exportedB1: createMockProxy({ type: 'mock.exported.b', }), }; diff --git a/plugins/ui/src/js/src/elements/ElementUtils.tsx b/plugins/ui/src/js/src/elements/ElementUtils.tsx index 009a13331..3e6a28f42 100644 --- a/plugins/ui/src/js/src/elements/ElementUtils.tsx +++ b/plugins/ui/src/js/src/elements/ElementUtils.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Text } from '@adobe/react-spectrum'; -import type { WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import { ITEM_ELEMENT_NAME } from './ElementConstants'; import ObjectView from './ObjectView'; @@ -69,12 +69,12 @@ export function isCallableNode(obj: unknown): obj is CallableNode { return obj != null && typeof obj === 'object' && CALLABLE_KEY in obj; } -export function isExportedObject(obj: unknown): obj is WidgetExportedObject { +export function isExportedObject(obj: unknown): obj is dh.WidgetExportedObject { return ( obj != null && typeof obj === 'object' && - typeof (obj as WidgetExportedObject).fetch === 'function' && - typeof (obj as WidgetExportedObject).type === 'string' + typeof (obj as dh.WidgetExportedObject).fetch === 'function' && + typeof (obj as dh.WidgetExportedObject).type === 'string' ); } @@ -161,9 +161,9 @@ export function wrapElementChildren(element: ElementNode): ElementNode { // Derive child keys based on type + index of the occurrence of the type const typeMap = new Map(); - const getChildKey = (type: string): string => { - const typeCount = typeMap.get(type) ?? 0; - typeMap.set(type, typeCount + 1); + const getChildKey = (type: string | null | undefined): string => { + const typeCount = typeMap.get(String(type)) ?? 0; + typeMap.set(String(type), typeCount + 1); return `${type}-${typeCount}`; }; diff --git a/plugins/ui/src/js/src/elements/ObjectView.tsx b/plugins/ui/src/js/src/elements/ObjectView.tsx index 630110c89..7488401f1 100644 --- a/plugins/ui/src/js/src/elements/ObjectView.tsx +++ b/plugins/ui/src/js/src/elements/ObjectView.tsx @@ -1,11 +1,11 @@ import React, { useCallback, useMemo } from 'react'; import Log from '@deephaven/log'; import { isWidgetPlugin, usePlugins } from '@deephaven/plugin'; -import type { Widget, WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; const log = Log.module('@deephaven/js-plugin-ui/ObjectView'); -export type ObjectViewProps = { object: WidgetExportedObject }; +export type ObjectViewProps = { object: dh.WidgetExportedObject }; function ObjectView(props: ObjectViewProps) { const { object } = props; log.info('Object is', object); @@ -13,7 +13,7 @@ function ObjectView(props: ObjectViewProps) { const fetch = useCallback(async () => { // We re-export the object in case this object is used in multiple places or closed/opened multiple times const reexportedObject = await object.reexport(); - return reexportedObject.fetch() as Promise; + return reexportedObject.fetch() as Promise; }, [object]); const plugins = usePlugins(); @@ -22,7 +22,7 @@ function ObjectView(props: ObjectViewProps) { () => [...plugins.values()] .filter(isWidgetPlugin) - .find(p => [p.supportedTypes].flat().includes(object.type)), + .find(p => [p.supportedTypes].flat().includes(object.type as string)), [plugins, object.type] ); diff --git a/plugins/ui/src/js/src/elements/SpectrumElementView.tsx b/plugins/ui/src/js/src/elements/SpectrumElementView.tsx index a83ef2daf..5c03613ce 100644 --- a/plugins/ui/src/js/src/elements/SpectrumElementView.tsx +++ b/plugins/ui/src/js/src/elements/SpectrumElementView.tsx @@ -14,10 +14,15 @@ export function SpectrumElementView({ element, }: SpectrumElementViewProps): JSX.Element | null { const { [ELEMENT_KEY]: name, props = {} } = element; - const Component = getSpectrumComponent(name); + + const Component = getSpectrumComponent(name) as + | React.ComponentType + | undefined; + if (Component == null) { throw new Error(`Unknown Spectrum component ${name}`); } + return ( // eslint-disable-next-line react/jsx-props-no-spreading, @typescript-eslint/no-explicit-any diff --git a/plugins/ui/src/js/src/elements/UITable.tsx b/plugins/ui/src/js/src/elements/UITable.tsx index c8fd58fc6..9d901f4df 100644 --- a/plugins/ui/src/js/src/elements/UITable.tsx +++ b/plugins/ui/src/js/src/elements/UITable.tsx @@ -9,9 +9,9 @@ import { IrisGridUtils, } from '@deephaven/iris-grid'; import { useApi } from '@deephaven/jsapi-bootstrap'; -import type { Table } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; -import { getSettings } from '@deephaven/redux'; +import { getSettings, RootState } from '@deephaven/redux'; import { EMPTY_ARRAY } from '@deephaven/utils'; import { UITableProps } from './UITableUtils'; import UITableMouseHandler from './UITableMouseHandler'; @@ -33,9 +33,9 @@ function UITable({ }: UITableProps) { const dh = useApi(); const [model, setModel] = useState(); - const [columns, setColumns] = useState(); + const [columns, setColumns] = useState(); const utils = useMemo(() => new IrisGridUtils(dh), [dh]); - const settings = useSelector(getSettings); + const settings = useSelector(getSettings); const hydratedSorts = useMemo(() => { if (sorts !== undefined && columns !== undefined) { @@ -69,7 +69,7 @@ function UITable({ let isCancelled = false; async function loadModel() { const reexportedTable = await exportedTable.reexport(); - const newTable = (await reexportedTable.fetch()) as Table; + const newTable = (await reexportedTable.fetch()) as dh.Table; const newModel = await IrisGridModelFactory.makeModel(dh, newTable); if (!isCancelled) { setColumns(newTable.columns); diff --git a/plugins/ui/src/js/src/elements/UITableUtils.tsx b/plugins/ui/src/js/src/elements/UITableUtils.tsx index 4573c000c..b86dc7bb4 100644 --- a/plugins/ui/src/js/src/elements/UITableUtils.tsx +++ b/plugins/ui/src/js/src/elements/UITableUtils.tsx @@ -1,4 +1,4 @@ -import type { WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import { ColumnName, DehydratedSort, RowIndex } from '@deephaven/iris-grid'; import { ELEMENT_KEY, ElementNode, isElementNode } from './ElementUtils'; import { UITableElementName, UITABLE_ELEMENT_TYPE } from './ElementConstants'; @@ -19,7 +19,7 @@ export type ColumnIndex = number; export type RowDataMap = Record; export interface UITableProps { - table: WidgetExportedObject; + table: dh.WidgetExportedObject; onCellPress?: (cellIndex: [ColumnIndex, RowIndex], data: CellData) => void; onCellDoublePress?: ( cellIndex: [ColumnIndex, RowIndex], diff --git a/plugins/ui/src/js/src/layout/ReactPanel.tsx b/plugins/ui/src/js/src/layout/ReactPanel.tsx index d77037a8b..3fa509efb 100644 --- a/plugins/ui/src/js/src/layout/ReactPanel.tsx +++ b/plugins/ui/src/js/src/layout/ReactPanel.tsx @@ -28,7 +28,7 @@ function ReactPanel({ children, title }: ReactPanelProps) { // If there is already a portal that exists, then we're rehydrating from a dehydrated state // Initialize the `isPanelOpenRef` and `openedWidgetRef` accordingly on initialization const isPanelOpenRef = useRef(portal != null); - const openedMetadataRef = useRef( + const openedMetadataRef = useRef( portal != null ? metadata : null ); const parent = useParentItem(); diff --git a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx index 5ad3ad41b..e5e2f81cb 100644 --- a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx @@ -3,7 +3,7 @@ */ import React, { useCallback } from 'react'; import { WidgetDescriptor } from '@deephaven/dashboard'; -import { Widget } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; import { ReadonlyWidgetData, WidgetDataUpdate, WidgetId } from './WidgetTypes'; import WidgetHandler from './WidgetHandler'; @@ -18,7 +18,7 @@ export interface DashboardWidgetHandlerProps { widget: WidgetDescriptor; /** Fetch the widget instance */ - fetch: () => Promise; + fetch: () => Promise; /** Widget data to display */ initialData?: ReadonlyWidgetData; diff --git a/plugins/ui/src/js/src/widget/WidgetHandler.test.tsx b/plugins/ui/src/js/src/widget/WidgetHandler.test.tsx index d4827ded4..adf999a7a 100644 --- a/plugins/ui/src/js/src/widget/WidgetHandler.test.tsx +++ b/plugins/ui/src/js/src/widget/WidgetHandler.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { act, render } from '@testing-library/react'; -import type { Widget } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import WidgetHandler, { WidgetHandlerProps } from './WidgetHandler'; import { DocumentHandlerProps } from './DocumentHandler'; import { @@ -40,8 +40,8 @@ it('mounts and unmounts', async () => { }); it('updates the document when event is received', async () => { - let fetchResolve: (value: Widget | PromiseLike) => void; - const fetchPromise = new Promise(resolve => { + let fetchResolve: (value: dh.Widget | PromiseLike) => void; + const fetchPromise = new Promise(resolve => { fetchResolve = resolve; }); const fetch = jest.fn(() => fetchPromise); diff --git a/plugins/ui/src/js/src/widget/WidgetHandler.tsx b/plugins/ui/src/js/src/widget/WidgetHandler.tsx index 455498a48..c7d25d7e0 100644 --- a/plugins/ui/src/js/src/widget/WidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/WidgetHandler.tsx @@ -15,7 +15,7 @@ import { JSONRPCServerAndClient, } from 'json-rpc-2.0'; import { WidgetDescriptor } from '@deephaven/dashboard'; -import type { Widget, WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; import { EMPTY_FUNCTION } from '@deephaven/utils'; import { @@ -40,7 +40,7 @@ export interface WidgetHandlerProps { widget: WidgetDescriptor; /** Fetch the widget instance */ - fetch: () => Promise; + fetch: () => Promise; /** Widget data to display */ initialData?: ReadonlyWidgetData; @@ -59,14 +59,14 @@ function WidgetHandler({ widget: descriptor, initialData: initialDataProp, }: WidgetHandlerProps) { - const [widget, setWidget] = useState(); + const [widget, setWidget] = useState(); const [document, setDocument] = useState(); const [initialData] = useState(initialDataProp); // When we fetch a widget, the client is then responsible for the exported objects. // These objects could stay alive even after the widget is closed if we wanted to, // but for our use case we want to close them when the widget is closed, so we close them all on unmount. - const exportedObjectMap = useRef>( + const exportedObjectMap = useRef>( new Map() ); const exportedObjectCount = useRef(0); @@ -156,7 +156,7 @@ function WidgetHandler({ ); const updateExportedObjects = useCallback( - (newExportedObjects: WidgetExportedObject[]) => { + (newExportedObjects: dh.WidgetExportedObject[]) => { for (let i = 0; i < newExportedObjects.length; i += 1) { const exportedObject = newExportedObjects[i]; const exportedObjectKey = exportedObjectCount.current; @@ -211,7 +211,10 @@ function WidgetHandler({ return; } // Need to reset the exported object map and count - const widgetExportedObjectMap = new Map(); + const widgetExportedObjectMap = new Map< + number, + dh.WidgetExportedObject + >(); exportedObjectMap.current = widgetExportedObjectMap; exportedObjectCount.current = 0; @@ -219,7 +222,7 @@ function WidgetHandler({ const activeClient = jsonClient; function receiveData( data: string, - newExportedObjects: WidgetExportedObject[] + newExportedObjects: dh.WidgetExportedObject[] ) { log.debug2('Data received', data, newExportedObjects); updateExportedObjects(newExportedObjects); @@ -277,9 +280,11 @@ function WidgetHandler({ const newWidget = await fetch(); if (isCancelled) { newWidget.close(); - newWidget.exportedObjects.forEach(exportedObject => { - exportedObject.close(); - }); + newWidget.exportedObjects.forEach( + (exportedObject: dh.WidgetExportedObject) => { + exportedObject.close(); + } + ); return; } log.debug('newWidget', descriptor, newWidget); diff --git a/plugins/ui/src/js/src/widget/WidgetTestUtils.ts b/plugins/ui/src/js/src/widget/WidgetTestUtils.ts index 11afff8b8..f7cec022e 100644 --- a/plugins/ui/src/js/src/widget/WidgetTestUtils.ts +++ b/plugins/ui/src/js/src/widget/WidgetTestUtils.ts @@ -1,6 +1,6 @@ import { WidgetDescriptor } from '@deephaven/dashboard'; import { TestUtils } from '@deephaven/utils'; -import type { Widget } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; export function makeDocumentUpdatedJsonRpc( document: Record = {} @@ -34,8 +34,8 @@ export function makeWidget({ addEventListener = jest.fn(() => jest.fn()), getDataAsString = () => makeDocumentUpdatedJsonRpcString(), exportedObjects = [], -}: Partial = {}): Widget { - return TestUtils.createMockProxy({ +}: Partial = {}): dh.Widget { + return TestUtils.createMockProxy({ addEventListener, getDataAsString, exportedObjects, diff --git a/plugins/ui/src/js/src/widget/WidgetTypes.ts b/plugins/ui/src/js/src/widget/WidgetTypes.ts index 4ab78403c..8c870cb53 100644 --- a/plugins/ui/src/js/src/widget/WidgetTypes.ts +++ b/plugins/ui/src/js/src/widget/WidgetTypes.ts @@ -1,16 +1,16 @@ -import { Widget, WidgetExportedObject } from '@deephaven/jsapi-types'; +import type { dh } from '@deephaven/jsapi-types'; export type WidgetId = string; export interface WidgetMessageDetails { getDataAsBase64(): string; getDataAsString(): string; - exportedObjects: WidgetExportedObject[]; + exportedObjects: dh.WidgetExportedObject[]; } export type WidgetMessageEvent = CustomEvent; -export type WidgetFetch = (takeOwnership?: boolean) => Promise; +export type WidgetFetch = (takeOwnership?: boolean) => Promise; export type WidgetData = { /** Panel IDs that are opened by this widget */