@nasl/cli 0.1.16 → 0.1.18

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 (52) hide show
  1. package/README.md +113 -11
  2. package/dist/bin/nasl.mjs +340 -43
  3. package/dist/bin/nasl.mjs.map +1 -1
  4. package/dist/bin/naslc.mjs +316 -20
  5. package/dist/bin/naslc.mjs.map +1 -1
  6. package/dist/index.mjs +336 -39
  7. package/dist/index.mjs.map +1 -1
  8. package/out/apis/cachable.d.ts +16 -0
  9. package/out/apis/cachable.d.ts.map +1 -0
  10. package/out/apis/cachable.js +142 -0
  11. package/out/apis/cachable.js.map +1 -0
  12. package/out/apis/compileApi.d.ts.map +1 -1
  13. package/out/apis/compileApi.js +2 -4
  14. package/out/apis/compileApi.js.map +1 -1
  15. package/out/apis/createAppApi.js +1 -1
  16. package/out/apis/createAppApi.js.map +1 -1
  17. package/out/apis/createAxios.d.ts +7 -1
  18. package/out/apis/createAxios.d.ts.map +1 -1
  19. package/out/apis/createAxios.js +33 -5
  20. package/out/apis/createAxios.js.map +1 -1
  21. package/out/apis/openapi.d.ts +37 -0
  22. package/out/apis/openapi.d.ts.map +1 -0
  23. package/out/apis/openapi.js +110 -0
  24. package/out/apis/openapi.js.map +1 -0
  25. package/out/apis/transformApi.d.ts +1 -1
  26. package/out/apis/transformApi.d.ts.map +1 -1
  27. package/out/apis/transformApi.js +4 -6
  28. package/out/apis/transformApi.js.map +1 -1
  29. package/out/bin/nasl.js +3 -3
  30. package/out/bin/nasl.js.map +1 -1
  31. package/out/commands/check.d.ts.map +1 -1
  32. package/out/commands/check.js +1 -4
  33. package/out/commands/check.js.map +1 -1
  34. package/out/commands/compile.d.ts.map +1 -1
  35. package/out/commands/compile.js +1 -4
  36. package/out/commands/compile.js.map +1 -1
  37. package/out/commands/createAppInIde.d.ts.map +1 -1
  38. package/out/commands/createAppInIde.js +4 -0
  39. package/out/commands/createAppInIde.js.map +1 -1
  40. package/out/commands/transform.d.ts.map +1 -1
  41. package/out/commands/transform.js +6 -4
  42. package/out/commands/transform.js.map +1 -1
  43. package/out/types/api.d.ts +8 -0
  44. package/out/types/api.d.ts.map +1 -1
  45. package/out/types/config.d.ts +6 -0
  46. package/out/types/config.d.ts.map +1 -1
  47. package/out/types/config.js +2 -2
  48. package/out/types/config.js.map +1 -1
  49. package/out/utils/config.d.ts.map +1 -1
  50. package/out/utils/config.js +31 -2
  51. package/out/utils/config.js.map +1 -1
  52. package/package.json +3 -1
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as sysPath from 'path';
2
- import sysPath__default from 'path';
3
- import require$$0$3, { unwatchFile, watchFile, watch as watch$1, stat as stat$3 } from 'fs';
2
+ import sysPath__default, { join } from 'path';
3
+ import require$$0$3, { promises, unwatchFile, watchFile, watch as watch$1, stat as stat$3 } from 'fs';
4
4
  import stream$4, { Readable } from 'stream';
5
5
  import require$$0$1, { type as type$1 } from 'os';
6
6
  import require$$0$2 from 'util';
@@ -11,23 +11,23 @@ import require$$5 from 'assert';
11
11
  import require$$3 from 'http';
12
12
  import require$$4 from 'https';
13
13
  import require$$0$6 from 'url';
14
- import require$$8 from 'crypto';
14
+ import crypto$1, { createHash } from 'crypto';
15
15
  import http2 from 'http2';
16
16
  import zlib from 'zlib';
17
17
  import { spawn, spawnSync } from 'child_process';
18
18
  import { realpath as realpath$1, stat as stat$2, lstat as lstat$1, open, readdir as readdir$1 } from 'fs/promises';
19
19
  import { lstat, stat as stat$1, readdir, realpath } from 'node:fs/promises';
20
20
  import { Readable as Readable$1 } from 'node:stream';
21
- import { resolve, join, relative, sep } from 'node:path';
21
+ import { resolve, join as join$1, relative, sep } from 'node:path';
22
22
 
23
23
  /**
24
24
  * 默认配置
25
25
  */
26
26
  const DEFAULT_CONFIG = {
27
- serverBaseURL: 'https://nasl.lcap.163yun.com/api/v1/nasl',
27
+ serverBaseURL: 'https://nasl.lcap.163yun.com',
28
28
  representation: 'NaturalTS',
29
29
  namespaceResolution: 'filename-as-namespace',
30
- ideVersion: '4.3',
30
+ ideVersion: '4.4',
31
31
  srcDir: 'src',
32
32
  outDir: 'out',
33
33
  };
@@ -13582,10 +13582,39 @@ function loadConfig(configDir) {
13582
13582
  const content = libExports.readFileSync(configPath, 'utf-8');
13583
13583
  const config = JSON.parse(content);
13584
13584
  // 验证必需字段
13585
- if (!config.serverBaseURL || !config.ideVersion || !config.srcDir || !config.outDir) {
13586
- defaultLogger.error('配置文件格式不正确,缺少必需字段');
13585
+ if (!config.srcDir || !config.outDir) {
13586
+ defaultLogger.error('配置文件格式不正确,缺少必需的 srcDir 或 outDir 字段');
13587
13587
  return defaultLogger.exit(1);
13588
13588
  }
13589
+ if (!config.ideVersion) {
13590
+ config.ideVersion = process.env.NASL_IDE_VERSION || '';
13591
+ if (!config.ideVersion) {
13592
+ defaultLogger.error('缺少配置 ideVersion,请在配置文件中添加,或在环境变量中配置 NASL_IDE_VERSION');
13593
+ return defaultLogger.exit(1);
13594
+ }
13595
+ }
13596
+ if (!config.serverBaseURL) {
13597
+ config.serverBaseURL = process.env.NASL_SERVER_BASE_URL || '';
13598
+ if (!config.serverBaseURL) {
13599
+ defaultLogger.error('缺少配置 serverBaseURL,请在配置文件中添加,或在环境变量中配置 NASL_SERVER_BASE_URL');
13600
+ return defaultLogger.exit(1);
13601
+ }
13602
+ }
13603
+ if (!config.useOPENAPI)
13604
+ config.useOPENAPI = process.env.USE_LCAP_OPENAPI === 'true';
13605
+ if (!config.OPENAPI_AK)
13606
+ config.OPENAPI_AK = process.env.LCAP_OPENAPI_AK;
13607
+ if (!config.OPENAPI_SK)
13608
+ config.OPENAPI_SK = process.env.LCAP_OPENAPI_SK;
13609
+ if (config.useOPENAPI) {
13610
+ if (!config.OPENAPI_AK || !config.OPENAPI_SK) {
13611
+ defaultLogger.error(`配置了 useOPENAPI,但缺少配置 OPENAPI_AK 和 OPENAPI_SK:
13612
+ - 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK
13613
+ - 或将 useOPENAPI 配置为 false
13614
+ `);
13615
+ return defaultLogger.exit(1);
13616
+ }
13617
+ }
13589
13618
  return config;
13590
13619
  }
13591
13620
  catch (error) {
@@ -27652,7 +27681,7 @@ function requireForm_data () {
27652
27681
  var parseUrl = require$$0$6.parse;
27653
27682
  var fs = require$$0$3;
27654
27683
  var Stream = stream$4.Stream;
27655
- var crypto = require$$8;
27684
+ var crypto = crypto$1;
27656
27685
  var mime = requireMimeTypes();
27657
27686
  var asynckit = requireAsynckit();
27658
27687
  var setToStringTag = /*@__PURE__*/ requireEsSetTostringtag();
@@ -28561,7 +28590,7 @@ const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {
28561
28590
  let str = '';
28562
28591
  const {length} = alphabet;
28563
28592
  const randomValues = new Uint32Array(size);
28564
- require$$8.randomFillSync(randomValues);
28593
+ crypto$1.randomFillSync(randomValues);
28565
28594
  for (let i = 0; i < size; i++) {
28566
28595
  str += alphabet[randomValues[i] % length];
28567
28596
  }
@@ -34346,14 +34375,286 @@ const {
34346
34375
  mergeConfig
34347
34376
  } = axios;
34348
34377
 
34349
- function createAxios(baseURL) {
34350
- return axios.create({
34378
+ // Unique ID creation requires a high quality random # generator. In the browser we therefore
34379
+ // require the crypto API and do not support built-in fallback to lower quality random number
34380
+ // generators (like Math.random()).
34381
+ let getRandomValues;
34382
+ const rnds8 = new Uint8Array(16);
34383
+ function rng() {
34384
+ // lazy load so that environments that need to polyfill have a chance to do so
34385
+ if (!getRandomValues) {
34386
+ // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
34387
+ getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
34388
+
34389
+ if (!getRandomValues) {
34390
+ throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
34391
+ }
34392
+ }
34393
+
34394
+ return getRandomValues(rnds8);
34395
+ }
34396
+
34397
+ /**
34398
+ * Convert array of 16 byte values to UUID string format of the form:
34399
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
34400
+ */
34401
+
34402
+ const byteToHex = [];
34403
+
34404
+ for (let i = 0; i < 256; ++i) {
34405
+ byteToHex.push((i + 0x100).toString(16).slice(1));
34406
+ }
34407
+
34408
+ function unsafeStringify(arr, offset = 0) {
34409
+ // Note: Be careful editing this code! It's been tuned for performance
34410
+ // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
34411
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
34412
+ }
34413
+
34414
+ const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
34415
+ var native = {
34416
+ randomUUID
34417
+ };
34418
+
34419
+ function v4(options, buf, offset) {
34420
+ if (native.randomUUID && true && !options) {
34421
+ return native.randomUUID();
34422
+ }
34423
+
34424
+ options = options || {};
34425
+ const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
34426
+
34427
+ rnds[6] = rnds[6] & 0x0f | 0x40;
34428
+ rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
34429
+
34430
+ return unsafeStringify(rnds);
34431
+ }
34432
+
34433
+ function generateHash(params) {
34434
+ const hash = createHash('sha256');
34435
+ hash.update(JSON.stringify(params));
34436
+ return hash.digest('hex');
34437
+ }
34438
+ async function getCachePathWithTimestamp(hash) {
34439
+ const cacheDir = join(process.cwd(), '.cache');
34440
+ await promises.mkdir(cacheDir, { recursive: true });
34441
+ return join(cacheDir, `${hash}_${Date.now()}.json`);
34442
+ }
34443
+ /**
34444
+ * 查找指定 hash 的有效缓存文件
34445
+ * @param hash 缓存标识
34446
+ * @param ttl 缓存有效期(毫秒)
34447
+ * @returns 缓存文件路径和缓存内容,如果没有有效缓存则返回 null
34448
+ */
34449
+ async function findValidCache(hash, ttl) {
34450
+ const cacheDir = join(process.cwd(), '.cache');
34451
+ try {
34452
+ await promises.mkdir(cacheDir, { recursive: true });
34453
+ const files = await promises.readdir(cacheDir);
34454
+ const now = Date.now();
34455
+ // 查找所有匹配的缓存文件
34456
+ const matchingFiles = files
34457
+ .filter((file) => file.startsWith(`${hash}_`) && file.endsWith('.json'))
34458
+ .map((file) => {
34459
+ const match = file.match(/_(\d+)\.json$/);
34460
+ if (!match)
34461
+ return null;
34462
+ const timestamp = parseInt(match[1], 10);
34463
+ return {
34464
+ path: join(cacheDir, file),
34465
+ timestamp,
34466
+ isExpired: now - timestamp > ttl,
34467
+ };
34468
+ })
34469
+ .filter((item) => item !== null);
34470
+ // 删除过期的缓存文件
34471
+ const expiredFiles = matchingFiles.filter((item) => item.isExpired);
34472
+ await Promise.all(expiredFiles.map((item) => promises.unlink(item.path).catch(() => { })));
34473
+ // 查找有效的缓存文件(按时间戳降序排序,获取最新的)
34474
+ const validFiles = matchingFiles.filter((item) => !item.isExpired).sort((a, b) => b.timestamp - a.timestamp);
34475
+ if (validFiles.length > 0) {
34476
+ const cacheFile = validFiles[0];
34477
+ const cacheContent = await promises.readFile(cacheFile.path, 'utf-8');
34478
+ const cachedResult = JSON.parse(cacheContent);
34479
+ return { path: cacheFile.path, data: cachedResult };
34480
+ }
34481
+ return null;
34482
+ }
34483
+ catch (error) {
34484
+ return null;
34485
+ }
34486
+ }
34487
+ /**
34488
+ * 高阶函数,为异步函数添加带时间戳的缓存功能
34489
+ * @param fn 需要添加缓存的函数
34490
+ * @param ttl 缓存有效期(毫秒),默认 1 小时
34491
+ * @param getCacheKey 可选的自定义缓存 key 生成函数,如果不提供则使用整个 params
34492
+ * @returns 带缓存的函数版本
34493
+ */
34494
+ function cachableWithTTL(fn, ttl = 3600 * 1000, // 默认 1 小时
34495
+ getCacheKey) {
34496
+ return async (params, extraParams) => {
34497
+ const functionName = fn.name;
34498
+ const logPrefix = functionName ? `[${functionName}]` : '[cachableWithTTL]';
34499
+ // 检查是否启用缓存
34500
+ if (process.env.NO_AI_CACHE) {
34501
+ return fn(params, extraParams);
34502
+ }
34503
+ // 使用自定义的 getCacheKey 或默认使用整个 params
34504
+ const cacheKey = getCacheKey ? getCacheKey(params) : params;
34505
+ const hash = generateHash(cacheKey);
34506
+ // 查找有效的缓存
34507
+ const validCache = await findValidCache(hash, ttl);
34508
+ if (validCache) {
34509
+ console.log(`${logPrefix} ✓ 使用缓存`);
34510
+ return validCache.data;
34511
+ }
34512
+ // 调用原函数
34513
+ const result = await fn(params, extraParams);
34514
+ // 保存结果到缓存(带时间戳)
34515
+ try {
34516
+ const cachePath = await getCachePathWithTimestamp(hash);
34517
+ await promises.writeFile(cachePath, JSON.stringify(result, null, 2), 'utf-8');
34518
+ }
34519
+ catch (error) {
34520
+ // 缓存写入失败,但不影响返回结果
34521
+ }
34522
+ return result;
34523
+ };
34524
+ }
34525
+
34526
+ /**
34527
+ * 生成客户端签名信息
34528
+ * @param appKey AppKey
34529
+ * @param secretKey SecretKey
34530
+ * @returns 签名信息
34531
+ */
34532
+ function generateClientSignature(appKey, secretKey) {
34533
+ const timestamp = Math.floor(Date.now() / 1000).toString();
34534
+ const nonce = v4();
34535
+ const plainText = `${appKey}&${nonce}&${timestamp}&${secretKey}`;
34536
+ const signature = crypto$1.createHash('md5').update(plainText).digest('hex');
34537
+ return {
34538
+ appKey,
34539
+ timestamp,
34540
+ nonce,
34541
+ signature,
34542
+ };
34543
+ }
34544
+ /**
34545
+ * 生成基础认证头
34546
+ * @param ak AppKey
34547
+ * @param sk SecretKey
34548
+ * @returns 基础认证头
34549
+ */
34550
+ function generateBaseHeaders(ak, sk) {
34551
+ const { timestamp, signature, nonce } = generateClientSignature(ak, sk);
34552
+ return {
34553
+ 'Content-Type': 'application/json',
34554
+ 'x-appKey': ak,
34555
+ 'x-timestamp': timestamp,
34556
+ 'x-nonce': nonce,
34557
+ 'x-signature': signature,
34558
+ };
34559
+ }
34560
+ /**
34561
+ * 获取租户的 signInfo(内部实现)
34562
+ * @param options 服务器选项
34563
+ * @param baseHeaders 基础认证头
34564
+ * @returns x-signInfo 值
34565
+ */
34566
+ async function _fetchSignInfo({ options, baseHeaders }) {
34567
+ const tenantName = options.tenantName || 'defaulttenant';
34568
+ const userName = tenantName === 'defaulttenant' ? 'admin' : `${tenantName}-admin`;
34569
+ const data = {
34570
+ tenantName,
34571
+ userName,
34572
+ source: 'Normal',
34573
+ };
34574
+ const url = `${options.serverBaseURL}/openapi/v3/auth/getSignInfo`;
34575
+ try {
34576
+ const tempAxios = axios.create({
34577
+ headers: baseHeaders,
34578
+ timeout: 120000,
34579
+ });
34580
+ const response = await tempAxios.post(url, data);
34581
+ return response?.data?.result || null;
34582
+ }
34583
+ catch (error) {
34584
+ console.error('Error fetching sign info:', error.response?.data);
34585
+ return null;
34586
+ }
34587
+ }
34588
+ /**
34589
+ * 获取租户的 signInfo(带缓存,1 小时过期)
34590
+ * @param options 服务器选项
34591
+ * @param baseHeaders 基础认证头
34592
+ * @returns x-signInfo 值
34593
+ */
34594
+ const fetchSignInfo = cachableWithTTL(_fetchSignInfo, 3600 * 1000, // 1 小时
34595
+ (params) => params.options);
34596
+ /**
34597
+ * 生成完整的认证头(包含 x-signInfo)
34598
+ * @param options 服务器选项
34599
+ * @returns 完整的认证头
34600
+ */
34601
+ async function generateCompleteHeaders(options) {
34602
+ const headers = {
34603
+ 'Content-Type': 'application/json',
34604
+ };
34605
+ // 如果没有提供 ak 和 sk,返回基础 headers
34606
+ if (!options.OPENAPI_AK || !options.OPENAPI_SK) {
34607
+ throw new Error(`配置了 useOPENAPI,但缺少配置 OPENAPI_AK 和 OPENAPI_SK:
34608
+ - 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK
34609
+ - 或将 useOPENAPI 配置为 false
34610
+ `);
34611
+ }
34612
+ // 生成基础认证头
34613
+ const baseHeaders = generateBaseHeaders(options.OPENAPI_AK, options.OPENAPI_SK);
34614
+ Object.assign(headers, baseHeaders);
34615
+ // 获取 signInfo
34616
+ const signInfo = await fetchSignInfo({ options, baseHeaders: headers });
34617
+ if (signInfo) {
34618
+ headers['x-signInfo'] = signInfo;
34619
+ }
34620
+ return headers;
34621
+ }
34622
+
34623
+ /**
34624
+ * 创建 Axios 实例
34625
+ * @param options 服务器选项,包含认证信息
34626
+ * @returns Axios 实例
34627
+ */
34628
+ async function createAxios(options) {
34629
+ // 如果需要鉴权,拼接 /openapi/v3/nasl;否则使用原始 URL
34630
+ const serverBaseURL = new URL(options.serverBaseURL).origin;
34631
+ const baseURL = options.useOPENAPI ? `${serverBaseURL}/openapi/v3/nasl` : `${serverBaseURL}/api/v1/nasl`;
34632
+ // 如果需要鉴权,生成完整的认证头;否则只使用基础 headers
34633
+ const headers = options.useOPENAPI ? await generateCompleteHeaders(options) : { 'Content-Type': 'application/json' };
34634
+ console.log('本次服务调用方为:', baseURL);
34635
+ const instance = axios.create({
34351
34636
  baseURL,
34352
- headers: {
34353
- 'Content-Type': 'application/json',
34354
- },
34637
+ headers,
34355
34638
  timeout: 120000,
34356
34639
  });
34640
+ const oldPost = instance.post;
34641
+ instance.post = async (url, data, config) => {
34642
+ return oldPost(url, data, config).then((res) => {
34643
+ const data = res.data;
34644
+ if (data.code !== 200)
34645
+ throw new Error(JSON.stringify(data));
34646
+ return res;
34647
+ }).catch((err) => {
34648
+ // console.log(err.response ? err.response.data : err);
34649
+ if (err.response) {
34650
+ throw new Error(JSON.stringify(err.response.data));
34651
+ }
34652
+ else {
34653
+ throw err;
34654
+ }
34655
+ });
34656
+ };
34657
+ return instance;
34357
34658
  }
34358
34659
 
34359
34660
  function truncate(str, maxLength) {
@@ -34367,13 +34668,11 @@ function truncate(str, maxLength) {
34367
34668
  async function compileApi(fullNaturalTS, options) {
34368
34669
  // 这里需要调用实际的编译服务接口
34369
34670
  // 示例实现:
34370
- const axios = createAxios(options.serverBaseURL);
34671
+ const axios = await createAxios(options);
34371
34672
  const res = await axios.post(`/compile/tsx?ideVersion=${options.ideVersion}&needAnnotation=true`, fullNaturalTS, {
34372
34673
  headers: { 'Content-Type': 'text/plain' },
34373
34674
  });
34374
34675
  const data = res.data;
34375
- if (data.code !== 200)
34376
- throw new Error(data.message);
34377
34676
  const { bundle } = data.result;
34378
34677
  const fileMap = bundle.frontendBundle.files;
34379
34678
  const files = Object.keys(fileMap).map((key) => {
@@ -34401,7 +34700,7 @@ window.backendApp = app;
34401
34700
  * TODO: 实现具体的 API 调用逻辑
34402
34701
  */
34403
34702
  async function checkApi(fullNaturalTS, options) {
34404
- const axios = createAxios(options.serverBaseURL);
34703
+ const axios = await createAxios(options);
34405
34704
  const res = await axios.post(`/check/tsx?ideVersion=${options.ideVersion}`, fullNaturalTS, {
34406
34705
  headers: { 'Content-Type': 'text/plain' },
34407
34706
  });
@@ -34419,7 +34718,7 @@ async function checkApi(fullNaturalTS, options) {
34419
34718
  async function createAppSyncApi(fullNaturalTS, options) {
34420
34719
  const url = new URL(options.serverBaseURL);
34421
34720
  const origin = url.origin + '/app-ai-creator';
34422
- const axios = createAxios(origin);
34721
+ const axios = await createAxios({ serverBaseURL: origin, ideVersion: options.ideVersion });
34423
34722
  try {
34424
34723
  const res = await axios.post('/api/createAppSync', {
34425
34724
  fullNaturalTS,
@@ -34466,10 +34765,7 @@ async function compile(entry, options) {
34466
34765
  logger.info('正在调用编译服务...');
34467
34766
  try {
34468
34767
  const fullNaturalTS = composeToString(collectedFiles);
34469
- const outputFiles = await compileApi(fullNaturalTS, {
34470
- serverBaseURL: config.serverBaseURL,
34471
- ideVersion: config.ideVersion,
34472
- });
34768
+ const outputFiles = await compileApi(fullNaturalTS, config);
34473
34769
  logger.success('编译成功!');
34474
34770
  // 写入输出文件
34475
34771
  for (const file of outputFiles) {
@@ -34516,10 +34812,7 @@ async function check(entry, options) {
34516
34812
  result = error.message.trim();
34517
34813
  }
34518
34814
  if (!result && fullNaturalTS) {
34519
- result = (await checkApi(fullNaturalTS, {
34520
- serverBaseURL: config.serverBaseURL,
34521
- ideVersion: config.ideVersion,
34522
- })).trim();
34815
+ result = (await checkApi(fullNaturalTS, config)).trim();
34523
34816
  }
34524
34817
  const checkResult = {
34525
34818
  success: !result,
@@ -34798,6 +35091,10 @@ async function createAppInIde(entry, options) {
34798
35091
  logger.info('开始创建应用在 IDE 中...');
34799
35092
  // 收集需要处理的文件
34800
35093
  const { collectedFiles, config } = await resolveNASLFiles(entry, logger, false, options?.verbose);
35094
+ if (config.useOPENAPI) {
35095
+ logger.error('create-app-in-ide 暂不支持 useOPENAPI 模式');
35096
+ logger.exit(1);
35097
+ }
34801
35098
  // 生成 fullNaturalTS
34802
35099
  logger.newLine();
34803
35100
  logger.info('正在生成 NaturalTS 代码...');
@@ -34859,15 +35156,13 @@ async function createAppInIde(entry, options) {
34859
35156
  * 编译 NASL 代码
34860
35157
  * TODO: 实现具体的 API 调用逻辑
34861
35158
  */
34862
- async function transformJson2FilesApi(jsonContent, options) {
35159
+ async function transformJson2FilesApi(json, options) {
34863
35160
  // 示例实现:
34864
- const axios = createAxios(options.serverBaseURL);
34865
- const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`, jsonContent, {
34866
- headers: { 'Content-Type': 'text/plain' },
35161
+ const axios = await createAxios(options);
35162
+ const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`, json, {
35163
+ headers: { 'Content-Type': 'application/json' },
34867
35164
  });
34868
35165
  const data = res.data;
34869
- if (data.code !== 200)
34870
- throw new Error(data.message);
34871
35166
  return data.result;
34872
35167
  }
34873
35168
 
@@ -34907,17 +35202,19 @@ const transformFns = {
34907
35202
  const projectRoot = getProjectRoot();
34908
35203
  logger.info(`项目根目录: ${projectRoot}`);
34909
35204
  logger.info(`源代码目录: ${config.srcDir}`);
35205
+ if (!libExports.existsSync(config.srcDir)) {
35206
+ logger.error(`当前目录下 ${config.srcDir} 目录不存在,请先创建`);
35207
+ logger.exit(1);
35208
+ }
34910
35209
  let jsonContent = '';
34911
35210
  if (!entry) {
34912
35211
  logger.warn('没有指定 JSON 文件路径,按照默认 IDE 版本的基础模板转换');
34913
35212
  }
34914
35213
  else {
34915
35214
  jsonContent = libExports.readFileSync(entry, 'utf-8');
35215
+ logger.info(`读取到 JSON 文件: ${entry}`);
34916
35216
  }
34917
- const files = await transformJson2FilesApi(jsonContent, {
34918
- serverBaseURL: config.serverBaseURL,
34919
- ideVersion: config.ideVersion,
34920
- });
35217
+ const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, config);
34921
35218
  await Promise.all(files.map(async (file) => {
34922
35219
  const outputPath = sysPath.join(projectRoot, config.srcDir, file.path);
34923
35220
  await libExports.writeFile(outputPath, file.content);
@@ -35101,7 +35398,7 @@ class ReaddirpStream extends Readable$1 {
35101
35398
  let entry;
35102
35399
  const basename = this._isDirent ? dirent.name : dirent;
35103
35400
  try {
35104
- const fullPath = resolve(join(path, basename));
35401
+ const fullPath = resolve(join$1(path, basename));
35105
35402
  entry = { path: relative(this._root, fullPath), fullPath, basename };
35106
35403
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
35107
35404
  }