UNPKG

@nsnanocat/util

Version:

Pure JS's util module for well-known iOS network tools

258 lines (250 loc) 5.99 kB
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); } } }; }