befly-shared 1.2.8 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/package.json +13 -30
  2. package/utils/arrayToTree.ts +135 -0
  3. package/utils/buildTreeByParentPath.ts +127 -0
  4. package/utils/scanViewsDir.ts +148 -0
  5. package/README.md +0 -439
  6. package/dist/addonHelper.js +0 -83
  7. package/dist/arrayKeysToCamel.js +0 -18
  8. package/dist/arrayToTree.js +0 -23
  9. package/dist/calcPerfTime.js +0 -13
  10. package/dist/configTypes.js +0 -1
  11. package/dist/constants.js +0 -46
  12. package/dist/deepTransformKeys.js +0 -139
  13. package/dist/fieldClear.js +0 -57
  14. package/dist/genShortId.js +0 -12
  15. package/dist/hashPassword.js +0 -22
  16. package/dist/index.js +0 -26
  17. package/dist/keysToCamel.js +0 -21
  18. package/dist/keysToSnake.js +0 -21
  19. package/dist/layouts.js +0 -59
  20. package/dist/pickFields.js +0 -16
  21. package/dist/redisKeys.js +0 -34
  22. package/dist/regex.js +0 -202
  23. package/dist/scanConfig.js +0 -83
  24. package/dist/scanFiles.js +0 -39
  25. package/dist/scanViews.js +0 -48
  26. package/dist/withDefaultColumns.js +0 -32
  27. package/src/addonHelper.ts +0 -88
  28. package/src/arrayKeysToCamel.ts +0 -18
  29. package/src/arrayToTree.ts +0 -31
  30. package/src/calcPerfTime.ts +0 -13
  31. package/src/configTypes.ts +0 -29
  32. package/src/constants.ts +0 -60
  33. package/src/deepTransformKeys.ts +0 -172
  34. package/src/fieldClear.ts +0 -75
  35. package/src/genShortId.ts +0 -12
  36. package/src/hashPassword.ts +0 -27
  37. package/src/index.ts +0 -29
  38. package/src/keysToCamel.ts +0 -22
  39. package/src/keysToSnake.ts +0 -22
  40. package/src/layouts.ts +0 -90
  41. package/src/pickFields.ts +0 -19
  42. package/src/redisKeys.ts +0 -44
  43. package/src/regex.ts +0 -225
  44. package/src/scanConfig.ts +0 -106
  45. package/src/scanFiles.ts +0 -49
  46. package/src/scanViews.ts +0 -55
  47. package/src/withDefaultColumns.ts +0 -36
  48. package/tests/addonHelper.test.ts +0 -55
  49. package/tests/arrayKeysToCamel.test.ts +0 -21
  50. package/tests/arrayToTree.test.ts +0 -98
  51. package/tests/calcPerfTime.test.ts +0 -19
  52. package/tests/deepTransformKeys.test.ts +0 -466
  53. package/tests/fieldClear.test.ts +0 -39
  54. package/tests/keysToCamel.test.ts +0 -22
  55. package/tests/keysToSnake.test.ts +0 -22
  56. package/tests/layouts.test.ts +0 -93
  57. package/tests/pickFields.test.ts +0 -22
  58. package/tests/regex.test.ts +0 -308
  59. package/tests/scanFiles.test.ts +0 -58
  60. package/tests/types.test.ts +0 -289
  61. package/types/addon.d.ts +0 -50
  62. package/types/addonConfigMerge.d.ts +0 -17
  63. package/types/addonHelper.d.ts +0 -24
  64. package/types/api.d.ts +0 -63
  65. package/types/arrayKeysToCamel.d.ts +0 -13
  66. package/types/arrayToTree.d.ts +0 -8
  67. package/types/calcPerfTime.d.ts +0 -4
  68. package/types/common.d.ts +0 -8
  69. package/types/configMerge.d.ts +0 -49
  70. package/types/configTypes.d.ts +0 -28
  71. package/types/constants.d.ts +0 -48
  72. package/types/context.d.ts +0 -38
  73. package/types/crypto.d.ts +0 -23
  74. package/types/database.d.ts +0 -55
  75. package/types/deepTransformKeys.d.ts +0 -84
  76. package/types/fieldClear.d.ts +0 -16
  77. package/types/genShortId.d.ts +0 -10
  78. package/types/hashPassword.d.ts +0 -11
  79. package/types/index.d.ts +0 -23
  80. package/types/jwt.d.ts +0 -99
  81. package/types/keysToCamel.d.ts +0 -10
  82. package/types/keysToSnake.d.ts +0 -10
  83. package/types/layouts.d.ts +0 -29
  84. package/types/loadAndMergeConfig.d.ts +0 -7
  85. package/types/logger.d.ts +0 -22
  86. package/types/menu.d.ts +0 -49
  87. package/types/mergeConfig.d.ts +0 -7
  88. package/types/pickFields.d.ts +0 -4
  89. package/types/redisKeys.d.ts +0 -34
  90. package/types/regex.d.ts +0 -145
  91. package/types/scanConfig.d.ts +0 -7
  92. package/types/scanFiles.d.ts +0 -12
  93. package/types/scanViews.d.ts +0 -11
  94. package/types/table.d.ts +0 -49
  95. package/types/tool.d.ts +0 -67
  96. package/types/types.d.ts +0 -44
  97. package/types/validate.d.ts +0 -69
  98. package/types/withDefaultColumns.d.ts +0 -7
package/src/scanFiles.ts DELETED
@@ -1,49 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { relative, basename, normalize } from 'pathe';
3
-
4
- export interface ScanFileResult {
5
- filePath: string; // 绝对路径
6
- relativePath: string; // 相对路径(无扩展名)
7
- fileName: string; // 文件名(无扩展名)
8
- }
9
-
10
- /**
11
- * 扫描指定目录下的文件
12
- * @param dir 目录路径
13
- * @param pattern Glob 模式
14
- * @param ignoreUnderline 是否忽略下划线开头的文件/目录
15
- */
16
- export async function scanFiles(dir: string, pattern: string = '**/*.{ts,js}', ignoreUnderline: boolean = true): Promise<ScanFileResult[]> {
17
- if (!existsSync(dir)) return [];
18
-
19
- const normalizedDir = normalize(dir);
20
- const glob = new Bun.Glob(pattern);
21
- const results: ScanFileResult[] = [];
22
-
23
- for await (const file of glob.scan({ cwd: dir, onlyFiles: true, absolute: true })) {
24
- if (file.endsWith('.d.ts')) continue;
25
-
26
- // 使用 pathe.normalize 统一路径分隔符为 /
27
- const normalizedFile = normalize(file);
28
-
29
- // 获取文件名(去除扩展名)
30
- const fileName = basename(normalizedFile).replace(/\.[^.]+$/, '');
31
-
32
- // 计算相对路径(pathe.relative 返回的已经是正斜杠路径)
33
- const relativePath = relative(normalizedDir, normalizedFile).replace(/\.[^/.]+$/, '');
34
-
35
- if (ignoreUnderline) {
36
- // 检查文件名是否以下划线开头
37
- if (fileName.startsWith('_')) continue;
38
- // 检查路径中是否包含下划线开头的目录
39
- if (relativePath.split('/').some((part) => part.startsWith('_'))) continue;
40
- }
41
-
42
- results.push({
43
- filePath: normalizedFile,
44
- relativePath,
45
- fileName
46
- });
47
- }
48
- return results;
49
- }
package/src/scanViews.ts DELETED
@@ -1,55 +0,0 @@
1
- import { readdirSync, existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
-
4
- /**
5
- * 扫描项目和所有 @befly-addon 包的 views 目录
6
- * 用于 unplugin-vue-router 的 routesFolder 配置
7
- * 注意:此函数只能在 vite.config.js 中使用(Node.js 环境),不能在浏览器中使用
8
- * @returns 路由文件夹配置数组
9
- */
10
- export function scanViews() {
11
- // 使用绝对路径:基于项目根目录(process.cwd())
12
- const projectRoot = process.cwd();
13
- const addonBasePath = join(projectRoot, 'node_modules', '@befly-addon');
14
- const routesFolders = [];
15
-
16
- // 1. 先添加项目自己的 views 目录
17
- const projectViewsPath = join(projectRoot, 'src', 'views');
18
- if (existsSync(projectViewsPath)) {
19
- routesFolders.push({
20
- src: projectViewsPath,
21
- path: '',
22
- exclude: ['**/components/**']
23
- });
24
- }
25
-
26
- // 2. 扫描 @befly-addon 包的 views 目录
27
- if (!existsSync(addonBasePath)) {
28
- return routesFolders;
29
- }
30
-
31
- try {
32
- const addonDirs = readdirSync(addonBasePath);
33
-
34
- for (const addonName of addonDirs) {
35
- const addonPath = join(addonBasePath, addonName);
36
-
37
- // 检查是否为目录(包括符号链接)
38
- if (!existsSync(addonPath)) continue;
39
-
40
- const viewsPath = join(addonPath, 'views');
41
-
42
- if (existsSync(viewsPath)) {
43
- routesFolders.push({
44
- src: viewsPath,
45
- path: `addon/${addonName}/`,
46
- exclude: ['**/components/**']
47
- });
48
- }
49
- }
50
- } catch (error) {
51
- console.error('扫描 @befly-addon 目录失败:', error);
52
- }
53
-
54
- return routesFolders;
55
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * 为表格列添加默认配置
3
- * @param columns - 列配置数组
4
- * @param customConfig - 自定义特殊列配置,可覆盖默认的 specialColumnConfig
5
- * @returns 添加默认配置后的列数组
6
- */
7
- export function withDefaultColumns(columns: any[], customConfig: Record<string, any> = {}): any[] {
8
- /**
9
- * 特殊列配置映射
10
- */
11
- const specialColumnConfig: Record<string, any> = {
12
- operation: { width: 100, align: 'center', fixed: 'right' },
13
- state: { width: 100, align: 'center' },
14
- id: { width: 200, align: 'center' },
15
- ...customConfig
16
- };
17
-
18
- return columns.map((col) => {
19
- const colKey = col.colKey;
20
-
21
- // 特殊列配置
22
- let specialConfig = specialColumnConfig[colKey];
23
-
24
- // 以 At 或 At2 结尾的列(时间字段)
25
- if (!specialConfig && colKey && (colKey.endsWith('At') || colKey.endsWith('At2'))) {
26
- specialConfig = { align: 'center' };
27
- }
28
-
29
- return {
30
- width: 200,
31
- ellipsis: true,
32
- ...specialConfig,
33
- ...col
34
- };
35
- });
36
- }
@@ -1,55 +0,0 @@
1
- import { describe, expect, test, beforeAll, afterAll } from 'bun:test';
2
- import { join, resolve } from 'pathe';
3
- import { mkdirSync, rmdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
4
- import { scanAddons, getAddonDir, addonDirExists } from '../src/addonHelper';
5
-
6
- // Use absolute path to workspace root temp dir
7
- const WORKSPACE_ROOT = resolve(__dirname, '../../..');
8
- const TEST_DIR = join(WORKSPACE_ROOT, 'temp', 'test-addons-util');
9
- const NODE_MODULES_DIR = join(TEST_DIR, 'node_modules');
10
- const BEFLY_ADDON_DIR = join(NODE_MODULES_DIR, '@befly-addon');
11
- // const LOCAL_ADDONS_DIR = join(TEST_DIR, 'addons');
12
-
13
- describe('addonHelper', () => {
14
- beforeAll(() => {
15
- // Setup test directories
16
- if (existsSync(TEST_DIR)) {
17
- rmSync(TEST_DIR, { recursive: true, force: true });
18
- }
19
- mkdirSync(TEST_DIR, { recursive: true });
20
- mkdirSync(BEFLY_ADDON_DIR, { recursive: true });
21
- // mkdirSync(LOCAL_ADDONS_DIR, { recursive: true });
22
-
23
- // Create dummy addons
24
- mkdirSync(join(BEFLY_ADDON_DIR, 'test-addon-1'), { recursive: true });
25
- mkdirSync(join(BEFLY_ADDON_DIR, 'test-addon-1', 'api'), { recursive: true });
26
-
27
- mkdirSync(join(BEFLY_ADDON_DIR, 'test-addon-2'), { recursive: true });
28
- });
29
-
30
- afterAll(() => {
31
- // Cleanup
32
- rmSync(TEST_DIR, { recursive: true, force: true });
33
- });
34
-
35
- test('scanAddons should find addons in node_modules', () => {
36
- const addons = scanAddons(TEST_DIR);
37
- expect(addons).toContain('test-addon-1');
38
- expect(addons).toContain('test-addon-2');
39
- });
40
-
41
- test('getAddonDir should return correct path', () => {
42
- const dir = getAddonDir('test-addon-1', 'api', TEST_DIR);
43
- expect(dir).toBe(join(BEFLY_ADDON_DIR, 'test-addon-1', 'api'));
44
- });
45
-
46
- test('addonDirExists should return true for existing dir', () => {
47
- const exists = addonDirExists('test-addon-1', 'api', TEST_DIR);
48
- expect(exists).toBe(true);
49
- });
50
-
51
- test('addonDirExists should return false for non-existing dir', () => {
52
- const exists = addonDirExists('test-addon-1', 'non-existent', TEST_DIR);
53
- expect(exists).toBe(false);
54
- });
55
- });
@@ -1,21 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { arrayKeysToCamel } from '../src/arrayKeysToCamel';
3
-
4
- describe('arrayKeysToCamel', () => {
5
- test('should convert array of objects to camelCase', () => {
6
- const input = [
7
- { user_id: 1, user_name: 'John' },
8
- { user_id: 2, user_name: 'Jane' }
9
- ];
10
- const expected = [
11
- { userId: 1, userName: 'John' },
12
- { userId: 2, userName: 'Jane' }
13
- ];
14
- expect(arrayKeysToCamel(input)).toEqual(expected);
15
- });
16
-
17
- test('should return original if not array', () => {
18
- expect(arrayKeysToCamel(null as any)).toBeNull();
19
- expect(arrayKeysToCamel({} as any)).toEqual({});
20
- });
21
- });
@@ -1,98 +0,0 @@
1
- import { test, expect } from 'bun:test';
2
- import { arrayToTree } from '../src/arrayToTree';
3
- import type { ArrayToTreeOptions } from '../types/arrayToTree';
4
-
5
- test('默认字段树结构', () => {
6
- const flat = [
7
- { id: 1, pid: 0, name: 'A' },
8
- { id: 2, pid: 1, name: 'B' },
9
- { id: 3, pid: 1, name: 'C' },
10
- { id: 4, pid: 2, name: 'D' }
11
- ];
12
- expect(arrayToTree(flat)).toEqual([
13
- {
14
- id: 1,
15
- pid: 0,
16
- name: 'A',
17
- children: [
18
- {
19
- id: 2,
20
- pid: 1,
21
- name: 'B',
22
- children: [{ id: 4, pid: 2, name: 'D' }]
23
- },
24
- { id: 3, pid: 1, name: 'C' }
25
- ]
26
- }
27
- ]);
28
- });
29
-
30
- test('自定义字段树结构', () => {
31
- const custom = [
32
- { key: 'a', parent: null, label: 'A' },
33
- { key: 'b', parent: 'a', label: 'B' },
34
- { key: 'c', parent: 'a', label: 'C' },
35
- { key: 'd', parent: 'b', label: 'D' }
36
- ];
37
- const options: ArrayToTreeOptions<(typeof custom)[0]> = {
38
- idField: 'key',
39
- pidField: 'parent',
40
- childrenField: 'nodes',
41
- rootPid: null
42
- };
43
- expect(arrayToTree(custom, options)).toEqual([
44
- {
45
- key: 'a',
46
- parent: null,
47
- label: 'A',
48
- nodes: [
49
- {
50
- key: 'b',
51
- parent: 'a',
52
- label: 'B',
53
- nodes: [{ key: 'd', parent: 'b', label: 'D' }]
54
- },
55
- { key: 'c', parent: 'a', label: 'C' }
56
- ]
57
- }
58
- ]);
59
- });
60
-
61
- test('mapFn 节点转换', () => {
62
- const custom = [
63
- { key: 'a', parent: null, label: 'A' },
64
- { key: 'b', parent: 'a', label: 'B' },
65
- { key: 'c', parent: 'a', label: 'C' },
66
- { key: 'd', parent: 'b', label: 'D' }
67
- ];
68
- const options: ArrayToTreeOptions<(typeof custom)[0]> = {
69
- idField: 'key',
70
- pidField: 'parent',
71
- childrenField: 'nodes',
72
- rootPid: null,
73
- mapFn: (node) => ({ ...node, extra: true })
74
- };
75
- expect(arrayToTree(custom, options)).toEqual([
76
- {
77
- key: 'a',
78
- parent: null,
79
- label: 'A',
80
- extra: true,
81
- nodes: [
82
- {
83
- key: 'b',
84
- parent: 'a',
85
- label: 'B',
86
- extra: true,
87
- nodes: [{ key: 'd', parent: 'b', label: 'D', extra: true }]
88
- },
89
- { key: 'c', parent: 'a', label: 'C', extra: true }
90
- ]
91
- }
92
- ]);
93
- });
94
-
95
- test('空数组和单节点', () => {
96
- expect(arrayToTree([], {})).toEqual([]);
97
- expect(arrayToTree([{ id: 1, pid: 0 }], {})).toEqual([{ id: 1, pid: 0 }]);
98
- });
@@ -1,19 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { calcPerfTime } from '../src/calcPerfTime';
3
-
4
- describe('calcPerfTime', () => {
5
- test('should return milliseconds for short duration', () => {
6
- const start = Bun.nanoseconds();
7
- // Simulate small delay
8
- const end = start + 500_000; // 0.5ms
9
- const result = calcPerfTime(start, end);
10
- expect(result).toMatch(/毫秒$/);
11
- });
12
-
13
- test('should return seconds for long duration', () => {
14
- const start = Bun.nanoseconds();
15
- const end = start + 2_000_000_000; // 2s
16
- const result = calcPerfTime(start, end);
17
- expect(result).toMatch(/秒$/);
18
- });
19
- });