UNPKG

@truenewx/tnxcore

Version:

互联网技术解决方案:Web核心扩展支持

183 lines (162 loc) 5.47 kB
/** * Yaml访问器 */ import yaml from 'js-yaml'; export default class Yaml { #config = {}; indent = 2; constructor(content, indent) { if (content) { if (typeof content === 'string') { this.#config = yaml.load(content) || {}; } else if (typeof content === 'object') { Object.assign(this.#config, content); } } if (indent > 0) { this.indent = indent; } } /** * 获取值 * @param {[String]} keys 键清单 * @return {*} 值 */ get(keys = []) { if (!Array.isArray(keys)) { throw new TypeError('keys必须是数组'); } let value = this.#config; for (let k of keys) { if (typeof k !== 'string') { throw new TypeError('keys中的元素必须是字符串'); } if (typeof value === 'object') { value = value[k]; } else { return undefined; } } return value; } /** * 设置值 * @param {[String]} keys 键清单 * @param {*} value 值 */ set(keys, value) { let parent = this.#getParentNode(keys); parent[keys[keys.length - 1]] = value; } #getParentNode(keys) { if (!Array.isArray(keys) || keys.length === 0) { throw new TypeError('keys必须是非空数组'); } // 确保路径上的所有父对象都存在 let parent = this.#config; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (typeof key !== 'string') { throw new TypeError('keys中的元素必须是字符串'); } if (parent[key] === undefined || parent[key] === null) { parent[key] = {}; } parent = parent[key]; } return parent; } /** * 仅当值不存在时设置 * @param {[String]} keys 键清单 * @param {*} value 值 * @returns {boolean} 是否设置成功 */ setIfAbsent(keys, value) { let parent = this.#getParentNode(keys); const lastKey = keys[keys.length - 1]; if (parent[lastKey] !== undefined && parent[lastKey] !== null) { return false; } parent[lastKey] = value; return true; } remove(keys) { if (!Array.isArray(keys) || keys.length === 0) { throw new TypeError('keys必须是非空数组'); } // 验证所有key必须是字符串 for (const key of keys) { if (typeof key !== 'string') { throw new TypeError('keys中的元素必须是字符串'); } } // 如果只有一个键,直接从根配置中删除 if (keys.length === 1) { if (keys[0] in this.#config) { delete this.#config[keys[0]]; return true; } return false; } // 递归删除并检查父节点 const removeRecursive = (obj, keyPath, index) => { // 已到达倒数第二层 if (index === keyPath.length - 1) { const lastKey = keyPath[index]; if (lastKey in obj) { delete obj[lastKey]; return true; } return false; } const currentKey = keyPath[index]; if (!(currentKey in obj) || typeof obj[currentKey] !== 'object' || Array.isArray(obj[currentKey])) { return false; // 路径不存在或不是对象 } const result = removeRecursive(obj[currentKey], keyPath, index + 1); // 如果删除成功且当前节点为空对象,则删除当前节点 if (result && Object.keys(obj[currentKey]).length === 0) { delete obj[currentKey]; } return result; }; return removeRecursive(this.#config, keys, 0); } isEmpty() { return Object.keys(this.#config).length === 0; } forEach(consumer) { const traverse = (obj, path = []) => { if (obj && typeof obj === 'object') { if (Array.isArray(obj)) { // 将数组作为叶子节点处理 consumer(path, obj); } else { for (const [key, value] of Object.entries(obj)) { const currentPath = [...path, key]; if (value === null || typeof value !== 'object' || Array.isArray(value)) { // 叶子节点:null、非对象值或数组 consumer(currentPath, value); } else { // 继续遍历子节点(普通对象) traverse(value, currentPath); } } } } }; traverse(this.#config); } toString() { if (this.isEmpty()) { return ''; } return yaml.dump(this.#config, { indent: this.indent, lineWidth: -1, quotingType: '"', forceQuotes: false, }); } }