@xubill/xx-cli 1.0.6

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.
@@ -0,0 +1,118 @@
1
+ /**
2
+ * 命令历史记录管理
3
+ * 用于存储和读取命令历史
4
+ * 支持浏览和重复执行之前的命令
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ // 历史记录文件路径
11
+ const historyPath = path.join(process.env.HOME || process.env.USERPROFILE, '.xx-cli', 'history.json');
12
+
13
+ /**
14
+ * 确保历史记录目录存在
15
+ */
16
+ function ensureHistoryDir() {
17
+ const historyDir = path.dirname(historyPath);
18
+ if (!fs.existsSync(historyDir)) {
19
+ fs.mkdirSync(historyDir, { recursive: true });
20
+ }
21
+ }
22
+
23
+ /**
24
+ * 读取命令历史
25
+ * @returns {Array} 命令历史数组
26
+ */
27
+ exports.readHistory = () => {
28
+ ensureHistoryDir();
29
+
30
+ if (fs.existsSync(historyPath)) {
31
+ try {
32
+ const history = fs.readFileSync(historyPath, 'utf8');
33
+ return JSON.parse(history);
34
+ } catch (error) {
35
+ console.error('读取命令历史失败:', error.message);
36
+ return [];
37
+ }
38
+ }
39
+
40
+ return [];
41
+ };
42
+
43
+ /**
44
+ * 写入命令历史
45
+ * @param {Array} history - 命令历史数组
46
+ */
47
+ exports.writeHistory = (history) => {
48
+ ensureHistoryDir();
49
+
50
+ try {
51
+ fs.writeFileSync(historyPath, JSON.stringify(history, null, 2));
52
+ } catch (error) {
53
+ console.error('写入命令历史失败:', error.message);
54
+ }
55
+ };
56
+
57
+ /**
58
+ * 添加命令到历史记录
59
+ * @param {string} command - 命令字符串
60
+ */
61
+ exports.addHistory = (command) => {
62
+ // 不记录空命令、帮助命令和 history 命令本身
63
+ if (!command ||
64
+ command.trim() === '' ||
65
+ command.includes('--help') ||
66
+ command.includes('-h') ||
67
+ command.startsWith('history') ||
68
+ command.startsWith('h ') ||
69
+ command === 'h') {
70
+ return;
71
+ }
72
+
73
+ const history = exports.readHistory();
74
+
75
+ // 移除重复的命令
76
+ const filteredHistory = history.filter(item => item.command !== command);
77
+
78
+ // 添加新命令到开头
79
+ const newHistory = [
80
+ {
81
+ command,
82
+ timestamp: new Date().toISOString()
83
+ },
84
+ ...filteredHistory
85
+ ];
86
+
87
+ // 限制历史记录数量
88
+ const limitedHistory = newHistory.slice(0, 100);
89
+
90
+ exports.writeHistory(limitedHistory);
91
+ };
92
+
93
+ /**
94
+ * 清除命令历史
95
+ */
96
+ exports.clearHistory = () => {
97
+ exports.writeHistory([]);
98
+ };
99
+
100
+ /**
101
+ * 获取命令历史
102
+ * @param {number} limit - 限制数量
103
+ * @returns {Array} 命令历史数组
104
+ */
105
+ exports.getHistory = (limit = 10) => {
106
+ const history = exports.readHistory();
107
+ return history.slice(0, limit);
108
+ };
109
+
110
+ /**
111
+ * 搜索命令历史
112
+ * @param {string} keyword - 搜索关键词
113
+ * @returns {Array} 匹配的命令历史数组
114
+ */
115
+ exports.searchHistory = (keyword) => {
116
+ const history = exports.readHistory();
117
+ return history.filter(item => item.command.includes(keyword));
118
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 日志工具模块
3
+ * 使用 winston 实现日志功能
4
+ */
5
+
6
+ const winston = require('winston');
7
+
8
+ // 自定义日志格式化
9
+ const consoleFormat = winston.format.combine(
10
+ winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
11
+ winston.format.printf(({ timestamp, level, message }) => {
12
+ return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
13
+ })
14
+ );
15
+
16
+ // 创建日志实例
17
+ const logger = winston.createLogger({
18
+ level: 'info',
19
+ format: winston.format.json(),
20
+ transports: [
21
+ // 控制台输出
22
+ new winston.transports.Console({
23
+ format: consoleFormat
24
+ })
25
+ ]
26
+ });
27
+
28
+ module.exports = logger;
@@ -0,0 +1,158 @@
1
+ /**
2
+ * 插件配置管理
3
+ * 用于管理插件的启用/禁用状态
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ // 插件配置文件路径
10
+ const configPath = path.join(process.env.HOME || process.env.USERPROFILE, '.xx-cli', 'plugin-config.json');
11
+
12
+ /**
13
+ * 确保配置目录存在
14
+ */
15
+ function ensureConfigDir() {
16
+ const configDir = path.dirname(configPath);
17
+ if (!fs.existsSync(configDir)) {
18
+ fs.mkdirSync(configDir, { recursive: true });
19
+ }
20
+ }
21
+
22
+ /**
23
+ * 读取插件配置
24
+ * @returns {Object} 插件配置
25
+ */
26
+ exports.readConfig = () => {
27
+ ensureConfigDir();
28
+
29
+ if (fs.existsSync(configPath)) {
30
+ try {
31
+ const config = fs.readFileSync(configPath, 'utf8');
32
+ return JSON.parse(config);
33
+ } catch (error) {
34
+ console.error('读取插件配置失败:', error.message);
35
+ return { disabled: [] };
36
+ }
37
+ }
38
+
39
+ return { disabled: [] };
40
+ };
41
+
42
+ /**
43
+ * 写入插件配置
44
+ * @param {Object} config - 插件配置
45
+ */
46
+ exports.writeConfig = (config) => {
47
+ ensureConfigDir();
48
+
49
+ try {
50
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
51
+ } catch (error) {
52
+ console.error('写入插件配置失败:', error.message);
53
+ }
54
+ };
55
+
56
+ /**
57
+ * 检查插件是否已禁用
58
+ * @param {string} pluginName - 插件名称
59
+ * @returns {boolean} 是否已禁用
60
+ */
61
+ exports.isPluginDisabled = (pluginName) => {
62
+ const config = exports.readConfig();
63
+ return config.disabled.includes(pluginName);
64
+ };
65
+
66
+ /**
67
+ * 禁用插件
68
+ * @param {string} pluginName - 插件名称
69
+ */
70
+ exports.disablePlugin = (pluginName) => {
71
+ const config = exports.readConfig();
72
+ if (!config.disabled.includes(pluginName)) {
73
+ config.disabled.push(pluginName);
74
+ exports.writeConfig(config);
75
+ }
76
+ };
77
+
78
+ /**
79
+ * 启用插件
80
+ * @param {string} pluginName - 插件名称
81
+ */
82
+ exports.enablePlugin = (pluginName) => {
83
+ const config = exports.readConfig();
84
+ config.disabled = config.disabled.filter(name => name !== pluginName);
85
+ exports.writeConfig(config);
86
+ };
87
+
88
+ /**
89
+ * 从配置中移除插件
90
+ * @param {string} pluginName - 插件名称
91
+ */
92
+ exports.removePluginFromConfig = (pluginName) => {
93
+ const config = exports.readConfig();
94
+ config.disabled = config.disabled.filter(name => name !== pluginName);
95
+
96
+ // 同时移除插件的配置
97
+ if (config.plugins && config.plugins[pluginName]) {
98
+ delete config.plugins[pluginName];
99
+ }
100
+
101
+ exports.writeConfig(config);
102
+ };
103
+
104
+ /**
105
+ * 设置插件配置
106
+ * @param {string} pluginName - 插件名称
107
+ * @param {string} key - 配置键
108
+ * @param {string} value - 配置值
109
+ */
110
+ exports.setPluginConfig = (pluginName, key, value) => {
111
+ const config = exports.readConfig();
112
+
113
+ // 确保 plugins 对象存在
114
+ if (!config.plugins) {
115
+ config.plugins = {};
116
+ }
117
+
118
+ // 确保插件的配置对象存在
119
+ if (!config.plugins[pluginName]) {
120
+ config.plugins[pluginName] = {};
121
+ }
122
+
123
+ // 设置配置值
124
+ config.plugins[pluginName][key] = value;
125
+
126
+ exports.writeConfig(config);
127
+ };
128
+
129
+ /**
130
+ * 获取插件配置
131
+ * @param {string} pluginName - 插件名称
132
+ * @param {string} key - 配置键
133
+ * @returns {*} 配置值
134
+ */
135
+ exports.getPluginConfig = (pluginName, key) => {
136
+ const config = exports.readConfig();
137
+
138
+ if (config.plugins && config.plugins[pluginName]) {
139
+ return config.plugins[pluginName][key];
140
+ }
141
+
142
+ return undefined;
143
+ };
144
+
145
+ /**
146
+ * 获取插件所有配置
147
+ * @param {string} pluginName - 插件名称
148
+ * @returns {Object} 插件配置对象
149
+ */
150
+ exports.getPluginConfigs = (pluginName) => {
151
+ const config = exports.readConfig();
152
+
153
+ if (config.plugins && config.plugins[pluginName]) {
154
+ return config.plugins[pluginName];
155
+ }
156
+
157
+ return {};
158
+ };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 获取输入配置
3
+ * 处理用户输入的模板配置,转换为标准格式
4
+ */
5
+
6
+ /**
7
+ * 处理模板配置
8
+ * @param {Object} config - 原始模板配置
9
+ * @returns {Object} 处理后的模板配置
10
+ */
11
+ function processTemplateConfig(config) {
12
+ // 确保配置对象存在
13
+ if (!config) {
14
+ return {
15
+ dir: '.lists',
16
+ pages: {},
17
+ routes: { isRender: false },
18
+ mock: false
19
+ };
20
+ }
21
+
22
+ // 处理默认值
23
+ return {
24
+ dir: config.dir || '.lists',
25
+ pages: config.pages || {},
26
+ routes: {
27
+ isRender: config.routes?.isRender ?? false,
28
+ ...config.routes
29
+ },
30
+ mock: config.mock ?? false,
31
+ templateType: config.templateType || 'element-ui'
32
+ };
33
+ }
34
+
35
+ /**
36
+ * 处理页面配置
37
+ * @param {Object} pageConfig - 原始页面配置
38
+ * @returns {Object} 处理后的页面配置
39
+ */
40
+ function processPageConfig(pageConfig) {
41
+ // 确保配置对象存在
42
+ if (!pageConfig) {
43
+ return {
44
+ template: {
45
+ cn: '列表页面',
46
+ en: 'list',
47
+ top: false,
48
+ bottom: false,
49
+ select: false,
50
+ btn: []
51
+ },
52
+ filter: {},
53
+ table: {}
54
+ };
55
+ }
56
+
57
+ // 处理默认值
58
+ return {
59
+ template: {
60
+ cn: pageConfig.template?.cn || '列表页面',
61
+ en: pageConfig.template?.en || 'list',
62
+ top: pageConfig.template?.top ?? false,
63
+ bottom: pageConfig.template?.bottom ?? false,
64
+ select: pageConfig.template?.select ?? false,
65
+ btn: pageConfig.template?.btn || [],
66
+ ...pageConfig.template
67
+ },
68
+ filter: pageConfig.filter || {},
69
+ table: pageConfig.table || {}
70
+ };
71
+ }
72
+
73
+ module.exports = {
74
+ processTemplateConfig,
75
+ processPageConfig
76
+ };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Transformers 统一入口
3
+ * 导出所有转换逻辑方法
4
+ */
5
+
6
+ // 导出筛选器转换
7
+ const { transformFilter, generateFieldName } = require('./transformFilter');
8
+
9
+ // 导出表格转换
10
+ const { transformTable } = require('./transformTable');
11
+
12
+ // 导出列表页面转换
13
+ const { transformList } = require('./transformList');
14
+
15
+ // 导出路由转换
16
+ const { transformRoutes } = require('./transformRoutes');
17
+
18
+ // 导出 Mock 数据转换
19
+ const { transformMock } = require('./transformMock');
20
+
21
+ // 导出渲染列表页面
22
+ const { renderLists } = require('./renderLists');
23
+
24
+ module.exports = {
25
+ // 筛选器相关
26
+ transformFilter,
27
+ generateFieldName,
28
+
29
+ // 表格相关
30
+ transformTable,
31
+
32
+ // 列表页面相关
33
+ transformList,
34
+
35
+ // 路由相关
36
+ transformRoutes,
37
+
38
+ // Mock 数据相关
39
+ transformMock,
40
+
41
+ // 渲染相关
42
+ renderLists
43
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * 渲染列表页面的主入口
3
+ * 协调各个转换模块,生成完整的页面文件
4
+ */
5
+
6
+ // 导入转换模块
7
+ const { processTemplateConfig, processPageConfig } = require('./getInput');
8
+ const { getSfcMaterial, getTransformersByType } = require('./sfcMaterial');
9
+ const { transformList } = require('./transformList');
10
+ const { transformRoutes } = require('./transformRoutes');
11
+ const { transformMock } = require('./transformMock');
12
+
13
+ /**
14
+ * 渲染列表页面
15
+ * @param {Object} config - 模板配置
16
+ * @returns {Object} 生成的文件内容
17
+ */
18
+ function renderLists(config) {
19
+ // 处理模板配置
20
+ const processedConfig = processTemplateConfig(config);
21
+
22
+ // 获取模板类型
23
+ const templateType = processedConfig.templateType;
24
+
25
+ // 获取组件材料
26
+ const material = getSfcMaterial(templateType);
27
+
28
+ // 获取转换函数
29
+ const transformers = getTransformersByType(templateType);
30
+
31
+ const results = {
32
+ pages: {},
33
+ routes: null,
34
+ mock: {}
35
+ };
36
+
37
+ // 处理每个页面
38
+ const pages = processedConfig.pages;
39
+ for (const [pageName, pageConfig] of Object.entries(pages)) {
40
+ // 处理页面配置
41
+ const processedPageConfig = processPageConfig(pageConfig);
42
+ const { template, filter, table } = processedPageConfig;
43
+
44
+ // 生成 Vue 文件内容
45
+ const vueContent = transformList(template, filter, table, material);
46
+ results.pages[pageName] = {
47
+ content: vueContent,
48
+ fileName: `${template.en}.vue`
49
+ };
50
+
51
+ // 生成 Mock 数据(如果需要)
52
+ if (processedConfig.mock) {
53
+ const mockContent = transformMock(template);
54
+ results.mock[pageName] = {
55
+ content: mockContent,
56
+ fileName: `${template.en}.mock.js`
57
+ };
58
+ }
59
+ }
60
+
61
+ // 生成路由配置(如果需要)
62
+ if (processedConfig.routes?.isRender) {
63
+ const routesContent = transformRoutes(processedConfig);
64
+ results.routes = {
65
+ content: routesContent,
66
+ fileName: 'routes.js'
67
+ };
68
+ }
69
+
70
+ return results;
71
+ }
72
+
73
+ /**
74
+ * 渲染单个页面
75
+ * @param {Object} pageConfig - 页面配置
76
+ * @param {string} templateType - 模板类型
77
+ * @returns {string} Vue 文件内容
78
+ */
79
+ function renderSinglePage(pageConfig, templateType = 'element-ui') {
80
+ // 处理页面配置
81
+ const processedPageConfig = processPageConfig(pageConfig);
82
+ const { template, filter, table } = processedPageConfig;
83
+
84
+ // 获取组件材料
85
+ const material = getSfcMaterial(templateType);
86
+
87
+ // 生成 Vue 文件内容
88
+ return transformList(template, filter, table, material);
89
+ }
90
+
91
+ module.exports = {
92
+ renderLists,
93
+ renderSinglePage
94
+ };
@@ -0,0 +1,113 @@
1
+ /**
2
+ * 组件材料管理
3
+ * 定义不同模板类型的组件标签映射
4
+ */
5
+
6
+ /**
7
+ * 获取组件材料
8
+ * @param {string} templateType - 模板类型
9
+ * @returns {Object} 组件材料配置
10
+ */
11
+ function getSfcMaterial(templateType = 'element-ui') {
12
+ const materials = {
13
+ 'element-ui': {
14
+ form: {
15
+ wrapper: 'el-form',
16
+ item: 'el-form-item',
17
+ input: 'el-input',
18
+ select: 'el-select',
19
+ option: 'el-option',
20
+ datePicker: 'el-date-picker',
21
+ button: 'el-button'
22
+ },
23
+ table: {
24
+ wrapper: 'el-table',
25
+ column: 'el-table-column',
26
+ pagination: 'el-pagination'
27
+ },
28
+ layout: {
29
+ container: 'el-container',
30
+ header: 'el-header',
31
+ main: 'el-main',
32
+ footer: 'el-footer',
33
+ row: 'el-row',
34
+ col: 'el-col'
35
+ },
36
+ button: 'el-button'
37
+ },
38
+ 'antd': {
39
+ form: {
40
+ wrapper: 'a-form',
41
+ item: 'a-form-item',
42
+ input: 'a-input',
43
+ select: 'a-select',
44
+ option: 'a-select-option',
45
+ datePicker: 'a-date-picker',
46
+ button: 'a-button'
47
+ },
48
+ table: {
49
+ wrapper: 'a-table',
50
+ column: 'a-table-column',
51
+ pagination: 'a-pagination'
52
+ },
53
+ layout: {
54
+ container: 'a-layout',
55
+ header: 'a-layout-header',
56
+ main: 'a-layout-content',
57
+ footer: 'a-layout-footer',
58
+ row: 'a-row',
59
+ col: 'a-col'
60
+ },
61
+ button: 'a-button'
62
+ },
63
+ 'element-plus': {
64
+ form: {
65
+ wrapper: 'el-form',
66
+ item: 'el-form-item',
67
+ input: 'el-input',
68
+ select: 'el-select',
69
+ option: 'el-option',
70
+ datePicker: 'el-date-picker',
71
+ button: 'el-button'
72
+ },
73
+ table: {
74
+ wrapper: 'el-table',
75
+ column: 'el-table-column',
76
+ pagination: 'el-pagination'
77
+ },
78
+ layout: {
79
+ container: 'el-container',
80
+ header: 'el-header',
81
+ main: 'el-main',
82
+ footer: 'el-footer',
83
+ row: 'el-row',
84
+ col: 'el-col'
85
+ },
86
+ button: 'el-button'
87
+ }
88
+ };
89
+
90
+ return materials[templateType] || materials['element-ui'];
91
+ }
92
+
93
+ /**
94
+ * 根据模板类型获取转换器
95
+ * @param {string} templateType - 模板类型
96
+ * @returns {Object} 转换器映射
97
+ */
98
+ function getTransformersByType(templateType = 'element-ui') {
99
+ // 这里可以根据需要返回不同模板类型的特定转换器
100
+ // 目前使用通用转换器,后续可以扩展
101
+ return {
102
+ list: require('./transformList'),
103
+ filter: require('./transformFilter'),
104
+ table: require('./transformTable'),
105
+ routes: require('./transformRoutes'),
106
+ mock: require('./transformMock')
107
+ };
108
+ }
109
+
110
+ module.exports = {
111
+ getSfcMaterial,
112
+ getTransformersByType
113
+ };