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,108 @@
1
+ /**
2
+ * ## `Ec.E`
3
+ *
4
+ * ### 1. 基本介绍
5
+ *
6
+ * 该类为错误信息定义专用类,方法名采用`fn<Code>`的方式执行最终输出的错误信息内容。通常使用下边代码:
7
+ *
8
+ * ```js
9
+ * // 第一种调用方法:第一参直接是错误代码
10
+ * Ec.fxError(10001, arg1, arg2);
11
+ *
12
+ * // 第二种调用方法:第一参是Boolean值,true就输出,第二参是错误代码
13
+ * const checked = true;
14
+ * Ec.fxError(checked, 10001, arg1, arg2);
15
+ *
16
+ * // 第三种调用方法:第一参是Function,执行后结果为true就输出,第二参是错误代码
17
+ * const fnChecked = () => true;
18
+ * Ec.fxError(fnChecked, 10001, arg1, arg2);
19
+ * ```
20
+ *
21
+ * ### 2. 错误代码表
22
+ *
23
+ * |代码|参数表|含义|
24
+ * |---|---|:---|
25
+ * |10001|`arg,type`|输入参数类型不匹配。|
26
+ * |10002|`arg,type,expected`|「带期望」输入参数和期望参数不匹配。|
27
+ * |10003|`fileType`|文件类型无法被解析。|
28
+ * |10004|`command`|无法识别命令名,不在可解析的命令中。|
29
+ * |10005|`command,expected`|「带期望」输入的命令不在期望的命令列表中。|
30
+ * |10006|`arg`|命令执行中丢失了必须的参数。|
31
+ * |10007|`path`|输入的目录不存在,或者输入路径并不是一个目录。|
32
+ * |10008|`path`|目录不存在,或输入路径是一个文件。|
33
+ * |10009|`path`|路径直接不存在,不论目录还是文件都不存在。|
34
+ * |10010|`projects`|系统检测到两个或两个以上的项目目录,系统无法定位操作项目环境。|
35
+ * |10011|`config`|「后端」配置数据中丢失了`api`属性值。|
36
+ * |10012|`member,clazz`|「后端」在查找的`clazz`类名中无法找到(成员变量/成员函数)`member`。|
37
+ * |10013|`lineType`|工具无法分析行类型,输入的文件内容不符合Zero Ai的基本规范,无法解析源代码。|
38
+ * |10014|`pkg`|「后端」系统找到了超过两个以上的`package`语句,这个在定义过程中是非法的,不可连续执行。|
39
+ * |10015|`method,clazz`|「后端」在查找的`clazz`类名中找到了重复的(成员函数/成员变量)`method`,所以非法。|
40
+ * |10016|`command`|「前端」Zero UI规范错误,不可执行当前命令。|
41
+ * |10017|`root`|「前端」Zero项目的目录并非一个合法的项目目录,请定位到合法的项目目录中。|
42
+ * |10018|`resource`|「前端」资源文件绑定过程中出现了资源错误,请检查环境或执行命令。|
43
+ * |10019|`root`|「前端」当前命令只能在项目根目录中执行(带有package.json文件),其他目录不可执行该方法。|
44
+ * |10020|`menuData`|「前端」当前菜单数据必须是一个合法的Array类型,当前类型不对。|
45
+ * |10021|`field,value`|条件`field=value`引起了重复数据记录,导致不匹配UK规范,检查重复数据专用错误。|
46
+ * |10022|`root`|「前端/后端」无法定位项目的根目录,不可执行项目专用类命令。|
47
+ * |10023|`folder`|「前端」初始化项目时检测到输入的文件路径是一个非空目录,不可执行Zero AI的初始化。|
48
+ * |10024|`path`|当前操作和输入的路径冲突,不可在路径中执行操作指令。|
49
+ * |10025|`configKey`|「前端」配置项主键丢失了核心配置,在生成前端Web组件时出现了规范冲突。|
50
+ * |10026|`path`|「前端」输入路径非法,不在支持的Zero Ui专用路径规范中。|
51
+ * |10027|`modulePath`|「前端」输入路径必须是`<module>/<page>`格式,当前路径并非该格式,和规范冲突。|
52
+ * |10028|`arg`|「前端」模块参数不在枚举值中,必须是四者之一:`FORM, FILTER, HALF, EDIT`。|
53
+ * |10029|`zt`|「带期望」环境变量缺失或者格式不对,必须是`<module>/<page>`格式。|
54
+ * |10030|`arg, key`|「开发专用」方法要求资源文件中必须包含`key`属性,当前`key`属性值不对。|
55
+ * |10031|`id`|「开发专用」当前HTML按钮元素要求`btn`前缀,输入前缀不合法。|
56
+ * |10032|`platform`|操作系统不支持当前命令,或者该操作系统平台中还未实现该命令的执行逻辑。|
57
+ * |10033|`path`|当前路径不符合Zero专用规范(基础Java/Maven规范)。|
58
+ * |10034|`path`|当前路径不符合Ox平台专用规范。|
59
+ *
60
+ * @class E
61
+ */
62
+ module.exports = {
63
+ // 基础
64
+ fn10001: (arg, type) => `[AI-10001] Argument must be '${type}', but now it's '${arg}'`,
65
+ fn10002: (arg, type, expected) => `[AI-10002] Argument must be in (${expected}), but now it's '${arg}' of '${type}'`,
66
+
67
+ // 命令
68
+ fn10003: (fileType) => `[AI-10003] The fileType='${fileType}' is unknown and could not found parser`,
69
+ fn10004: (command) => `[AI-10004] The executor of command '${command}' could not be found(执行器丢失)`,
70
+ fn10005: (command = "未输入", expected) => `[AI-10005] The command '${command}' could not be found, expected '${expected}'`,
71
+ fn10006: (arg) => `[AI-10006] The command missed required arguments: '${arg}'`,
72
+
73
+ // 路径
74
+ fn10007: (path) => `[AI-10007] The file '${path}' does not exist or it's a directory.`,
75
+ fn10008: (path) => `[AI-10008] The directory '${path}' does not exist or it's a file.`,
76
+ fn10009: (path) => `[AI-10009] The path '${path}' does not exist.`,
77
+
78
+ // 后端
79
+ fn10010: (projects = []) => `[AI-10010] The tool detect more than one project folders, found '${projects.length}', please switch.`,
80
+ fn10011: (config) => `[AI-10011] 'api' attribute has been missed in current config ${JSON.stringify(config)}`,
81
+ fn10012: (member, clazz) => `[AI-10012] Duplicated member '${member}' found in class '${clazz}', please check.`,
82
+ fn10013: (lineType) => `[AI-10013] Zero system could not analyze the code line type, type = ${lineType} is Unknown`,
83
+ fn10014: (pkg) => `[AI-10014] More than one 'package' sentence found.${JSON.stringify(pkg)}`,
84
+ fn10015: (method, clazz) => `[AI-10015] Duplicated method '${method}' found in class '${clazz}', please check.`,
85
+
86
+ // 前端
87
+ fn10016: (command) => `[AI-10016] Zero UI specification wrong, you could not execute in '${command}'`,
88
+ fn10017: (root) => `[AI-10017] Current folder '${root}' is not project folder, please switch to project root directory`,
89
+ fn10018: (resource) => `[AI-10018] Zero Resource config file missing '${resource}', please check.`,
90
+ fn10019: (root) => `[AI-10019] This command could run in project root folder only, current folder = ${root}`,
91
+ fn10020: (menuData) => `[AI-10020] The menu data file must be json format with 'data' (Array) node, current = ${menuData}`,
92
+ fn10021: (field, value) => `[AI-10021] The condition '${field} = ${value}' hit duplicated record in your file.`,
93
+ fn10022: (root) => `[AI-10022] Could not find root folder of current project. ${root}`,
94
+ fn10023: (folder) => `[AI-10023] Initialized folder must be empty, current ${folder} is invalid`,
95
+ fn10024: (path) => `[AI-10024] This operation is not allowed for current path ${path}`,
96
+ fn10025: (configKey) => `[AI-10025] Web control initialized require "actual.data" must be string, current:${configKey}`,
97
+ fn10026: (path) => `[AI-10026] The path is invalid, ${path}, system support one of ".", "src/components/xxx", "xxx".`,
98
+ fn10027: (modulePath) => `[AI-10027] The path must be formatted with "<module>/<page>", could not be others, current = ${modulePath}`,
99
+ fn10028: (arg) => `[AI-10028] The "module" parameter must be one of "FORM", "FILTER", "HALF", "EDIT" values. current = ${arg}`,
100
+ fn10029: (zt, name) => `[AI-10029] [DEV] You'll use development command, please set "${name}" environment first, current = ${zt}. React format = "<module>/<page>", Java for other.`,
101
+ fn10030: (arg, key) => `[AI-10030] [DEV] This method require "${key}" in your resource file, but current "${key}" = ${arg}`,
102
+ fn10031: (id) => `[AI-10031] [DEV] Button key must start with "btn", current ${id}`,
103
+ fn10032: (platform) => `[AI-10032] This api is not implemented in current platform os.platform() -> '${platform}'`,
104
+ fn10033: (path) => `[AI-10033] (Zero) Current path '${path}' is not correct Zero work folder under specification`,
105
+ fn10034: (path) => `[AI-10034] (Ox) Current path '${path}' is not correct Ox work folder`,
106
+ fn10035: (path) => `[AI-10035] (Mod) The "initialize.json" configuration file has been missed in '${path}'`,
107
+ fn10036: (mode) => `[AI-10036] (Mod) The mode must be in "REPLACE, APPEND", could not been parsed: ${mode}`,
108
+ };
@@ -0,0 +1,20 @@
1
+ const fs = require('fs');
2
+ const U = require("underscore");
3
+ const isFile = (path) => {
4
+ if (fs.existsSync(path)) {
5
+ return fs.statSync(path).isFile();
6
+ }
7
+ };
8
+ const isDirectory = (path) => {
9
+ if (fs.existsSync(path)) {
10
+ return fs.statSync(path).isDirectory();
11
+ }
12
+ };
13
+ const isExist = (path) => fs.existsSync(path);
14
+
15
+ module.exports = {
16
+ isExist,
17
+ isFile,
18
+ isDirectory,
19
+ isFunction: (input) => U.isFunction(input),
20
+ }
@@ -0,0 +1,26 @@
1
+ const sortString = (left = "", right = "", asc = true) => {
2
+ const minLen = Math.max(left.length, right.length);
3
+ let order = 0;
4
+ for (let idx = 0; idx < minLen; idx++) {
5
+ let leftCode = left.charCodeAt(idx);
6
+ let rightCode = right.charCodeAt(idx);
7
+ // 空白的处理
8
+ if (leftCode !== rightCode) {
9
+ // 修正长度不等的时候的基础算法
10
+ if (isNaN(leftCode)) leftCode = 0;
11
+ if (isNaN(rightCode)) rightCode = 0;
12
+ if (asc) {
13
+ order = leftCode - rightCode;
14
+ } else {
15
+ order = rightCode - leftCode;
16
+ }
17
+ break;
18
+ }
19
+ }
20
+ return order;
21
+ };
22
+
23
+ module.exports = {
24
+ sorterSAsc: (left, right) => sortString(left, right, true),
25
+ sorterSDesc: (left, right) => sortString(left, right, false),
26
+ }
@@ -0,0 +1,37 @@
1
+ const os = require("os");
2
+ const _V = require('./zero.__.v.constant');
3
+
4
+ const findTrace = (path = "") => {
5
+ const folderTrace = path.split(_V.FILE_DELIMITER).filter(each => '' !== each);
6
+ const folderInfo = [];
7
+ folderTrace.forEach((trace, index) => {
8
+ const formatted = `${_V.FILE_DELIMITER}${trace}`;
9
+ const previous = folderInfo[index - 1];
10
+ let item = null;
11
+ if (previous) {
12
+ item = `${previous}${formatted}`;
13
+ } else {
14
+ if (os.platform() === 'win32') {
15
+ item = `${trace}`
16
+ } else {
17
+ item = `${formatted}`;
18
+ }
19
+ }
20
+ folderInfo.push(item);
21
+ });
22
+ return folderInfo
23
+ };
24
+ const findMaxFields = (array = []) => {
25
+ let keys = {};
26
+ for (let idx = 0; idx < array.length; idx++) {
27
+ const length = Object.keys(array[idx]).length;
28
+ if (length > Object.keys(keys).length) {
29
+ keys = array[idx];
30
+ }
31
+ }
32
+ return Object.keys(keys);
33
+ };
34
+ module.exports = {
35
+ findTrace,
36
+ findMaxFields,
37
+ }
@@ -0,0 +1,5 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ FILE_DELIMITER: path.sep,
5
+ }
@@ -0,0 +1,50 @@
1
+ const Log = require("./momo.fn.log");
2
+
3
+ const func_element = require('./momo.fn.element');
4
+ const func_it = require('./momo.fn.it');
5
+ const func_cx = require('./momo.fn.cx');
6
+ const func_fx = require('./momo.fn.fx');
7
+ const func_sorter = require("./momo.fn.sorter");
8
+ const func_str = require("./momo.fn.str");
9
+
10
+ const func_is = require("./momo.fn.is");
11
+ const func_dir = require("./momo.fn.dir");
12
+ const func_to = require("./momo.fn.to");
13
+ const func_io = require("./momo.fn.io");
14
+ const func_out = require("./momo.fn.out");
15
+
16
+ const Immutable = require("immutable");
17
+
18
+ const lain_execute = require("./lain.fn.execute");
19
+ const lain_parse = require("./lain.fn.parse");
20
+
21
+ const exported = {
22
+ ...func_is,
23
+ ...func_dir,
24
+ ...func_to,
25
+ ...func_io,
26
+ ...func_out,
27
+
28
+ ...func_str,
29
+ // Util
30
+ ...func_element,
31
+ ...func_it,
32
+ ...func_cx,
33
+ ...func_fx,
34
+ ...func_sorter,
35
+ // clone method
36
+ clone: input => Immutable.fromJS(input).toJS(),
37
+ info: Log.info,
38
+ error: Log.error,
39
+ warn: Log.warn,
40
+ waiting: Log.execute,
41
+ ask: Log.ask,
42
+ askClose: Log.askClose,
43
+
44
+ ...lain_execute,
45
+ ...lain_parse
46
+ };
47
+ /**
48
+ * @module _epic
49
+ **/
50
+ module.exports = exported;
@@ -0,0 +1,116 @@
1
+ const program = require('commander');
2
+ const U = require('underscore');
3
+ const co = require('co');
4
+ const Immutable = require('immutable');
5
+ const __LOG = require('./momo.fn.log');
6
+ const __IT = require('./momo.fn.it');
7
+ const __FX = require('./momo.fn.fx');
8
+
9
+
10
+ const _buildOption = (options = []) => {
11
+ let optionStr = "";
12
+ const optionItem = [];
13
+ options.forEach((option, index) => {
14
+ const keys = Object.keys(option);
15
+ const key0 = keys[0].toString();
16
+ const key1 = keys[1] ? keys[1].toString() : undefined;
17
+ if (key1) {
18
+ const short = key0.length < key1.length ? key0 : key1;
19
+ const long = key0.length > key1.length ? key0 : key1;
20
+ const key = `-${short}, --${long}`;
21
+ const opt = {};
22
+ opt.key = key;
23
+ opt.desc = option[short] ? option[short] : option[long];
24
+ optionItem.push(opt);
25
+ optionStr += key;
26
+ if (index < options.length - 1) {
27
+ optionStr += ' | ';
28
+ }
29
+ }
30
+ });
31
+ return {
32
+ item: optionItem,
33
+ usage: optionStr
34
+ };
35
+ };
36
+
37
+ const _validateArgs = (keys = []) => {
38
+ const commandArg = process.argv[2];
39
+ const skip = Immutable.fromJS(["-h", '-V', '--version', '--help']);
40
+ if (!skip.contains(commandArg)) {
41
+ const $keys = Immutable.fromJS(keys.concat(['help']));
42
+ const isError = !$keys.contains(commandArg);
43
+ // 检测未通过时,打印错误信息
44
+ __FX.fxError(isError, 10005, commandArg, keys);
45
+ return !isError;
46
+ } else {
47
+ // 直接跳过,检测未通过
48
+ return false;
49
+ }
50
+ };
51
+ /**
52
+ * ## `Ec.executeHeader`
53
+ *
54
+ * 执行命令时打印头信息
55
+ *
56
+ * @memberOf module:_epic
57
+ * @param {String} app 应用程序名
58
+ */
59
+ const executeHeader = (app) => {
60
+ const appInfo = require('../../package.json');
61
+ program.allowUnknownOption();
62
+ program.version(appInfo.version);
63
+ __LOG.info(`----------------- Rachel Momo / AI工具项 ------------------`.rainbow);
64
+ __LOG.info('应用名称: '.bold + app);
65
+ __LOG.info('工具主页: '.bold + appInfo.homepage.blue);
66
+ __LOG.info(`工具版本: ` + `${appInfo.version}`.red + ' ' + `( Node >= 22.x )`.yellow);
67
+ __LOG.info();
68
+ __LOG.info("----------------- AI 系统启动…… ----------------------------".rainbow);
69
+ if (3 > process.argv.length) {
70
+ __LOG.error("命令缺失,请输入正确的命令!");
71
+ }
72
+ };
73
+ /**
74
+ * ## `Ec.executeBody`
75
+ *
76
+ * 执行命令的主方法
77
+ *
78
+ * @memberOf module:_epic
79
+ * @param {Array} commanders 指令集
80
+ * @param {Object} Executor 指令执行集`field = Function`格式
81
+ */
82
+ const executeBody = (commanders = [], Executor = {}) => {
83
+ if (_validateArgs(commanders.map(commander => commander.command))) {
84
+ __IT.itArray(commanders, (commander) => {
85
+ if (!commander.options) commander.options = [];
86
+ const executor = Executor[commander.executor];
87
+ __FX.fxError(!U.isFunction(executor), 10004, commander.command);
88
+ const option = _buildOption(commander.options);
89
+ const cmd = program.command(commander.command)
90
+ .description(commander.description)
91
+ .usage(`[options] [${option.usage}]`);
92
+ __FX.fxContinue(0 < commander.options.length, () => {
93
+ // 设置选项
94
+ commander.options.forEach(option => {
95
+ cmd.option(`-${option.alias}`, option.description);
96
+ cmd.option(`--${option.name}`, option.description);
97
+ })
98
+ });
99
+ cmd.action(() => co(() => executor(commander.options)));
100
+ });
101
+ }
102
+ };
103
+ /**
104
+ * ## `Ec.executeEnd`
105
+ *
106
+ * @memberOf module:_epic
107
+ * 执行命令时打印尾信息
108
+ */
109
+ const executeEnd = () => {
110
+ program.parse(process.argv);
111
+ };
112
+ module.exports = {
113
+ executeHeader,
114
+ executeBody,
115
+ executeEnd,
116
+ };
@@ -0,0 +1,94 @@
1
+ const _IO = require("./momo.fn.io");
2
+
3
+ const parseMetadata = () => {
4
+ const commandMeta = _IO.ioRoot() + "/commander";
5
+ const commandFiles = _IO.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 = _IO.ioRoot() + "/commander/" + command + ".json";
12
+ const commandJ = _IO.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,81 @@
1
+ const fs = require('fs');
2
+ const U = require('underscore');
3
+ const Immutable = require('immutable');
4
+
5
+ // Import
6
+ const __LOG = require('./momo.fn.log');
7
+ const __EC = require('./momo.v.errorcode');
8
+
9
+ const isFile = (path, file = true) => {
10
+ let existing = fs.existsSync(path);
11
+ if (existing) {
12
+ const etat = fs.statSync(path);
13
+ if (file) {
14
+ return etat.isFile();
15
+ } else {
16
+ return etat.isDirectory();
17
+ }
18
+ } else {
19
+ return false;
20
+ }
21
+ };
22
+ const FUNS = {
23
+ Function: U.isFunction,
24
+ String: arg => "string" === typeof arg,
25
+ JString: arg => {
26
+ try {
27
+ JSON.parse(arg);
28
+ return true;
29
+ } catch (e) {
30
+ return false;
31
+ }
32
+ },
33
+ Enum: (arg, expected = []) => {
34
+ expected = !U.isArray(expected) ? [] : expected;
35
+ const $expected = Immutable.fromJS(expected);
36
+ return $expected.contains(arg);
37
+ },
38
+ Valid: (arg) => !!arg,
39
+ File: (arg) => isFile(arg),
40
+ Directory: (arg) => isFile(arg, false),
41
+ Exist: (arg) => fs.existsSync(arg),
42
+ Empty: (arg) => {
43
+ const etat = fs.statSync(arg);
44
+ if (etat.isFile()) {
45
+ return false;
46
+ }
47
+ const children = fs.readdirSync(arg);
48
+ return 0 === children.length;
49
+ }
50
+ };
51
+ const EFUNS = {
52
+ Function: __EC.fn10001,
53
+ String: __EC.fn10001,
54
+ JString: __EC.fn10001,
55
+ Valid: __EC.fn10001,
56
+ Enum: __EC.fn10002,
57
+ File: __EC.fn10007,
58
+ Directory: __EC.fn10008,
59
+ Exist: __EC.fn10009,
60
+ Empty: __EC.fn10023,
61
+ };
62
+ const _sure = (type) => (arg, config = {}) => {
63
+ const check = FUNS[type];
64
+ const message = EFUNS[type](arg, type, config);
65
+ const checked = !check(arg, config);
66
+ if (checked) {
67
+ __LOG.error(message);
68
+ throw new Error(`错误!${message}`);
69
+ } else return true;
70
+ };
71
+ module.exports = {
72
+ cxFunction: _sure('Function'),
73
+ cxString: _sure('String'),
74
+ cxJString: _sure('JString'),
75
+ cxEnum: _sure('Enum'),
76
+ cxValid: _sure('Valid'),
77
+ cxFile: _sure('File'),
78
+ cxExist: _sure('Exist'),
79
+ cxDirectory: _sure('Directory'),
80
+ cxEmpty: _sure('Empty')
81
+ };
@@ -0,0 +1,87 @@
1
+ const __FX = require("./momo.fn.fx");
2
+ const fs = require("fs");
3
+ const U = require("underscore");
4
+ const __LOG = require("./momo.fn.log");
5
+ const __V = require("./momo.v.constant");
6
+ const __U = require("./momo.fn.find");
7
+ const __IS = require("./momo.fn.is");
8
+ const __IO = require("./momo.fn.io");
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,52 @@
1
+ const __FX = require('./momo.fn.fx');
2
+ /**
3
+ * ## `Ec.elementZip`
4
+ *
5
+ * (后期将升级或被废弃)
6
+ *
7
+ * @memberOf module:_epic
8
+ * @deprecated
9
+ * @param {Array} source 原数组
10
+ * @param {Array} target 目标数组
11
+ * @param {Boolean} merged 执行合并的模式,覆盖和追加
12
+ * @returns {Object} 返回最终的数据信息
13
+ */
14
+ const elementZip = (source = [], target = [], merged = false) => {
15
+ const length = Math.min(source.length, target.length);
16
+ const dataItem = {};
17
+ for (let idx = 0; idx < length; idx++) {
18
+ if (merged) {
19
+ dataItem[source[idx]] = target[idx];
20
+ } else {
21
+ dataItem['source'] = source[idx];
22
+ dataItem['target'] = target[idx];
23
+ }
24
+
25
+ }
26
+ return dataItem;
27
+ };
28
+ /**
29
+ * ## `Ec.elementUnique`
30
+ *
31
+ * ### 1. 基本介绍
32
+ *
33
+ * 在输入数组中查找`field = value`的唯一元素对象。
34
+ *
35
+ * @memberOf module:_epic
36
+ * @param {Array} array 输入数组信息
37
+ * @param {String} field 查找的字段信息
38
+ * @param value 执行过滤和匹配的`field = value`的值
39
+ * @returns {*} 返回查找的唯一元素
40
+ */
41
+ const elementUnique = (array = [], field, value) => {
42
+ if (field && value) {
43
+ const filtered = array.filter(item => value === item[field]);
44
+ __FX.fxError(1 < filtered.length, 10021, field, value);
45
+ return filtered[0];
46
+ }
47
+ };
48
+ const exported = {
49
+ elementZip,
50
+ elementUnique
51
+ };
52
+ module.exports = exported;