@nasl/cli 0.3.3 → 0.3.5

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 (48) hide show
  1. package/README.md +24 -3
  2. package/dist/bin/nasl.mjs +192 -124
  3. package/dist/bin/nasl.mjs.map +1 -1
  4. package/dist/bin/naslc.mjs +38 -15
  5. package/dist/bin/naslc.mjs.map +1 -1
  6. package/dist/index.mjs +179 -97
  7. package/dist/index.mjs.map +1 -1
  8. package/out/apis/appApi.d.ts +17 -0
  9. package/out/apis/appApi.d.ts.map +1 -0
  10. package/out/apis/appApi.js +36 -0
  11. package/out/apis/appApi.js.map +1 -0
  12. package/out/apis/index.d.ts +1 -1
  13. package/out/apis/index.d.ts.map +1 -1
  14. package/out/apis/index.js +1 -1
  15. package/out/apis/index.js.map +1 -1
  16. package/out/bin/nasl.js +14 -61
  17. package/out/bin/nasl.js.map +1 -1
  18. package/out/commands/createAppInIde.d.ts +0 -3
  19. package/out/commands/createAppInIde.d.ts.map +1 -1
  20. package/out/commands/createAppInIde.js +26 -93
  21. package/out/commands/createAppInIde.js.map +1 -1
  22. package/out/commands/index.d.ts +1 -0
  23. package/out/commands/index.d.ts.map +1 -1
  24. package/out/commands/index.js +1 -0
  25. package/out/commands/index.js.map +1 -1
  26. package/out/commands/updateAppInIde.d.ts +3 -0
  27. package/out/commands/updateAppInIde.d.ts.map +1 -0
  28. package/out/commands/updateAppInIde.js +59 -0
  29. package/out/commands/updateAppInIde.js.map +1 -0
  30. package/out/constants/nasl-file-types.d.ts +1 -1
  31. package/out/constants/nasl-file-types.d.ts.map +1 -1
  32. package/out/constants/nasl-file-types.js +8 -1
  33. package/out/constants/nasl-file-types.js.map +1 -1
  34. package/out/services/compose.d.ts.map +1 -1
  35. package/out/services/compose.js +21 -8
  36. package/out/services/compose.js.map +1 -1
  37. package/out/services/resolve.d.ts.map +1 -1
  38. package/out/services/resolve.js +7 -5
  39. package/out/services/resolve.js.map +1 -1
  40. package/out/utils/appName.d.ts +8 -0
  41. package/out/utils/appName.d.ts.map +1 -0
  42. package/out/utils/appName.js +71 -0
  43. package/out/utils/appName.js.map +1 -0
  44. package/out/utils/prompt.d.ts +5 -0
  45. package/out/utils/prompt.d.ts.map +1 -0
  46. package/out/utils/prompt.js +54 -0
  47. package/out/utils/prompt.js.map +1 -0
  48. package/package.json +1 -1
package/README.md CHANGED
@@ -159,9 +159,13 @@ nasl transform files2json [entry] --output [outputPath]
159
159
  # 默认输出到 ./files.json
160
160
  ```
161
161
 
162
- ### 在 IDE 中直接创建应用(nasl create-app-in-ide)
162
+ ### 在 IDE 中创建 / 更新应用
163
163
 
164
- **注意**:目前该命令不支持 useOPENAPI 模式,只在测试环境使用。
164
+ **注意**:`create-app-in-ide` `update-app-in-ide` 只能在测试环境使用。
165
+
166
+ 两个命令都会先按 [入口文件说明](#入口文件说明) 解析本地 NASL(可选 `[entry]`,不传则处理整个 `src`),将源码组合为 fullNaturalTS(含依赖)后调用远程服务。均支持 `--quiet` 跳过确认、`--verbose` 输出依赖分析等详细信息。
167
+
168
+ #### 在 IDE 中创建应用(nasl create-app-in-ide)
165
169
 
166
170
  ```bash
167
171
  # 会询问确认(默认)
@@ -174,7 +178,24 @@ nasl create-app-in-ide [entry] --quiet
174
178
  nasl create-app-in-ide [entry] --verbose
175
179
  ```
176
180
 
177
- 此命令会将当前项目的 NASL 代码上传到远程服务,在 IDE 中创建新的应用。默认会询问用户确认,使用 `--quiet` 选项可以跳过确认。
181
+ 执行前会展示即将使用的**应用名称**、**包名**、IDE 版本与租户。应用名与包名由项目目录推导:若存在 `specs/` 目录,则取其中**第一个子文件夹名**作为基础名;否则使用**项目根目录名**。基础名经清洗(仅保留字母数字、去掉开头数字、最长 12 字符)后,再拼接时间后缀生成最终名称。
182
+
183
+ #### 在 IDE 中更新已有应用(nasl update-app-in-ide)
184
+
185
+ 第一个参数为远程应用的 **appId**(必填),其余与创建命令一致。
186
+
187
+ ```bash
188
+ # 会询问确认(默认)
189
+ nasl update-app-in-ide <appId> [entry]
190
+
191
+ # 跳过确认
192
+ nasl update-app-in-ide <appId> [entry] --quiet
193
+
194
+ # 显示详细信息
195
+ nasl update-app-in-ide <appId> [entry] --verbose
196
+ ```
197
+
198
+ 将当前本地 NASL 同步到指定应用,用于在 IDE 中更新已有应用而非新建。
178
199
 
179
200
  ## 环境变量配置
180
201
 
package/dist/bin/nasl.mjs CHANGED
@@ -29227,41 +29227,33 @@ async function checkApi(fullNaturalTS, options) {
29227
29227
  }
29228
29228
 
29229
29229
  /**
29230
- * 创建应用同步
29230
+ * 创建应用(POST /nasl/app/create)
29231
29231
  */
29232
- async function createAppSyncApi(fullNaturalTS, options) {
29233
- const url = new URL(options.serverBaseURL);
29234
- const origin = url.origin + '/app-ai-creator';
29235
- const axios = await createAxios({ serverBaseURL: origin, ideVersion: options.ideVersion });
29236
- try {
29237
- const res = await axios.post('/api/createAppSync', {
29238
- fullNaturalTS,
29239
- packageName: options.packageName,
29240
- appName: options.appName,
29241
- hostname: url.hostname,
29242
- enableAuthTemplate: false,
29243
- ideVersion: options.ideVersion,
29244
- fullVersion: `${options.ideVersion}.0`,
29245
- });
29246
- if (res.data.success) {
29247
- return {
29248
- success: true,
29249
- appId: res.data.data?.appId,
29250
- appURL: res.data.data?.appURL,
29251
- message: res.data.data?.message,
29252
- };
29253
- }
29254
- else {
29255
- return {
29256
- success: false,
29257
- error: res.data.message || '应用创建失败',
29258
- };
29259
- }
29260
- }
29261
- catch (error) {
29262
- console.log(error);
29263
- throw error;
29264
- }
29232
+ async function createApp(fullNaturalTS, options, appName, packageName) {
29233
+ const axiosInstance = await createAxios(options);
29234
+ const res = await axiosInstance.post('/app/create', {
29235
+ fullNaturalTS,
29236
+ packageName,
29237
+ appName,
29238
+ ideVersion: options.ideVersion,
29239
+ }, {
29240
+ headers: { ...buildNaslHeaders(options), 'Content-Type': 'application/json' },
29241
+ });
29242
+ return res.data.result;
29243
+ }
29244
+ /**
29245
+ * 更新应用(POST /nasl/app/update)
29246
+ */
29247
+ async function updateApp(fullNaturalTS, options, appId) {
29248
+ const axiosInstance = await createAxios(options);
29249
+ const res = await axiosInstance.post('/app/update', {
29250
+ fullNaturalTS,
29251
+ appId,
29252
+ ideVersion: options.ideVersion,
29253
+ }, {
29254
+ headers: { ...buildNaslHeaders(options), 'Content-Type': 'application/json' },
29255
+ });
29256
+ return res.data.result;
29265
29257
  }
29266
29258
 
29267
29259
  async function installDependenciesApi(dependenciesJSON, options) {
@@ -29276,7 +29268,18 @@ async function installDependenciesApi(dependenciesJSON, options) {
29276
29268
  }
29277
29269
 
29278
29270
  function createSorter() {
29279
- const priorityOrder = ['app.dataSources', 'app.enums', 'app.structures', 'app.logics', 'app.frontendTypes'];
29271
+ const priorityOrder = [
29272
+ 'extensions',
29273
+ 'apis',
29274
+ 'connectors',
29275
+ 'app.backend.variables',
29276
+ 'app.roles',
29277
+ 'app.enums',
29278
+ 'app.dataSources',
29279
+ 'app.structures',
29280
+ 'app.logics',
29281
+ 'app.frontendTypes',
29282
+ ];
29280
29283
  // 获取优先级索引
29281
29284
  const getPriority = (str) => {
29282
29285
  const prefixIndex = priorityOrder.findIndex((p) => str.startsWith(p));
@@ -29290,13 +29293,11 @@ function createSorter() {
29290
29293
  return aPriority - bPriority;
29291
29294
  }
29292
29295
  // 如果是frontendTypes,按字母顺序排序
29293
- if (aPriority === 4) {
29296
+ if (a.startsWith('app.frontendTypes') && b.startsWith('app.frontendTypes')) {
29294
29297
  return a.localeCompare(b);
29295
29298
  }
29296
- else {
29297
- // 其他情况保持原顺序
29298
- return 0;
29299
- }
29299
+ // 其他情况保持原顺序
29300
+ return 0;
29300
29301
  };
29301
29302
  }
29302
29303
  const sorter = createSorter();
@@ -29364,11 +29365,15 @@ function composeToString(files, options) {
29364
29365
  const isVariablesFile = nameFromPath === 'variables';
29365
29366
  const isExtensionsFile = arr[0] === 'extensions';
29366
29367
  const isThemeCss = ext === 'css' && nameFromPath === 'theme';
29367
- const isSpecialFile = isVariablesFile || isExtensionsFile || isThemeCss;
29368
+ const isRolesJson = file.path === 'app.roles.json';
29369
+ const isSpecialFile = isVariablesFile || isExtensionsFile || isThemeCss || isRolesJson;
29368
29370
  // 特殊文件的 namespace ${包含文件名,普通文件不包含
29369
29371
  const namespace = isSpecialFile ? [...arr, nameFromPath].join('.') : arr.join('.');
29370
29372
  let content = file.content;
29371
- if (['ts', 'tsx'].includes(ext)) {
29373
+ if (isRolesJson) {
29374
+ content = ` $roles(${content});`;
29375
+ }
29376
+ else if (['ts', 'tsx'].includes(ext)) {
29372
29377
  if (isVariablesFile) {
29373
29378
  validateVariablesFile(file, errors);
29374
29379
  }
@@ -37935,6 +37940,13 @@ var globby = /*@__PURE__*/getDefaultExportFromCjs(globbyExports);
37935
37940
  * NASL 支持的所有文件类型配置
37936
37941
  */
37937
37942
  const NASL_FILE_TYPES = [
37943
+ {
37944
+ name: 'roles',
37945
+ description: '角色',
37946
+ fileNamePattern: 'app\\.roles\\.json',
37947
+ codeRefPattern: '',
37948
+ extension: 'json',
37949
+ },
37938
37950
  {
37939
37951
  name: 'theme-css',
37940
37952
  description: '主题样式',
@@ -38031,7 +38043,7 @@ const fileNamePatterns = getFileNamePatterns();
38031
38043
  * 获取用于提取代码引用的正则表达式数组
38032
38044
  */
38033
38045
  function getCodeRefPatterns() {
38034
- return NASL_FILE_TYPES.map((type) => new RegExp(type.codeRefPattern, 'g'));
38046
+ return NASL_FILE_TYPES.filter((type) => type.codeRefPattern).map((type) => new RegExp(type.codeRefPattern, 'g'));
38035
38047
  }
38036
38048
  const codeRefPatterns = getCodeRefPatterns();
38037
38049
  /**
@@ -38066,7 +38078,7 @@ function shouldSkipDependencyTraversal(depPath) {
38066
38078
  async function scanNASLFiles(srcDir, representation, logger) {
38067
38079
  try {
38068
38080
  const pattern = representation === 'NaturalTS' ? '**/*.{ts,tsx}' : '**/*.nasl';
38069
- const files = await globby([pattern, '**/app.frontendTypes.pc.frontends.pc.theme.css'], {
38081
+ const files = await globby([pattern, 'app.frontendTypes.pc.frontends.pc.theme.css', 'app.roles.json'], {
38070
38082
  cwd: srcDir,
38071
38083
  onlyFiles: true,
38072
38084
  absolute: false,
@@ -38300,9 +38312,9 @@ function buildExternalDependencies(refs, mergedDeps, logger) {
38300
38312
  function replaceViewAsSignature(content, hasSubViews = false) {
38301
38313
  if (hasSubViews) {
38302
38314
  // 如果有子页面,替换为返回 ElRouterView 的函数
38303
- return content.replace(/export function ((\w+)\([^)]*\)) \{[\s\S]+$/, 'export function $1 {\n return <ElRouterView />\n}');
38315
+ return content.replace(/export function ((\w+)\([\s\S]*?\)) \{[\s\S]+$/, 'export function $1 {\n return <ElRouterView />\n}');
38304
38316
  }
38305
- return content.replace(/export function ((\w+)\([^)]*\)) \{[\s\S]+$/, 'export declare function $1;');
38317
+ return content.replace(/export function ((\w+)\([\s\S]*?\)) \{[\s\S]+$/, 'export declare function $1;');
38306
38318
  }
38307
38319
  /**
38308
38320
  * 处理单个文件的依赖
@@ -38344,8 +38356,10 @@ function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFil
38344
38356
  processedFileMap.set(pathRelativeToSrc, fileInfo);
38345
38357
  // 提取依赖
38346
38358
  // extensions/connectors/apis/uilibs 作为叶子节点,不再向下递归查找依赖
38359
+ // JSON 文件(如 app.roles.json)无代码引用,跳过依赖分析
38347
38360
  const isExternalDep = shouldSkipDependencyTraversal(pathRelativeToSrc);
38348
- const deps = isExternalDep ? [] : extractDeps(fileInfo.content);
38361
+ const isRolesJson = pathRelativeToSrc === 'app.roles.json';
38362
+ const deps = isExternalDep || isRolesJson ? [] : extractDeps(fileInfo.content);
38349
38363
  // 查找依赖文件
38350
38364
  if (isView) {
38351
38365
  const pathArr = pathRelativeToSrc.split('.');
@@ -38471,7 +38485,7 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38471
38485
  }
38472
38486
  let externalRefs = null;
38473
38487
  if (!entry && depMode)
38474
- entry = 'src/**/app.*.{ts,tsx,css}';
38488
+ entry = ['src/**/app.*.{ts,tsx,css}', 'src/app.roles.json'];
38475
38489
  if (entry) {
38476
38490
  // 检查入口路径是否在源代码目录外面
38477
38491
  // if (entry.startsWith('..')) throw new Error('入口路径不能在源代码目录外面');
@@ -38935,78 +38949,94 @@ async function build(entry, options) {
38935
38949
  }
38936
38950
 
38937
38951
  /**
38938
- * 获取 specs 下第1个文件夹的名字
38952
+ * specs/ 目录取第一个子文件夹名;若无则退回项目根目录名
38939
38953
  */
38940
- function getFirstSpecFolderName(projectRoot) {
38941
- const dirname = path$1.basename(projectRoot);
38954
+ function getSpecBaseName(projectRoot) {
38942
38955
  const specsDir = path$1.join(projectRoot, 'specs');
38943
- if (!libExports.existsSync(specsDir))
38944
- return dirname;
38945
- const entries = libExports.readdirSync(specsDir, { withFileTypes: true });
38946
- const folders = entries
38947
- .filter(entry => entry.isDirectory())
38948
- .map(entry => entry.name);
38949
- if (folders.length === 0)
38950
- return dirname;
38951
- return folders[0];
38956
+ if (libExports.existsSync(specsDir)) {
38957
+ const folders = libExports.readdirSync(specsDir, { withFileTypes: true })
38958
+ .filter(e => e.isDirectory())
38959
+ .map(e => e.name);
38960
+ if (folders.length > 0)
38961
+ return folders[0];
38962
+ }
38963
+ return path$1.basename(projectRoot);
38952
38964
  }
38953
38965
  /**
38954
- * 创建应用在 IDE 中
38966
+ * 从项目目录推导出合法的应用名称和包名
38955
38967
  */
38968
+ function deriveAppNames(projectRoot) {
38969
+ const baseName = getSpecBaseName(projectRoot);
38970
+ const suffix = dayjs().format('MMDDHHmmss');
38971
+ let cleaned = baseName.replace(/[^a-zA-Z0-9]/g, '').replace(/^\d+/, '').slice(0, 12);
38972
+ if (!cleaned)
38973
+ cleaned = 'app';
38974
+ return {
38975
+ appName: `${cleaned}_${suffix}`,
38976
+ packageName: `${cleaned}${suffix}`,
38977
+ };
38978
+ }
38979
+
38980
+ /**
38981
+ * 使用 readline 询问用户确认
38982
+ */
38983
+ function askForConfirmation(question) {
38984
+ const rl = readline.createInterface({
38985
+ input: process.stdin,
38986
+ output: process.stdout,
38987
+ });
38988
+ return new Promise((resolve) => {
38989
+ rl.question(question, (answer) => {
38990
+ rl.close();
38991
+ const a = answer.trim().toLowerCase();
38992
+ resolve(!a || a === 'y' || a === 'yes' || a === '是');
38993
+ });
38994
+ });
38995
+ }
38996
+
38956
38997
  async function createAppInIde(entry, options) {
38957
38998
  const logger = options?.logger || defaultLogger;
38958
- logger.info('开始创建应用在 IDE 中...');
38959
- // 收集需要处理的文件
38960
- const { collectedFiles, config } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38961
- if (config.useOPENAPI) {
38962
- logger.error('create-app-in-ide 暂不支持 useOPENAPI 模式');
38963
- logger.exit(1);
38999
+ // ── 扫描 ─────────────────────────────────────────────
39000
+ const { collectedFiles, config, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
39001
+ // ── 展示参数 ──────────────────────────────────────────
39002
+ const { appName, packageName } = deriveAppNames(getProjectRoot());
39003
+ logger.newLine();
39004
+ logger.info(`应用名称: ${appName}`);
39005
+ logger.info(`包名: ${packageName}`);
39006
+ logger.info(`IDE 版本: ${config.ideVersion}`);
39007
+ logger.info(`租户名称: ${config.tenantName || 'defaulttenant'}`);
39008
+ // ── 确认 ──────────────────────────────────────────────
39009
+ if (!options?.quiet) {
39010
+ logger.newLine();
39011
+ const confirmed = await askForConfirmation('即将在 IDE 中创建新的应用,请确认是否继续?(Y/n): ');
39012
+ if (!confirmed) {
39013
+ logger.info('已取消操作');
39014
+ process.exit(0);
39015
+ }
38964
39016
  }
38965
- // 生成 fullNaturalTS
39017
+ // ── 执行 ──────────────────────────────────────────────
38966
39018
  logger.newLine();
38967
39019
  logger.info('正在生成 NaturalTS 代码...');
38968
- let fullNaturalTS = '';
39020
+ let fullNaturalTS;
38969
39021
  try {
38970
39022
  fullNaturalTS = composeToString(collectedFiles);
39023
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38971
39024
  }
38972
39025
  catch (error) {
38973
39026
  logger.error(`生成 NaturalTS 代码失败: ${error.message}`);
38974
39027
  throw error;
38975
39028
  }
38976
- // 获取 specs 下第1个文件夹
38977
- const projectRoot = getProjectRoot();
38978
- const firstSpecFolderName = getFirstSpecFolderName(projectRoot);
38979
- const suffix = dayjs().format('MMDDHHmmss');
38980
- let cleaned = firstSpecFolderName.replace(/[^a-zA-Z0-9]/g, '').replace(/^\d+/, '').slice(0, 12);
38981
- if (!cleaned)
38982
- cleaned = 'app';
38983
- const appName = `${cleaned}_${suffix}`;
38984
- const packageName = `${cleaned}${suffix}`;
38985
- logger.info(`应用名称: ${appName}`);
38986
- logger.info(`包名: ${packageName}`);
38987
- logger.info(`IDE 版本: ${config.ideVersion}`);
38988
- logger.info(`完整版本: ${config.ideVersion}.0`);
38989
- // 调用创建应用 API
38990
- logger.newLine();
38991
39029
  logger.info('正在调用创建应用服务...');
38992
39030
  try {
38993
- const result = await createAppSyncApi(fullNaturalTS, {
38994
- packageName: packageName,
38995
- appName: appName,
38996
- serverBaseURL: config.serverBaseURL,
38997
- ideVersion: config.ideVersion,
38998
- });
39031
+ const result = await createApp(fullNaturalTS, config, appName, packageName);
38999
39032
  if (result.success) {
39000
39033
  logger.success('应用创建成功!');
39001
- if (result.appURL) {
39034
+ if (result.appURL)
39002
39035
  logger.info(`应用 URL: ${result.appURL}`);
39003
- }
39004
- if (result.appId) {
39036
+ if (result.appId)
39005
39037
  logger.info(`应用 ID: ${result.appId}`);
39006
- }
39007
- if (result.message) {
39038
+ if (result.message)
39008
39039
  logger.info(result.message);
39009
- }
39010
39040
  }
39011
39041
  else {
39012
39042
  logger.error(`应用创建失败: ${result.error || '未知错误'}`);
@@ -39019,6 +39049,57 @@ async function createAppInIde(entry, options) {
39019
39049
  }
39020
39050
  }
39021
39051
 
39052
+ async function updateAppInIde(appId, entry, options) {
39053
+ const logger = options?.logger || defaultLogger;
39054
+ // ── 扫描 ─────────────────────────────────────────────
39055
+ const { collectedFiles, config, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
39056
+ // ── 展示参数 ──────────────────────────────────────────
39057
+ logger.newLine();
39058
+ logger.info(`应用 ID: ${appId}`);
39059
+ logger.info(`IDE 版本: ${config.ideVersion}`);
39060
+ logger.info(`租户名称: ${config.tenantName || 'defaulttenant'}`);
39061
+ // ── 确认 ──────────────────────────────────────────────
39062
+ if (!options?.quiet) {
39063
+ logger.newLine();
39064
+ const confirmed = await askForConfirmation(`即将更新应用 ${appId},请确认是否继续?(Y/n): `);
39065
+ if (!confirmed) {
39066
+ logger.info('已取消操作');
39067
+ process.exit(0);
39068
+ }
39069
+ }
39070
+ // ── 执行 ──────────────────────────────────────────────
39071
+ logger.newLine();
39072
+ logger.info('正在生成 NaturalTS 代码...');
39073
+ let fullNaturalTS;
39074
+ try {
39075
+ fullNaturalTS = composeToString(collectedFiles);
39076
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
39077
+ }
39078
+ catch (error) {
39079
+ logger.error(`生成 NaturalTS 代码失败: ${error.message}`);
39080
+ throw error;
39081
+ }
39082
+ logger.info('正在调用更新应用服务...');
39083
+ try {
39084
+ const result = await updateApp(fullNaturalTS, config, appId);
39085
+ if (result.success) {
39086
+ logger.success('应用更新成功!');
39087
+ if (result.appURL)
39088
+ logger.info(`应用 URL: ${result.appURL}`);
39089
+ if (result.message)
39090
+ logger.info(result.message);
39091
+ }
39092
+ else {
39093
+ logger.error(`应用更新失败: ${result.error || '未知错误'}`);
39094
+ throw new Error(result.error || '应用更新失败');
39095
+ }
39096
+ }
39097
+ catch (error) {
39098
+ logger.error(`调用更新应用服务失败: ${error.message}`);
39099
+ throw error;
39100
+ }
39101
+ }
39102
+
39022
39103
  /**
39023
39104
  * 编译 NASL 代码
39024
39105
  * TODO: 实现具体的 API 调用逻辑
@@ -39384,27 +39465,11 @@ async function installByJSON(json, options) {
39384
39465
  logger.success(`成功写入 ${writtenCount} 个依赖文件到 ${config.srcDir} 目录`);
39385
39466
  }
39386
39467
 
39387
- var version = "0.3.3";
39468
+ var version = "0.3.5";
39388
39469
  var pkg = {
39389
39470
  version: version};
39390
39471
 
39391
39472
  const program = new Command();
39392
- /**
39393
- * 使用 readline 询问用户确认
39394
- */
39395
- function askForConfirmation(question) {
39396
- const rl = readline.createInterface({
39397
- input: process.stdin,
39398
- output: process.stdout,
39399
- });
39400
- return new Promise((resolve) => {
39401
- rl.question(question, (answer) => {
39402
- rl.close();
39403
- const normalizedAnswer = answer.trim().toLowerCase();
39404
- resolve(!normalizedAnswer || normalizedAnswer === 'y' || normalizedAnswer === 'yes' || normalizedAnswer === '是');
39405
- });
39406
- });
39407
- }
39408
39473
  const entryDescription = `是相对于项目根目录的路径,支持 glob 模式(注意要用引号包裹),例如:
39409
39474
  - src/app.enums.Status.ts 支持具体文件
39410
39475
  - "src/app.enums.*.ts" 表示所有枚举
@@ -39526,17 +39591,6 @@ program
39526
39591
  .option('-q, --quiet', '不询问问题')
39527
39592
  .action(async (entry, options) => {
39528
39593
  try {
39529
- // 如果不是 quiet 模式,询问用户确认
39530
- if (!options?.quiet) {
39531
- defaultLogger.newLine();
39532
- defaultLogger.info('即将在 IDE 中创建新的应用,此操作将调用远程接口。');
39533
- const confirmed = await askForConfirmation('请确认是否继续?(Y/n): ');
39534
- if (!confirmed) {
39535
- defaultLogger.info('已取消操作');
39536
- process.exit(0);
39537
- }
39538
- defaultLogger.newLine();
39539
- }
39540
39594
  await createAppInIde(entry, options);
39541
39595
  }
39542
39596
  catch (error) {
@@ -39544,6 +39598,20 @@ program
39544
39598
  process.exit(1);
39545
39599
  }
39546
39600
  });
39601
+ program
39602
+ .command('update-app-in-ide <appId> [entry]')
39603
+ .description('在 IDE 中更新已有应用')
39604
+ .option('-v, --verbose', '显示详细信息,如依赖分析树')
39605
+ .option('-q, --quiet', '不询问问题')
39606
+ .action(async (appId, entry, options) => {
39607
+ try {
39608
+ await updateAppInIde(appId, entry, options);
39609
+ }
39610
+ catch (error) {
39611
+ defaultLogger.error(`更新应用过程发生错误:${error.message}`);
39612
+ process.exit(1);
39613
+ }
39614
+ });
39547
39615
  program
39548
39616
  .command('transform <transformType> [entry]')
39549
39617
  .description('转换文件格式\n transformType: files2full (将 src 文件组合成 fullNaturalTS), json2files (将 JSON 转换为文件), files2json (将 src 文件转换为 JSON), doc2full (将 plan markdown 文档组合成 fullNaturalTS)')