mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 23:02:10 +03:00
feat(db): add apiKeyContextSources module + migration 092
Implements per-API-key context source configuration table and CRUD functions required by the Obsidian PR. Restores getApiKeyContextSource in obsidian.ts (was stubbed to null during conflict resolution). 11/11 tests pass in obsidian-config.test.ts.
This commit is contained in:
107
src/lib/db/apiKeyContextSources.ts
Normal file
107
src/lib/db/apiKeyContextSources.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { getDbInstance } from "./core";
|
||||
|
||||
export interface ApiKeyContextSource {
|
||||
apiKeyId: string;
|
||||
sourceType: string;
|
||||
token: string | null;
|
||||
baseUrl: string | null;
|
||||
vaultPath: string | null;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
interface ContextSourceRow {
|
||||
api_key_id: string;
|
||||
source_type: string;
|
||||
token: string | null;
|
||||
base_url: string | null;
|
||||
vault_path: string | null;
|
||||
enabled: number;
|
||||
}
|
||||
|
||||
function rowToSource(row: ContextSourceRow): ApiKeyContextSource {
|
||||
return {
|
||||
apiKeyId: row.api_key_id,
|
||||
sourceType: row.source_type,
|
||||
token: row.token,
|
||||
baseUrl: row.base_url,
|
||||
vaultPath: row.vault_path,
|
||||
enabled: row.enabled === 1,
|
||||
};
|
||||
}
|
||||
|
||||
export function getApiKeyContextSource(
|
||||
apiKeyId: string | null | undefined,
|
||||
sourceType: string
|
||||
): (ApiKeyContextSource & { enabled: true }) | null {
|
||||
if (!apiKeyId) return null;
|
||||
const db = getDbInstance();
|
||||
const row = db
|
||||
.prepare(
|
||||
"SELECT * FROM api_key_context_sources WHERE api_key_id = ? AND source_type = ? AND enabled = 1"
|
||||
)
|
||||
.get(apiKeyId, sourceType) as ContextSourceRow | undefined;
|
||||
if (!row) return null;
|
||||
return rowToSource(row) as ApiKeyContextSource & { enabled: true };
|
||||
}
|
||||
|
||||
export function setApiKeyContextSource(
|
||||
apiKeyId: string,
|
||||
sourceType: string,
|
||||
config: { token?: string; baseUrl?: string; vaultPath?: string; enabled?: boolean }
|
||||
): void {
|
||||
const db = getDbInstance();
|
||||
const existing = db
|
||||
.prepare("SELECT * FROM api_key_context_sources WHERE api_key_id = ? AND source_type = ?")
|
||||
.get(apiKeyId, sourceType) as ContextSourceRow | undefined;
|
||||
|
||||
const now = new Date().toISOString();
|
||||
if (existing) {
|
||||
db.prepare(
|
||||
`UPDATE api_key_context_sources SET
|
||||
token = COALESCE(?, token),
|
||||
base_url = COALESCE(?, base_url),
|
||||
vault_path = COALESCE(?, vault_path),
|
||||
enabled = COALESCE(?, enabled),
|
||||
updated_at = ?
|
||||
WHERE api_key_id = ? AND source_type = ?`
|
||||
).run(
|
||||
config.token ?? null,
|
||||
config.baseUrl ?? null,
|
||||
config.vaultPath ?? null,
|
||||
config.enabled !== undefined ? (config.enabled ? 1 : 0) : null,
|
||||
now,
|
||||
apiKeyId,
|
||||
sourceType
|
||||
);
|
||||
} else {
|
||||
db.prepare(
|
||||
`INSERT INTO api_key_context_sources
|
||||
(api_key_id, source_type, token, base_url, vault_path, enabled, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
).run(
|
||||
apiKeyId,
|
||||
sourceType,
|
||||
config.token ?? null,
|
||||
config.baseUrl ?? null,
|
||||
config.vaultPath ?? null,
|
||||
config.enabled !== undefined ? (config.enabled ? 1 : 0) : 1,
|
||||
now,
|
||||
now
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteApiKeyContextSource(apiKeyId: string, sourceType: string): void {
|
||||
const db = getDbInstance();
|
||||
db.prepare(
|
||||
"DELETE FROM api_key_context_sources WHERE api_key_id = ? AND source_type = ?"
|
||||
).run(apiKeyId, sourceType);
|
||||
}
|
||||
|
||||
export function listApiKeyContextSources(apiKeyId: string): ApiKeyContextSource[] {
|
||||
const db = getDbInstance();
|
||||
const rows = db
|
||||
.prepare("SELECT * FROM api_key_context_sources WHERE api_key_id = ?")
|
||||
.all(apiKeyId) as ContextSourceRow[];
|
||||
return rows.map(rowToSource);
|
||||
}
|
||||
13
src/lib/db/migrations/092_api_key_context_sources.sql
Normal file
13
src/lib/db/migrations/092_api_key_context_sources.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Per-API-key context source configuration (Obsidian, Notion, etc.)
|
||||
CREATE TABLE IF NOT EXISTS api_key_context_sources (
|
||||
api_key_id TEXT NOT NULL,
|
||||
source_type TEXT NOT NULL,
|
||||
token TEXT,
|
||||
base_url TEXT,
|
||||
vault_path TEXT,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
PRIMARY KEY (api_key_id, source_type),
|
||||
FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getDbInstance } from "./core";
|
||||
import { getApiKeyContextSource } from "./apiKeyContextSources";
|
||||
|
||||
const OBSIDIAN_NAMESPACE = "obsidian";
|
||||
const OBSIDIAN_TOKEN_KEY = "api_key";
|
||||
@@ -251,8 +252,7 @@ export function getObsidianConfigForApiKey(apiKeyId: string | null | undefined):
|
||||
} {
|
||||
if (apiKeyId) {
|
||||
try {
|
||||
// Per-key context source lookup not yet implemented — fall through to global
|
||||
const perKey = null as null | { enabled: boolean; token: string; baseUrl?: string; vaultPath?: string };
|
||||
const perKey = getApiKeyContextSource(apiKeyId, "obsidian");
|
||||
if (perKey && perKey.enabled && perKey.token) {
|
||||
return {
|
||||
token: perKey.token,
|
||||
|
||||
@@ -603,3 +603,11 @@ export {
|
||||
} from "./db/plugins";
|
||||
|
||||
export type { PluginRow, PluginCreateInput } from "./db/plugins";
|
||||
|
||||
export {
|
||||
getApiKeyContextSource,
|
||||
setApiKeyContextSource,
|
||||
deleteApiKeyContextSource,
|
||||
listApiKeyContextSources,
|
||||
} from "./db/apiKeyContextSources";
|
||||
export type { ApiKeyContextSource } from "./db/apiKeyContextSources";
|
||||
|
||||
Reference in New Issue
Block a user