@nsnanocat/util
Version:
Pure JS's util module for well-known iOS network tools
258 lines (250 loc) • 5.99 kB
JavaScript
import { $app } from "../lib/app.mjs";
import { Lodash as _ } from "./Lodash.mjs";
/**
* Storage
*
* @link https://developer.mozilla.org/zh-CN/docs/Web/API/Storage/setItem
* @export
* @class Storage
* @typedef {Storage}
*/
export class Storage {
/**
* data
*
* @static
* @type {file}
*/
static data = null;
static dataFile = "box.dat";
/**
* nameRegex
*
* @static
* @type {regexp}
*/
static #nameRegex = /^@(?<key>[^.]+)(?:\.(?<path>.*))?$/;
/**
* getItem
*
* @static
* @param {string} keyName
* @param {*} [defaultValue]
* @returns {*}
*/
static getItem(keyName, defaultValue = null) {
let keyValue = defaultValue;
// 如果以 @
switch (keyName.startsWith("@")) {
case true: {
const { key, path } = keyName.match(Storage.#nameRegex)?.groups;
keyName = key;
let value = Storage.getItem(keyName, {});
if (typeof value !== "object") value = {};
keyValue = _.get(value, path);
try {
keyValue = JSON.parse(keyValue);
} catch (e) {}
break;
}
default:
switch ($app) {
case "Surge":
case "Loon":
case "Stash":
case "Egern":
case "Shadowrocket":
keyValue = $persistentStore.read(keyName);
break;
case "Quantumult X":
keyValue = $prefs.valueForKey(keyName);
break;
case "Node.js":
Storage.data = Storage.#loaddata(Storage.dataFile);
keyValue = Storage.data?.[keyName];
break;
default:
keyValue = Storage.data?.[keyName] || null;
break;
}
try {
keyValue = JSON.parse(keyValue);
} catch (e) {
// do nothing
}
break;
}
return keyValue ?? defaultValue;
}
/**
* setItem
*
* @static
* @param {string} keyName
* @param {*} keyValue
* @returns {boolean}
*/
static setItem(keyName = new String(), keyValue = new String()) {
let result = false;
switch (typeof keyValue) {
case "object":
keyValue = JSON.stringify(keyValue);
break;
default:
keyValue = String(keyValue);
break;
}
switch (keyName.startsWith("@")) {
case true: {
const { key, path } = keyName.match(Storage.#nameRegex)?.groups;
keyName = key;
let value = Storage.getItem(keyName, {});
if (typeof value !== "object") value = {};
_.set(value, path, keyValue);
result = Storage.setItem(keyName, value);
break;
}
default:
switch ($app) {
case "Surge":
case "Loon":
case "Stash":
case "Egern":
case "Shadowrocket":
result = $persistentStore.write(keyValue, keyName);
break;
case "Quantumult X":
result = $prefs.setValueForKey(keyValue, keyName);
break;
case "Node.js":
Storage.data = Storage.#loaddata(Storage.dataFile);
Storage.data[keyName] = keyValue;
Storage.#writedata(Storage.dataFile);
result = true;
break;
default:
result = Storage.data?.[keyName] || null;
break;
}
break;
}
return result;
}
/**
* removeItem
*
* @static
* @param {string} keyName
* @returns {boolean}
*/
static removeItem(keyName) {
let result = false;
switch (keyName.startsWith("@")) {
case true: {
const { key, path } = keyName.match(Storage.#nameRegex)?.groups;
keyName = key;
let value = Storage.getItem(keyName);
if (typeof value !== "object") value = {};
keyValue = _.unset(value, path);
result = Storage.setItem(keyName, value);
break;
}
default:
switch ($app) {
case "Surge":
case "Loon":
case "Stash":
case "Egern":
case "Shadowrocket":
result = false;
break;
case "Quantumult X":
result = $prefs.removeValueForKey(keyName);
break;
case "Node.js":
result = false;
break;
default:
result = false;
break;
}
break;
}
return result;
}
/**
* clear
*
* @static
* @returns {boolean}
*/
static clear() {
let result = false;
switch ($app) {
case "Surge":
case "Loon":
case "Stash":
case "Egern":
case "Shadowrocket":
result = false;
break;
case "Quantumult X":
result = $prefs.removeAllValues();
break;
case "Node.js":
result = false;
break;
default:
result = false;
break;
}
return result;
}
/**
* #loaddata
*
* @param {string} dataFile
* @returns {*}
*/
static #loaddata = dataFile => {
if ($app === "Node.js") {
this.fs = this.fs ? this.fs : require("node:fs");
this.path = this.path ? this.path : require("node:path");
const curDirDataFilePath = this.path.resolve(dataFile);
const rootDirDataFilePath = this.path.resolve(process.cwd(), dataFile);
const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath);
const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath);
if (isCurDirDataFile || isRootDirDataFile) {
const datPath = isCurDirDataFile ? curDirDataFilePath : rootDirDataFilePath;
try {
return JSON.parse(this.fs.readFileSync(datPath));
} catch (e) {
return {};
}
} else return {};
} else return {};
};
/**
* #writedata
*
* @param {string} [dataFile=this.dataFile]
*/
static #writedata = (dataFile = this.dataFile) => {
if ($app === "Node.js") {
this.fs = this.fs ? this.fs : require("node:fs");
this.path = this.path ? this.path : require("node:path");
const curDirDataFilePath = this.path.resolve(dataFile);
const rootDirDataFilePath = this.path.resolve(process.cwd(), dataFile);
const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath);
const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath);
const jsondata = JSON.stringify(this.data);
if (isCurDirDataFile) {
this.fs.writeFileSync(curDirDataFilePath, jsondata);
} else if (isRootDirDataFile) {
this.fs.writeFileSync(rootDirDataFilePath, jsondata);
} else {
this.fs.writeFileSync(curDirDataFilePath, jsondata);
}
}
};
}