158 lines
4.9 KiB
TypeScript
158 lines
4.9 KiB
TypeScript
import { Cache } from './login-cache.ts';
|
||
import { homedir } from 'node:os';
|
||
import { join, dirname } from 'node:path';
|
||
import fs from 'node:fs';
|
||
import { readFileSync, writeFileSync, accessSync, unlinkSync, mkdirSync } from 'node:fs';
|
||
export const fileExists = (
|
||
filePath: string,
|
||
{ createIfNotExists = true, isFile = true, isDir = false }: { createIfNotExists?: boolean; isFile?: boolean; isDir?: boolean } = {},
|
||
) => {
|
||
try {
|
||
accessSync(filePath, fs.constants.F_OK);
|
||
return true;
|
||
} catch (error) {
|
||
if (createIfNotExists && isDir) {
|
||
mkdirSync(filePath, { recursive: true });
|
||
return true;
|
||
} else if (createIfNotExists && isFile) {
|
||
mkdirSync(dirname(filePath), { recursive: true });
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
};
|
||
export const readConfigFile = (filePath: string) => {
|
||
try {
|
||
const data = readFileSync(filePath, 'utf-8');
|
||
const jsonData = JSON.parse(data);
|
||
return jsonData;
|
||
} catch (error) {
|
||
return {};
|
||
}
|
||
};
|
||
export const writeConfigFile = (filePath: string, data: any) => {
|
||
writeFileSync(filePath, JSON.stringify(data, null, 2));
|
||
};
|
||
/**
|
||
* 获取主机名,
|
||
* 例如:https://kevisual.cn 返回 kevisual.cn
|
||
* 这里是读取默认的配置文件 ~/.config/envision/config.json 中的 baseURL 字段来获取主机名的,如果没有配置 baseURL 则默认使用 https://kevisual.cn
|
||
* @returns 主机名
|
||
*/
|
||
export const getHostName = (baseURL?: string) => {
|
||
const configDir = join(homedir(), '.config', 'envision');
|
||
const configFile = join(configDir, 'config.json');
|
||
const config = readConfigFile(configFile);
|
||
const _baseURL = baseURL || config.baseURL || 'https://kevisual.cn';
|
||
const hostname = new URL(_baseURL).hostname;
|
||
return hostname;
|
||
};
|
||
export class StorageNode implements Storage {
|
||
cacheData: any;
|
||
filePath: string = '';
|
||
hostname: string = '';
|
||
isLoaded: boolean = false;
|
||
constructor(opts?: { baseURL?: string, load?: boolean }) {
|
||
this.cacheData = {};
|
||
const hostname = getHostName(opts?.baseURL);
|
||
this.setHostName(hostname, { load: opts?.load });
|
||
}
|
||
setHostName(hostname: string, opts?: { load?: boolean }) {
|
||
const load = opts?.load ?? false;
|
||
if (hostname.startsWith('http')) {
|
||
hostname = new URL(hostname).hostname;
|
||
}
|
||
const configDir = join(homedir(), '.config', 'envision');
|
||
this.filePath = join(configDir, 'config', `${hostname}-storage.json`);
|
||
this.hostname = hostname;
|
||
fileExists(this.filePath, { isFile: true });
|
||
if (load) {
|
||
this.loadCache();
|
||
}
|
||
}
|
||
loadCache(force?: boolean) {
|
||
if (this.isLoaded && !force) return;
|
||
const filePath = this.filePath;
|
||
try {
|
||
const data = readConfigFile(filePath);
|
||
this.cacheData = data;
|
||
this.isLoaded = true;
|
||
} catch (error) {
|
||
this.cacheData = {};
|
||
writeFileSync(filePath, JSON.stringify(this.cacheData, null, 2));
|
||
}
|
||
}
|
||
get length() {
|
||
return Object.keys(this.cacheData).length;
|
||
}
|
||
getItem(key: string) {
|
||
return this.cacheData[key];
|
||
}
|
||
setItem(key: string, value: any) {
|
||
this.cacheData[key] = value;
|
||
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
||
}
|
||
removeItem(key: string) {
|
||
delete this.cacheData[key];
|
||
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
||
}
|
||
clear() {
|
||
this.cacheData = {};
|
||
writeFileSync(this.filePath, JSON.stringify(this.cacheData, null, 2));
|
||
}
|
||
key(index: number) {
|
||
return Object.keys(this.cacheData)[index];
|
||
}
|
||
}
|
||
export class LoginNodeCache implements Cache {
|
||
filepath: string;
|
||
isLoaded: boolean = false;
|
||
constructor(opts?: { baseURL?: string, load?: boolean }) {
|
||
this.filepath = join(homedir(), '.config', 'envision', 'config', `${getHostName(opts?.baseURL)}-login.json`);
|
||
fileExists(this.filepath, { isFile: true });
|
||
if (opts?.load) {
|
||
this.loadCache(this.filepath);
|
||
}
|
||
}
|
||
async get(_key: string) {
|
||
try {
|
||
const filePath = this.filepath;
|
||
const data = readConfigFile(filePath);
|
||
return data;
|
||
} catch (error) {
|
||
console.log('get error', error);
|
||
return {};
|
||
}
|
||
}
|
||
async set(_key: string, value: any) {
|
||
try {
|
||
const data = readConfigFile(this.filepath);
|
||
const newData = { ...data, ...value };
|
||
writeConfigFile(this.filepath, newData);
|
||
} catch (error) {
|
||
console.log('set error', error);
|
||
}
|
||
}
|
||
async del() {
|
||
unlinkSync(this.filepath);
|
||
}
|
||
loadCache(filePath: string, force?: boolean) {
|
||
if (this.isLoaded && !force) return;
|
||
try {
|
||
const data = readFileSync(filePath, 'utf-8');
|
||
const jsonData = JSON.parse(data);
|
||
this.isLoaded = true;
|
||
return jsonData;
|
||
} catch (error) {
|
||
// console.log('loadCache error', error);
|
||
console.log('create new cache file:', filePath);
|
||
const defaultData = { loginUsers: [] };
|
||
writeConfigFile(filePath, defaultData);
|
||
return defaultData;
|
||
}
|
||
}
|
||
init() {
|
||
return this.loadCache(this.filepath);
|
||
}
|
||
}
|