/** * Profile types + ProfileManager (v2.18) * * Multi-DB profile management: save/list/delete profiles, runtime live connections, * read/write routing, global schema view. * * Implementation broken into multiple tasks: * - Task 2: Profile types + ProfileStore (SQLite CRUD) * - Task 3: QueryRouter * - Task 4: ProfileManager facade + LiveProfile * - Task 5: GlobalSchemaView */ import type { DbConfig } from '../types/adapter.js'; export type ProfileRole = 'primary' | 'replica' | 'analytics'; export type ReadRouting = 'round-robin' | 'random' | 'least-loaded'; export type PermissionMode = 'safe' | 'readwrite' | 'full'; export type ProfileCategory = 'rdbms' | 'kv' | 'document' | 'columnar' | 'search' | 'unknown'; export interface Profile { id: string; name: string; description: string; type: string; config: DbConfig; role: ProfileRole; tags: string[]; enabled: boolean; created_at: string; updated_at: string; created_by: string; use_count: number; permissionMode: PermissionMode; category: ProfileCategory; productName: string | null; version: string | null; } export interface ProfileInput { name: string; description: string; type: string; config: DbConfig; role?: ProfileRole; tags?: string[]; enabled?: boolean; permissionMode?: PermissionMode; category?: ProfileCategory; productName?: string | null; version?: string | null; } /** * v4.2.0:profile 命名严格约束 — 必须 /^[a-zA-Z0-9_-]+$/ * 因为 profile 名作为子目录名(/~/.universal-db-mcp//history.db 等), * 不能含 `.`、空格、中文、路径分隔符等。 */ export declare function isValidProfileName(name: string): boolean; import { ProfileStore } from './profile-store.js'; import { DatabaseService, SchemaCacheConfig } from './database-service.js'; import type { DbAdapter, QueryResult } from '../types/adapter.js'; import type { QueryAnalyzer } from './query-analyzer.js'; import { type ImportMode, type ImportResult } from './profile-serializer.js'; export interface ProfileManagerOptions { enabled: boolean; profilesDbPath: string; maxProfiles: number; defaultRole: ProfileRole; readRouting: ReadRouting; /** v2.19: SQLCipher key for profiles.db encryption (optional, falls back to plaintext) */ cipherKey?: string; /** v2.20: rotation old key (used by KeyRotator on startup). */ cipherKeyOld?: string; cacheConfig?: Partial; } export interface LiveProfile { profile: Profile; adapter: DbAdapter; service: DatabaseService; connectedAt: Date; } export declare class ProfileManager { private store; private router; private liveProfiles; private enabled; private maxProfiles; /** * v3.2: expose the underlying ProfileStore so MCP/HTTP handlers can call * setEnabled() for enable_profile/disable_profile tools. */ getProfileStore(): ProfileStore; private defaultRole; private readRouting; /** v2.19: cipher key for ProfileStore (Task 3 wires it through). */ readonly cipherKey?: string; private lruOrder; private cacheConfig?; /** v2.19: optional QueryAnalyzer for routeQuery history recording. */ private queryAnalyzer; constructor(opts: ProfileManagerOptions); /** * v2.19: wire a QueryAnalyzer so {@link routeQuery} records history rows * tagged with `profile_name`. Pass `null` to detach. */ setQueryAnalyzer(qa: QueryAnalyzer | null): void; /** v2.19: diagnostic accessor. */ getQueryAnalyzer(): QueryAnalyzer | null; /** * v2.20: export profiles to a YAML or JSON string. * Passwords are REDACTED by default; pass `{ includeSecrets: true }` to keep them. */ exportProfiles(format?: 'yaml' | 'json', opts?: { includeSecrets?: boolean; }): Promise; /** * v2.20: import profiles from a YAML or JSON string. * `mode`: * - 'merge' (default): insert new profiles, update existing ones * - 'replace': delete all current profiles and replace with input * `dryRun`: when true, do not actually save; returns a what-if preview. * * Profiles whose config contains REDACTED placeholders for sensitive fields * MUST be re-supplied by the caller via `passwords: { [name]: { password: 'x' } }`. * Without those, importing leaves the redaction in place. */ importProfiles(input: string, opts?: { mode?: ImportMode; format?: 'yaml' | 'json'; dryRun?: boolean; passwords?: Record>; }): Promise; isEnabled(): boolean; createProfile(input: ProfileInput, createdBy?: string): Promise; /** * v5.0.0: saveProfile() is a deprecated alias for createProfile(). New code should * use createProfile() to make the INSERT-only semantic explicit. */ saveProfile(input: ProfileInput, createdBy?: string): Promise; /** * v5.0.0: 修改已存在的 profile(UPDATE-only)。profile 不存在抛 'profile ... does not exist'。 * 不会动 use_count / created_at / created_by / id。 */ updateProfile(input: ProfileInput): Promise; listProfiles(filter?: { role?: string; tag?: string; enabled?: boolean; }): Promise; getProfile(name: string): Promise; deleteProfile(name: string, opts?: { confirm?: boolean; }): Promise; /** * v5.0.0: 预览 delete_profile 会清理哪些文件。返回 null 表示 profile 不存在。 * 不传 confirm 时被 deleteProfile 调用,作为错误消息的一部分告知用户。 */ private previewProfileDelete; loadProfile(name: string): Promise; unloadProfile(name: string): Promise; getLive(name: string): Promise; listLive(): Promise; routeQuery(profileName: string, sql: string, kind: 'read' | 'write', params?: unknown[]): Promise; closeAll(): Promise; getMetricsSnapshot(): { enabled: boolean; total_profiles: number; live_profiles: string[]; read_routing: ReadRouting; }; private touchLRU; private evictIfOverLimit; } //# sourceMappingURL=profile-manager.d.ts.map