| 25 | }; |
| 26 | |
| 27 | export class APIManager extends ConfigStoreItem { |
| 28 | onAddCredential: Signal<(credential: APICredential) => void> = new Signal(); |
| 29 | onUpdateCredential: Signal<(credential: APICredential) => void> = new Signal(); |
| 30 | onRemoveCredential: Signal<(credential: APICredential) => void> = new Signal(); |
| 31 | |
| 32 | #apis: Record<string, APIRecord> = {}; |
| 33 | #credentials: Record<string, APICredential> = {}; |
| 34 | |
| 35 | deserialize(data: object) { |
| 36 | if (!data) // accepts empty config |
| 37 | data = {}; |
| 38 | if (typeof data != 'object') |
| 39 | throw new Error(`Unknown data for "apis": ${data}.`); |
| 40 | this.#credentials = {}; |
| 41 | for (const id in data) { |
| 42 | const credential = APICredential.deserialize(data[id]); |
| 43 | credential.id = id; |
| 44 | this.#credentials[id] = credential; |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | serialize() { |
| 49 | const data = {}; |
| 50 | for (const id in this.#credentials) |
| 51 | data[id] = this.#credentials[id].serialize(); |
| 52 | return data; |
| 53 | } |
| 54 | |
| 55 | registerAPI(record: APIRecord) { |
| 56 | if (record.name in this.#apis) |
| 57 | throw new Error(`API with name "${record.name}" has already been registered.`); |
| 58 | this.#apis[record.name] = record; |
| 59 | this.saveConfig(); |
| 60 | } |
| 61 | |
| 62 | unregisterAPI(name: string) { |
| 63 | if (!(name in this.#apis)) |
| 64 | throw new Error(`There is no API named "${name}".`); |
| 65 | if (this.getCredentials().find(e => e.type == name)) |
| 66 | throw new Error(`Can not unregister API "${name}" because there is an API credential using it.`); |
| 67 | delete this.#apis[name]; |
| 68 | this.saveConfig(); |
| 69 | } |
| 70 | |
| 71 | getAPISelections(): Selection[] { |
| 72 | return Object.keys(this.#apis).map(k => ({name: k, value: this.#apis[k]})).sort(sortByPriority); |
| 73 | } |
| 74 | |
| 75 | getAPIRecord(name: string) { |
| 76 | if (!(name in this.#apis)) |
| 77 | throw new Error(`API with name "${name}" does not exist.`); |
| 78 | return this.#apis[name]; |
| 79 | } |
| 80 | |
| 81 | createAPIForCredential(credential: APICredential) { |
| 82 | if (!(credential.type in this.#apis)) |
| 83 | throw new Error(`Unable to find API implementation for credential ${credential.type}.`); |
| 84 | return new (this.#apis[credential.type].apiClass)(credential); |
nothing calls this directly
no outgoing calls
no test coverage detected