Browse Source

refactor: add strict typing to core database methods in PlatformServiceMixin

- Replace all `any` types in $db, $exec, $one, $query, $first, and $contacts with proper interfaces:
  - Use QueryExecResult and DatabaseExecResult for raw database operations
  - Use Contact[] for contact queries
  - Add generics for mapped query results
- Update PlatformService and database interfaces to match new types
- Remove unused type imports and fix linter errors
- Reduces risk of runtime errors and improves type safety for all database access
pull/142/head
Matthew Raymer 3 days ago
parent
commit
829edaf7d7
  1. 20
      src/interfaces/database.ts
  2. 7
      src/services/PlatformService.ts
  3. 60
      src/utils/PlatformServiceMixin.ts

20
src/interfaces/database.ts

@ -5,11 +5,23 @@ export interface QueryExecResult {
values: Array<Array<SqlValue>>;
}
export interface DatabaseExecResult {
changes: number;
lastId?: number;
}
export interface DatabaseService {
initialize(): Promise<void>;
query(sql: string, params?: unknown[]): Promise<QueryExecResult[]>;
run(
sql: string,
params?: unknown[],
): Promise<{ changes: number; lastId?: number }>;
run(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
}
/**
* Generic database result type for mapped query results
*/
export type DatabaseResult<T = Record<string, unknown>> = T;
/**
* Database query result that can be either a single result or an array
*/
export type DatabaseQueryResult<T = Record<string, unknown>> = T | T[] | null;

7
src/services/PlatformService.ts

@ -1,4 +1,4 @@
import { QueryExecResult } from "@/interfaces/database";
import { QueryExecResult, DatabaseExecResult } from "@/interfaces/database";
/**
* Represents the result of an image capture or selection operation.
@ -145,10 +145,7 @@ export interface PlatformService {
* @param params - The parameters to pass to the statement
* @returns Promise resolving to the result of the statement
*/
dbExec(
sql: string,
params?: unknown[],
): Promise<{ changes: number; lastId?: number }>;
dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
/**
* Executes a SQL query and returns the first row as an array.

60
src/utils/PlatformServiceMixin.ts

@ -40,6 +40,8 @@ import { mapColumnsToValues, parseJsonField } from "@/db/databaseUtil";
import { MASTER_SETTINGS_KEY, type Settings } from "@/db/tables/settings";
import * as databaseUtil from "@/db/databaseUtil";
import { logger } from "@/utils/logger";
import { Contact } from "@/db/tables/contacts";
import { QueryExecResult, DatabaseExecResult } from "@/interfaces/database";
// =================================================
// CACHING INFRASTRUCTURE
@ -385,7 +387,10 @@ export const PlatformServiceMixin = {
* @param sql SQL query string
* @param params Query parameters
*/
async $db(sql: string, params: unknown[] = []): Promise<any> {
async $db(
sql: string,
params: unknown[] = [],
): Promise<QueryExecResult | undefined> {
return await (this as any).platformService.dbQuery(sql, params);
},
@ -394,7 +399,10 @@ export const PlatformServiceMixin = {
* @param sql SQL statement string
* @param params Statement parameters
*/
async $exec(sql: string, params: unknown[] = []): Promise<any> {
async $exec(
sql: string,
params: unknown[] = [],
): Promise<DatabaseExecResult> {
return await (this as any).platformService.dbExec(sql, params);
},
@ -403,7 +411,10 @@ export const PlatformServiceMixin = {
* @param sql SQL query string
* @param params Query parameters
*/
async $one(sql: string, params: unknown[] = []): Promise<any> {
async $one(
sql: string,
params: unknown[] = [],
): Promise<unknown[] | undefined> {
return await (this as any).platformService.dbGetOneRow(sql, params);
},
@ -418,12 +429,16 @@ export const PlatformServiceMixin = {
* @param params Query parameters
* @returns Mapped array of results
*/
async $query(sql: string, params: unknown[] = []): Promise<any[]> {
async $query<T = Record<string, unknown>>(
sql: string,
params: unknown[] = [],
): Promise<T[]> {
const result = await (this as any).platformService.dbQuery(sql, params);
if (!result?.columns || !result?.values) {
return [];
}
return mapColumnsToValues(result.columns, result.values) || [];
const mappedResults = mapColumnsToValues(result.columns, result.values);
return mappedResults as T[];
},
/**
@ -432,9 +447,12 @@ export const PlatformServiceMixin = {
* @param params Query parameters
* @returns First mapped result or null
*/
async $first(sql: string, params: unknown[] = []): Promise<any | null> {
async $first<T = Record<string, unknown>>(
sql: string,
params: unknown[] = [],
): Promise<T | null> {
const results = await (this as any).$query(sql, params);
return results.length > 0 ? results[0] : null;
return results.length > 0 ? (results[0] as T) : null;
},
// =================================================
@ -446,9 +464,9 @@ export const PlatformServiceMixin = {
* Ultra-concise shortcut with 60s TTL for performance
* @returns Cached mapped array of all contacts
*/
async $contacts(): Promise<any[]> {
async $contacts(): Promise<Contact[]> {
const cacheKey = "contacts_all";
const cached = this._getCached<any[]>(cacheKey);
const cached = this._getCached<Contact[]>(cacheKey);
if (cached) {
return cached;
}
@ -456,7 +474,11 @@ export const PlatformServiceMixin = {
const contacts = await this.$query(
"SELECT * FROM contacts ORDER BY name",
);
return this._setCached(cacheKey, contacts, CACHE_DEFAULTS.contacts);
return this._setCached(
cacheKey,
contacts as Contact[],
CACHE_DEFAULTS.contacts,
);
},
/**
@ -656,13 +678,19 @@ declare module "@vue/runtime-core" {
capabilities: any;
// Ultra-concise database methods (shortest possible names)
$db(sql: string, params?: unknown[]): Promise<any>;
$exec(sql: string, params?: unknown[]): Promise<any>;
$one(sql: string, params?: unknown[]): Promise<any>;
$db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>;
$exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
$one(sql: string, params?: unknown[]): Promise<unknown[] | undefined>;
// Query + mapping combo methods
$query(sql: string, params?: unknown[]): Promise<any[]>;
$first(sql: string, params?: unknown[]): Promise<any | null>;
$query<T = Record<string, unknown>>(
sql: string,
params?: unknown[],
): Promise<T[]>;
$first<T = Record<string, unknown>>(
sql: string,
params?: unknown[],
): Promise<T | null>;
// Enhanced utility methods
$dbQuery(sql: string, params?: unknown[]): Promise<any>;
@ -680,7 +708,7 @@ declare module "@vue/runtime-core" {
$withTransaction<T>(fn: () => Promise<T>): Promise<T>;
// Cached specialized shortcuts (massive performance boost)
$contacts(): Promise<any[]>;
$contacts(): Promise<Contact[]>;
$settings(defaults?: Settings): Promise<Settings>;
$accountSettings(did?: string, defaults?: Settings): Promise<Settings>;

Loading…
Cancel
Save