worsoft-frontend-codegen-local-mcp 0.1.78 → 0.1.80

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.78';
8
+ const SERVER_VERSION = '0.1.80';
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(
@@ -2509,14 +2527,15 @@ function renderMultiLevelOptionsTs(model, dictRegistryRefs) {
2509
2527
  ].join('\n');
2510
2528
  }
2511
2529
 
2512
- function renderMultiLevelApiFunctions(moduleModel) {
2513
- const pkAttr = moduleModel.pk.attrName;
2514
- const basePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.apiPath);
2515
- const enablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.enableApi);
2516
- const disablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.disableApi);
2517
- return [
2518
- `// 查询${moduleModel.title}分页列表`,
2519
- `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) {`,
2520
2539
  ' return request({',
2521
2540
  ` url: '${basePath}/page',`,
2522
2541
  " method: 'get',",
@@ -2524,7 +2543,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2524
2543
  ' });',
2525
2544
  '}',
2526
2545
  '',
2527
- `// 查询${moduleModel.title}详情`,
2546
+ `// 查询${title}详情`,
2528
2547
  `export function get${moduleModel.className}Obj(id: string | number) {`,
2529
2548
  ' return request({',
2530
2549
  ` url: '${basePath}/getById',`,
@@ -2533,7 +2552,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2533
2552
  ' });',
2534
2553
  '}',
2535
2554
  '',
2536
- `// 新增${moduleModel.title}`,
2555
+ `// 新增${title}`,
2537
2556
  `export function add${moduleModel.className}Obj(data: any) {`,
2538
2557
  ' return request({',
2539
2558
  ` url: '${basePath}/save',`,
@@ -2542,7 +2561,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2542
2561
  ' });',
2543
2562
  '}',
2544
2563
  '',
2545
- `// 更新${moduleModel.title}`,
2564
+ `// 更新${title}`,
2546
2565
  `export function put${moduleModel.className}Obj(data: any) {`,
2547
2566
  ' return request({',
2548
2567
  ` url: '${basePath}/updateById',`,
@@ -2551,17 +2570,27 @@ function renderMultiLevelApiFunctions(moduleModel) {
2551
2570
  ' });',
2552
2571
  '}',
2553
2572
  '',
2554
- `// 删除${moduleModel.title}`,
2555
- `export function del${moduleModel.className}Objs(data: Array<string | number>) {`,
2556
- ' return request({',
2557
- ` url: '${basePath}/removeByIds',`,
2558
- " method: 'post',",
2559
- ' data,',
2560
- ' });',
2561
- '}',
2562
- '',
2563
- `// 启用${moduleModel.title}`,
2564
- `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) {`,
2565
2594
  ' return request({',
2566
2595
  ` url: '${enablePath}',`,
2567
2596
  " method: 'post',",
@@ -2569,7 +2598,7 @@ function renderMultiLevelApiFunctions(moduleModel) {
2569
2598
  ' });',
2570
2599
  '}',
2571
2600
  '',
2572
- `// 禁用${moduleModel.title}`,
2601
+ `// 禁用${title}`,
2573
2602
  `export function disable${moduleModel.className}(id: string | number) {`,
2574
2603
  ' return request({',
2575
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.78",
3
+ "version": "0.1.80",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",