worsoft-frontend-codegen-local-mcp 0.1.77 → 0.1.79

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.
@@ -2,6 +2,6 @@
2
2
  import { createCrudApi } from '/@/api/common/crudFactory';
3
3
  {{API_REQUEST_IMPORT}}
4
4
 
5
- // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
6
- export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
5
+ // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新、导出接口
6
+ export const { fetchList, addObj, getObj, delObjs, putObj, exportObj } = createCrudApi('/{{API_PATH}}');
7
7
  {{EXTRA_API_FUNCTIONS}}
@@ -2,8 +2,8 @@
2
2
  import { createCrudApi } from '/@/api/common/crudFactory';
3
3
  {{API_REQUEST_IMPORT}}
4
4
 
5
- // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
6
- export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
5
+ // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新、导出接口
6
+ export const { fetchList, addObj, getObj, delObjs, putObj, exportObj } = createCrudApi('/{{API_PATH}}');
7
7
 
8
8
  {{DICT_API_FUNCTIONS}}
9
9
  {{EXTRA_API_FUNCTIONS}}
@@ -2,6 +2,6 @@
2
2
  import { createCrudApi } from '/@/api/common/crudFactory';
3
3
  {{API_REQUEST_IMPORT}}
4
4
 
5
- // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新接口
6
- export const { fetchList, addObj, getObj, delObjs, putObj } = createCrudApi('/{{API_PATH}}');
5
+ // {{FEATURE_TITLE}} 通用列表、新增、详情、删除、更新、导出接口
6
+ export const { fetchList, addObj, getObj, delObjs, putObj, exportObj } = createCrudApi('/{{API_PATH}}');
7
7
  {{EXTRA_API_FUNCTIONS}}
package/mcp_server.js CHANGED
@@ -5,7 +5,7 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
 
7
7
  const SERVER_NAME = 'worsoft-codegen-local';
8
- const SERVER_VERSION = '0.1.77';
8
+ const SERVER_VERSION = '0.1.79';
9
9
  const PROTOCOL_VERSION = '2024-11-05';
10
10
  const TOOL_NAME = 'worsoft_codegen_local_generate_frontend';
11
11
  const STYLE_CATALOG_PATH = path.join(__dirname, 'assets', 'style-catalog.json');
@@ -151,13 +151,14 @@ export function createCrudSchema(
151
151
 
152
152
  const DEFAULT_CRUD_FACTORY_TEMPLATE = `import request from '/@/utils/request';
153
153
 
154
- export interface CrudApiPathOverrides {
155
- page?: string;
156
- save?: string;
157
- detail?: string;
158
- remove?: string;
159
- update?: string;
160
- }
154
+ export interface CrudApiPathOverrides {
155
+ page?: string;
156
+ save?: string;
157
+ detail?: string;
158
+ remove?: string;
159
+ update?: string;
160
+ export?: string;
161
+ }
161
162
 
162
163
  const joinApiPath = (baseUrl: string, suffix: string) => {
163
164
  const normalizedBase = String(baseUrl || '').replace(/\\/+$/, '');
@@ -165,8 +166,8 @@ const joinApiPath = (baseUrl: string, suffix: string) => {
165
166
  return normalizedSuffix ? \`\${normalizedBase}/\${normalizedSuffix}\` : normalizedBase;
166
167
  };
167
168
 
168
- // 生成标准业务功能 CRUD 接口:分页、新增、详情、删除、更新。
169
- export const createCrudApi = (baseUrl: string, overrides: CrudApiPathOverrides = {}) => ({
169
+ // 生成标准业务功能 CRUD 接口:分页、新增、详情、删除、更新、导出。
170
+ export const createCrudApi = (baseUrl: string, overrides: CrudApiPathOverrides = {}) => ({
170
171
  fetchList: (query?: object) =>
171
172
  request({
172
173
  url: overrides.page || joinApiPath(baseUrl, 'page'),
@@ -195,14 +196,22 @@ export const createCrudApi = (baseUrl: string, overrides: CrudApiPathOverrides =
195
196
  data: ids,
196
197
  }),
197
198
 
198
- putObj: (obj?: object) =>
199
- request({
200
- url: overrides.update || joinApiPath(baseUrl, 'updateById'),
201
- method: 'post',
202
- data: obj,
203
- }),
204
- });
205
- `;
199
+ putObj: (obj?: object) =>
200
+ request({
201
+ url: overrides.update || joinApiPath(baseUrl, 'updateById'),
202
+ method: 'post',
203
+ data: obj,
204
+ }),
205
+
206
+ exportObj: (query?: object) =>
207
+ request({
208
+ url: overrides.export || joinApiPath(baseUrl, 'export'),
209
+ method: 'get',
210
+ params: query,
211
+ responseType: 'blob',
212
+ }),
213
+ });
214
+ `;
206
215
 
207
216
  const DEFAULT_CLOSE_CURRENT_PAGE_TEMPLATE = `import type { RouteLocationNormalizedLoaded } from 'vue-router';
208
217
  import { useRoute } from 'vue-router';
@@ -925,20 +934,29 @@ function ensureCrudSchemaSupportFile(frontendPath) {
925
934
  };
926
935
  }
927
936
 
928
- function ensureCrudFactorySupportFile(frontendPath) {
929
- const factoryPath = path.join(frontendPath, 'src', 'api', 'common', 'crudFactory.ts');
930
- const exists = fs.existsSync(factoryPath);
931
- const currentContent = exists ? readUtf8File(factoryPath) : '';
932
- const isCompatible = !exists || currentContent.includes('export const createCrudApi');
933
-
934
- return {
935
- path: factoryPath,
936
- content: DEFAULT_CRUD_FACTORY_TEMPLATE,
937
- exists,
938
- isCompatible,
939
- needsWrite: !exists,
940
- };
941
- }
937
+ function ensureCrudFactorySupportFile(frontendPath) {
938
+ const factoryPath = path.join(frontendPath, 'src', 'api', 'common', 'crudFactory.ts');
939
+ const exists = fs.existsSync(factoryPath);
940
+ const currentContent = exists ? readUtf8File(factoryPath) : '';
941
+ const hasCoreShape =
942
+ currentContent.includes('export const createCrudApi') &&
943
+ currentContent.includes('fetchList') &&
944
+ currentContent.includes('addObj') &&
945
+ currentContent.includes('getObj') &&
946
+ currentContent.includes('delObjs') &&
947
+ currentContent.includes('putObj');
948
+ const supportsExportObj = currentContent.includes('exportObj');
949
+ const shouldUpgradeLegacy = exists && hasCoreShape && !supportsExportObj;
950
+ const isCompatible = !exists || (hasCoreShape && supportsExportObj) || shouldUpgradeLegacy;
951
+
952
+ return {
953
+ path: factoryPath,
954
+ content: DEFAULT_CRUD_FACTORY_TEMPLATE,
955
+ exists,
956
+ isCompatible,
957
+ needsWrite: !exists || shouldUpgradeLegacy,
958
+ };
959
+ }
942
960
 
943
961
  function ensureCloseCurrentPageSupportFile(frontendPath) {
944
962
  const hookPath = path.join(frontendPath, 'src', 'hooks', 'useCloseCurrentPage.ts');
@@ -1057,11 +1075,11 @@ function maybeWriteSharedSupport(sharedSupport, writeToDisk) {
1057
1075
 
1058
1076
  if (sharedSupport.crudFactory.needsWrite) {
1059
1077
  if (!sharedSupport.crudFactory.isCompatible) {
1060
- throw new Error(
1061
- 'Detected an existing src/api/common/crudFactory.ts that MCP could not merge safely. ' +
1062
- 'Please align the createCrudApi export manually before enabling writeSupportFiles.'
1063
- );
1064
- }
1078
+ throw new Error(
1079
+ 'Detected an existing src/api/common/crudFactory.ts that MCP could not merge safely. ' +
1080
+ 'Please align the createCrudApi/exportObj helper shape manually before enabling writeSupportFiles.'
1081
+ );
1082
+ }
1065
1083
  writeSupportFile(sharedSupport.crudFactory.path, sharedSupport.crudFactory.content);
1066
1084
  }
1067
1085
 
@@ -1112,12 +1130,12 @@ function buildSupportNote(sharedSupport, localeZhSupport) {
1112
1130
  );
1113
1131
  }
1114
1132
 
1115
- if (sharedSupport.crudFactory.exists && !sharedSupport.crudFactory.isCompatible) {
1116
- notes.push(
1117
- 'Detected an existing src/api/common/crudFactory.ts that does not export createCrudApi. ' +
1118
- 'MCP preserved the existing file and did not overwrite it. Generated API modules now depend on that file being manually aligned.'
1119
- );
1120
- }
1133
+ if (sharedSupport.crudFactory.exists && !sharedSupport.crudFactory.isCompatible) {
1134
+ notes.push(
1135
+ 'Detected an existing src/api/common/crudFactory.ts that does not match the expected createCrudApi/exportObj helper shape. ' +
1136
+ 'MCP preserved the existing file and did not overwrite it. Generated API modules now depend on that file being manually aligned.'
1137
+ );
1138
+ }
1121
1139
 
1122
1140
  if (sharedSupport.dictRegistry.exists && !sharedSupport.dictRegistry.isCompatible) {
1123
1141
  notes.push(
@@ -1350,9 +1368,8 @@ function parseOptionalOrder(value, label) {
1350
1368
  if (value === undefined || value === null || value === '') return undefined;
1351
1369
  const order = Number.parseInt(String(value), 10);
1352
1370
  if (Number.isNaN(order) || order < 0) {
1353
- throw new Error(`${label} must be a positive integer when provided, or 0/empty when unspecified`);
1354
- }
1355
- if (order === 0) return undefined;
1371
+ throw new Error(`${label} must be a non-negative integer when provided, or empty when unspecified`);
1372
+ }
1356
1373
  return order;
1357
1374
  }
1358
1375
 
@@ -2510,14 +2527,15 @@ function renderMultiLevelOptionsTs(model, dictRegistryRefs) {
2510
2527
  ].join('\n');
2511
2528
  }
2512
2529
 
2513
- function renderMultiLevelApiFunctions(moduleModel) {
2514
- const pkAttr = moduleModel.pk.attrName;
2515
- const basePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.apiPath);
2516
- const enablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.enableApi);
2517
- const disablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.disableApi);
2518
- return [
2519
- `// 查询${moduleModel.title}分页列表`,
2520
- `export function fetch${moduleModel.className}List(query?: any) {`,
2530
+ function renderMultiLevelApiFunctions(moduleModel) {
2531
+ const pkAttr = moduleModel.pk.attrName;
2532
+ const basePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.apiPath);
2533
+ const enablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.enableApi);
2534
+ const disablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.disableApi);
2535
+ const title = moduleModel.tableComment || moduleModel.tableName || moduleModel.className;
2536
+ return [
2537
+ `// 查询${title}分页列表`,
2538
+ `export function fetch${moduleModel.className}List(query?: any) {`,
2521
2539
  ' return request({',
2522
2540
  ` url: '${basePath}/page',`,
2523
2541
  " method: 'get',",
@@ -2525,7 +2543,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2525
2543
  ' });',
2526
2544
  '}',
2527
2545
  '',
2528
- `// 查询${moduleModel.title}详情`,
2546
+ `// 查询${title}详情`,
2529
2547
  `export function get${moduleModel.className}Obj(id: string | number) {`,
2530
2548
  ' return request({',
2531
2549
  ` url: '${basePath}/getById',`,
@@ -2534,7 +2552,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2534
2552
  ' });',
2535
2553
  '}',
2536
2554
  '',
2537
- `// 新增${moduleModel.title}`,
2555
+ `// 新增${title}`,
2538
2556
  `export function add${moduleModel.className}Obj(data: any) {`,
2539
2557
  ' return request({',
2540
2558
  ` url: '${basePath}/save',`,
@@ -2543,7 +2561,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2543
2561
  ' });',
2544
2562
  '}',
2545
2563
  '',
2546
- `// 更新${moduleModel.title}`,
2564
+ `// 更新${title}`,
2547
2565
  `export function put${moduleModel.className}Obj(data: any) {`,
2548
2566
  ' return request({',
2549
2567
  ` url: '${basePath}/updateById',`,
@@ -2552,17 +2570,27 @@ function renderMultiLevelApiFunctions(moduleModel) {
2552
2570
  ' });',
2553
2571
  '}',
2554
2572
  '',
2555
- `// 删除${moduleModel.title}`,
2556
- `export function del${moduleModel.className}Objs(data: Array<string | number>) {`,
2557
- ' return request({',
2558
- ` url: '${basePath}/removeByIds',`,
2559
- " method: 'post',",
2560
- ' data,',
2561
- ' });',
2562
- '}',
2563
- '',
2564
- `// 启用${moduleModel.title}`,
2565
- `export function enable${moduleModel.className}(id: string | number) {`,
2573
+ `// 删除${title}`,
2574
+ `export function del${moduleModel.className}Objs(data: Array<string | number>) {`,
2575
+ ' return request({',
2576
+ ` url: '${basePath}/removeByIds',`,
2577
+ " method: 'post',",
2578
+ ' data,',
2579
+ ' });',
2580
+ '}',
2581
+ '',
2582
+ `// 导出${title}`,
2583
+ `export function export${moduleModel.className}Obj(query?: any) {`,
2584
+ ' return request({',
2585
+ ` url: '${basePath}/export',`,
2586
+ " method: 'get',",
2587
+ ' params: query,',
2588
+ " responseType: 'blob',",
2589
+ ' });',
2590
+ '}',
2591
+ '',
2592
+ `// 启用${title}`,
2593
+ `export function enable${moduleModel.className}(id: string | number) {`,
2566
2594
  ' return request({',
2567
2595
  ` url: '${enablePath}',`,
2568
2596
  " method: 'post',",
@@ -2570,7 +2598,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2570
2598
  ' });',
2571
2599
  '}',
2572
2600
  '',
2573
- `// 禁用${moduleModel.title}`,
2601
+ `// 禁用${title}`,
2574
2602
  `export function disable${moduleModel.className}(id: string | number) {`,
2575
2603
  ' return request({',
2576
2604
  ` url: '${disablePath}',`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",