diff --git a/.github/workflows/web-test-code-quality.yml b/.github/workflows/web-test-code-quality.yml index f941e80fc74..301008cd37d 100644 --- a/.github/workflows/web-test-code-quality.yml +++ b/.github/workflows/web-test-code-quality.yml @@ -64,3 +64,6 @@ jobs: npx eslint web-auth --quiet npx svelte-check --workspace web-auth --no-tsconfig + - name: type check non-svelte files (with temporary whitelist) + run: |- + sh ./scripts/tsc-with-whitelist.sh diff --git a/scripts/tsc-with-whitelist.sh b/scripts/tsc-with-whitelist.sh new file mode 100644 index 00000000000..62486dbbebc --- /dev/null +++ b/scripts/tsc-with-whitelist.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Run TypeScript compiler and filter out some errors +output=$(npx tsc --noEmit | grep "error TS" | grep -v -E 'TS18048|TS2345|TS2322|TS18047|TS2532|TS2339|TS2538|TS2769|TS18046|TS2614') + +# Check if 'error' is in the output +if echo "$output" | grep -q "error"; then + echo "TypeScript errors found:" + echo "$output" + exit 1 # Exit with error code +else + echo "No TypeScript errors detected." + exit 0 # Exit without error +fi \ No newline at end of file diff --git a/web-common/src/components/data-graphic/actions/forward-events-action-factory.ts b/web-common/src/components/data-graphic/actions/forward-events-action-factory.ts deleted file mode 100644 index bc41b84e76c..00000000000 --- a/web-common/src/components/data-graphic/actions/forward-events-action-factory.ts +++ /dev/null @@ -1,78 +0,0 @@ -// based on https://github.com/hperrin/svelte-material-ui/blob/master/packages/common/forwardEvents.js -import type { SvelteComponent } from "svelte"; -import { bubble, listen } from "svelte/internal"; - -const DEFAULT_EVENTS = [ - "focus", - "blur", - "fullscreenchange", - "fullscreenerror", - "scroll", - "cut", - "copy", - "paste", - "keydown", - "keypress", - "keyup", - "auxclick", - "click", - "contextmenu", - "dblclick", - "mousedown", - "mouseenter", - "mouseleave", - "mousemove", - "mouseover", - "mouseout", - "mouseup", - "pointerlockchange", - "pointerlockerror", - "select", - "wheel", - "drag", - "dragend", - "dragenter", - "dragstart", - "dragleave", - "dragover", - "drop", - "touchcancel", - "touchend", - "touchmove", - "touchstart", - "pointerover", - "pointerenter", - "pointerdown", - "pointermove", - "pointerup", - "pointercancel", - "pointerout", - "pointerleave", - "gotpointercapture", - "lostpointercapture", -]; - -export function forwardEvents( - component: SvelteComponent, - additionalEvents = [], - overridingEvents = [], -) { - const eventSet = [ - ...(overridingEvents.length ? overridingEvents : DEFAULT_EVENTS), - ...additionalEvents, - ]; - - return (node: HTMLElement | SVGElement) => { - const destructors = eventSet.map((event) => - listen(node, event, (e) => bubble(component, e)), - ); - - return { - destroy: () => { - destructors.forEach((destructor) => { - destructor(); - }); - }, - }; - }; -} diff --git a/web-common/src/components/data-graphic/elements/SimpleDataGraphic.svelte b/web-common/src/components/data-graphic/elements/SimpleDataGraphic.svelte index b1e3e4846b9..cf901dbf7be 100644 --- a/web-common/src/components/data-graphic/elements/SimpleDataGraphic.svelte +++ b/web-common/src/components/data-graphic/elements/SimpleDataGraphic.svelte @@ -39,7 +39,6 @@ A simple composable container for SVG-based data graphics. /** this makes a wide variety of normal events, such as on:click, available * to the consumer */ - // const forwardAll = forwardEvents(getComponent(), []); segment.length === 1); diff --git a/web-common/src/components/data-graphic/marks/segment.ts b/web-common/src/components/data-graphic/marks/segment.ts index a3562384728..05236d14b80 100644 --- a/web-common/src/components/data-graphic/marks/segment.ts +++ b/web-common/src/components/data-graphic/marks/segment.ts @@ -1,39 +1,50 @@ +function pathIsDefined(yAccessor: string) { + return (d: Record) => { + const val = d[yAccessor]; + return !( + val === undefined || + (typeof val === "number" && isNaN(val)) || + val === null + ); + }; +} + /** * Helper function to compute the contiguous segments of the data * based on https://github.com/pbeshai/d3-line-chunked/blob/master/src/lineChunked.js */ -export function computeSegments(lineData, defined, isNext = () => true) { +export function computeSegments( + lineData: Record[], + yAccessor: string, +): Record[][] { let startNewSegment = true; + const defined = pathIsDefined(yAccessor); // split into segments of continuous data - const segments = lineData.reduce(function (segments, d) { - // skip if this point has no data - if (!defined(d)) { - startNewSegment = true; - return segments; - } - - // if we are starting a new segment, start it with this point - if (startNewSegment) { - segments.push([d]); - startNewSegment = false; - - // otherwise see if we are adding to the last segment - } else { - const lastSegment = segments[segments.length - 1]; - const lastDatum = lastSegment[lastSegment.length - 1]; - // if we expect this point to come next, add it to the segment - if (isNext(lastDatum, d)) { - lastSegment.push(d); + const segments = lineData.reduce( + (segments: Record[][], d) => { + // skip if this point has no data + if (!defined(d)) { + startNewSegment = true; + return segments; + } - // otherwise create a new segment - } else { + // if we are starting a new segment, start it with this point + if (startNewSegment) { segments.push([d]); + startNewSegment = false; + + // otherwise see if we are adding to the last segment + } else { + const lastSegment = segments[segments.length - 1]; + lastSegment.push(d); + // if we expect this point to come next, add it to the segment } - } - return segments; - }, []); + return segments; + }, + [], + ); return segments; } diff --git a/web-common/src/components/data-graphic/utils.ts b/web-common/src/components/data-graphic/utils.ts index fbcaa837f0d..f0016addb42 100644 --- a/web-common/src/components/data-graphic/utils.ts +++ b/web-common/src/components/data-graphic/utils.ts @@ -32,16 +32,6 @@ const curves = { curveStepExtended, }; -export function pathIsDefined(yAccessor: string) { - return (d) => { - return !( - d[yAccessor] === undefined || - isNaN(d[yAccessor]) || - d[yAccessor] === null - ); - }; -} - export function pathDoesNotDropToZero(yAccessor: string) { return (d, i: number, arr) => { return ( diff --git a/web-common/src/components/date-picker/datetime.ts b/web-common/src/components/date-picker/datetime.ts index 10534cc19bc..7543cc08dc2 100644 --- a/web-common/src/components/date-picker/datetime.ts +++ b/web-common/src/components/date-picker/datetime.ts @@ -517,7 +517,11 @@ export class DateTime { return this; } - public diff(date: DateTime, unit = "seconds"): number { + // FIXME: I'm pretty sure this is never used anywhere. Even if it is, + // it doesn't do anything, because it doesn't return anything, + // and it doesn't mutate anything. Also it has a dangling TODO + // that was unfinished when Speros left. + public diff(date: DateTime, unit = "seconds") { const oneDay = 1000 * 60 * 60 * 24; switch (unit) { diff --git a/web-common/src/components/editor/indent-guide/index.ts b/web-common/src/components/editor/indent-guide/index.ts index 40946373718..481de33aafc 100644 --- a/web-common/src/components/editor/indent-guide/index.ts +++ b/web-common/src/components/editor/indent-guide/index.ts @@ -40,7 +40,8 @@ export const indentGuide = () => /** Creates a Monaco-like indent */ decorationsFromLine(lineNumber) { const line = this.view.state.doc.line(lineNumber); - const indent = /^\s*/.exec(line.text)[0]; + // empty string if no whitespace at start of line + const indent = /^\s*/.exec(line.text)?.[0] ?? ""; const indentSize = indent.length; const decorations = []; diff --git a/web-common/src/components/editor/line-status/line-number-gutter.ts b/web-common/src/components/editor/line-status/line-number-gutter.ts index a0c2aeb0e29..820d45c8418 100644 --- a/web-common/src/components/editor/line-status/line-number-gutter.ts +++ b/web-common/src/components/editor/line-status/line-number-gutter.ts @@ -1,6 +1,7 @@ import { GutterMarker, gutter } from "@codemirror/view"; import LineNumberGutterMarkerComponent from "./LineNumberGutterMarker.svelte"; import { lineStatusesStateField, updateLineStatuses } from "./state"; +import type { SvelteComponent } from "svelte"; export const LINE_NUMBER_GUTTER_CLASS = "cm-line-number-gutter"; diff --git a/web-common/src/components/notifications/notificationStore.ts b/web-common/src/components/notifications/notificationStore.ts index 707985bfb7e..ff32b9c711f 100644 --- a/web-common/src/components/notifications/notificationStore.ts +++ b/web-common/src/components/notifications/notificationStore.ts @@ -39,7 +39,7 @@ interface NotificationOptions { function createNotificationStore(): NotificationStore { const _notification = writable({} as NotificationMessage); - let timeout: ReturnType; + let timeout: ReturnType | undefined = undefined; function send({ message, diff --git a/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte b/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte index 31d28defa6e..561c36999d3 100644 --- a/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte +++ b/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte @@ -39,6 +39,7 @@ (sel, g) => sel + g.items.length, 0, ); + $: searchResultCount = menuGroups.reduce( (sel, mg) => sel + mg.items.length, 0, diff --git a/web-common/src/features/dashboards/show-hide-selectors.spec.ts b/web-common/src/features/dashboards/show-hide-selectors.spec.ts index a1d1bdbd736..43ecc9a8d4d 100644 --- a/web-common/src/features/dashboards/show-hide-selectors.spec.ts +++ b/web-common/src/features/dashboards/show-hide-selectors.spec.ts @@ -125,11 +125,7 @@ describe("Show/Hide Selectors", () => { }, ]); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_DELETED_MEASURE, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_DELETED_MEASURE); expect(get(showHideMeasure).availableKeys).toEqual([ AD_BIDS_IMPRESSIONS_MEASURE, ]); @@ -153,11 +149,7 @@ describe("Show/Hide Selectors", () => { mock.setMeasures(AD_BIDS_THREE_MEASURES); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_THREE_MEASURES, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_THREE_MEASURES); expect(get(showHideMeasure).availableKeys).toEqual([ AD_BIDS_IMPRESSIONS_MEASURE, AD_BIDS_BID_PRICE_MEASURE, @@ -180,11 +172,7 @@ describe("Show/Hide Selectors", () => { mock.setMeasures(AD_BIDS_THREE_MEASURES); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_THREE_MEASURES, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_THREE_MEASURES); expect(get(showHideMeasure).availableKeys).toEqual([ AD_BIDS_IMPRESSIONS_MEASURE, AD_BIDS_BID_PRICE_MEASURE, @@ -291,11 +279,7 @@ describe("Show/Hide Selectors", () => { }, ]); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_DELETED_DIMENSION, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_DELETED_DIMENSION); expect(get(showHideDimensions).availableKeys).toEqual([ AD_BIDS_PUBLISHER_DIMENSION, ]); @@ -320,11 +304,7 @@ describe("Show/Hide Selectors", () => { mock.setDimensions(AD_BIDS_THREE_DIMENSIONS); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_THREE_DIMENSIONS, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_THREE_DIMENSIONS); expect(get(showHideDimensions).availableKeys).toEqual([ AD_BIDS_PUBLISHER_DIMENSION, AD_BIDS_DOMAIN_DIMENSION, @@ -352,11 +332,7 @@ describe("Show/Hide Selectors", () => { mock.setDimensions(AD_BIDS_THREE_DIMENSIONS); // we have to manually call sync since in the app it is handled by a reactive statement - metricsExplorerStore.sync( - AD_BIDS_NAME, - AD_BIDS_WITH_THREE_DIMENSIONS, - undefined, - ); + metricsExplorerStore.sync(AD_BIDS_NAME, AD_BIDS_WITH_THREE_DIMENSIONS); expect(get(showHideDimensions).availableKeys).toEqual([ AD_BIDS_PUBLISHER_DIMENSION, AD_BIDS_DOMAIN_DIMENSION, diff --git a/web-common/src/features/dashboards/state-managers/actions/types.ts b/web-common/src/features/dashboards/state-managers/actions/types.ts index 687846dcc20..85f3c8faf32 100644 --- a/web-common/src/features/dashboards/state-managers/actions/types.ts +++ b/web-common/src/features/dashboards/state-managers/actions/types.ts @@ -1,4 +1,5 @@ import type { MetricsExplorerEntity } from "../../stores/metrics-explorer-entity"; +import type { Expand } from "../types"; // Note: the types below are helper types to simplify the type inference // used in the creation of StateManagerActions, so that we can have nice diff --git a/web-common/src/features/dashboards/state-managers/selectors/types.ts b/web-common/src/features/dashboards/state-managers/selectors/types.ts index 6f7a7cd9373..4db88ed5a77 100644 --- a/web-common/src/features/dashboards/state-managers/selectors/types.ts +++ b/web-common/src/features/dashboards/state-managers/selectors/types.ts @@ -6,6 +6,7 @@ import type { V1ColumnTimeRangeResponse, V1MetricsViewSpec, } from "@rilldata/web-common/runtime-client"; +import type { Expand } from "../types"; /** * DashboardDataSources collects all the information about a dashboard diff --git a/web-common/src/features/dashboards/state-managers/types.ts b/web-common/src/features/dashboards/state-managers/types.ts index b731c96da7e..0f9ccb8c5f7 100644 --- a/web-common/src/features/dashboards/state-managers/types.ts +++ b/web-common/src/features/dashboards/state-managers/types.ts @@ -6,3 +6,14 @@ * the other keys will be optional */ export type AtLeast = Partial & Pick; + +/** + * Helper type based on the internal `Expand` type from the TypeScript. + * + * If types on actions and selectors ever look nasty, + * it's probably because we're missing an `Expand` somewhere. + * + * + * see https://stackoverflow.com/questions/57683303/how-can-i-see-the-full-expanded-contract-of-a-typescript-type + */ +export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/web-common/src/features/dashboards/stores/dashboard-store-defaults.ts b/web-common/src/features/dashboards/stores/dashboard-store-defaults.ts index 124450cadc1..6794cf86b0e 100644 --- a/web-common/src/features/dashboards/stores/dashboard-store-defaults.ts +++ b/web-common/src/features/dashboards/stores/dashboard-store-defaults.ts @@ -124,7 +124,6 @@ export function getDefaultMetricsExplorerEntity( const metricsExplorer: MetricsExplorerEntity = { name, - selectedMeasureNames: [...defaultMeasureNames], visibleMeasureKeys: new Set(defaultMeasureNames), allMeasuresVisible: true, visibleDimensionKeys: new Set(defaultDimNames), diff --git a/web-common/src/features/dashboards/stores/dashboard-stores-test-data.ts b/web-common/src/features/dashboards/stores/dashboard-stores-test-data.ts index 00f99012f52..32d5c40e95d 100644 --- a/web-common/src/features/dashboards/stores/dashboard-stores-test-data.ts +++ b/web-common/src/features/dashboards/stores/dashboard-stores-test-data.ts @@ -174,7 +174,6 @@ export function initAdBidsMirrorInStore() { metricsExplorerStore.init( AD_BIDS_MIRROR_NAME, { - name: AD_BIDS_MIRROR_NAME, measures: AD_BIDS_INIT_MEASURES, dimensions: AD_BIDS_INIT_DIMENSIONS, }, diff --git a/web-common/src/features/dashboards/time-controls/time-control-store.ts b/web-common/src/features/dashboards/time-controls/time-control-store.ts index a32ebac116b..140f85914b1 100644 --- a/web-common/src/features/dashboards/time-controls/time-control-store.ts +++ b/web-common/src/features/dashboards/time-controls/time-control-store.ts @@ -249,8 +249,8 @@ function calculateComparisonTimeRangePartial( const showComparison = Boolean( metricsExplorer.showTimeComparison && selectedComparisonTimeRange?.start, ); - let comparisonAdjustedStart: string; - let comparisonAdjustedEnd: string; + let comparisonAdjustedStart: string | undefined = undefined; + let comparisonAdjustedEnd: string | undefined = undefined; if (showComparison && selectedComparisonTimeRange) { const adjustedComparisonTime = getAdjustedFetchTime( selectedComparisonTimeRange.start, @@ -376,7 +376,8 @@ function getComparisonTimeRange( ) { if (!comparisonTimeRange || !timeRange.name) return undefined; - let selectedComparisonTimeRange: DashboardTimeControls; + let selectedComparisonTimeRange: DashboardTimeControls | undefined = + undefined; if (!comparisonTimeRange?.name) { const comparisonOption = DEFAULT_TIME_RANGES[ timeRange.name as TimeComparisonOption diff --git a/web-common/src/features/dashboards/time-controls/time-range-utils.spec.disabled.ts b/web-common/src/features/dashboards/time-controls/time-range-utils.spec.disabled.ts index e51e115671f..026f0909822 100644 --- a/web-common/src/features/dashboards/time-controls/time-range-utils.spec.disabled.ts +++ b/web-common/src/features/dashboards/time-controls/time-range-utils.spec.disabled.ts @@ -1,5 +1,6 @@ import { V1TimeGrain } from "../../../runtime-client"; import { getDefaultTimeGrain } from "./time-range-utils"; +import { describe, it, expect } from "vitest"; describe("getDefaultTimeGrain", () => { it("should return the default time grain (for a 5 day time range)", () => { diff --git a/web-common/src/features/metrics-views/workspace/editor/create-placeholder.ts b/web-common/src/features/metrics-views/workspace/editor/create-placeholder.ts index fdeda954d3e..82ac4004bd2 100644 --- a/web-common/src/features/metrics-views/workspace/editor/create-placeholder.ts +++ b/web-common/src/features/metrics-views/workspace/editor/create-placeholder.ts @@ -74,6 +74,7 @@ export function createPlaceholderElement(metricsName: string) { target: DOMElement, props: { metricsName, + view: undefined, }, }); return { diff --git a/web-common/src/features/models/utils/Debounce.ts b/web-common/src/features/models/utils/Debounce.ts index 71421ae0c4e..a1586346e87 100644 --- a/web-common/src/features/models/utils/Debounce.ts +++ b/web-common/src/features/models/utils/Debounce.ts @@ -14,7 +14,8 @@ export class Debounce { id, setTimeout(() => { this.debounceMap.delete(id); - this.callbackMap.get(id)(); + const callback = this.callbackMap.get(id); + if (callback) callback(); }, time), ); } diff --git a/web-common/src/features/sources/modal/file-upload.ts b/web-common/src/features/sources/modal/file-upload.ts index 753510199b0..735513178db 100644 --- a/web-common/src/features/sources/modal/file-upload.ts +++ b/web-common/src/features/sources/modal/file-upload.ts @@ -33,7 +33,7 @@ export async function* uploadTableFiles( if (!files?.length) return; const { validFiles, invalidFiles } = filterValidFileExtensions(files); - let lastTableName: string; + let lastTableName: string | undefined = undefined; for (const validFile of validFiles) { // check if the file is already present. get the file and diff --git a/web-common/src/layout/app-store.ts b/web-common/src/layout/app-store.ts index de045d880ea..c023aeb623d 100644 --- a/web-common/src/layout/app-store.ts +++ b/web-common/src/layout/app-store.ts @@ -18,8 +18,8 @@ export interface ActiveEntity { * Currently caches active entity from URL */ interface AppStore { - activeEntity: ActiveEntity; - previousActiveEntity: ActiveEntity; + activeEntity: ActiveEntity | undefined; + previousActiveEntity: ActiveEntity | undefined; } export const appScreen = derived(page, ($page) => { diff --git a/web-common/src/lib/actions/shift-click-action.ts b/web-common/src/lib/actions/shift-click-action.ts index 192d023d6d4..bb3715b3af0 100644 --- a/web-common/src/lib/actions/shift-click-action.ts +++ b/web-common/src/lib/actions/shift-click-action.ts @@ -66,7 +66,7 @@ export function createShiftClickAction( node.dispatchEvent(new CustomEvent("shift-click")); // fire all callbacks. const cbs = get(callbacks); - cbs.forEach((cb) => cb()); + cbs.forEach((cb: () => void) => cb()); // prevent the regular on:click event here. if (_stopImmediatePropagation) { diff --git a/web-common/src/lib/number-formatting/strategies/per-range.ts b/web-common/src/lib/number-formatting/strategies/per-range.ts index d5289e6fca8..4044d9c17a5 100644 --- a/web-common/src/lib/number-formatting/strategies/per-range.ts +++ b/web-common/src/lib/number-formatting/strategies/per-range.ts @@ -115,7 +115,7 @@ export class PerRangeFormatter implements Formatter { if (isPercent) x = 100 * x; - let numParts: NumberParts; + let numParts: NumberParts | undefined = undefined; if (x === 0) { numParts = { int: "0", dot: "", frac: "", suffix: "" }; diff --git a/web-common/src/lib/time/grains/index.spec.ts b/web-common/src/lib/time/grains/index.spec.ts index ff9354954fc..e85c96b4322 100644 --- a/web-common/src/lib/time/grains/index.spec.ts +++ b/web-common/src/lib/time/grains/index.spec.ts @@ -133,18 +133,21 @@ const timeGrainOptions: TimeGrain[] = [ grain: V1TimeGrain.TIME_GRAIN_DAY, label: "day", duration: Period.DAY, + d3format: "", formatDate: {}, }, { grain: V1TimeGrain.TIME_GRAIN_WEEK, label: "week", duration: Period.WEEK, + d3format: "", formatDate: {}, }, { grain: V1TimeGrain.TIME_GRAIN_MONTH, label: "month", duration: Period.MONTH, + d3format: "", formatDate: {}, }, ]; diff --git a/web-common/src/lib/time/transforms/index.ts b/web-common/src/lib/time/transforms/index.ts index d2e0862cb79..5532b40aa62 100644 --- a/web-common/src/lib/time/transforms/index.ts +++ b/web-common/src/lib/time/transforms/index.ts @@ -148,7 +148,11 @@ export function getDurationMultiple(duration: string, multiple: number) { .toISO(); } -export function subtractFromPeriod(duration: Duration, period: Period) { - if (!PeriodToUnitsMap[period]) return duration; - return duration.minus({ [PeriodToUnitsMap[period]]: 1 }); +export function subtractFromPeriod( + duration: Duration, + period: Period, +): Duration { + const period_duration = PeriodToUnitsMap[period]; + if (!period_duration) return duration; + return duration.minus({ [period_duration]: 1 }); } diff --git a/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts b/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts index e7f3c67913d..e8f94146b5d 100644 --- a/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts +++ b/web-common/src/runtime-client/http-request-queue/HttpRequestQueue.ts @@ -178,9 +178,9 @@ export class HttpRequestQueue { private async fireForEntry(entry: RequestQueueEntry) { try { const resp = await fetchWrapper(entry.requestOptions); - entry.resolve(resp); + if (entry?.resolve) entry.resolve(resp); } catch (err) { - entry.reject(err); + if (entry?.reject) entry.reject(err); } this.activeCount--; appQueryStatusStore.set(this.activeCount > 0); diff --git a/web-local/src/lib/util/command-click-action.ts b/web-local/src/lib/util/command-click-action.ts index d8cdbbcdc83..f30f8289b7a 100644 --- a/web-local/src/lib/util/command-click-action.ts +++ b/web-local/src/lib/util/command-click-action.ts @@ -50,7 +50,7 @@ export function createCommandClickAction( node.dispatchEvent(new CustomEvent("command-click")); // fire all callbacks. const cbs = get(callbacks); - cbs.forEach((cb) => cb()); + cbs.forEach((cb: () => void) => cb()); // prevent the regular on:click event here. if (_stopImmediatePropagation) { diff --git a/web-local/test/temp/get-table-references.test.ts b/web-local/test/temp/get-table-references.test.ts index 254d836c2c9..8ef1a3aad91 100644 --- a/web-local/test/temp/get-table-references.test.ts +++ b/web-local/test/temp/get-table-references.test.ts @@ -3,6 +3,7 @@ import { getTableReferences, } from "@rilldata/web-common/features/models/utils/get-table-references"; import { tests } from "@rilldata/web-common/features/models/utils/get-table-references/test-data"; +import { describe, it, expect } from "vitest"; describe("getAllTableReferences", () => { it("correctly assesses the table references", () => { diff --git a/web-local/test/ui/utils/helpers.ts b/web-local/test/ui/utils/helpers.ts index 2d9bda71189..1566499261b 100644 --- a/web-local/test/ui/utils/helpers.ts +++ b/web-local/test/ui/utils/helpers.ts @@ -55,7 +55,7 @@ export async function wrapRetryAssertion( timeout = 1000, interval = 100, ) { - let lastError: Error; + let lastError: Error | undefined | string = undefined; await asyncWaitUntil( async () => { try { @@ -63,7 +63,8 @@ export async function wrapRetryAssertion( lastError = undefined; return true; } catch (err) { - lastError = err; + if (err instanceof Error) lastError = err; + else lastError = JSON.stringify(err); return false; } },