gorig-cli 1.0.24 → 1.0.26
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/LICENSE +21 -0
- package/README.md +129 -40
- package/commands/create.js +267 -112
- package/commands/doc.js +21 -8
- package/commands/init.js +316 -255
- package/commands/skill.js +55 -17
- package/package.json +1 -1
- package/templates/config.go.ejs +6 -5
- package/templates/config.yaml.ejs +3 -38
- package/templates/controller.go.ejs +11 -42
- package/templates/crud.controller.go.ejs +71 -0
- package/templates/crud.doc.md.ejs +60 -0
- package/templates/crud.dto.go.ejs +103 -0
- package/templates/crud.integration.init_test.go.ejs +17 -0
- package/templates/crud.integration_test.go.ejs +66 -0
- package/templates/crud.model.go.ejs +25 -0
- package/templates/crud.module.README.md.ejs +70 -0
- package/templates/crud.mongo.config.yaml.ejs +19 -0
- package/templates/crud.mysql.config.yaml.ejs +14 -0
- package/templates/crud.router.go.ejs +18 -0
- package/templates/crud.service.go.ejs +179 -0
- package/templates/crud.test.go.ejs +52 -0
- package/templates/dto.go.ejs +16 -0
- package/templates/gitignore.ejs +18 -49
- package/templates/hello.controller.go.ejs +19 -0
- package/templates/hello.router.go.ejs +12 -0
- package/templates/hello.service.go.ejs +31 -0
- package/templates/hello.test.go.ejs +34 -0
- package/templates/init.go.ejs +1 -27
- package/templates/main.go.ejs +2 -5
- package/templates/model.go.ejs +3 -4
- package/templates/project.README.md.ejs +35 -0
- package/templates/router.go.ejs +4 -8
- package/templates/service.go.ejs +25 -77
- package/templates/skills/gorig-backend/SKILL.md +89 -0
- package/templates/skills/gorig-backend/agents/openai.yaml +4 -0
- package/templates/skills/gorig-backend/assets/api-doc-template.md +59 -0
- package/templates/skills/gorig-backend/assets/gorig.gitignore +65 -0
- package/templates/skills/gorig-backend/assets/module-readme-template.md +58 -0
- package/templates/skills/gorig-backend/references/advanced-data-access.md +275 -0
- package/templates/skills/gorig-backend/references/auth-security.md +194 -0
- package/templates/skills/gorig-backend/references/business-scenarios.md +155 -0
- package/templates/skills/gorig-backend/references/cache.md +301 -0
- package/templates/skills/gorig-backend/references/capability-matrix.md +37 -0
- package/templates/skills/gorig-backend/references/configuration.md +48 -0
- package/templates/skills/gorig-backend/references/framework-api.md +190 -0
- package/templates/skills/gorig-backend/references/messaging.md +143 -0
- package/templates/skills/gorig-backend/references/onboarding-files.md +46 -0
- package/templates/skills/gorig-backend/references/outbound-http.md +162 -0
- package/templates/skills/gorig-backend/references/persistent-crud.md +332 -0
- package/templates/skills/gorig-backend/references/project-bootstrap.md +128 -0
- package/templates/skills/gorig-backend/references/scheduled-tasks.md +231 -0
- package/templates/skills/gorig-backend/references/service-lifecycle.md +51 -0
- package/templates/skills/gorig-backend/references/source-map.md +43 -0
- package/templates/skills/gorig-backend/references/source-policy.md +58 -0
- package/templates/skills/gorig-backend/references/sse.md +121 -0
- package/templates/skills/gorig-backend/references/testing.md +171 -0
- package/templates/skills/gorig-backend/scripts/check-source-links.sh +48 -0
- package/templates/skills/gorig-backend/scripts/detect-gorig-context.sh +67 -0
- package/templates/skills/gorig-backend/scripts/verify-basic-project.sh +108 -0
- package/npm_publish copy.sh +0 -65
- package/templates/internal.go.ejs +0 -49
- package/templates/req.go.ejs +0 -8
- package/templates/resp.go.ejs +0 -8
- package/templates/service.pub.go.ejs +0 -22
- package/templates/skills/claude/gorig-backend/SKILL.md +0 -766
- package/templates/skills/claude/gorig-backend/assets/api-doc-template.md +0 -50
- package/templates/skills/claude/gorig-backend/assets/module-readme-template.md +0 -46
- package/templates/skills/claude/gorig-backend/references/onboarding-files.md +0 -44
- package/templates/skills/codex/gorig-backend/SKILL.md +0 -766
- package/templates/skills/codex/gorig-backend/agents/openai.yaml +0 -4
- package/templates/skills/codex/gorig-backend/assets/api-doc-template.md +0 -50
- package/templates/skills/codex/gorig-backend/assets/module-readme-template.md +0 -46
- package/templates/skills/codex/gorig-backend/references/onboarding-files.md +0 -44
package/commands/create.js
CHANGED
|
@@ -8,6 +8,88 @@ import { fileURLToPath } from 'url';
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
+
const readOptionValue = (args, index, name) => {
|
|
12
|
+
const arg = args[index];
|
|
13
|
+
const prefix = `${name}=`;
|
|
14
|
+
if (arg.startsWith(prefix)) {
|
|
15
|
+
return { value: arg.slice(prefix.length), nextIndex: index };
|
|
16
|
+
}
|
|
17
|
+
if (index + 1 >= args.length || args[index + 1].startsWith('--')) {
|
|
18
|
+
throw new Error(`Missing value for ${name}`);
|
|
19
|
+
}
|
|
20
|
+
return { value: args[index + 1], nextIndex: index + 1 };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const toModuleName = (moduleName) => moduleName
|
|
24
|
+
.split('_')
|
|
25
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
26
|
+
.join('');
|
|
27
|
+
|
|
28
|
+
export const parseCreateArgs = (args) => {
|
|
29
|
+
if (args.length < 1) {
|
|
30
|
+
throw new Error('Please use the correct command format: gorig-cli create <module name>');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const moduleName = args[0];
|
|
34
|
+
if (!/^[a-z][a-z0-9_]*$/.test(moduleName)) {
|
|
35
|
+
throw new Error('Module name must use lower snake_case, for example: user or supply_order');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const options = {
|
|
39
|
+
moduleName,
|
|
40
|
+
ModuleName: toModuleName(moduleName),
|
|
41
|
+
crud: false,
|
|
42
|
+
db: '',
|
|
43
|
+
dbName: '',
|
|
44
|
+
http: true,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
for (let i = 1; i < args.length; i += 1) {
|
|
48
|
+
const arg = args[i];
|
|
49
|
+
if (arg === '--crud') {
|
|
50
|
+
options.crud = true;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (arg === '--no-http') {
|
|
54
|
+
options.http = false;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const valueOptions = ['--db', '--database', '--store', '--db-name'];
|
|
59
|
+
const optionName = valueOptions.find((name) => arg === name || arg.startsWith(`${name}=`));
|
|
60
|
+
if (!optionName) {
|
|
61
|
+
throw new Error(`Unknown create option: ${arg}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const { value, nextIndex } = readOptionValue(args, i, optionName);
|
|
65
|
+
i = nextIndex;
|
|
66
|
+
|
|
67
|
+
if (['--db', '--database', '--store'].includes(optionName)) {
|
|
68
|
+
options.crud = true;
|
|
69
|
+
options.db = value.toLowerCase();
|
|
70
|
+
} else if (optionName === '--db-name') {
|
|
71
|
+
options.dbName = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (options.crud) {
|
|
76
|
+
if (!['mysql', 'mongo', 'mongodb'].includes(options.db)) {
|
|
77
|
+
throw new Error('Persistent CRUD modules require --db mysql or --db mongo');
|
|
78
|
+
}
|
|
79
|
+
if (options.db === 'mongodb') {
|
|
80
|
+
options.db = 'mongo';
|
|
81
|
+
}
|
|
82
|
+
if (!options.dbName) {
|
|
83
|
+
options.dbName = options.db === 'mysql' ? 'Main' : 'main';
|
|
84
|
+
}
|
|
85
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(options.dbName)) {
|
|
86
|
+
throw new Error('Database connection name must start with a letter and contain only letters, numbers, or underscores');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return options;
|
|
91
|
+
};
|
|
92
|
+
|
|
11
93
|
// Get the module name from the go.mod file
|
|
12
94
|
const getGoModModuleName = async () => {
|
|
13
95
|
try {
|
|
@@ -25,135 +107,208 @@ const getGoModModuleName = async () => {
|
|
|
25
107
|
}
|
|
26
108
|
};
|
|
27
109
|
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
110
|
+
const renderTemplate = async (templateName, destination, data) => {
|
|
111
|
+
const templatePath = path.join(__dirname, '../templates', templateName);
|
|
112
|
+
const content = await ejs.renderFile(templatePath, data);
|
|
113
|
+
await fs.ensureDir(path.dirname(destination));
|
|
114
|
+
await fs.writeFile(destination, content);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const renderTemplateContent = async (templateName, data) => {
|
|
118
|
+
const templatePath = path.join(__dirname, '../templates', templateName);
|
|
119
|
+
return ejs.renderFile(templatePath, data);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const insertYamlConnection = (content, topKey, connectionName, connectionBlock) => {
|
|
123
|
+
const normalized = content.endsWith('\n') ? content : `${content}\n`;
|
|
124
|
+
const lines = normalized.split('\n');
|
|
125
|
+
const topIndex = lines.findIndex((line) => line === `${topKey}:`);
|
|
126
|
+
|
|
127
|
+
if (topIndex < 0) {
|
|
128
|
+
return `${normalized.trimEnd()}\n\n${topKey}:\n${connectionBlock.trimEnd()}\n`;
|
|
33
129
|
}
|
|
34
130
|
|
|
35
|
-
|
|
36
|
-
|
|
131
|
+
let endIndex = lines.length - 1;
|
|
132
|
+
for (let i = topIndex + 1; i < lines.length; i += 1) {
|
|
133
|
+
if (/^[A-Za-z0-9_.-]+\s*:/.test(lines[i])) {
|
|
134
|
+
endIndex = i;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
37
138
|
|
|
38
|
-
|
|
39
|
-
|
|
139
|
+
const connectionPattern = new RegExp(`^ ${connectionName}:\\s*$`);
|
|
140
|
+
if (lines.slice(topIndex + 1, endIndex).some((line) => connectionPattern.test(line))) {
|
|
141
|
+
return content;
|
|
142
|
+
}
|
|
40
143
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
144
|
+
lines.splice(endIndex, 0, ...connectionBlock.trimEnd().split('\n'));
|
|
145
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
146
|
+
};
|
|
44
147
|
|
|
45
|
-
|
|
46
|
-
const
|
|
148
|
+
const ensureCrudConfig = async (projectDir, data) => {
|
|
149
|
+
const topKey = data.db === 'mysql' ? 'Mysql' : 'mongo';
|
|
150
|
+
const templateName = data.db === 'mysql'
|
|
151
|
+
? 'crud.mysql.config.yaml.ejs'
|
|
152
|
+
: 'crud.mongo.config.yaml.ejs';
|
|
153
|
+
const connectionBlock = await renderTemplateContent(templateName, data);
|
|
154
|
+
const configPaths = [
|
|
155
|
+
'_bin/local.yaml',
|
|
156
|
+
'_bin/dev.yaml',
|
|
157
|
+
'_bin/prod.yaml',
|
|
158
|
+
'test/_bin/local.yaml',
|
|
159
|
+
];
|
|
47
160
|
|
|
48
|
-
|
|
161
|
+
for (const relativePath of configPaths) {
|
|
162
|
+
const configPath = path.join(projectDir, relativePath);
|
|
163
|
+
if (!await fs.pathExists(configPath)) {
|
|
164
|
+
console.log(chalk.yellow(`Could not find ${relativePath}, skipping database configuration`));
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
49
167
|
|
|
50
|
-
|
|
51
|
-
const
|
|
168
|
+
const original = await fs.readFile(configPath, 'utf8');
|
|
169
|
+
const updated = insertYamlConnection(original, topKey, data.dbName, connectionBlock);
|
|
170
|
+
if (updated !== original) {
|
|
171
|
+
await fs.writeFile(configPath, updated);
|
|
172
|
+
console.log(chalk.green(`Successfully updated ${chalk.bold(relativePath)} database configuration`));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
52
176
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
177
|
+
const updateDomainInit = async (domainDir, projectName, moduleName) => {
|
|
178
|
+
const initFilePath = path.join(domainDir, 'init.go');
|
|
179
|
+
if (!await fs.pathExists(initFilePath)) {
|
|
180
|
+
console.log(chalk.yellow(`Could not find ${chalk.bold('init.go')} file, skipping import statement addition`));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let initFileContent = await fs.readFile(initFilePath, 'utf-8');
|
|
185
|
+
const importStatement = `import _ "${projectName}/domain/${moduleName}"`;
|
|
186
|
+
|
|
187
|
+
if (initFileContent.includes(importStatement)) {
|
|
188
|
+
console.log(chalk.yellow('The corresponding import statement already exists in init.go, no need to add it again'));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const packageMatch = initFileContent.match(/^package\s+\w+\s*$/m);
|
|
193
|
+
if (!packageMatch) {
|
|
194
|
+
console.log(chalk.yellow('package declaration not found, skipping import statement addition'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const insertPosition = packageMatch.index + packageMatch[0].length;
|
|
199
|
+
const rest = initFileContent.slice(insertPosition).trimStart();
|
|
200
|
+
initFileContent =
|
|
201
|
+
`${initFileContent.slice(0, insertPosition).trimEnd()}\n\n` +
|
|
202
|
+
`${importStatement}\n` +
|
|
203
|
+
(rest ? `\n${rest}` : '');
|
|
204
|
+
|
|
205
|
+
await fs.writeFile(initFilePath, initFileContent);
|
|
206
|
+
console.log(chalk.green(`Successfully updated ${chalk.bold('init.go')} file, added import statement`));
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const createSimpleModule = async (moduleDir, data) => {
|
|
210
|
+
const { moduleName } = data;
|
|
211
|
+
|
|
212
|
+
await renderTemplate('model.go.ejs', path.join(moduleDir, 'model', `${moduleName}.go`), data);
|
|
213
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('model.go')} file`));
|
|
214
|
+
|
|
215
|
+
await renderTemplate('dto.go.ejs', path.join(moduleDir, 'dto.go'), data);
|
|
216
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('dto.go')} file`));
|
|
217
|
+
|
|
218
|
+
await renderTemplate('service.go.ejs', path.join(moduleDir, 'service.go'), data);
|
|
219
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('service.go')} file`));
|
|
220
|
+
|
|
221
|
+
await renderTemplate('controller.go.ejs', path.join(moduleDir, 'controller.go'), data);
|
|
222
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('controller.go')} file`));
|
|
223
|
+
|
|
224
|
+
await renderTemplate('router.go.ejs', path.join(moduleDir, 'router.go'), data);
|
|
225
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('router.go')} file`));
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const createCrudModule = async (moduleDir, projectDir, data, options) => {
|
|
229
|
+
const { moduleName } = data;
|
|
230
|
+
const crudData = {
|
|
231
|
+
...data,
|
|
232
|
+
...options,
|
|
233
|
+
dbTitle: options.db === 'mysql' ? 'MySQL' : 'MongoDB',
|
|
234
|
+
dbEnvName: options.dbName.replace(/[^A-Za-z0-9]/g, '_').toUpperCase(),
|
|
235
|
+
dbSchema: path.basename(projectDir).replace(/[^a-z0-9]/gi, '_').toLowerCase(),
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
await ensureCrudConfig(projectDir, crudData);
|
|
239
|
+
|
|
240
|
+
await renderTemplate('crud.model.go.ejs', path.join(moduleDir, 'model', `${moduleName}.go`), crudData);
|
|
241
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('model.go')} file`));
|
|
242
|
+
|
|
243
|
+
await renderTemplate('crud.dto.go.ejs', path.join(moduleDir, 'dto.go'), crudData);
|
|
244
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('dto.go')} file`));
|
|
245
|
+
|
|
246
|
+
await renderTemplate('crud.service.go.ejs', path.join(moduleDir, 'service.go'), crudData);
|
|
247
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('service.go')} file`));
|
|
248
|
+
|
|
249
|
+
await renderTemplate('crud.module.README.md.ejs', path.join(moduleDir, 'README.md'), crudData);
|
|
250
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('README.md')} file`));
|
|
251
|
+
|
|
252
|
+
await renderTemplate('crud.test.go.ejs', path.join(projectDir, 'test', `${moduleName}_test.go`), crudData);
|
|
253
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('test file')} file`));
|
|
254
|
+
|
|
255
|
+
const integrationInitPath = path.join(projectDir, 'test', `init_${options.db}_integration_test.go`);
|
|
256
|
+
if (!await fs.pathExists(integrationInitPath)) {
|
|
257
|
+
await renderTemplate('crud.integration.init_test.go.ejs', integrationInitPath, crudData);
|
|
258
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('database integration init file')} file`));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
await renderTemplate(
|
|
262
|
+
'crud.integration_test.go.ejs',
|
|
263
|
+
path.join(projectDir, 'test', `${moduleName}_integration_test.go`),
|
|
264
|
+
crudData,
|
|
265
|
+
);
|
|
266
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('database integration test file')} file`));
|
|
267
|
+
|
|
268
|
+
if (options.http) {
|
|
269
|
+
await renderTemplate('crud.controller.go.ejs', path.join(moduleDir, 'controller.go'), crudData);
|
|
114
270
|
console.log(chalk.green(`Successfully created ${chalk.bold('controller.go')} file`));
|
|
115
271
|
|
|
116
|
-
|
|
117
|
-
const routerGoFilePath = path.join(apiDir, `router.go`);
|
|
118
|
-
const routerGoTemplatePath = path.join(__dirname, '../templates/router.go.ejs');
|
|
119
|
-
const routerGoContent = await ejs.renderFile(routerGoTemplatePath, { moduleName, ModuleName, projectName });
|
|
120
|
-
await fs.writeFile(routerGoFilePath, routerGoContent);
|
|
272
|
+
await renderTemplate('crud.router.go.ejs', path.join(moduleDir, 'router.go'), crudData);
|
|
121
273
|
console.log(chalk.green(`Successfully created ${chalk.bold('router.go')} file`));
|
|
122
274
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} else {
|
|
148
|
-
console.log(chalk.yellow(`The corresponding import statement already exists in init.go, no need to add it again`));
|
|
149
|
-
}
|
|
275
|
+
await renderTemplate('crud.doc.md.ejs', path.join(projectDir, 'doc', `${moduleName}.md`), crudData);
|
|
276
|
+
console.log(chalk.green(`Successfully created ${chalk.bold('doc file')} file`));
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Create module main function
|
|
281
|
+
const createModule = async (args) => {
|
|
282
|
+
try {
|
|
283
|
+
const options = parseCreateArgs(args);
|
|
284
|
+
const { moduleName, ModuleName } = options;
|
|
285
|
+
const currentDir = process.cwd();
|
|
286
|
+
const domainDir = path.join(currentDir, 'domain');
|
|
287
|
+
const moduleDir = path.join(domainDir, moduleName);
|
|
288
|
+
|
|
289
|
+
console.log(chalk.blue(`\nStarting to create module: ${chalk.bold(moduleName)}`));
|
|
290
|
+
|
|
291
|
+
const projectName = await getGoModModuleName();
|
|
292
|
+
const data = { moduleName, ModuleName, projectName };
|
|
293
|
+
|
|
294
|
+
await fs.ensureDir(domainDir);
|
|
295
|
+
await fs.ensureDir(path.join(moduleDir, 'model'));
|
|
296
|
+
|
|
297
|
+
if (options.crud) {
|
|
298
|
+
await createCrudModule(moduleDir, currentDir, data, options);
|
|
150
299
|
} else {
|
|
151
|
-
|
|
300
|
+
await createSimpleModule(moduleDir, data);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!options.crud || options.http) {
|
|
304
|
+
await updateDomainInit(domainDir, projectName, moduleName);
|
|
152
305
|
}
|
|
153
306
|
|
|
154
|
-
|
|
307
|
+
const profile = options.crud ? `persistent CRUD (${options.db})` : 'basic';
|
|
308
|
+
console.log(chalk.blue(`\nModule ${chalk.bold(moduleName)} has been successfully created in ${chalk.bold(`domain/${moduleName}`)} directory [${profile}]`));
|
|
155
309
|
} catch (error) {
|
|
156
310
|
console.error(chalk.red('Error creating module:'), chalk.redBright(error.message));
|
|
311
|
+
process.exitCode = 1;
|
|
157
312
|
}
|
|
158
313
|
};
|
|
159
314
|
|
package/commands/doc.js
CHANGED
|
@@ -422,16 +422,27 @@ const generateOpenAPIDocs = async (moduleName = null) => {
|
|
|
422
422
|
|
|
423
423
|
for (const module of modulesToProcess) {
|
|
424
424
|
const modulePath = path.join(domainDir, module);
|
|
425
|
-
const
|
|
426
|
-
const
|
|
425
|
+
const flatRouterFilePath = path.join(modulePath, 'router.go');
|
|
426
|
+
const flatControllerFilePath = path.join(modulePath, 'controller.go');
|
|
427
|
+
const legacyRouterFilePath = path.join(modulePath, 'api/router.go');
|
|
428
|
+
const legacyControllerFilePath = path.join(modulePath, 'api/controller.go');
|
|
429
|
+
const routerFilePath = await fs.pathExists(flatRouterFilePath) ? flatRouterFilePath : legacyRouterFilePath;
|
|
430
|
+
const controllerFilePath = await fs.pathExists(flatControllerFilePath) ? flatControllerFilePath : legacyControllerFilePath;
|
|
427
431
|
const modelFilePath = path.join(modulePath, 'model', `${module}.go`);
|
|
432
|
+
const dtoFilePath = path.join(modulePath, 'dto.go');
|
|
428
433
|
const reqFilePath = path.join(modulePath, 'api', 'req', 'req.go');
|
|
429
434
|
|
|
430
435
|
// 检查文件是否存在
|
|
431
|
-
if (!(await fs.pathExists(routerFilePath)) || !(await fs.pathExists(controllerFilePath)) || !(await fs.pathExists(modelFilePath))
|
|
436
|
+
if (!(await fs.pathExists(routerFilePath)) || !(await fs.pathExists(controllerFilePath)) || !(await fs.pathExists(modelFilePath))) {
|
|
432
437
|
console.warn(chalk.yellow(`Module "${module}" is missing required files, skipping...`));
|
|
433
438
|
continue;
|
|
434
439
|
}
|
|
440
|
+
const schemaFilePaths = [modelFilePath];
|
|
441
|
+
if (await fs.pathExists(dtoFilePath)) {
|
|
442
|
+
schemaFilePaths.push(dtoFilePath);
|
|
443
|
+
} else if (await fs.pathExists(reqFilePath)) {
|
|
444
|
+
schemaFilePaths.push(reqFilePath);
|
|
445
|
+
}
|
|
435
446
|
|
|
436
447
|
// 扫描 router.go 获取路由信息
|
|
437
448
|
const routes = await scanRouterFile(routerFilePath);
|
|
@@ -439,13 +450,15 @@ const generateOpenAPIDocs = async (moduleName = null) => {
|
|
|
439
450
|
|
|
440
451
|
// 扫描 controller.go 获取方法参数
|
|
441
452
|
const controllerContent = await fs.readFile(controllerFilePath, 'utf-8');
|
|
442
|
-
const
|
|
453
|
+
const reqDir = await fs.pathExists(reqFilePath) ? path.dirname(reqFilePath) : modulePath;
|
|
454
|
+
const controllerParams = await extractParamsFromController(controllerContent, reqDir, path.dirname(modelFilePath));
|
|
443
455
|
// console.log(`Extracted controller parameters for module "${module}":`, controllerParams);
|
|
444
456
|
|
|
445
|
-
// 扫描 model.go 和 req.go 获取字段
|
|
446
|
-
const
|
|
447
|
-
const
|
|
448
|
-
|
|
457
|
+
// 扫描 model.go 和 dto.go/req.go 获取字段
|
|
458
|
+
const allFields = [];
|
|
459
|
+
for (const schemaFilePath of schemaFilePaths) {
|
|
460
|
+
allFields.push(...await extractModelFields(schemaFilePath));
|
|
461
|
+
}
|
|
449
462
|
|
|
450
463
|
// 生成 OpenAPI 格式文档
|
|
451
464
|
const openAPIDoc = {
|