67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
|
|
import type { ISecretBackend, TBackendType } from './smartsecret.backends.base.js';
|
||
|
|
import { MacosKeychainBackend } from './smartsecret.backends.macos.js';
|
||
|
|
import { LinuxSecretServiceBackend } from './smartsecret.backends.linux.js';
|
||
|
|
import { FileEncryptedBackend } from './smartsecret.backends.file.js';
|
||
|
|
|
||
|
|
export interface ISmartSecretOptions {
|
||
|
|
service?: string;
|
||
|
|
vaultPath?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export class SmartSecret {
|
||
|
|
private service: string;
|
||
|
|
private vaultPath?: string;
|
||
|
|
private backend: ISecretBackend | null = null;
|
||
|
|
|
||
|
|
constructor(options?: ISmartSecretOptions) {
|
||
|
|
this.service = options?.service ?? 'smartsecret';
|
||
|
|
this.vaultPath = options?.vaultPath;
|
||
|
|
}
|
||
|
|
|
||
|
|
private async getBackend(): Promise<ISecretBackend> {
|
||
|
|
if (this.backend) return this.backend;
|
||
|
|
|
||
|
|
const candidates: ISecretBackend[] = [
|
||
|
|
new MacosKeychainBackend(this.service),
|
||
|
|
new LinuxSecretServiceBackend(this.service),
|
||
|
|
new FileEncryptedBackend(this.service, this.vaultPath),
|
||
|
|
];
|
||
|
|
|
||
|
|
for (const candidate of candidates) {
|
||
|
|
if (await candidate.isAvailable()) {
|
||
|
|
this.backend = candidate;
|
||
|
|
return this.backend;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// File backend is always available, so we should never reach here
|
||
|
|
this.backend = candidates[candidates.length - 1];
|
||
|
|
return this.backend;
|
||
|
|
}
|
||
|
|
|
||
|
|
async setSecret(account: string, secret: string): Promise<void> {
|
||
|
|
const backend = await this.getBackend();
|
||
|
|
await backend.setSecret(account, secret);
|
||
|
|
}
|
||
|
|
|
||
|
|
async getSecret(account: string): Promise<string | null> {
|
||
|
|
const backend = await this.getBackend();
|
||
|
|
return backend.getSecret(account);
|
||
|
|
}
|
||
|
|
|
||
|
|
async deleteSecret(account: string): Promise<boolean> {
|
||
|
|
const backend = await this.getBackend();
|
||
|
|
return backend.deleteSecret(account);
|
||
|
|
}
|
||
|
|
|
||
|
|
async listAccounts(): Promise<string[]> {
|
||
|
|
const backend = await this.getBackend();
|
||
|
|
return backend.listAccounts();
|
||
|
|
}
|
||
|
|
|
||
|
|
async getBackendType(): Promise<TBackendType> {
|
||
|
|
const backend = await this.getBackend();
|
||
|
|
return backend.backendType;
|
||
|
|
}
|
||
|
|
}
|