chore: update helpers
parent
8f1b054bb1
commit
fc423c3657
|
@ -7,7 +7,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
"directory": "packages/@vben-core/helpers"
|
"directory": "packages/@vben-core/forward/helpers"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"scripts": {
|
"scripts": {
|
|
@ -0,0 +1,132 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { flattenObject } from './flatten-object';
|
||||||
|
|
||||||
|
describe('flattenObject', () => {
|
||||||
|
it('should flatten a nested object correctly', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
language: 'en',
|
||||||
|
notifications: {
|
||||||
|
email: true,
|
||||||
|
push: {
|
||||||
|
sound: true,
|
||||||
|
vibration: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
theme: 'light',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
language: 'en',
|
||||||
|
notificationsEmail: true,
|
||||||
|
notificationsPushSound: true,
|
||||||
|
notificationsPushVibration: false,
|
||||||
|
theme: 'light',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty objects', () => {
|
||||||
|
const nestedObject = {};
|
||||||
|
const expected = {};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle objects with primitive values', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
active: true,
|
||||||
|
age: 30,
|
||||||
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
active: true,
|
||||||
|
age: 30,
|
||||||
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle objects with null values', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
user: {
|
||||||
|
age: null,
|
||||||
|
name: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
userAge: null,
|
||||||
|
userName: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle nested empty objects', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
a: {},
|
||||||
|
b: { c: {} },
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle arrays within objects', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
hobbies: ['reading', 'gaming'],
|
||||||
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
hobbies: ['reading', 'gaming'],
|
||||||
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
it('should flatten objects with nested arrays correctly', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
person: {
|
||||||
|
hobbies: ['reading', 'gaming'],
|
||||||
|
name: 'Alice',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
personHobbies: ['reading', 'gaming'],
|
||||||
|
personName: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle objects with undefined values', () => {
|
||||||
|
const nestedObject = {
|
||||||
|
user: {
|
||||||
|
age: undefined,
|
||||||
|
name: 'Alice',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
userAge: undefined,
|
||||||
|
userName: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = flattenObject(nestedObject);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,21 +1,6 @@
|
||||||
import type { Flatten } from '@vben-core/typings';
|
import type { Flatten } from '@vben-core/typings';
|
||||||
|
|
||||||
import {
|
import { capitalizeFirstLetter } from '@vben-core/toolkit';
|
||||||
capitalizeFirstLetter,
|
|
||||||
toLowerCaseFirstLetter,
|
|
||||||
} from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成驼峰命名法的键名
|
|
||||||
* @param key
|
|
||||||
* @param parentKey
|
|
||||||
*/
|
|
||||||
function toCamelCase(key: string, parentKey: string): string {
|
|
||||||
if (!parentKey) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
return parentKey + key.charAt(0).toUpperCase() + key.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将嵌套对象扁平化
|
* 将嵌套对象扁平化
|
||||||
|
@ -70,74 +55,7 @@ function flattenObject<T extends Record<string, any>>(
|
||||||
return result as Flatten<T>;
|
return result as Flatten<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export { flattenObject };
|
||||||
* 将扁平对象转换为嵌套对象。
|
|
||||||
*
|
|
||||||
* @template T - 输入对象值的类型
|
|
||||||
* @param {Record<string, T>} obj - 要转换的扁平对象
|
|
||||||
* @param {number} level - 嵌套的层级
|
|
||||||
* @returns {T} 嵌套对象
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* 将扁平对象转换为嵌套对象,嵌套层级为 1
|
|
||||||
* const flatObject = {
|
|
||||||
* 'commonAppName': 1,
|
|
||||||
* 'anotherKeyExample': 2,
|
|
||||||
* 'someOtherKey': 3
|
|
||||||
* };
|
|
||||||
* const nestedObject = toNestedObject(flatObject, 1);
|
|
||||||
* console.log(nestedObject);
|
|
||||||
* 输出:
|
|
||||||
* {
|
|
||||||
* commonAppName: 1,
|
|
||||||
* anotherKeyExample: 2,
|
|
||||||
* someOtherKey: 3
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* 将扁平对象转换为嵌套对象,嵌套层级为 2
|
|
||||||
* const flatObject = {
|
|
||||||
* 'appCommonName': 1,
|
|
||||||
* 'appAnotherKeyExample': 2,
|
|
||||||
* 'appSomeOtherKey': 3
|
|
||||||
* };
|
|
||||||
* const nestedObject = toNestedObject(flatObject, 2);
|
|
||||||
* console.log(nestedObject);
|
|
||||||
* 输出:
|
|
||||||
* {
|
|
||||||
* app: {
|
|
||||||
* commonName: 1,
|
|
||||||
* anotherKeyExample: 2,
|
|
||||||
* someOtherKey: 3
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
function toNestedObject<T>(obj: Record<string, T>, level: number): T {
|
|
||||||
const result: any = {};
|
|
||||||
|
|
||||||
for (const key in obj) {
|
|
||||||
const keys = key.split(/(?=[A-Z])/);
|
|
||||||
// 将驼峰式分割为数组;
|
|
||||||
let current = result;
|
|
||||||
|
|
||||||
for (let i = 0; i < keys.length; i++) {
|
|
||||||
const lowerKey = keys[i].toLowerCase();
|
|
||||||
if (i === level - 1) {
|
|
||||||
const remainingKeys = keys.slice(i).join(''); // 保留后续部分作为键的一部分
|
|
||||||
current[toLowerCaseFirstLetter(remainingKeys)] = obj[key];
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
current[lowerKey] = current[lowerKey] || {};
|
|
||||||
current = current[lowerKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { flattenObject, toCamelCase, toNestedObject };
|
|
||||||
|
|
||||||
// 定义递归类型,用于推断扁平化后的对象类型
|
// 定义递归类型,用于推断扁平化后的对象类型
|
||||||
// 限制递归深度的辅助类型
|
// 限制递归深度的辅助类型
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './flatten-object';
|
||||||
|
export * from './nested-object';
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { nestedObject } from './nested-object';
|
||||||
|
|
||||||
|
describe('nestedObject', () => {
|
||||||
|
it('should convert flat object to nested object with level 1', () => {
|
||||||
|
const flatObject = {
|
||||||
|
anotherKeyExample: 2,
|
||||||
|
commonAppName: 1,
|
||||||
|
someOtherKey: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedNestedObject = {
|
||||||
|
anotherKeyExample: 2,
|
||||||
|
commonAppName: 1,
|
||||||
|
someOtherKey: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert flat object to nested object with level 2', () => {
|
||||||
|
const flatObject = {
|
||||||
|
appAnotherKeyExample: 2,
|
||||||
|
appCommonName: 1,
|
||||||
|
appSomeOtherKey: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedNestedObject = {
|
||||||
|
app: {
|
||||||
|
anotherKeyExample: 2,
|
||||||
|
commonName: 1,
|
||||||
|
someOtherKey: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 2)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert flat object to nested object with level 3', () => {
|
||||||
|
const flatObject = {
|
||||||
|
appAnotherKeyExampleValue: 2,
|
||||||
|
appCommonNameKey: 1,
|
||||||
|
appSomeOtherKeyItem: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedNestedObject = {
|
||||||
|
app: {
|
||||||
|
another: {
|
||||||
|
keyExampleValue: 2,
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
nameKey: 1,
|
||||||
|
},
|
||||||
|
some: {
|
||||||
|
otherKeyItem: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 3)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty object', () => {
|
||||||
|
const flatObject = {};
|
||||||
|
|
||||||
|
const expectedNestedObject = {};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle single key object', () => {
|
||||||
|
const flatObject = {
|
||||||
|
singleKey: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedNestedObject = {
|
||||||
|
singleKey: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle complex keys', () => {
|
||||||
|
const flatObject = {
|
||||||
|
anotherComplexKeyWithParts: 2,
|
||||||
|
complexKeyWithMultipleParts: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedNestedObject = {
|
||||||
|
anotherComplexKeyWithParts: 2,
|
||||||
|
complexKeyWithMultipleParts: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { toLowerCaseFirstLetter } from '@vben-core/toolkit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将扁平对象转换为嵌套对象。
|
||||||
|
*
|
||||||
|
* @template T - 输入对象值的类型
|
||||||
|
* @param {Record<string, T>} obj - 要转换的扁平对象
|
||||||
|
* @param {number} level - 嵌套的层级
|
||||||
|
* @returns {T} 嵌套对象
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* 将扁平对象转换为嵌套对象,嵌套层级为 1
|
||||||
|
* const flatObject = {
|
||||||
|
* 'commonAppName': 1,
|
||||||
|
* 'anotherKeyExample': 2,
|
||||||
|
* 'someOtherKey': 3
|
||||||
|
* };
|
||||||
|
* const nestedObject = nestedObject(flatObject, 1);
|
||||||
|
* console.log(nestedObject);
|
||||||
|
* 输出:
|
||||||
|
* {
|
||||||
|
* commonAppName: 1,
|
||||||
|
* anotherKeyExample: 2,
|
||||||
|
* someOtherKey: 3
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* 将扁平对象转换为嵌套对象,嵌套层级为 2
|
||||||
|
* const flatObject = {
|
||||||
|
* 'appCommonName': 1,
|
||||||
|
* 'appAnotherKeyExample': 2,
|
||||||
|
* 'appSomeOtherKey': 3
|
||||||
|
* };
|
||||||
|
* const nestedObject = nestedObject(flatObject, 2);
|
||||||
|
* console.log(nestedObject);
|
||||||
|
* 输出:
|
||||||
|
* {
|
||||||
|
* app: {
|
||||||
|
* commonName: 1,
|
||||||
|
* anotherKeyExample: 2,
|
||||||
|
* someOtherKey: 3
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
function nestedObject<T>(obj: Record<string, T>, level: number): T {
|
||||||
|
const result: any = {};
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
const keys = key.split(/(?=[A-Z])/);
|
||||||
|
// 将驼峰式分割为数组;
|
||||||
|
let current = result;
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const lowerKey = keys[i].toLowerCase();
|
||||||
|
if (i === level - 1) {
|
||||||
|
const remainingKeys = keys.slice(i).join(''); // 保留后续部分作为键的一部分
|
||||||
|
current[toLowerCaseFirstLetter(remainingKeys)] = obj[key];
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
current[lowerKey] = current[lowerKey] || {};
|
||||||
|
current = current[lowerKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { nestedObject };
|
|
@ -7,7 +7,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
"directory": "packages/@vben-core/preferences"
|
"directory": "packages/@vben-core/forward/preferences"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import type {
|
||||||
} from '@vben-core/typings';
|
} from '@vben-core/typings';
|
||||||
|
|
||||||
import { StorageManager } from '@vben-core/cache';
|
import { StorageManager } from '@vben-core/cache';
|
||||||
import { flattenObject, toNestedObject } from '@vben-core/helpers';
|
import { flattenObject, nestedObject } from '@vben-core/helpers';
|
||||||
import { convertToHslCssVar, merge } from '@vben-core/toolkit';
|
import { convertToHslCssVar, merge } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -190,7 +190,7 @@ class PreferenceManager {
|
||||||
* @param {FlattenObject<Preferences>} newValue - 新的扁平对象
|
* @param {FlattenObject<Preferences>} newValue - 新的扁平对象
|
||||||
*/
|
*/
|
||||||
private updateState(newValue: Flatten<Preferences>) {
|
private updateState(newValue: Flatten<Preferences>) {
|
||||||
const nestObj = toNestedObject(newValue, 2);
|
const nestObj = nestedObject(newValue, 2);
|
||||||
Object.assign(this.state, merge(nestObj, this.state));
|
Object.assign(this.state, merge(nestObj, this.state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
"directory": "packages/@vben-core/stores"
|
"directory": "packages/@vben-core/forward/stores"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './object';
|
|
|
@ -1,245 +0,0 @@
|
||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
|
|
||||||
import { flattenObject, toCamelCase, toNestedObject } from './object';
|
|
||||||
|
|
||||||
describe('toCamelCase', () => {
|
|
||||||
it('should return the key if parentKey is empty', () => {
|
|
||||||
expect(toCamelCase('child', '')).toBe('child');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should combine parentKey and key in camel case', () => {
|
|
||||||
expect(toCamelCase('child', 'parent')).toBe('parentChild');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle empty key and parentKey', () => {
|
|
||||||
expect(toCamelCase('', '')).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle key with capital letters', () => {
|
|
||||||
expect(toCamelCase('Child', 'parent')).toBe('parentChild');
|
|
||||||
expect(toCamelCase('Child', 'Parent')).toBe('ParentChild');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('flattenObject', () => {
|
|
||||||
it('should flatten a nested object correctly', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
language: 'en',
|
|
||||||
notifications: {
|
|
||||||
email: true,
|
|
||||||
push: {
|
|
||||||
sound: true,
|
|
||||||
vibration: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
theme: 'light',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
language: 'en',
|
|
||||||
notificationsEmail: true,
|
|
||||||
notificationsPushSound: true,
|
|
||||||
notificationsPushVibration: false,
|
|
||||||
theme: 'light',
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle empty objects', () => {
|
|
||||||
const nestedObject = {};
|
|
||||||
const expected = {};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle objects with primitive values', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
active: true,
|
|
||||||
age: 30,
|
|
||||||
name: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
active: true,
|
|
||||||
age: 30,
|
|
||||||
name: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle objects with null values', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
user: {
|
|
||||||
age: null,
|
|
||||||
name: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
userAge: null,
|
|
||||||
userName: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle nested empty objects', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
a: {},
|
|
||||||
b: { c: {} },
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle arrays within objects', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
hobbies: ['reading', 'gaming'],
|
|
||||||
name: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
hobbies: ['reading', 'gaming'],
|
|
||||||
name: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
it('should flatten objects with nested arrays correctly', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
person: {
|
|
||||||
hobbies: ['reading', 'gaming'],
|
|
||||||
name: 'Alice',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
personHobbies: ['reading', 'gaming'],
|
|
||||||
personName: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle objects with undefined values', () => {
|
|
||||||
const nestedObject = {
|
|
||||||
user: {
|
|
||||||
age: undefined,
|
|
||||||
name: 'Alice',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected = {
|
|
||||||
userAge: undefined,
|
|
||||||
userName: 'Alice',
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = flattenObject(nestedObject);
|
|
||||||
expect(result).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toNestedObject', () => {
|
|
||||||
it('should convert flat object to nested object with level 1', () => {
|
|
||||||
const flatObject = {
|
|
||||||
anotherKeyExample: 2,
|
|
||||||
commonAppName: 1,
|
|
||||||
someOtherKey: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedNestedObject = {
|
|
||||||
anotherKeyExample: 2,
|
|
||||||
commonAppName: 1,
|
|
||||||
someOtherKey: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert flat object to nested object with level 2', () => {
|
|
||||||
const flatObject = {
|
|
||||||
appAnotherKeyExample: 2,
|
|
||||||
appCommonName: 1,
|
|
||||||
appSomeOtherKey: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedNestedObject = {
|
|
||||||
app: {
|
|
||||||
anotherKeyExample: 2,
|
|
||||||
commonName: 1,
|
|
||||||
someOtherKey: 3,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 2)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert flat object to nested object with level 3', () => {
|
|
||||||
const flatObject = {
|
|
||||||
appAnotherKeyExampleValue: 2,
|
|
||||||
appCommonNameKey: 1,
|
|
||||||
appSomeOtherKeyItem: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedNestedObject = {
|
|
||||||
app: {
|
|
||||||
another: {
|
|
||||||
keyExampleValue: 2,
|
|
||||||
},
|
|
||||||
common: {
|
|
||||||
nameKey: 1,
|
|
||||||
},
|
|
||||||
some: {
|
|
||||||
otherKeyItem: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 3)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle empty object', () => {
|
|
||||||
const flatObject = {};
|
|
||||||
|
|
||||||
const expectedNestedObject = {};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle single key object', () => {
|
|
||||||
const flatObject = {
|
|
||||||
singleKey: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedNestedObject = {
|
|
||||||
singleKey: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle complex keys', () => {
|
|
||||||
const flatObject = {
|
|
||||||
anotherComplexKeyWithParts: 2,
|
|
||||||
complexKeyWithMultipleParts: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const expectedNestedObject = {
|
|
||||||
anotherComplexKeyWithParts: 2,
|
|
||||||
complexKeyWithMultipleParts: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toNestedObject(flatObject, 1)).toEqual(expectedNestedObject);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -7,7 +7,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
"directory": "packages/@vben-core/shared/toolkit"
|
"directory": "packages/@vben-core/shared/cache"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
"directory": "packages/@vben-core/iconify"
|
"directory": "packages/@vben-core/shared/iconify"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { capitalizeFirstLetter, toLowerCaseFirstLetter } from './letter';
|
import {
|
||||||
|
capitalizeFirstLetter,
|
||||||
|
toCamelCase,
|
||||||
|
toLowerCaseFirstLetter,
|
||||||
|
} from './letter';
|
||||||
|
|
||||||
// 编写测试用例
|
// 编写测试用例
|
||||||
describe('capitalizeFirstLetter', () => {
|
describe('capitalizeFirstLetter', () => {
|
||||||
|
@ -53,3 +57,22 @@ describe('toLowerCaseFirstLetter', () => {
|
||||||
expect(toLowerCaseFirstLetter('123Number')).toBe('123Number');
|
expect(toLowerCaseFirstLetter('123Number')).toBe('123Number');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('toCamelCase', () => {
|
||||||
|
it('should return the key if parentKey is empty', () => {
|
||||||
|
expect(toCamelCase('child', '')).toBe('child');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should combine parentKey and key in camel case', () => {
|
||||||
|
expect(toCamelCase('child', 'parent')).toBe('parentChild');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty key and parentKey', () => {
|
||||||
|
expect(toCamelCase('', '')).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle key with capital letters', () => {
|
||||||
|
expect(toCamelCase('Child', 'parent')).toBe('parentChild');
|
||||||
|
expect(toCamelCase('Child', 'Parent')).toBe('ParentChild');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -17,4 +17,16 @@ function toLowerCaseFirstLetter(str: string): string {
|
||||||
return str.charAt(0).toLowerCase() + str.slice(1);
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { capitalizeFirstLetter, toLowerCaseFirstLetter };
|
/**
|
||||||
|
* 生成驼峰命名法的键名
|
||||||
|
* @param key
|
||||||
|
* @param parentKey
|
||||||
|
*/
|
||||||
|
function toCamelCase(key: string, parentKey: string): string {
|
||||||
|
if (!parentKey) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return parentKey + key.charAt(0).toUpperCase() + key.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { capitalizeFirstLetter, toCamelCase, toLowerCaseFirstLetter };
|
||||||
|
|
|
@ -457,6 +457,15 @@ importers:
|
||||||
specifier: ^3.0.2
|
specifier: ^3.0.2
|
||||||
version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.13.0)(sass@1.77.4)(terser@5.31.0))
|
version: 3.0.2(esbuild@0.20.2)(mockjs@1.1.0)(vite@6.0.0-alpha.17(@types/node@20.13.0)(sass@1.77.4)(terser@5.31.0))
|
||||||
|
|
||||||
|
packages/@vben-core/forward/helpers:
|
||||||
|
dependencies:
|
||||||
|
'@vben-core/toolkit':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../shared/toolkit
|
||||||
|
'@vben-core/typings':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../shared/typings
|
||||||
|
|
||||||
packages/@vben-core/forward/preferences:
|
packages/@vben-core/forward/preferences:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vben-core/cache':
|
'@vben-core/cache':
|
||||||
|
@ -464,7 +473,7 @@ importers:
|
||||||
version: link:../../shared/chche
|
version: link:../../shared/chche
|
||||||
'@vben-core/helpers':
|
'@vben-core/helpers':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../helpers
|
version: link:../helpers
|
||||||
'@vben-core/toolkit':
|
'@vben-core/toolkit':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../shared/toolkit
|
version: link:../../shared/toolkit
|
||||||
|
@ -499,15 +508,6 @@ importers:
|
||||||
specifier: ^4.3.2
|
specifier: ^4.3.2
|
||||||
version: 4.3.2(vue@3.4.27(typescript@5.4.5))
|
version: 4.3.2(vue@3.4.27(typescript@5.4.5))
|
||||||
|
|
||||||
packages/@vben-core/helpers:
|
|
||||||
dependencies:
|
|
||||||
'@vben-core/toolkit':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../shared/toolkit
|
|
||||||
'@vben-core/typings':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../shared/typings
|
|
||||||
|
|
||||||
packages/@vben-core/shared/chche: {}
|
packages/@vben-core/shared/chche: {}
|
||||||
|
|
||||||
packages/@vben-core/shared/design:
|
packages/@vben-core/shared/design:
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
"name": "@vben/vite-config",
|
"name": "@vben/vite-config",
|
||||||
"path": "internal/vite-config",
|
"path": "internal/vite-config",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "@vben-core/helpers",
|
||||||
|
"path": "packages/@vben-core/forward/helpers",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "@vben-core/preferences",
|
"name": "@vben-core/preferences",
|
||||||
"path": "packages/@vben-core/forward/preferences",
|
"path": "packages/@vben-core/forward/preferences",
|
||||||
|
@ -48,10 +52,6 @@
|
||||||
"name": "@vben-core/stores",
|
"name": "@vben-core/stores",
|
||||||
"path": "packages/@vben-core/forward/stores",
|
"path": "packages/@vben-core/forward/stores",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "@vben-core/helpers",
|
|
||||||
"path": "packages/@vben-core/helpers",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "@vben-core/cache",
|
"name": "@vben-core/cache",
|
||||||
"path": "packages/@vben-core/shared/chche",
|
"path": "packages/@vben-core/shared/chche",
|
||||||
|
|
Loading…
Reference in New Issue