momo-ai 1.0.0 → 1.0.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 (107) hide show
  1. package/README.md +116 -0
  2. package/package.json +2 -1
  3. package/src/_template/LAIN/.momo/advanced/actor.md +42 -0
  4. package/src/_template/LAIN/.momo/scripts/submodule-clean.sh +56 -0
  5. package/src/_template/LAIN/AGENTS.md +103 -0
  6. package/src/_template/LAIN/changes/proposal.md +39 -0
  7. package/src/_template/LAIN/changes/tasks/task-detail.md +45 -0
  8. package/src/_template/LAIN/changes/tasks.md +49 -0
  9. package/src/_template/LAIN/execute/admin-n-f-dashboard.md +53 -0
  10. package/src/_template/LAIN/execute/admin-n-f-form.md +51 -0
  11. package/src/_template/LAIN/execute/admin-n-f-home.md +49 -0
  12. package/src/_template/LAIN/execute/admin-n-f-list.md +52 -0
  13. package/src/_template/LAIN/execute/admin-n-f-login.md +56 -0
  14. package/src/_template/LAIN/specification/project-model.md +13 -0
  15. package/src/_template/LAIN/specification/project.md +73 -0
  16. package/src/_template/LAIN/specification/requirement.md +25 -0
  17. package/src/_template/PROMPT/add.md.ejs +5 -0
  18. package/src/_template/PROMPT/plan.md.ejs +5 -0
  19. package/src/_template/PROMPT/run.md.ejs +9 -0
  20. package/src/_template/PROMPT/tasks.md.ejs +5 -0
  21. package/src/commander/actor.json +12 -0
  22. package/src/commander/actors.json +6 -0
  23. package/src/commander/add.json +12 -0
  24. package/src/commander/archive.json +12 -0
  25. package/src/commander/env.json +7 -0
  26. package/src/commander/help.json +7 -0
  27. package/src/commander/init.json +13 -0
  28. package/src/commander/list.json +7 -0
  29. package/src/commander/open.json +7 -0
  30. package/src/commander/plan.json +12 -0
  31. package/src/commander/repo.json +18 -0
  32. package/src/commander/run.json +18 -0
  33. package/src/commander/show.json +12 -0
  34. package/src/commander/tasks.json +18 -0
  35. package/src/commander/unlock.json +6 -0
  36. package/src/commander/validate.json +12 -0
  37. package/src/epic/history/ai.economy.impl.fn.excel.js +148 -0
  38. package/src/epic/history/ai.economy.impl.fn.execute.js +117 -0
  39. package/src/epic/history/ai.economy.impl.fn.java.js +140 -0
  40. package/src/epic/history/ai.economy.impl.fn.json.js +23 -0
  41. package/src/epic/history/ai.economy.impl.fn.plugin.js +160 -0
  42. package/src/epic/history/ai.economy.impl.fn.react.js +219 -0
  43. package/src/epic/history/ai.export.impl.fn.parse.js +345 -0
  44. package/src/epic/history/ai.export.impl.fn.seek.js +42 -0
  45. package/src/epic/history/ai.export.interface.fn.string.js +5 -0
  46. package/src/epic/history/ai.export.interface.io.js +69 -0
  47. package/src/epic/history/ai.export.interface.util.js +17 -0
  48. package/src/epic/history/ai.parse.metadata.js +94 -0
  49. package/src/epic/history/ai.path.fn.dir.operation.js +87 -0
  50. package/src/epic/history/ai.path.fn.io.command.js +43 -0
  51. package/src/epic/history/ai.path.fn.io.specification.js +59 -0
  52. package/src/epic/history/ai.path.fn.io.typed.js +63 -0
  53. package/src/epic/history/ai.path.fn.out.content.js +47 -0
  54. package/src/epic/history/ai.string.fn.str.util.js +63 -0
  55. package/src/epic/history/ai.uncork.fn.element.feature.js +52 -0
  56. package/src/epic/history/ai.uncork.fn.it.feature.js +118 -0
  57. package/src/epic/history/ai.uncork.fn.to.typed.js +74 -0
  58. package/src/epic/history/ai.under.fn.cx.evaluate.js +81 -0
  59. package/src/epic/history/ai.under.fn.fx.terminal.js +143 -0
  60. package/src/epic/history/ai.unified.fn.fn.error.code.js +108 -0
  61. package/src/epic/history/ai.unified.fn.is.decision.js +20 -0
  62. package/src/epic/history/ai.unified.fn.sorter.element.js +26 -0
  63. package/src/epic/history/zero.__.fn.find.util.js +37 -0
  64. package/src/epic/history/zero.__.v.constant.js +5 -0
  65. package/src/epic/index.js +50 -0
  66. package/src/epic/lain.fn.execute.js +116 -0
  67. package/src/epic/lain.fn.parse.js +94 -0
  68. package/src/epic/momo.fn.cx.js +81 -0
  69. package/src/epic/momo.fn.dir.js +87 -0
  70. package/src/epic/momo.fn.element.js +52 -0
  71. package/src/epic/momo.fn.find.js +37 -0
  72. package/src/epic/momo.fn.fx.js +143 -0
  73. package/src/epic/momo.fn.io.js +157 -0
  74. package/src/epic/momo.fn.is.js +20 -0
  75. package/src/epic/momo.fn.it.js +118 -0
  76. package/src/epic/momo.fn.log.js +50 -0
  77. package/src/epic/momo.fn.out.js +47 -0
  78. package/src/epic/momo.fn.sorter.js +26 -0
  79. package/src/epic/momo.fn.str.js +63 -0
  80. package/src/epic/momo.fn.to.js +74 -0
  81. package/src/epic/momo.v.constant.js +5 -0
  82. package/src/epic/momo.v.errorcode.js +108 -0
  83. package/src/executor/executeActor.js +113 -0
  84. package/src/executor/executeActors.js +58 -0
  85. package/src/executor/executeAdd.js +248 -0
  86. package/src/executor/executeArchive.js +124 -0
  87. package/src/executor/executeEnv.js +158 -0
  88. package/src/executor/executeHelp.js +23 -0
  89. package/src/executor/executeInit.js +321 -0
  90. package/src/executor/executeList.js +111 -0
  91. package/src/executor/executeOpen.js +130 -0
  92. package/src/executor/executePlan.js +134 -0
  93. package/src/executor/executeRepo.js +234 -0
  94. package/src/executor/executeRun.js +321 -0
  95. package/src/executor/executeShow.js +164 -0
  96. package/src/executor/executeTasks.js +260 -0
  97. package/src/executor/executeUnlock.js +110 -0
  98. package/src/executor/executeValidate.js +210 -0
  99. package/src/executor/index.js +35 -0
  100. package/src/momo.js +39 -1
  101. package/.idea/copilot.data.migration.agent.xml +0 -6
  102. package/.idea/copilot.data.migration.ask.xml +0 -6
  103. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  104. package/.idea/copilot.data.migration.edit.xml +0 -6
  105. package/.idea/modules.xml +0 -8
  106. package/.idea/r2mo-lain.iml +0 -12
  107. package/.idea/vcs.xml +0 -6
@@ -0,0 +1,345 @@
1
+ const fs = require('fs');
2
+ const Immutable = require('immutable');
3
+ const U = require('underscore');
4
+ const __CX = require('./ai.under.fn.cx.evaluate');
5
+ const __FX = require('./ai.under.fn.fx.terminal');
6
+ const __IT = require('./ai.uncork.fn.it.feature');
7
+ const __IO = require('./ai.export.interface.io');
8
+ const __LOG = require('../momo.fn.log');
9
+ const __STR = require('./ai.export.interface.fn.string');
10
+
11
+ const _parseButtons = (value) => {
12
+ if (value.startsWith('(') && value.endsWith(')')) {
13
+ // 分组的情况
14
+ } else {
15
+ value = value.split('-');
16
+ const buttons = [];
17
+ value.forEach((eachVal) => {
18
+ const button = {};
19
+ const eachVals = eachVal.split(':');
20
+ button.text = eachVals[0];
21
+ if (eachVals[1]) {
22
+ button.key = `btn${__STR.strFirstUpper(eachVals[1])}`;
23
+ }
24
+ if (eachVals[2]) {
25
+ button.type = eachVals[2];
26
+ }
27
+ buttons.push(button);
28
+ });
29
+ return buttons;
30
+ }
31
+ };
32
+ const _parseTopbar = (key, value = "") => {
33
+ const textes = value.split(',');
34
+ const ret = {};
35
+ const config = {};
36
+ textes.forEach(text => {
37
+ if (0 <= text.indexOf('=')) {
38
+ const kv = text.split('=');
39
+ const key = kv[0].trim();
40
+ let value = kv[1].trim();
41
+ if ("buttons" === key) {
42
+ value = _parseButtons(value);
43
+ }
44
+ config[key] = value;
45
+ }
46
+ });
47
+ ret[`_${key}`] = config;
48
+ return ret;
49
+ };
50
+ const _parseTabs = (key, value = "") => {
51
+ const textes = value.split(',');
52
+ const ret = {};
53
+ const items = [];
54
+ textes.forEach((each, index) => {
55
+ const item = {};
56
+ item.tab = each;
57
+ item.key = `tabItem${index}`;
58
+ items.push(item);
59
+ });
60
+ ret[`_${key}`] = {items};
61
+ return ret;
62
+ };
63
+ const _parseNav = (key, value = "") => {
64
+ const textes = value.split(',');
65
+ const ret = {};
66
+ const items = [];
67
+ textes.forEach(each => {
68
+ const item = {};
69
+ if (0 <= each.indexOf('-')) {
70
+ const meta = each.split('-');
71
+ item.text = meta[0];
72
+ item.uri = meta[1];
73
+ } else {
74
+ item.text = each;
75
+ }
76
+ items.push(item);
77
+ });
78
+ if (0 < items.length && items[0]) {
79
+ items[0].uri = '$MAIN$';
80
+ }
81
+ if (1 < items.length && items[items.length - 1]) {
82
+ items[items.length - 1].uri = '$SELF$';
83
+ }
84
+ items.forEach((item, index) => {
85
+ item.key = `lnkNav${index}`;
86
+ });
87
+ ret[`_${key}`] = items;
88
+ return ret;
89
+ };
90
+ const _parser = {
91
+ NAV: _parseNav,
92
+ TOPBAR: _parseTopbar,
93
+ TABS: _parseTabs
94
+ };
95
+ const _parseLine = (line = "") => {
96
+ // 以#号为配置项
97
+ if (0 <= line.indexOf('#')) {
98
+ const kv = line.split('#');
99
+ const prefix = kv[0];
100
+ const value = kv[1];
101
+ const type = prefix.toUpperCase();
102
+ if (_parser[type]) {
103
+ return _parser[type](prefix, value);
104
+ }
105
+ } else {
106
+ __LOG.warn(`不合法格式(不包含#)跳过配置行${line}`)
107
+ }
108
+ return {};
109
+ };
110
+ const parseUi = (lines = []) => {
111
+ const result = {};
112
+ lines.forEach(line => {
113
+ const kv = _parseLine(line);
114
+ Object.assign(result, kv);
115
+ });
116
+ return result;
117
+ };
118
+
119
+ const _parseValue = (value = "") => {
120
+ // 是否数值
121
+ if (value) {
122
+ if ("true" === value.toString().toLowerCase()
123
+ || "false" === value.toString().toLowerCase()) {
124
+ value = "true" === value.toString().toLowerCase();
125
+ } else if (value.startsWith("[")) {
126
+ value = JSON.parse(value);
127
+ } else {
128
+ const reg = /^([1-9]\d*|-[1-9]\d*)$/;
129
+ if (reg.test(value)) {
130
+ value = parseInt(value, 10);
131
+ }
132
+ }
133
+ }
134
+ return value;
135
+ };
136
+ const _parseExpr = (item = "") => {
137
+ let ret = item;
138
+ if (item) {
139
+ item = item.toString().trim();
140
+ if (0 < item.indexOf('=')) {
141
+ const kv = item.split('=');
142
+ kv[1] = _parseValue(kv[1]);
143
+ ret = [kv[0], kv[1]];
144
+ } else {
145
+ ret = [item, item];
146
+ }
147
+ }
148
+ return ret;
149
+ };
150
+
151
+ const _parseRel = (lines = []) => {
152
+ const array = [];
153
+ lines.forEach(line => {
154
+ const parsed = _parseExpr(line.trim());
155
+ array.push(parsed);
156
+ });
157
+ return array;
158
+ };
159
+
160
+ const _parseOption = (item = "", name = "option") => {
161
+ const root = __IO.ioRoot();
162
+ const prop = parseZero(root + "/commander/" + name + ".zero", ["P;"]);
163
+ const kv = _parseExpr(item);
164
+ const pair = {};
165
+ pair[kv[0]] = kv[1];
166
+ if (prop[kv[0]]) pair[prop[kv[0]]] = kv[1];
167
+ delete pair[undefined];
168
+ return pair;
169
+ };
170
+
171
+ const _parseArray = (lines = []) => {
172
+ const fields = lines.shift();
173
+ const fieldArr = fields.split(',');
174
+ const result = [];
175
+ lines.forEach(line => {
176
+ const valueArr = line.toString().trim().split(',');
177
+ const entity = {};
178
+ __IT.itPair(fieldArr, valueArr, (first, second) => {
179
+ first = first ? first.trim() : first;
180
+ second = second ? second.trim() : second;
181
+ if (first.startsWith('option')) {
182
+ const optionValue = _parseOption(second);
183
+ if (0 < Object.keys(optionValue).length) {
184
+ entity[first] = optionValue;
185
+ }
186
+ } else {
187
+ entity[first] = second;
188
+ }
189
+ });
190
+ result.push(entity);
191
+ });
192
+ return result;
193
+ };
194
+
195
+ const _parseProp = (lines) => {
196
+ const data = {};
197
+ lines.forEach(line => {
198
+ const parsed = _parseExpr(line.trim());
199
+ data[parsed[0]] = parsed[1];
200
+ });
201
+ return data;
202
+ };
203
+ const _parseKv = (lines = []) => {
204
+ let content = "";
205
+ lines.forEach(line => content += line);
206
+ const pairs = content.split(',');
207
+ const result = {};
208
+ pairs.forEach(pair => {
209
+ const input = pair.trim();
210
+ const kv = _parseExpr(input);
211
+ result[kv[0].trim()] = kv[1];
212
+ });
213
+ return result;
214
+ };
215
+
216
+ const PARSER = {
217
+ "P;": _parseProp, "P": _parseProp,
218
+ "A;": _parseArray, "A": _parseArray,
219
+ "KV;": _parseKv, "KV": _parseKv,
220
+ "UI;": parseUi, "UI": parseUi,
221
+ "R;": _parseRel, "R": _parseRel
222
+ };
223
+ /**
224
+ * ## `Ec.parseZero`
225
+ *
226
+ * ### 1. 基本介绍
227
+ *
228
+ * 解析路径中的特殊文件,文件后缀使用`.zero`,作为当前工具的核心配置数据,文件内容通常如下(`UTF-8`方式读取内容):
229
+ *
230
+ * ```shell
231
+ * PREFIX;
232
+ * <Content>
233
+ * ```
234
+ *
235
+ * 此处`PREFIX`则是第二参数,表示不同的文件类型,不同文件类型的解析方式有所区别。
236
+ *
237
+ * ### 2. 文件类型
238
+ *
239
+ * |前缀|含义|
240
+ * |:---|:---|
241
+ * |`P;`|属性文件专用集,用于描述基础属性文件内容。|
242
+ * |`KV;`|`P;`的不换行模式,直接以`,`为每一个键值对的匹配项,去`\n`换行符过后统一解析,不支持`ENUM`枚举信息。|
243
+ * |`R;`|关系专用解析文件,可解析关系数据文件(后期可增强)。|
244
+ * |`A;`|命令解析专用,表格解析器,解析以`\t`为分隔符的表格,然后解析尾部`optionX`部分为配置选项。|
245
+ * |`UI;`|Jsx文件专用解析器,根据文件模板解析数据。|
246
+ * |`J;`|Java文件专用解析器,解析Java源代码文件数据专用。|
247
+ *
248
+ * @memberOf module:_epic
249
+ * @param {String} path 解析文件的路径
250
+ * @param {Array} fileTypes 文件前缀类型
251
+ * @returns {Any} 最终解析出来的数据内容
252
+ */
253
+ const parseZero = (path, fileTypes = ['J;', 'P;', 'A;', 'KV;', "UI;", 'R;']) => {
254
+ if (fs.existsSync(path)) {
255
+ const content = fs.readFileSync(path, "utf-8").trim();
256
+ const lines = content.split(/\r?\n/g); //for darwin, it is \n; for win32, it is \r\n.
257
+ const fileType = lines.shift();
258
+ __CX.cxEnum(fileType, fileTypes);
259
+ const parser = PARSER[fileType];
260
+ __FX.fxError(!U.isFunction(parser), 10003, fileType);
261
+ return parser(lines);
262
+ } else {
263
+ __FX.fxError(10009, path);
264
+ }
265
+ };
266
+ /**
267
+ * ## `Ec.parseArgs`
268
+ *
269
+ * @memberOf module:_epic
270
+ * @param {Number} ensure 参数允许的长度解析,如果长度不合法,则直接退出
271
+ * @returns {Object} 解析成功后的数据信息
272
+ */
273
+ const parseArgs = (ensure) => {
274
+ const inputArgs = process.argv.splice(3);
275
+ if (ensure === inputArgs.length) {
276
+ const config = {};
277
+ let key = undefined;
278
+ let value = undefined;
279
+ for (let idx = 0; idx <= inputArgs.length; idx++) {
280
+ if (0 === idx % 2) {
281
+ key = inputArgs[idx];
282
+ } else {
283
+ value = inputArgs[idx];
284
+ }
285
+ if (key && value) {
286
+ config[key] = value;
287
+ key = undefined;
288
+ value = undefined;
289
+ }
290
+ }
291
+ return config;
292
+ } else {
293
+ __LOG.error(`参数丢失,期望参数: ${ensure / 2} 个.`);
294
+ process.exit();
295
+ }
296
+ };
297
+
298
+ const parseInput = (required = []) => {
299
+ const inputArgs = process.argv.splice(3);
300
+ const config = {};
301
+ let key = undefined;
302
+ let value = undefined;
303
+ for (let idx = 0; idx <= inputArgs.length; idx++) {
304
+ if (0 === idx % 2) {
305
+ key = inputArgs[idx];
306
+ } else {
307
+ value = inputArgs[idx];
308
+ }
309
+ if (key && value) {
310
+ config[key] = value;
311
+ key = undefined;
312
+ value = undefined;
313
+ }
314
+ }
315
+ const $keys = Immutable.fromJS(Object.keys(config));
316
+ __IT.itArray(required, (each) => {
317
+ const checked = 1 < each.length && (!($keys.contains(each[0]) || $keys.contains(each[1])));
318
+ __FX.fxError(checked, 10006, each);
319
+ });
320
+ return config;
321
+ };
322
+ const parseFormat = (args = {}, pairs = []) => {
323
+ const actual = {};
324
+ pairs.forEach(item => __FX.fxContinue(U.isArray(item), () => {
325
+ const arg0 = item[0];
326
+ const arg1 = item[1];
327
+ let finalKey = arg0.length > arg1.length ? arg0 : arg1;
328
+ finalKey = finalKey.toString().replace(/-/g, '');
329
+ const dft = item[2];
330
+ __IT.itObject(args, (key, value) => __FX.fxContinue(arg0 === key || arg1 === key, () => {
331
+ actual[finalKey] = value;
332
+ }));
333
+ __FX.fxContinue(!args.hasOwnProperty(arg0) && !args.hasOwnProperty(arg1) && undefined !== dft, () => {
334
+ actual[finalKey] = dft;
335
+ });
336
+ }));
337
+ __LOG.info(`Zero AI 加载输入参数:\n${JSON.stringify(actual, null, 4).blue}`);
338
+ return actual;
339
+ };
340
+ module.exports = {
341
+ parseInput,
342
+ parseFormat,
343
+ parseArgs,
344
+ parseZero,
345
+ };
@@ -0,0 +1,42 @@
1
+ const __IO = require('./ai.export.interface.io');
2
+ const Ec = require("../index");
3
+
4
+ const seekResource = (path = ".") => {
5
+ const parent = __IO.dirTree(path, folder => __IO.isExist(folder + "/pom.xml"));
6
+ // 查找最近的项目目录资源信息
7
+ let found;
8
+ parent.forEach(item => {
9
+ if (found) {
10
+ if (item.length > found.length) {
11
+ found = item;
12
+ }
13
+ } else {
14
+ found = item;
15
+ }
16
+ });
17
+ // 追加 src/main/resources/
18
+ return `${found}/src/main/resources`;
19
+ }
20
+
21
+ const seekChildren = (path = ".", filterFn) => {
22
+ const children = __IO.dirChildren(path, true);
23
+ const fileArray = [];
24
+ children.forEach(child => {
25
+ const files = __IO.ioFiles(child);
26
+ files.forEach(file => {
27
+ if (__IO.isFunction(filterFn)) {
28
+ if (filterFn(file.file)) {
29
+ fileArray.push(file.path.replace(path, ""));
30
+ }
31
+ } else {
32
+ fileArray.push(file.path.replace(path, ""));
33
+ }
34
+ })
35
+ })
36
+ return fileArray;
37
+ }
38
+
39
+ module.exports = {
40
+ seekResource,
41
+ seekChildren,
42
+ }
@@ -0,0 +1,5 @@
1
+ const __STR = require("./ai.string.fn.str.util");
2
+
3
+ module.exports = {
4
+ ...__STR,
5
+ };
@@ -0,0 +1,69 @@
1
+ const __IS = require('./ai.unified.fn.is.decision');
2
+ const __TO = require('./ai.uncork.fn.to.typed');
3
+ const __OUT = require("./ai.path.fn.out.content");
4
+
5
+ const __IO_CMD = require("./ai.path.fn.io.command");
6
+ const __IO_SPEC = require('./ai.path.fn.io.specification');
7
+ const __IO_TYPED = require('./ai.path.fn.io.typed');
8
+
9
+ const __DIR = require("./ai.path.fn.dir.operation");
10
+
11
+ const __IO = {
12
+ ...__IO_CMD,
13
+ ...__IO_TYPED,
14
+ ...__IO_SPEC,
15
+ }
16
+ module.exports = {
17
+
18
+ // interface.
19
+ /*
20
+ dirChildren,
21
+ dirParent,
22
+ dirTree,
23
+ dirCreate,
24
+ dirResolve,
25
+ */
26
+ ...__DIR,
27
+ // interface.
28
+ /*
29
+ ioCopy,
30
+ ioDelete,
31
+
32
+ ioJArray,
33
+ ioJObject,
34
+ ioString,
35
+ ioStream,
36
+ ioCsv,
37
+ ioProp,
38
+ ioFiles,
39
+
40
+ ioName,
41
+ ioRoot,
42
+ ioDataA,
43
+ ioSwitch,
44
+ */
45
+ ...__IO,
46
+
47
+ // interface.
48
+ /*
49
+ outJson,
50
+ outString,
51
+ outCopy,
52
+ */
53
+ ...__OUT,
54
+ // interface.
55
+ /*
56
+ toTable,
57
+ toJObject,
58
+ toJArray,
59
+ toCsv,
60
+ */
61
+ ...__TO,
62
+ // interface.
63
+ /*
64
+ isFile,
65
+ isDirectory,
66
+ isExist
67
+ */
68
+ ...__IS,
69
+ };
@@ -0,0 +1,17 @@
1
+ const func_uncork_element_feature = require('./ai.uncork.fn.element.feature');
2
+ const func_unbind_it_feature = require('./ai.uncork.fn.it.feature');
3
+ const func_under_cx_evaluate = require('./ai.under.fn.cx.evaluate');
4
+ const func_under_fx_terminal = require('./ai.under.fn.fx.terminal');
5
+ const func_under___logging = require('../momo.fn.log');
6
+ const func_unified_sorter_element = require("./ai.unified.fn.sorter.element");
7
+ const Immutable = require("immutable");
8
+ module.exports = {
9
+ ...func_uncork_element_feature,
10
+ ...func_unbind_it_feature,
11
+ ...func_under_cx_evaluate,
12
+ ...func_under_fx_terminal,
13
+ ...func_under___logging,
14
+ ...func_unified_sorter_element,
15
+ // clone method
16
+ clone: input => Immutable.fromJS(input).toJS(),
17
+ }
@@ -0,0 +1,94 @@
1
+ const IoR = require("./ai.path.fn.io.specification");
2
+ const IoT = require("./ai.path.fn.io.typed");
3
+ const parseMetadata = () => {
4
+ const commandMeta = IoR.ioRoot() + "/commander";
5
+ const commandFiles = IoT.ioFiles(commandMeta);
6
+ const commandList = [];
7
+ commandFiles.forEach(fileObj => {
8
+ const filename = fileObj.file.toString();
9
+ if (filename.endsWith(".json")) {
10
+ const command = filename.substring(0, filename.indexOf("."));
11
+ const commandPath = IoR.ioRoot() + "/commander/" + command + ".json";
12
+ const commandJ = IoT.ioJObject(commandPath);
13
+ commandList.push(commandJ);
14
+ }
15
+ });
16
+ return commandList;
17
+ }
18
+
19
+ const parseArgument = (options = []) => {
20
+ const args = process.argv.splice(3);
21
+ const result = {};
22
+ const argsLength = args.length;
23
+
24
+ // 将 options 转换为 map 以便快速查找
25
+ const optionsMap = new Map();
26
+ const aliasesMap = new Map();
27
+
28
+ options.forEach(option => {
29
+ optionsMap.set(option.name, option);
30
+ if (option.alias) {
31
+ aliasesMap.set(option.alias, option);
32
+ }
33
+ });
34
+
35
+ // 解析参数
36
+ for (let i = 0; i < argsLength; i += 2) {
37
+ const key = args[i];
38
+ const value = args[i + 1];
39
+
40
+ if (!key || !value) {
41
+ // 如果参数不成对,报错
42
+ if (key && !value) {
43
+ throw new Error(`[ ZERO ] 缺少参数 ${key} 的值`);
44
+ }
45
+ break;
46
+ }
47
+
48
+ // 移除前缀(- 或 --)
49
+ let cleanKey = key;
50
+ if (key.startsWith('--')) {
51
+ cleanKey = key.substring(2);
52
+ } else if (key.startsWith('-')) {
53
+ cleanKey = key.substring(1);
54
+ }
55
+
56
+ // 查找对应的选项
57
+ const option = optionsMap.get(cleanKey) || aliasesMap.get(cleanKey);
58
+
59
+ if (!option) {
60
+ throw new Error(`[ ZERO ] 未知的参数: ${key}`);
61
+ }
62
+
63
+ // 转换值的类型
64
+ let parsedValue = value;
65
+ if (option.type === 'number') {
66
+ parsedValue = Number(value);
67
+ if (isNaN(parsedValue)) {
68
+ throw new Error(`[ ZERO ] 参数 ${key} 的值 ${value} 不是有效的数字`);
69
+ }
70
+ } else if (option.type === 'boolean') {
71
+ parsedValue = value.toLowerCase() === 'true';
72
+ }
73
+
74
+ result[option.name] = parsedValue;
75
+ }
76
+
77
+ // 处理默认值和必需参数
78
+ options.forEach(option => {
79
+ const key = option.name;
80
+ if (!(key in result)) {
81
+ if ('default' in option) {
82
+ result[key] = option.default;
83
+ } else if (option.required) {
84
+ throw new Error(`[ ZERO ] 必需的参数缺失: ${key}`);
85
+ }
86
+ }
87
+ });
88
+
89
+ return result;
90
+ }
91
+ module.exports = {
92
+ parseMetadata,
93
+ parseArgument,
94
+ }
@@ -0,0 +1,87 @@
1
+ const __FX = require("./ai.under.fn.fx.terminal");
2
+ const fs = require("fs");
3
+ const U = require("underscore");
4
+ const __LOG = require("../momo.fn.log");
5
+ const __V = require("./zero.__.v.constant");
6
+ const __U = require("./zero.__.fn.find.util");
7
+ const __IS = require("./ai.unified.fn.is.decision");
8
+ const __IO = require("./ai.path.fn.io.specification");
9
+ const dirResolve = (path = "") => {
10
+ let result = path.trim();
11
+ if (result.endsWith(__V.FILE_DELIMITER)) {
12
+ result = result.substring(0, result.length - 1);
13
+ }
14
+ return result;
15
+ };
16
+ const dirTree = (pathDir = ".", pathFilterFn) => {
17
+ // 截取当前运行目录
18
+ const pathStart = __IO.ioSwitch(pathDir);
19
+ // 往上查找项目根目录
20
+ const pathArr = pathStart.split(__V.FILE_DELIMITER);
21
+ const pathIt = [];
22
+ while (0 < pathArr.length) {
23
+ const folder = pathArr.join("/");
24
+ if ('' !== folder) {
25
+ if (U.isFunction(pathFilterFn)) {
26
+ if (pathFilterFn(folder)) {
27
+ pathIt.push(folder);
28
+ }
29
+ } else {
30
+ pathIt.push(folder);
31
+ }
32
+ }
33
+ pathArr.pop();
34
+ }
35
+ return pathIt;
36
+ }
37
+ const dirParent = (path, includeCurrent = false) => {
38
+ let result = [];
39
+ if (includeCurrent) {
40
+ result.push(path);
41
+ }
42
+ __FX.fxContinue(fs.existsSync(path), () => {
43
+ let parent = dirResolve(path);
44
+ parent = parent.substring(0, parent.lastIndexOf(__V.FILE_DELIMITER));
45
+ result.push(parent);
46
+ result = result.concat(dirParent(parent, false));
47
+ });
48
+ return result;
49
+ };
50
+
51
+ const dirChildren = (path, includeCurrent = true) => {
52
+ let result = [];
53
+ if (includeCurrent) {
54
+ result.push(path);
55
+ }
56
+ __FX.fxContinue(fs.existsSync(path), () => {
57
+ const folders = fs.readdirSync(path);
58
+ const directory = dirResolve(path) + __V.FILE_DELIMITER;
59
+ folders.forEach(item => __FX.fxContinue(!item.startsWith('.'), () => {
60
+ const absolute = directory + item;
61
+ if (__IS.isDirectory(absolute)) {
62
+ result.push(absolute);
63
+ result = result.concat(dirChildren(absolute, false));
64
+ }
65
+ }));
66
+ });
67
+ return result;
68
+ };
69
+
70
+ const dirCreate = (path = "") => {
71
+ // TODO: Path专用
72
+ const folderInfo = __U.findTrace(path);
73
+ // 查找第一个存在的目录
74
+ const lefts = folderInfo.filter(item => !__IS.isExist(item)).sort((left, right) => left.length - right.length);
75
+ lefts.filter(item => '' !== item).forEach(left => {
76
+ __LOG.info("创建目录:" + left.yellow);
77
+ fs.mkdirSync(left);
78
+ });
79
+ return true;
80
+ };
81
+ module.exports = {
82
+ dirCreate,
83
+ dirChildren,
84
+ dirParent,
85
+ dirResolve,
86
+ dirTree,
87
+ }
@@ -0,0 +1,43 @@
1
+ const fs = require("fs");
2
+ const __LOG = require("../momo.fn.log");
3
+ const __FX = require("./ai.under.fn.fx.terminal");
4
+ const __IO = require('./ai.path.fn.io.typed');
5
+ const __IS = require("./ai.unified.fn.is.decision");
6
+ const __OUT = require("./ai.path.fn.out.content");
7
+ const __V = require("./zero.__.v.constant");
8
+
9
+ const __ioDeleteDir = (path) => {
10
+ if (fs.existsSync(path)) {
11
+ const etat = fs.statSync(path);
12
+ if (etat.isDirectory()) {
13
+ const children = fs.readdirSync(path);
14
+ if (0 === children.length) {
15
+ fs.rmdirSync(path);
16
+ } else {
17
+ children.forEach(item => {
18
+ const hitted = path + __V.FILE_DELIMITER + item;
19
+ __ioDeleteDir(hitted);
20
+ });
21
+ }
22
+ } else {
23
+ __LOG.info(`删除文件:${path}`);
24
+ fs.unlinkSync(path);
25
+ }
26
+ }
27
+ };
28
+
29
+ const ioCopy = (from, to) => {
30
+ __FX.fxContinue(__IS.isExist(from) && !__IS.isExist(to) && __IS.isFile(from), () => {
31
+ const content = __IO.ioString(from);
32
+ __OUT.outString(to, content);
33
+ });
34
+ };
35
+
36
+ const ioDelete = (path) => {
37
+ __FX.fxError(__V.FILE_DELIMITER === path.trim(), 10024, path);
38
+ __ioDeleteDir(path);
39
+ };
40
+ module.exports = {
41
+ ioCopy,
42
+ ioDelete,
43
+ }