zero-ai 1.0.79 → 1.0.81
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.
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# CLAUDE.md — r2mo-init (zero-ai)
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
`r2mo-init` (npm: `zero-ai`, binary: `ai`) is a Node.js CLI tool for the **Zero Ecotope** ecosystem. It scaffolds full-stack Java applications (Spring Boot / Vert.x), React frontends, and manages RBAC permissions via Excel workflows. Dedicated to **Rachel Momo**.
|
|
6
|
+
|
|
7
|
+
- Version: 1.0.80
|
|
8
|
+
- Entry point: `src/ai.js`
|
|
9
|
+
- Author: Lang
|
|
10
|
+
|
|
11
|
+
## Tech Stack
|
|
12
|
+
|
|
13
|
+
- **Runtime**: Node.js (pure JavaScript, no TypeScript)
|
|
14
|
+
- **CLI Framework**: commander v11 + inquirer v8
|
|
15
|
+
- **Template Engines**: EJS, Handlebars
|
|
16
|
+
- **Excel Processing**: exceljs
|
|
17
|
+
- **Database**: MySQL (mysql2 driver, no ORM)
|
|
18
|
+
- **Data**: immutable, lodash, underscore, js-yaml
|
|
19
|
+
- **HTTP**: superagent
|
|
20
|
+
- **Crypto**: crypto-js, uuid
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/
|
|
26
|
+
├── ai.js # CLI entry (bin), wires header → body → end
|
|
27
|
+
├── commander/ # Command definitions (JSON configs)
|
|
28
|
+
├── commander-ai/ # Command implementations (fn.*.js)
|
|
29
|
+
├── commander-shared/ # Shared init/parse utilities
|
|
30
|
+
├── epic/ # Core utility library (internal toolkit)
|
|
31
|
+
│ ├── ai.economy.* # Code generation (Excel, Java, React, JSON, plugin)
|
|
32
|
+
│ ├── ai.export.* # I/O, string utils, seek/parse
|
|
33
|
+
│ ├── ai.path.* # File/dir operations, content output
|
|
34
|
+
│ ├── ai.string.* # String utilities
|
|
35
|
+
│ ├── ai.uncork.* # Element/feature transforms
|
|
36
|
+
│ ├── ai.under.* # Evaluation, terminal functions
|
|
37
|
+
│ ├── ai.unified.* # Logging, error codes, sorting, decisions
|
|
38
|
+
│ └── zero.__.* # Constants, find utilities
|
|
39
|
+
├── cab/ # Templates & resources
|
|
40
|
+
│ ├── form/ # React form templates
|
|
41
|
+
│ ├── list/ # React list templates
|
|
42
|
+
│ ├── perm/ # RBAC permission Excel templates
|
|
43
|
+
│ ├── plugin/ # Java plugin templates
|
|
44
|
+
│ └── resource/ # Resource files
|
|
45
|
+
├── _template/ # Project scaffolding templates
|
|
46
|
+
│ ├── SPRING/ # Spring Boot scaffold
|
|
47
|
+
│ ├── ZERO/ # Vert.x Zero scaffold
|
|
48
|
+
│ ├── MODULE/ # Module templates
|
|
49
|
+
│ ├── EXCEL/ # Excel templates (ex-api, ex-crud)
|
|
50
|
+
│ └── APP/ # Application templates
|
|
51
|
+
└── previous/ # Legacy code (do not modify)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Boot Sequence
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
ai.js → Ec.executeHeader() # Print CLI banner
|
|
58
|
+
→ Ut.parseMetadata() # Load JSON configs from src/commander/*.json
|
|
59
|
+
→ Ec.executeBody() # Match command → dispatch to commander-ai executor
|
|
60
|
+
→ Ec.executeEnd() # Print footer
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Each command is defined by a JSON file in `src/commander/` with shape:
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"executor": "executeFunctionName",
|
|
67
|
+
"description": "...",
|
|
68
|
+
"command": "commandName",
|
|
69
|
+
"options": [{ "name": "...", "alias": "...", "description": "...", "default": "..." }]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The executor function is resolved from `src/commander-ai/index.js`.
|
|
74
|
+
|
|
75
|
+
## CLI Commands
|
|
76
|
+
|
|
77
|
+
| Command | Executor | Purpose |
|
|
78
|
+
|---------|----------|---------|
|
|
79
|
+
| `ai spring` | `executeSpring` | Generate Spring Boot scaffold |
|
|
80
|
+
| `ai zero` | `executeZero` | Generate Vert.x Zero scaffold |
|
|
81
|
+
| `ai web` | `executeWeb` | Clone React frontend from Gitee |
|
|
82
|
+
| `ai sync` | `executeFrontendSync` | Sync Zero UI framework updates |
|
|
83
|
+
| `ai ex-api` | `executeExApi` | Generate RBAC Excel from YAML metadata |
|
|
84
|
+
| `ai ex-crud` | `executeExCrud` | Generate CRUD Excel from YAML metadata |
|
|
85
|
+
| `ai ex-perm` | `executeExPerm` | Generate permission Excel files |
|
|
86
|
+
| `ai apply` | `executeApply` | Install Cursor AI rules from remote repo |
|
|
87
|
+
| `ai uuid` | `executeUuid` | Generate UUIDs (clipboard on macOS) |
|
|
88
|
+
| `ai str` | `executeString` | Generate random strings |
|
|
89
|
+
| `ai md5` | `executeMD5` | MD5 hash generation |
|
|
90
|
+
| `ai help` | `executeHelp` | Show help information |
|
|
91
|
+
|
|
92
|
+
## Environment Variables
|
|
93
|
+
|
|
94
|
+
| Variable | Purpose |
|
|
95
|
+
|----------|---------|
|
|
96
|
+
| `Z_DB_TYPE` | Database type |
|
|
97
|
+
| `Z_DB_HOST` | Database host |
|
|
98
|
+
| `Z_DB_PORT` | Database port |
|
|
99
|
+
| `Z_DBS_INSTANCE` | Database instance name |
|
|
100
|
+
| `Z_DB_APP_USER` | Database username |
|
|
101
|
+
| `Z_DB_APP_PASS` | Database password |
|
|
102
|
+
| `Z_APP_ID` | Application ID (multi-tenant) |
|
|
103
|
+
| `Z_TENANT` | Tenant identifier |
|
|
104
|
+
| `Z_SIGMA` | Sigma dimension key (multi-tenant) |
|
|
105
|
+
| `Z_AI_SYNC` | Skeleton project path for `ai sync` |
|
|
106
|
+
|
|
107
|
+
## Naming Conventions
|
|
108
|
+
|
|
109
|
+
### File Naming (src/epic/)
|
|
110
|
+
Pattern: `ai.<domain>.<layer>.<type>.<feature>.js`
|
|
111
|
+
- Domain: `economy`, `export`, `path`, `string`, `uncork`, `under`, `unified`
|
|
112
|
+
- Layer: `impl` (internal), `interface` (exported), `fn` (function)
|
|
113
|
+
- Type: `fn` (function), `io` (I/O), `v` (value/constant)
|
|
114
|
+
|
|
115
|
+
### File Naming (src/commander-ai/)
|
|
116
|
+
Pattern: `fn.<category>.<feature>.js`
|
|
117
|
+
- Categories: `source` (scaffold), `ex` (Excel), `random` (generators), `help`
|
|
118
|
+
|
|
119
|
+
### Module Exports
|
|
120
|
+
All modules use spread-merge pattern for flat namespace:
|
|
121
|
+
```js
|
|
122
|
+
module.exports = { ...moduleA, ...moduleB, ...moduleC };
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Adding a New Command
|
|
126
|
+
|
|
127
|
+
1. Create JSON config in `src/commander/<command>.json`
|
|
128
|
+
2. Create executor in `src/commander-ai/fn.<category>.<feature>.js`
|
|
129
|
+
3. Register executor in `src/commander-ai/index.js`
|
|
130
|
+
4. The CLI auto-discovers commands from JSON configs via `Ut.parseMetadata()`
|
|
131
|
+
|
|
132
|
+
## Key Modules
|
|
133
|
+
|
|
134
|
+
- **`Ec` (epic)**: Core utility library — import via `require('./epic')`. Provides file I/O, string manipulation, template rendering, Excel processing, Java/React code generation, logging, and terminal output.
|
|
135
|
+
- **`Ut` (commander-shared)**: Command parsing, project initialization helpers for Spring/Zero/Module/App scaffolds, input validation (`nameValid`).
|
|
136
|
+
- **`Executor` (commander-ai)**: Map of all command executor functions, dispatched by command name.
|
|
137
|
+
|
|
138
|
+
## Code Style
|
|
139
|
+
|
|
140
|
+
- Pure CommonJS (`require` / `module.exports`), no ES modules
|
|
141
|
+
- No TypeScript, no linter, no formatter configured
|
|
142
|
+
- Comments in Chinese (中文注释)
|
|
143
|
+
- Immutable.js used for data structures where applicable
|
|
144
|
+
- Generator-based async with `co` + `bluebird` (legacy pattern)
|
|
145
|
+
- No test framework configured (test script points to a single file)
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Install dependencies
|
|
151
|
+
npm install
|
|
152
|
+
|
|
153
|
+
# Link CLI globally for local dev
|
|
154
|
+
npm link
|
|
155
|
+
|
|
156
|
+
# Run a command
|
|
157
|
+
ai <command> [options]
|
|
158
|
+
|
|
159
|
+
# Example: generate Spring Boot scaffold
|
|
160
|
+
ai spring -n my-app -c app.json -o ./output
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Template System
|
|
164
|
+
|
|
165
|
+
- EJS templates in `src/cab/` and `src/_template/`
|
|
166
|
+
- Templates use `<%= variable %>` syntax for interpolation
|
|
167
|
+
- Excel templates in `src/cab/perm/` use `{TABLE}` markers for data injection
|
|
168
|
+
- Java templates generate Maven POM, Spring Boot configs, Vert.x verticles
|
|
169
|
+
- React templates generate form/list components
|
|
170
|
+
|
|
171
|
+
## Database Schema Patterns
|
|
172
|
+
|
|
173
|
+
- Multi-tenant: every table includes `SIGMA`, `TENANT_ID`, `APP_ID` columns
|
|
174
|
+
- RBAC tables: `S_USER`, `S_ROLE`, `S_PERMISSION`, `S_ACTION`, etc.
|
|
175
|
+
- Audit columns: `CREATED_AT`, `CREATED_BY`, `UPDATED_AT`, `UPDATED_BY`
|
|
176
|
+
- Soft delete: `ACTIVE` boolean column
|
|
177
|
+
- Primary key: `KEY` column (UUID)
|
|
178
|
+
|
|
179
|
+
## Important Notes
|
|
180
|
+
|
|
181
|
+
- `src/previous/` contains legacy code — do not modify
|
|
182
|
+
- `src/cab/perm/` has 66+ Excel template files — changes here affect RBAC generation for all projects
|
|
183
|
+
- `_template/` directories are scaffold blueprints — edits propagate to all newly generated projects
|
|
184
|
+
- The CLI copies to clipboard on macOS for uuid/str/md5 commands
|
|
185
|
+
- `package-lock.json` is gitignored — only `package.json` is tracked
|
package/package.json
CHANGED
package/src/commander/sync.json
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"options": [
|
|
6
6
|
{"name": "path", "alias": "p", "description": "本地配置文件路径,默认 .zero", "default": ".zero"},
|
|
7
7
|
{"name": "mode", "alias": "m", "description": "指定同步模块的模式,是否本地同步", "default": false},
|
|
8
|
-
{"name": "reverse", "alias": "r", "type": "boolean", "description": "逆向拷贝:从当前项目拷贝到
|
|
8
|
+
{"name": "reverse", "alias": "r", "type": "boolean", "description": "逆向拷贝:从当前项目拷贝到 Z_AI_SYNC 指定的骨架项目本地副本", "default": false}
|
|
9
9
|
]
|
|
10
10
|
}
|
|
@@ -94,6 +94,7 @@ module.exports = async (options) => {
|
|
|
94
94
|
type: "checkbox",
|
|
95
95
|
name: "selectedFiles",
|
|
96
96
|
message: "请选择要安装的规则文件:",
|
|
97
|
+
loop: false,
|
|
97
98
|
choices: ruleFiles.map(file => ({
|
|
98
99
|
name: file,
|
|
99
100
|
value: file,
|
|
@@ -112,6 +113,7 @@ module.exports = async (options) => {
|
|
|
112
113
|
type: "checkbox",
|
|
113
114
|
name: "selectedTargets",
|
|
114
115
|
message: "请选择输出目标(选几个就输出几个):",
|
|
116
|
+
loop: false,
|
|
115
117
|
choices: [
|
|
116
118
|
{ name: "Cursor:.cursor/rules(.mdc)", value: "cursor", checked: true },
|
|
117
119
|
{ name: "Trae:.trae/rules(.md)", value: "trae", checked: true },
|
|
@@ -92,10 +92,10 @@ const executeLocal = (actual = {}, options = {}) => {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
* 逆向拷贝:从当前项目将 COMMANDS 所列内容拷贝到
|
|
95
|
+
* 逆向拷贝:从当前项目将 COMMANDS 所列内容拷贝到 Z_AI_SYNC 指定的骨架项目本地副本
|
|
96
96
|
*/
|
|
97
97
|
const executeReverse = (targetBase, options = {}) => {
|
|
98
|
-
Ec.info(
|
|
98
|
+
Ec.info(`逆向拷贝目标(骨架项目本地副本):${targetBase}`);
|
|
99
99
|
Ec.info(`开始逆向拷贝主框架(与正向 sync 相同内容):......`.yellow);
|
|
100
100
|
COMMANDS.forEach((command) => {
|
|
101
101
|
Ec.info(`处理:${command.green}`);
|
|
@@ -145,17 +145,12 @@ module.exports = (options) => {
|
|
|
145
145
|
process.argv.splice(3 + flagIdx + 1, 0, "true");
|
|
146
146
|
}
|
|
147
147
|
const parsed = Ut.parseArgument(options);
|
|
148
|
-
// 1. 环境检查
|
|
149
|
-
if (!Ec.isExist(".git")) {
|
|
150
|
-
Ec.error("请选择带`.git`或`vertx-ui`的目录执行当前命令!");
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
148
|
|
|
154
|
-
// 逆向拷贝:-r 时从当前项目拷贝到
|
|
149
|
+
// 逆向拷贝:-r 时从当前项目拷贝到 Z_AI_SYNC 指定的骨架项目本地副本
|
|
155
150
|
if (parsed.reverse) {
|
|
156
|
-
const targetBase = process.env.
|
|
151
|
+
const targetBase = process.env.Z_AI_SYNC;
|
|
157
152
|
if (!targetBase || !targetBase.trim()) {
|
|
158
|
-
Ec.error("逆向拷贝需要设置环境变量
|
|
153
|
+
Ec.error("逆向拷贝需要设置环境变量 Z_AI_SYNC(骨架项目本地副本路径),未设置则退出。");
|
|
159
154
|
process.exit(1);
|
|
160
155
|
}
|
|
161
156
|
const resolved = path.resolve(targetBase.trim());
|
|
@@ -163,6 +158,12 @@ module.exports = (options) => {
|
|
|
163
158
|
return;
|
|
164
159
|
}
|
|
165
160
|
|
|
161
|
+
// 1. 环境检查(仅正向同步需要)
|
|
162
|
+
if (!Ec.isExist(".git")) {
|
|
163
|
+
Ec.error("请选择带`.git`或`vertx-ui`的目录执行当前命令!");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
166
167
|
let pathSource;
|
|
167
168
|
if (parsed.mode) {
|
|
168
169
|
// 本地模式
|