UNPKG

@anyme/anymejs

Version:
197 lines (194 loc) 6.67 kB
import { existsSync, readFileSync } from 'node:fs'; import { resolve, isAbsolute, sep } from 'node:path'; import { pathToFileURL } from 'node:url'; import { randomBytes, createCipheriv, createHash, createDecipheriv } from 'node:crypto'; import { IV_LENGTH, ENC_DEFAULT_KEY } from './constants.js'; function merge(target, source) { if (!isObject(source)) return target; if (!isObject(target)) return source; const result = { ...target }; [...Object.keys(source)].forEach((key) => { if (isObject(target[key]) && isObject(source[key])) { result[key] = merge(target[key], source[key]); } else result[key] = source[key]; }); return result; } function deepMerge(target, ...sources) { if (sources.length === 0) return { ...target }; return [...sources].reduce((acc, source) => { if (isEmpty(source)) return acc; return merge(acc, source); }, { ...target }); } function isObject(obj) { return (typeof obj === "object" && obj !== null && !Array.isArray(obj) && Object.prototype.toString.call(obj) === "[object Object]"); } function isEmpty(value) { if (!value) return true; if (typeof value === "string" || Array.isArray(value) || (typeof value === "object" && "length" in value && typeof value.length === "number")) { return value.length === 0; } if (value instanceof Map || value instanceof Set) { return value.size === 0; } if (Object.prototype.toString.call(value) === "[object Object]") { return Object.keys(value).length === 0; } return false; } function isFunction(value) { return (typeof value === "function" && (Object.prototype.toString.call(value) === "[object Function]" || Object.prototype.toString.call(value) === "[object AsyncFunction]")); } function validateKey(key) { const keyBuffer = Buffer.from(key); if (keyBuffer.length === 32) return keyBuffer; return createHash("sha256").update(key).digest(); } function getEncryptionKey() { return process.env.ENCRYPT_KEY || ENC_DEFAULT_KEY; } function encrypt(text, key) { if (isEmpty(key)) throw new Error("Encryption key cannot be empty"); const keyBuffer = validateKey(key); const iv = randomBytes(IV_LENGTH); const cipher = createCipheriv("aes-256-cbc", keyBuffer, iv); let encrypted = cipher.update(text, "utf8"); encrypted = Buffer.concat([encrypted, cipher.final()]); return `${iv.toString("hex")}:${encrypted.toString("hex")}`; } function decrypt(encryptedText, key) { const keyBuffer = validateKey(key); const [ivHex, encryptedHex] = encryptedText.split(":"); if (!ivHex || !encryptedHex) { throw new Error('Invalid encrypted text format. Expected "iv:encryptedData"'); } const iv = Buffer.from(ivHex, "hex"); if (iv.length !== IV_LENGTH) { throw new Error(`Invalid IV length: ${iv.length} bytes. Expected ${IV_LENGTH} bytes.`); } const encrypted = Buffer.from(encryptedHex, "hex"); const decipher = createDecipheriv("aes-256-cbc", keyBuffer, iv); let decrypted = decipher.update(encrypted); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString("utf8"); } function getAbsolutePath(path, cwd) { return resolve(process.cwd(), path); } function readPackage() { const pkgPath = resolve("package.json"); if (!existsSync(pkgPath)) throw new Error("package.json not found"); return JSON.parse(readFileSync(pkgPath, "utf8")); } function isPackage(path) { const isScopedPackage = path.startsWith("@") && path.split("/").length === 2; if (isScopedPackage) return true; if (path.startsWith("./") || path.startsWith("../")) return false; if (isAbsolute(path)) return false; const hasPathSeparator = path.includes("/") || path.includes(sep); if (hasPathSeparator) return false; return true; } function importJson(path, options = {}) { const { throwIfMissing = false, throwIfInvalid = false } = options; if (!existsSync(path)) { const error = new Error(`JSON 文件不存在: ${path}`); if (throwIfMissing) throw error; console.warn(error.message); return {}; } try { const content = readFileSync(path, "utf-8").trim(); if (!content) return {}; return JSON.parse(content); } catch (error) { const parseError = error instanceof Error ? new Error(`解析 JSON 失败 (${path}): ${error.message}`) : new Error(`解析 JSON 失败 (${path})`); if (throwIfInvalid) throw parseError; return {}; } } async function importModule(path, cwd) { const isPkg = isPackage(path); const absolutePath = getAbsolutePath(path); if (typeof require === "undefined") { const module = await import(isPkg ? path : pathToFileURL(absolutePath).href); return isPkg ? module : module.default ?? module; } else { const module = require(isPkg ? path : absolutePath); if (module.default && Object.keys(module).length === 1) return module.default; if (module.__esModule) return module.default ?? module; return module; } } function ENC(text) { return decrypt(text, getEncryptionKey()); } function set(str, value) { const keys = str.trim().split("."); const result = {}; let current = result; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (!current[key]) current[key] = {}; current = current[key]; } const lastKey = keys[keys.length - 1]; current[lastKey] = value; return result; } function ctx() { const pkg = readPackage(); return { name: pkg.name ?? "anyme", version: pkg.version ?? "0.0.0", pkg, env: process.env.NODE_ENV || "development", ENC, ROOT: process.cwd(), HOME: resolve(process.env.HOME_PATH || "src"), }; } function defineConfig(configOptions) { if (!isFunction(configOptions)) return configOptions; return configOptions(ctx()); } function all(iterable, mapfn, thisArg) { return Promise.all(mapfn ? Array.from(iterable, mapfn, thisArg) : Array.from(iterable)); } export { all, ctx, decrypt, deepMerge, defineConfig, encrypt, getAbsolutePath, getEncryptionKey, importJson, importModule, isEmpty, isFunction, isObject, merge, set }; //# sourceMappingURL=index.js.map