worsoft-frontend-codegen-local-mcp 0.1.39 → 0.1.40

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 (2) hide show
  1. package/mcp_server.js +90 -61
  2. package/package.json +1 -1
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.39';
8
+ const SERVER_VERSION = '0.1.40';
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');
@@ -993,12 +993,34 @@ function normalizeStructuredSourceKind(value) {
993
993
  return 'entity';
994
994
  }
995
995
 
996
- function normalizeApiPath(value) {
997
- return String(value || '')
998
- .trim()
999
- .replace(/^\/+/, '')
1000
- .replace(/\/+$/, '');
1001
- }
996
+ function normalizeApiPath(value) {
997
+ return String(value || '')
998
+ .trim()
999
+ .replace(/^\/+/, '')
1000
+ .replace(/\/+$/, '');
1001
+ }
1002
+
1003
+ function buildApiRoutePath(moduleName, apiPath) {
1004
+ const normalizedApiPath = normalizeApiPath(apiPath);
1005
+ if (!normalizedApiPath) return '';
1006
+
1007
+ const normalizedModuleName = normalizeModuleName(moduleName || '')
1008
+ .split('/')
1009
+ .filter(Boolean);
1010
+ const apiSegments = normalizedApiPath.split('/').filter(Boolean);
1011
+
1012
+ if (!normalizedModuleName.length) {
1013
+ return '/' + apiSegments.join('/');
1014
+ }
1015
+
1016
+ const modulePrefix = normalizedModuleName.join('/');
1017
+ const currentApiPath = apiSegments.join('/');
1018
+ if (currentApiPath === modulePrefix || currentApiPath.startsWith(modulePrefix + '/')) {
1019
+ return '/' + currentApiPath;
1020
+ }
1021
+
1022
+ return '/' + [...normalizedModuleName, ...apiSegments].join('/');
1023
+ }
1002
1024
 
1003
1025
  function normalizeStructuredSqlType(value) {
1004
1026
  const normalized = String(value || '').trim();
@@ -1358,7 +1380,7 @@ function normalizeLevelPosition(levels, levelIndex, explicitPosition) {
1358
1380
  return 'right';
1359
1381
  }
1360
1382
 
1361
- function buildMultiLevelDictModel(safeArgs) {
1383
+ function buildMultiLevelDictModel(safeArgs) {
1362
1384
  if (!safeArgs.levels.length) {
1363
1385
  throw new Error('multi_level_dict requires levels[] with explicit hierarchy metadata');
1364
1386
  }
@@ -1390,6 +1412,9 @@ function buildMultiLevelDictModel(safeArgs) {
1390
1412
  });
1391
1413
  const allModules = builtLevels.flatMap((level) => level.modules);
1392
1414
  const dictTypes = [...new Set(allModules.flatMap((module) => module.optionFields.map((field) => field.dictType).filter(Boolean)))];
1415
+ allModules.forEach((moduleModel) => {
1416
+ moduleModel.moduleName = resolvedTargets.moduleName;
1417
+ });
1393
1418
 
1394
1419
  return {
1395
1420
  featureTitle: safeArgs.featureTitle || safeArgs.tableComment || parentModule.tableComment,
@@ -1913,19 +1938,22 @@ function renderMultiLevelOptionField(field, model, moduleModel, dictRegistryRefs
1913
1938
  return `${indent}{ ${parts.join(', ')} },`;
1914
1939
  }
1915
1940
 
1916
- function renderMultiLevelModuleDefinition(model, moduleModel, dictRegistryRefs) {
1917
- const lines = [
1918
- ` ${moduleModel.key}: {`,
1919
- ` key: '${moduleModel.key}',`,
1920
- ` titleKey: '${buildMultiLevelModuleTitleKey(model, moduleModel)}',`,
1921
- ` apiPath: '${moduleModel.apiPath}',`,
1922
- ` primaryKey: '${moduleModel.pk.attrName}',`,
1923
- ];
1941
+ function renderMultiLevelModuleDefinition(model, moduleModel, dictRegistryRefs) {
1942
+ const moduleApiPath = buildApiRoutePath(model.moduleName, moduleModel.apiPath);
1943
+ const moduleEnableApi = buildApiRoutePath(model.moduleName, moduleModel.enableApi);
1944
+ const moduleDisableApi = buildApiRoutePath(model.moduleName, moduleModel.disableApi);
1945
+ const lines = [
1946
+ ` ${moduleModel.key}: {`,
1947
+ ` key: '${moduleModel.key}',`,
1948
+ ` titleKey: '${buildMultiLevelModuleTitleKey(model, moduleModel)}',`,
1949
+ ` apiPath: '${moduleApiPath}',`,
1950
+ ` primaryKey: '${moduleModel.pk.attrName}',`,
1951
+ ];
1924
1952
  if (moduleModel.queryParentField) lines.push(` queryParentField: '${moduleModel.queryParentField}',`);
1925
1953
  if (moduleModel.statusField) lines.push(` statusField: '${moduleModel.statusField}',`);
1926
1954
  if (moduleModel.statusDictType) lines.push(` statusDictType: ${getDictRegistryReference(moduleModel.statusDictType, dictRegistryRefs)},`);
1927
- lines.push(` enableApi: '${moduleModel.enableApi.startsWith('/') ? moduleModel.enableApi : '/' + moduleModel.enableApi}',`);
1928
- lines.push(` disableApi: '${moduleModel.disableApi.startsWith('/') ? moduleModel.disableApi : '/' + moduleModel.disableApi}',`);
1955
+ lines.push(` enableApi: '${moduleEnableApi}',`);
1956
+ lines.push(` disableApi: '${moduleDisableApi}',`);
1929
1957
  lines.push(' fields: [');
1930
1958
  lines.push(moduleModel.optionFields.map((field) => renderMultiLevelOptionField(field, model, moduleModel, dictRegistryRefs)).join('\n'));
1931
1959
  lines.push(' ],');
@@ -1987,12 +2015,12 @@ function renderMultiLevelOptionsTs(model, dictRegistryRefs) {
1987
2015
  ].join('\n');
1988
2016
  }
1989
2017
 
1990
- function renderMultiLevelApiFunctions(moduleModel) {
1991
- const pkAttr = moduleModel.pk.attrName;
1992
- const basePath = moduleModel.apiPath.startsWith('/') ? moduleModel.apiPath : '/' + moduleModel.apiPath;
1993
- const enablePath = moduleModel.enableApi.startsWith('/') ? moduleModel.enableApi : '/' + moduleModel.enableApi;
1994
- const disablePath = moduleModel.disableApi.startsWith('/') ? moduleModel.disableApi : '/' + moduleModel.disableApi;
1995
- return [
2018
+ function renderMultiLevelApiFunctions(moduleModel) {
2019
+ const pkAttr = moduleModel.pk.attrName;
2020
+ const basePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.apiPath);
2021
+ const enablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.enableApi);
2022
+ const disablePath = buildApiRoutePath(moduleModel.moduleName, moduleModel.disableApi);
2023
+ return [
1996
2024
  `export function fetch${moduleModel.className}List(query?: any) {`,
1997
2025
  ' return request({',
1998
2026
  ` url: '${basePath}/page',`,
@@ -2051,14 +2079,14 @@ function renderMultiLevelApiFunctions(moduleModel) {
2051
2079
  ].join('\n');
2052
2080
  }
2053
2081
 
2054
- function renderMultiLevelApiTs(model) {
2055
- return [
2056
- "import request from '/@/utils/request';",
2057
- '',
2058
- model.modules.map(renderMultiLevelApiFunctions).join('\n\n'),
2059
- '',
2060
- ].join('\n');
2061
- }
2082
+ function renderMultiLevelApiTs(model) {
2083
+ return [
2084
+ "import request from '/@/utils/request';",
2085
+ '',
2086
+ model.modules.map(renderMultiLevelApiFunctions).join('\n\n'),
2087
+ '',
2088
+ ].join('\n');
2089
+ }
2062
2090
 
2063
2091
  function renderMultiLevelFormField(field) {
2064
2092
  const labelExpr = `getFieldLabel('${field.attrName}')`;
@@ -2581,13 +2609,14 @@ function renderMultiLevelFiles(model, sharedSupport, localeZhSupport) {
2581
2609
  return files;
2582
2610
  }
2583
2611
 
2584
- function buildReplacements(model, sharedSupport) {
2585
- const menuBaseId = Date.now();
2586
- const apiModulePath = model.apiPath || `${model.moduleName}/${model.functionName}`;
2587
- const routePath = `${model.moduleName}/${model.functionName}`;
2588
- const permissionPrefix = `${model.moduleName}/${model.functionName}`.replace(/\//g, '_');
2589
- const dictRegistryRefs = sharedSupport.dictRegistry.keyByValue;
2590
- const i18nNamespace = buildI18nNamespace(model);
2612
+ function buildReplacements(model, sharedSupport) {
2613
+ const menuBaseId = Date.now();
2614
+ const apiModulePath = model.targetApiModule || `${model.moduleName}/${model.functionName}`;
2615
+ const apiRoutePath = buildApiRoutePath(model.moduleName, model.apiPath || model.functionName).replace(/^\/+/, '');
2616
+ const routePath = `${model.moduleName}/${model.functionName}`;
2617
+ const permissionPrefix = `${model.moduleName}/${model.functionName}`.replace(/\//g, '_');
2618
+ const dictRegistryRefs = sharedSupport.dictRegistry.keyByValue;
2619
+ const i18nNamespace = buildI18nNamespace(model);
2591
2620
 
2592
2621
  return {
2593
2622
  TABLE_NAME: model.tableName,
@@ -2596,8 +2625,8 @@ function buildReplacements(model, sharedSupport) {
2596
2625
  CLASS_NAME: model.className,
2597
2626
  FUNCTION_NAME: model.functionName,
2598
2627
  PK_ATTR: model.pk.attrName,
2599
- API_MODULE_PATH: apiModulePath,
2600
- API_PATH: apiModulePath,
2628
+ API_MODULE_PATH: apiModulePath,
2629
+ API_PATH: apiRoutePath,
2601
2630
  VIEW_MODULE_PATH: routePath,
2602
2631
  MENU_ROUTE_PATH: routePath,
2603
2632
  I18N_NAMESPACE: i18nNamespace,
@@ -2735,10 +2764,10 @@ function buildManifest(model, safeArgs, stylePreset, files, note) {
2735
2764
  style: safeArgs.style,
2736
2765
  pageType: model.pageType || '',
2737
2766
  styleLabel: stylePreset.label,
2738
- runtimeSupported: hasRuntimeSupport(stylePreset),
2767
+ runtimeSupported: hasRuntimeSupport(stylePreset),
2739
2768
  tableName: model.tableName,
2740
2769
  tableComment: model.tableComment,
2741
- apiPath: model.apiPath,
2770
+ apiPath: buildApiRoutePath(model.moduleName, model.apiPath).replace(/^\/+/, ''),
2742
2771
  moduleName: model.moduleName,
2743
2772
  targetViewDir: model.targetViewDir,
2744
2773
  targetApiModule: model.targetApiModule,
@@ -2749,22 +2778,22 @@ function buildManifest(model, safeArgs, stylePreset, files, note) {
2749
2778
  mergeI18nZh: safeArgs.mergeI18nZh,
2750
2779
  },
2751
2780
  files: files.map((file) => ({ type: file.type, path: file.path, bytes: Buffer.byteLength(file.content, 'utf8'), status: file.status || (safeArgs.writeToDisk ? 'success' : 'rendered') })),
2752
- levels: model.levels.map((level) => ({
2753
- levelIndex: level.levelIndex,
2754
- position: level.position,
2755
- modules: level.modules.map((moduleModel) => ({
2756
- key: moduleModel.key,
2757
- tableName: moduleModel.tableName,
2758
- tableComment: moduleModel.tableComment,
2759
- apiPath: moduleModel.apiPath,
2760
- primaryKey: moduleModel.pk.fieldName,
2761
- queryParentField: moduleModel.queryParentField,
2762
- statusField: moduleModel.statusField,
2763
- statusDictType: moduleModel.statusDictType,
2764
- enableApi: moduleModel.enableApi,
2765
- disableApi: moduleModel.disableApi,
2766
- })),
2767
- })),
2781
+ levels: model.levels.map((level) => ({
2782
+ levelIndex: level.levelIndex,
2783
+ position: level.position,
2784
+ modules: level.modules.map((moduleModel) => ({
2785
+ key: moduleModel.key,
2786
+ tableName: moduleModel.tableName,
2787
+ tableComment: moduleModel.tableComment,
2788
+ apiPath: buildApiRoutePath(model.moduleName, moduleModel.apiPath).replace(/^\/+/, ''),
2789
+ primaryKey: moduleModel.pk.fieldName,
2790
+ queryParentField: moduleModel.queryParentField,
2791
+ statusField: moduleModel.statusField,
2792
+ statusDictType: moduleModel.statusDictType,
2793
+ enableApi: buildApiRoutePath(model.moduleName, moduleModel.enableApi).replace(/^\/+/, ''),
2794
+ disableApi: buildApiRoutePath(model.moduleName, moduleModel.disableApi).replace(/^\/+/, ''),
2795
+ })),
2796
+ })),
2768
2797
  summary: {
2769
2798
  totalLevels: model.levels.length,
2770
2799
  totalModules: model.modules.length,
@@ -2791,10 +2820,10 @@ function buildManifest(model, safeArgs, stylePreset, files, note) {
2791
2820
  style: safeArgs.style,
2792
2821
  pageType: model.pageType || '',
2793
2822
  styleLabel: stylePreset.label,
2794
- runtimeSupported: hasRuntimeSupport(stylePreset),
2823
+ runtimeSupported: hasRuntimeSupport(stylePreset),
2795
2824
  tableName: model.tableName,
2796
2825
  tableComment: model.tableComment,
2797
- apiPath: model.apiPath,
2826
+ apiPath: buildApiRoutePath(model.moduleName, model.apiPath).replace(/^\/+/, ''),
2798
2827
  moduleName: model.moduleName,
2799
2828
  targetViewDir: model.targetViewDir,
2800
2829
  targetApiModule: model.targetApiModule,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worsoft-frontend-codegen-local-mcp",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "Worsoft frontend local-template code generation MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "worsoft <sw@worsoft.vip>",