Skip to content

Commit 0db7ce7

Browse files
BotellaAclaude
andcommitted
fix(oxlint): keep unsafe type assertions on a single line
oxlint-tsgolint 7.0.2004 reports a multi-line type assertion at its first line, so the disable comment above its last line no longer applied. - Bridge Dexie's liveQuery to rxjs Observable in a liveObservable helper - Move the WidgetHandle cast to an asWidgetHandle helper - Await the WebSocket client before casting it to RpcClient Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 41c7c71 commit 0db7ce7

7 files changed

Lines changed: 41 additions & 39 deletions

File tree

‎app/composables/clipping_planes_widget_entries.ts‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ function asWidgetFactory(widget: PlaneWidget): vtkAbstractWidgetFactory<vtkAbstr
4747
return widget as unknown as vtkAbstractWidgetFactory<vtkAbstractWidget>;
4848
}
4949

50+
function asWidgetHandle(widget: unknown): WidgetHandle {
51+
// oxlint-disable-next-line no-unsafe-type-assertion -- vtk.js WidgetManager.addWidget is untyped for our custom WidgetHandle shape; narrowed here.
52+
return widget as WidgetHandle;
53+
}
54+
5055
interface WidgetEntryManagerParams {
5156
planes: Ref<ClippingPlane[]>;
5257
debouncedApply: (...args: readonly unknown[]) => void;
@@ -136,10 +141,7 @@ function useWidgetEntryManager({ planes, debouncedApply }: WidgetEntryManagerPar
136141
if (!widgetEntries[idx]) {
137142
// oxlint-disable-next-line no-unsafe-call no-unsafe-type-assertion -- vtk.js has no types for ImplicitPlaneWidget's factory; narrowed here.
138143
const planeWidget = vtkImplicitPlaneWidget() as PlaneWidget;
139-
const widgetHandle = widgetManager.addWidget(
140-
asWidgetFactory(planeWidget),
141-
// oxlint-disable-next-line no-unsafe-type-assertion -- vtk.js WidgetManager.addWidget is untyped for our custom WidgetHandle shape; narrowed here.
142-
) as unknown as WidgetHandle;
144+
const widgetHandle = asWidgetHandle(widgetManager.addWidget(asWidgetFactory(planeWidget)));
143145
widgetEntries.push(createWidgetEntry(planeWidget, widgetHandle, idx));
144146
}
145147
const entry = widgetEntries[idx];

‎app/stores/camera_manager.ts‎

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { type Table, liveQuery } from "dexie";
2-
import type { Observable } from "rxjs";
1+
import type { Table } from "dexie";
32
import { useObservable } from "@vueuse/rxjs";
43

54
// Local imports
65
import type { CameraOptions } from "@ogw_internal/stores/hybrid_viewer/vtk_types.js";
76
import { database } from "@ogw_internal/database/database.js";
7+
import { liveObservable } from "@ogw_front/utils/live_observable";
88
import { useViewerStore } from "@ogw_front/stores/viewer";
99
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_typed_schemas.js";
1010

@@ -26,16 +26,11 @@ export const useCameraManagerStore = defineStore("camera_manager", () => {
2626
>;
2727

2828
function refAllCameraPositions(): Ref<CameraPositionRecord[]> {
29-
// Dexie's liveQuery() returns Dexie's own minimal Observable shape, not an
30-
// Actual rxjs Observable instance (useObservable's declared parameter type);
31-
// The two are structurally close enough at runtime (vueuse only calls
32-
// `.subscribe`) but not identical, hence the cast.
3329
return useObservable(
34-
liveQuery(async () => {
30+
liveObservable(async () => {
3531
const positions = await camera_positions_db.toArray();
3632
return positions;
37-
// oxlint-disable-next-line no-unsafe-type-assertion -- trusted vueuse/Dexie Observable boundary; see comment above.
38-
}) as unknown as Observable<CameraPositionRecord[]>,
33+
}),
3934
{ initialValue: [] as CameraPositionRecord[] },
4035
);
4136
}

‎app/stores/data.ts‎

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// oxlint-disable eslint/max-lines
22
// Third party imports
3-
import { type Table, liveQuery } from "dexie";
4-
import type { Observable } from "rxjs";
3+
import type { Table } from "dexie";
54
import { useObservable } from "@vueuse/rxjs";
65
import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_typed_schemas.js";
76

87
// Local imports
98
import { type ModelComponentRecord, useDataMesh } from "./data_helpers/mesh.js";
109
import { database } from "@ogw_internal/database/database.js";
10+
import { liveObservable } from "@ogw_front/utils/live_observable";
1111
import { useDataCollections } from "./data_helpers/collections.js";
1212
import { useViewerStore } from "@ogw_front/stores/viewer";
1313

@@ -137,16 +137,11 @@ export const useDataStore = defineStore("data", () => {
137137
return items;
138138
}
139139
function refItem(id: string): Ref<DataItem | undefined> {
140-
// Dexie's liveQuery() returns Dexie's own minimal Observable shape, not an
141-
// Actual rxjs Observable instance (useObservable's declared parameter type);
142-
// The two are structurally close enough at runtime (vueuse only calls
143-
// `.subscribe`) but not identical, hence the cast.
144140
return useObservable(
145-
liveQuery(async () => {
141+
liveObservable(async () => {
146142
const data_item = await data_db.get(id);
147143
return data_item;
148-
// oxlint-disable-next-line no-unsafe-type-assertion -- trusted vueuse/Dexie Observable boundary; see comment above.
149-
}) as unknown as Observable<DataItem | undefined>,
144+
}),
150145
{
151146
// oxlint-disable-next-line no-unsafe-type-assertion -- placeholder until the live query resolves; consumers must treat this as possibly incomplete.
152147
initialValue: {} as DataItem,
@@ -155,11 +150,10 @@ export const useDataStore = defineStore("data", () => {
155150
}
156151
function refAllItems(): Ref<DataItem[]> {
157152
return useObservable(
158-
liveQuery(async () => {
153+
liveObservable(async () => {
159154
const items = await data_db.toArray();
160155
return items;
161-
// oxlint-disable-next-line no-unsafe-type-assertion -- trusted vueuse/Dexie Observable boundary; see comment above.
162-
}) as unknown as Observable<DataItem[]>,
156+
}),
163157
{
164158
initialValue: [] as DataItem[],
165159
},

‎app/stores/data_helpers/collections.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { type FormattedComponent, type ModelComponentRecord, useDataMesh } from "./mesh.js";
22
import { MESH_COMPONENT_TYPES } from "@ogw_front/utils/default_styles";
3-
import type { Observable } from "rxjs";
43
import type { Ref } from "vue";
54
import { getTable } from "@ogw_internal/database/database.js";
6-
import { liveQuery } from "dexie";
5+
import { liveObservable } from "@ogw_front/utils/live_observable";
76
import { useObservable } from "@vueuse/rxjs";
87

98
interface ModelComponentRelationRecord {
@@ -115,12 +114,10 @@ export function useDataCollections(): {
115114
modelId: string,
116115
): Ref<CollectionComponentGroup[] | undefined> {
117116
return useObservable(
118-
// Dexie's liveQuery returns its own Observable-like type, not rxjs's Observable, so bridging needs a cast.
119-
liveQuery(async () => {
117+
liveObservable(async () => {
120118
const groups = await formatedCollectionComponents(modelId);
121119
return groups;
122-
// oxlint-disable-next-line no-unsafe-type-assertion
123-
}) as unknown as Observable<CollectionComponentGroup[]>,
120+
}),
124121
{
125122
initialValue: undefined,
126123
},

‎app/stores/data_helpers/mesh.ts‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { type Table, liveQuery } from "dexie";
2-
import type { Observable } from "rxjs";
1+
import type { Table } from "dexie";
32
import { database } from "@ogw_internal/database/database.js";
3+
import { liveObservable } from "@ogw_front/utils/live_observable";
44
import { useObservable } from "@vueuse/rxjs";
55

66
interface ModelComponentRecord {
@@ -87,11 +87,10 @@ export function useDataMesh(): {
8787

8888
function refFormatedMeshComponents(modelId: string): Ref<FormattedComponentGroup[] | undefined> {
8989
return useObservable(
90-
liveQuery(async () => {
90+
liveObservable(async () => {
9191
const components = await formatedMeshComponents(modelId);
9292
return components;
93-
// oxlint-disable-next-line no-unsafe-type-assertion
94-
}) as unknown as Observable<FormattedComponentGroup[]>,
93+
}),
9594
{
9695
initialValue: undefined,
9796
},

‎app/stores/viewer.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ export const useViewerStore = defineStore(
142142
}
143143
try {
144144
status.value = Status.CONNECTING;
145-
client.value = (await initWebSocketClient(base_url.value, client.value, {
145+
const wsClient = await initWebSocketClient(base_url.value, client.value, {
146146
onConnectionClose: () => {
147147
status.value = Status.NOT_CONNECTED;
148148
},
149-
// oxlint-disable-next-line no-unsafe-type-assertion -- initWebSocketClient's return is not typed as RpcClient.
150-
})) as unknown as RpcClient;
149+
});
150+
// oxlint-disable-next-line no-unsafe-type-assertion -- initWebSocketClient's return is not typed as RpcClient.
151+
client.value = wsClient as unknown as RpcClient;
151152
connectImageStream(client.value.getConnection().getSession());
152153
// oxlint-disable-next-line no-unsafe-type-assertion -- endBusy is not part of the RpcClient type.
153154
(client.value as unknown as { endBusy: () => void }).endBusy();

‎app/utils/live_observable.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Third party imports
2+
import type { Observable } from "rxjs";
3+
import { liveQuery } from "dexie";
4+
5+
// Dexie's liveQuery() returns Dexie's own minimal Observable shape, not an
6+
// Actual rxjs Observable instance (useObservable's declared parameter type);
7+
// The two are structurally close enough at runtime (vueuse only calls
8+
// `.subscribe`) but not identical, hence the cast.
9+
function liveObservable<Value>(query: () => Promise<Value>): Observable<Value> {
10+
// oxlint-disable-next-line no-unsafe-type-assertion -- trusted vueuse/Dexie Observable boundary; see comment above.
11+
return liveQuery(query) as unknown as Observable<Value>;
12+
}
13+
14+
export { liveObservable };

0 commit comments

Comments
 (0)