@truenewx/tnxcore
Version:
互联网技术解决方案:JavaScript核心扩展支持
143 lines (124 loc) • 4.21 kB
text/typescript
import yaml from 'js-yaml';
/**
* Yaml访问器
*/
export default class Yaml {
#config: Record<string, any> = {};
indent = 2;
constructor(content: string | Record<string, any>, indent?: number) {
if (content) {
if (typeof content === 'string') {
this.#config = yaml.load(content) || {};
} else if (typeof content === 'object') {
Object.assign(this.#config, content);
}
}
if (indent && indent > 0) {
this.indent = indent;
}
}
/**
* 获取值
* @param {[String]} keys 键清单
* @return {*} 值
*/
get(keys: string[] = []): string | Record<string, any> | undefined {
let value: string | Record<string, any> = this.#config;
for (let k of keys) {
if (typeof value === 'object') {
value = value[k];
} else {
return undefined;
}
}
return value;
}
/**
* 设置值
* @param {[String]} keys 键清单
* @param {*} value 值
*/
set(keys: string[], value: any): void {
let parent = this.#getParentNode(keys);
parent[keys[keys.length - 1]] = value;
}
#getParentNode(keys: string[]): Record<string, any> {
// 确保路径上的所有父对象都存在
let parent = this.#config;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (parent[key] === undefined || parent[key] === null) {
parent[key] = {};
}
parent = parent[key];
}
return parent;
}
/**
* 仅当值不存在时设置
* @param {[String]} keys 键清单
* @param {*} value 值
* @returns {boolean} 是否设置成功
*/
setIfAbsent(keys: string[], value: any): boolean {
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;
}
/**
* 删除指定键路径上的值
* - 验证所有key必须是字符串
* - 递归删除并在父节点为空对象时一并清理
*/
remove(keys: string[]) {
// 如果只有一个键,直接从根配置中删除
if (keys.length === 1) {
if (keys[0] in this.#config) {
delete this.#config[keys[0]];
return true;
}
return false;
}
// 递归删除并检查父节点
const removeRecursive = (obj: Record<string, any>, keyPath: string[], index: number): boolean => {
// 已到达倒数第二层
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(): boolean {
return Object.keys(this.#config).length === 0;
}
toString() {
if (this.isEmpty()) {
return '';
}
return yaml.dump(this.#config, {
indent: this.indent,
lineWidth: -1,
quotingType: '"',
forceQuotes: false,
});
}
}