MCPcopy Create free account
hub / github.com/OpenAnonymity/oa-chat / ApiKeyStore

Class ApiKeyStore

chat/services/apiKeyStore.js:11–160  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

9const ACCESS_DB_KEY = 'apiKeyData';
10
11class ApiKeyStore {
12 constructor() {
13 this.listeners = [];
14 this.state = {
15 apiKey: null,
16 apiKeyInfo: null,
17 expiresAt: null,
18 ticketUsed: null
19 };
20 }
21
22 getState() {
23 return { ...this.state };
24 }
25
26 subscribe(listener) {
27 this.listeners.push(listener);
28 }
29
30 unsubscribe(listener) {
31 this.listeners = this.listeners.filter(l => l !== listener);
32 }
33
34 notify() {
35 this.listeners.forEach(listener => listener());
36 }
37
38 async loadApiKey() {
39 try {
40 if (typeof chatDB !== 'undefined') {
41 if (!chatDB.db && typeof chatDB.init === 'function') {
42 await chatDB.init();
43 }
44 const stored = await chatDB.getSetting(ACCESS_DB_KEY);
45 if (stored) {
46 this.state = {
47 apiKey: stored.key,
48 apiKeyInfo: stored,
49 expiresAt: stored.expiresAt || stored.expires_at, // Support both formats
50 ticketUsed: stored.ticketUsed || stored.ticket_used
51 };
52 console.log('📥 Loaded API key from IndexedDB');
53 this.notify();
54 return;
55 }
56 }
57
58 const legacyStored = localStorage.getItem(ACCESS_STORAGE_KEY);
59 if (legacyStored) {
60 const data = JSON.parse(legacyStored);
61 this.state = {
62 apiKey: data.key,
63 apiKeyInfo: data,
64 expiresAt: data.expiresAt || data.expires_at,
65 ticketUsed: data.ticketUsed || data.ticket_used
66 };
67 let persisted = false;
68 if (typeof chatDB !== 'undefined' && chatDB.db) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected