Skip to content

Commit 4bad192

Browse files
Copilothotlong
andcommitted
refactor: improve type safety with named interfaces per code review
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent eb7a399 commit 4bad192

2 files changed

Lines changed: 38 additions & 19 deletions

File tree

packages/foundation/plugin-security/src/storage-database.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ import type { IPermissionStorage, SecurityPluginConfig } from './types';
2222
/** Default table name for storing permission metadata */
2323
const DEFAULT_TABLE = 'objectql_permissions';
2424

25+
/**
26+
* Interface for permission storage row structure
27+
*/
28+
interface PermissionRow {
29+
_id?: string | number;
30+
id?: string | number;
31+
object_name: string;
32+
config: string;
33+
updated_at?: string;
34+
}
35+
2536
/**
2637
* Resolver function that locates a Driver instance by datasource name.
2738
* Typically wired from the ObjectQL application layer.
@@ -118,9 +129,9 @@ export class DatabasePermissionStorage implements IPermissionStorage {
118129
filters: [['object_name', '=', objectName]],
119130
top: 1,
120131
});
121-
const row = Array.isArray(rows) ? rows[0] : undefined;
132+
const row = Array.isArray(rows) ? rows[0] as unknown as PermissionRow | undefined : undefined;
122133
if (!row) return undefined;
123-
return JSON.parse((row as Record<string, unknown>).config as string) as PermissionConfig;
134+
return JSON.parse(row.config) as PermissionConfig;
124135
} catch {
125136
return undefined;
126137
}
@@ -131,12 +142,11 @@ export class DatabasePermissionStorage implements IPermissionStorage {
131142
const result = new Map<string, PermissionConfig>();
132143
try {
133144
const rows = await driver.find(this.tableName, {});
134-
const items = Array.isArray(rows) ? rows : [];
145+
const items = Array.isArray(rows) ? rows as unknown as PermissionRow[] : [];
135146
for (const row of items) {
136147
try {
137-
const rowData = row as Record<string, unknown>;
138-
const config = JSON.parse(rowData.config as string) as PermissionConfig;
139-
result.set(rowData.object_name as string, config);
148+
const config = JSON.parse(row.config) as PermissionConfig;
149+
result.set(row.object_name, config);
140150
} catch {
141151
// Skip rows with corrupt JSON
142152
}
@@ -153,11 +163,11 @@ export class DatabasePermissionStorage implements IPermissionStorage {
153163
try {
154164
const rows = await driver.find(this.tableName, {});
155165
// Create a shallow copy to avoid issues when deleting during iteration
156-
const items = Array.isArray(rows) ? [...rows] : [];
166+
const items = Array.isArray(rows) ? rows as unknown as PermissionRow[] : [];
157167
for (const row of items) {
158-
const rowData = row as Record<string, unknown>;
159-
if (rowData._id || rowData.id || rowData.object_name) {
160-
await driver.delete(this.tableName, (rowData._id ?? rowData.id ?? rowData.object_name) as string | number, {});
168+
const id = row._id ?? row.id ?? row.object_name;
169+
if (id !== undefined) {
170+
await driver.delete(this.tableName, id, {});
161171
}
162172
}
163173
} catch {
@@ -187,14 +197,15 @@ export class DatabasePermissionStorage implements IPermissionStorage {
187197
filters: [['object_name', '=', config.object]],
188198
top: 1,
189199
});
190-
const row = Array.isArray(rows) ? rows[0] : undefined;
200+
const row = Array.isArray(rows) ? rows[0] as unknown as PermissionRow | undefined : undefined;
191201
if (row) {
192-
const rowData = row as Record<string, unknown>;
193-
const id = rowData._id ?? rowData.id ?? rowData.object_name;
194-
await driver.update(this.tableName, id as string | number, {
202+
const id = row._id ?? row.id ?? row.object_name;
203+
if (id !== undefined) {
204+
await driver.update(this.tableName, id, {
195205
config: JSON.stringify(config),
196206
updated_at: new Date().toISOString(),
197207
}, {});
208+
}
198209
}
199210
} else {
200211
await driver.create(this.tableName, {
@@ -215,11 +226,12 @@ export class DatabasePermissionStorage implements IPermissionStorage {
215226
filters: [['object_name', '=', objectName]],
216227
top: 1,
217228
});
218-
const row = Array.isArray(rows) ? rows[0] : undefined;
229+
const row = Array.isArray(rows) ? rows[0] as unknown as PermissionRow | undefined : undefined;
219230
if (row) {
220-
const rowData = row as Record<string, unknown>;
221-
const id = rowData._id ?? rowData.id ?? rowData.object_name;
222-
await driver.delete(this.tableName, id as string | number, {});
231+
const id = row._id ?? row.id ?? row.object_name;
232+
if (id !== undefined) {
233+
await driver.delete(this.tableName, id, {});
234+
}
223235
}
224236
} catch {
225237
// Row may not exist

packages/foundation/plugin-validator/src/validator.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ import {
2727
ValidationOperator,
2828
} from '@objectql/types';
2929

30+
/**
31+
* Minimal API interface expected by validation context
32+
*/
33+
interface ValidationApi {
34+
count(objectName: string, filters: Record<string, unknown>): Promise<number>;
35+
}
36+
3037
/**
3138
* Configuration options for the Validator.
3239
*/
@@ -480,7 +487,7 @@ export class Validator {
480487

481488
try {
482489
// Query database to count existing records with same field values
483-
const count = await (context.api as { count: (obj: string, filters: Record<string, unknown>) => Promise<number> }).count(objectName, filters);
490+
const count = await (context.api as ValidationApi).count(objectName, filters);
484491

485492
const valid = count === 0;
486493

0 commit comments

Comments
 (0)