@nasl/cli 0.1.16 → 0.1.17

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 (41) hide show
  1. package/dist/bin/nasl.mjs +214 -34
  2. package/dist/bin/nasl.mjs.map +1 -1
  3. package/dist/bin/naslc.mjs +196 -16
  4. package/dist/bin/naslc.mjs.map +1 -1
  5. package/dist/index.mjs +210 -30
  6. package/dist/index.mjs.map +1 -1
  7. package/out/apis/compileApi.d.ts.map +1 -1
  8. package/out/apis/compileApi.js +2 -4
  9. package/out/apis/compileApi.js.map +1 -1
  10. package/out/apis/createAppApi.js +1 -1
  11. package/out/apis/createAppApi.js.map +1 -1
  12. package/out/apis/createAxios.d.ts +7 -1
  13. package/out/apis/createAxios.d.ts.map +1 -1
  14. package/out/apis/createAxios.js +34 -5
  15. package/out/apis/createAxios.js.map +1 -1
  16. package/out/apis/openapi.d.ts +34 -0
  17. package/out/apis/openapi.d.ts.map +1 -0
  18. package/out/apis/openapi.js +114 -0
  19. package/out/apis/openapi.js.map +1 -0
  20. package/out/apis/transformApi.d.ts +1 -1
  21. package/out/apis/transformApi.d.ts.map +1 -1
  22. package/out/apis/transformApi.js +4 -6
  23. package/out/apis/transformApi.js.map +1 -1
  24. package/out/bin/nasl.js +3 -3
  25. package/out/bin/nasl.js.map +1 -1
  26. package/out/commands/check.d.ts.map +1 -1
  27. package/out/commands/check.js +1 -4
  28. package/out/commands/check.js.map +1 -1
  29. package/out/commands/compile.d.ts.map +1 -1
  30. package/out/commands/compile.js +1 -4
  31. package/out/commands/compile.js.map +1 -1
  32. package/out/commands/transform.d.ts.map +1 -1
  33. package/out/commands/transform.js +6 -1
  34. package/out/commands/transform.js.map +1 -1
  35. package/out/types/api.d.ts +8 -0
  36. package/out/types/api.d.ts.map +1 -1
  37. package/out/types/config.d.ts +6 -0
  38. package/out/types/config.d.ts.map +1 -1
  39. package/out/types/config.js +2 -2
  40. package/out/types/config.js.map +1 -1
  41. package/package.json +3 -1
package/dist/bin/nasl.mjs CHANGED
@@ -15,7 +15,7 @@ import require$$1$1 from 'tty';
15
15
  import require$$3 from 'http';
16
16
  import require$$4$1 from 'https';
17
17
  import require$$0$6 from 'url';
18
- import require$$8 from 'crypto';
18
+ import crypto$1 from 'crypto';
19
19
  import http2 from 'http2';
20
20
  import zlib from 'zlib';
21
21
  import * as readline from 'readline';
@@ -6192,10 +6192,10 @@ var libExports = /*@__PURE__*/ requireLib();
6192
6192
  * 默认配置
6193
6193
  */
6194
6194
  const DEFAULT_CONFIG = {
6195
- serverBaseURL: 'https://nasl.lcap.163yun.com/api/v1/nasl',
6195
+ serverBaseURL: 'https://nasl.lcap.163yun.com',
6196
6196
  representation: 'NaturalTS',
6197
6197
  namespaceResolution: 'filename-as-namespace',
6198
- ideVersion: '4.3',
6198
+ ideVersion: '4.4',
6199
6199
  srcDir: 'src',
6200
6200
  outDir: 'out',
6201
6201
  };
@@ -22146,7 +22146,7 @@ function requireForm_data () {
22146
22146
  var parseUrl = require$$0$6.parse;
22147
22147
  var fs = require$$0$2;
22148
22148
  var Stream = stream$4.Stream;
22149
- var crypto = require$$8;
22149
+ var crypto = crypto$1;
22150
22150
  var mime = requireMimeTypes();
22151
22151
  var asynckit = requireAsynckit();
22152
22152
  var setToStringTag = /*@__PURE__*/ requireEsSetTostringtag();
@@ -23055,7 +23055,7 @@ const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {
23055
23055
  let str = '';
23056
23056
  const {length} = alphabet;
23057
23057
  const randomValues = new Uint32Array(size);
23058
- require$$8.randomFillSync(randomValues);
23058
+ crypto$1.randomFillSync(randomValues);
23059
23059
  for (let i = 0; i < size; i++) {
23060
23060
  str += alphabet[randomValues[i] % length];
23061
23061
  }
@@ -28840,14 +28840,199 @@ const {
28840
28840
  mergeConfig
28841
28841
  } = axios;
28842
28842
 
28843
- function createAxios(baseURL) {
28844
- return axios.create({
28843
+ // Unique ID creation requires a high quality random # generator. In the browser we therefore
28844
+ // require the crypto API and do not support built-in fallback to lower quality random number
28845
+ // generators (like Math.random()).
28846
+ let getRandomValues;
28847
+ const rnds8 = new Uint8Array(16);
28848
+ function rng() {
28849
+ // lazy load so that environments that need to polyfill have a chance to do so
28850
+ if (!getRandomValues) {
28851
+ // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
28852
+ getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
28853
+
28854
+ if (!getRandomValues) {
28855
+ throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
28856
+ }
28857
+ }
28858
+
28859
+ return getRandomValues(rnds8);
28860
+ }
28861
+
28862
+ /**
28863
+ * Convert array of 16 byte values to UUID string format of the form:
28864
+ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
28865
+ */
28866
+
28867
+ const byteToHex = [];
28868
+
28869
+ for (let i = 0; i < 256; ++i) {
28870
+ byteToHex.push((i + 0x100).toString(16).slice(1));
28871
+ }
28872
+
28873
+ function unsafeStringify(arr, offset = 0) {
28874
+ // Note: Be careful editing this code! It's been tuned for performance
28875
+ // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
28876
+ 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]];
28877
+ }
28878
+
28879
+ const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
28880
+ var native = {
28881
+ randomUUID
28882
+ };
28883
+
28884
+ function v4(options, buf, offset) {
28885
+ if (native.randomUUID && true && !options) {
28886
+ return native.randomUUID();
28887
+ }
28888
+
28889
+ options = options || {};
28890
+ const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
28891
+
28892
+ rnds[6] = rnds[6] & 0x0f | 0x40;
28893
+ rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
28894
+
28895
+ return unsafeStringify(rnds);
28896
+ }
28897
+
28898
+ /**
28899
+ * 构建签名字符串
28900
+ */
28901
+ function buildStringToSign(appKey, nonce, timestamp, secretKey) {
28902
+ return `${appKey}&${nonce}&${timestamp}&${secretKey}`;
28903
+ }
28904
+ /**
28905
+ * 生成 MD5 签名
28906
+ */
28907
+ function generateSignature(plainText) {
28908
+ return crypto$1.createHash('md5').update(plainText).digest('hex');
28909
+ }
28910
+ /**
28911
+ * 生成客户端签名信息
28912
+ * @param appKey AppKey
28913
+ * @param secretKey SecretKey
28914
+ * @returns 签名信息
28915
+ */
28916
+ function generateClientSignature(appKey, secretKey) {
28917
+ const timestamp = Math.floor(Date.now() / 1000).toString();
28918
+ const nonce = v4();
28919
+ const plainText = buildStringToSign(appKey, nonce, timestamp, secretKey);
28920
+ const signature = generateSignature(plainText);
28921
+ return {
28922
+ appKey,
28923
+ timestamp,
28924
+ nonce,
28925
+ signature,
28926
+ };
28927
+ }
28928
+ /**
28929
+ * 生成基础认证头
28930
+ * @param ak AppKey
28931
+ * @param sk SecretKey
28932
+ * @returns 基础认证头
28933
+ */
28934
+ function generateBaseHeaders(ak, sk) {
28935
+ const { timestamp, signature, nonce } = generateClientSignature(ak, sk);
28936
+ return {
28937
+ 'Content-Type': 'application/json',
28938
+ 'x-appKey': ak,
28939
+ 'x-timestamp': timestamp,
28940
+ 'x-nonce': nonce,
28941
+ 'x-signature': signature,
28942
+ };
28943
+ }
28944
+ /**
28945
+ * 获取租户的 signInfo
28946
+ * @param options 服务器选项
28947
+ * @param baseHeaders 基础认证头
28948
+ * @returns x-signInfo 值
28949
+ */
28950
+ async function fetchSignInfo(options, baseHeaders) {
28951
+ const tenantName = options.tenantName || 'defaulttenant';
28952
+ const userName = tenantName === 'defaulttenant' ? 'admin' : `${tenantName}-admin`;
28953
+ const data = {
28954
+ tenantName,
28955
+ userName,
28956
+ source: 'Normal',
28957
+ };
28958
+ const url = `${options.serverBaseURL}/openapi/v3/auth/getSignInfo`;
28959
+ try {
28960
+ const tempAxios = axios.create({
28961
+ headers: baseHeaders,
28962
+ timeout: 120000,
28963
+ });
28964
+ const response = await tempAxios.post(url, data);
28965
+ return response?.data?.result || null;
28966
+ }
28967
+ catch (error) {
28968
+ console.error('Error fetching sign info:', error.response?.data);
28969
+ return null;
28970
+ }
28971
+ }
28972
+ /**
28973
+ * 生成完整的认证头(包含 x-signInfo)
28974
+ * @param options 服务器选项
28975
+ * @returns 完整的认证头
28976
+ */
28977
+ async function generateCompleteHeaders(options) {
28978
+ const headers = {
28979
+ 'Content-Type': 'application/json',
28980
+ };
28981
+ const OPENAPI_AK = options.OPENAPI_AK || process.env.LCAP_OPENAPI_AK;
28982
+ const OPENAPI_SK = options.OPENAPI_SK || process.env.LCAP_OPENAPI_SK;
28983
+ // 如果没有提供 ak 和 sk,返回基础 headers
28984
+ if (!OPENAPI_AK || !OPENAPI_SK) {
28985
+ throw new Error(`配置了 useOPENAPI,但没有提供 OPENAPI_AK 和 OPENAPI_SK:
28986
+ - 可取消配置 useOPENAPI
28987
+ - 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK`);
28988
+ }
28989
+ // 生成基础认证头
28990
+ const baseHeaders = generateBaseHeaders(OPENAPI_AK, OPENAPI_SK);
28991
+ Object.assign(headers, baseHeaders);
28992
+ // 获取 signInfo
28993
+ const signInfo = await fetchSignInfo(options, headers);
28994
+ if (signInfo) {
28995
+ headers['x-signInfo'] = signInfo;
28996
+ }
28997
+ return headers;
28998
+ }
28999
+
29000
+ /**
29001
+ * 创建 Axios 实例
29002
+ * @param options 服务器选项,包含认证信息
29003
+ * @returns Axios 实例
29004
+ */
29005
+ async function createAxios(options) {
29006
+ // 如果需要鉴权,拼接 /openapi/v3/nasl;否则使用原始 URL
29007
+ const serverBaseURL = new URL(options.serverBaseURL).origin;
29008
+ const useOPENAPI = options.useOPENAPI || process.env.USE_LCAP_OPENAPI === 'true';
29009
+ const baseURL = useOPENAPI ? `${serverBaseURL}/openapi/v3/nasl` : `${serverBaseURL}/api/v1/nasl`;
29010
+ // 如果需要鉴权,生成完整的认证头;否则只使用基础 headers
29011
+ const headers = useOPENAPI ? await generateCompleteHeaders(options) : { 'Content-Type': 'application/json' };
29012
+ console.log('本次服务调用方为:', baseURL);
29013
+ const instance = axios.create({
28845
29014
  baseURL,
28846
- headers: {
28847
- 'Content-Type': 'application/json',
28848
- },
29015
+ headers,
28849
29016
  timeout: 120000,
28850
29017
  });
29018
+ const oldPost = instance.post;
29019
+ instance.post = async (url, data, config) => {
29020
+ return oldPost(url, data, config).then((res) => {
29021
+ const data = res.data;
29022
+ if (data.code !== 200)
29023
+ throw new Error(JSON.stringify(data));
29024
+ return res;
29025
+ }).catch((err) => {
29026
+ // console.log(err.response ? err.response.data : err);
29027
+ if (err.response) {
29028
+ throw new Error(JSON.stringify(err.response.data));
29029
+ }
29030
+ else {
29031
+ throw err;
29032
+ }
29033
+ });
29034
+ };
29035
+ return instance;
28851
29036
  }
28852
29037
 
28853
29038
  function truncate(str, maxLength) {
@@ -28861,13 +29046,11 @@ function truncate(str, maxLength) {
28861
29046
  async function compileApi(fullNaturalTS, options) {
28862
29047
  // 这里需要调用实际的编译服务接口
28863
29048
  // 示例实现:
28864
- const axios = createAxios(options.serverBaseURL);
29049
+ const axios = await createAxios(options);
28865
29050
  const res = await axios.post(`/compile/tsx?ideVersion=${options.ideVersion}&needAnnotation=true`, fullNaturalTS, {
28866
29051
  headers: { 'Content-Type': 'text/plain' },
28867
29052
  });
28868
29053
  const data = res.data;
28869
- if (data.code !== 200)
28870
- throw new Error(data.message);
28871
29054
  const { bundle } = data.result;
28872
29055
  const fileMap = bundle.frontendBundle.files;
28873
29056
  const files = Object.keys(fileMap).map((key) => {
@@ -28895,7 +29078,7 @@ window.backendApp = app;
28895
29078
  * TODO: 实现具体的 API 调用逻辑
28896
29079
  */
28897
29080
  async function checkApi(fullNaturalTS, options) {
28898
- const axios = createAxios(options.serverBaseURL);
29081
+ const axios = await createAxios(options);
28899
29082
  const res = await axios.post(`/check/tsx?ideVersion=${options.ideVersion}`, fullNaturalTS, {
28900
29083
  headers: { 'Content-Type': 'text/plain' },
28901
29084
  });
@@ -28913,7 +29096,7 @@ async function checkApi(fullNaturalTS, options) {
28913
29096
  async function createAppSyncApi(fullNaturalTS, options) {
28914
29097
  const url = new URL(options.serverBaseURL);
28915
29098
  const origin = url.origin + '/app-ai-creator';
28916
- const axios = createAxios(origin);
29099
+ const axios = await createAxios({ serverBaseURL: origin});
28917
29100
  try {
28918
29101
  const res = await axios.post('/api/createAppSync', {
28919
29102
  fullNaturalTS,
@@ -37796,10 +37979,7 @@ async function compile(entry, options) {
37796
37979
  logger.info('正在调用编译服务...');
37797
37980
  try {
37798
37981
  const fullNaturalTS = composeToString(collectedFiles);
37799
- const outputFiles = await compileApi(fullNaturalTS, {
37800
- serverBaseURL: config.serverBaseURL,
37801
- ideVersion: config.ideVersion,
37802
- });
37982
+ const outputFiles = await compileApi(fullNaturalTS, config);
37803
37983
  logger.success('编译成功!');
37804
37984
  // 写入输出文件
37805
37985
  for (const file of outputFiles) {
@@ -37846,10 +38026,7 @@ async function check(entry, options) {
37846
38026
  result = error.message.trim();
37847
38027
  }
37848
38028
  if (!result && fullNaturalTS) {
37849
- result = (await checkApi(fullNaturalTS, {
37850
- serverBaseURL: config.serverBaseURL,
37851
- ideVersion: config.ideVersion,
37852
- })).trim();
38029
+ result = (await checkApi(fullNaturalTS, config)).trim();
37853
38030
  }
37854
38031
  const checkResult = {
37855
38032
  success: !result,
@@ -38189,15 +38366,13 @@ async function createAppInIde(entry, options) {
38189
38366
  * 编译 NASL 代码
38190
38367
  * TODO: 实现具体的 API 调用逻辑
38191
38368
  */
38192
- async function transformJson2FilesApi(jsonContent, options) {
38369
+ async function transformJson2FilesApi(json, options) {
38193
38370
  // 示例实现:
38194
- const axios = createAxios(options.serverBaseURL);
38195
- const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`, jsonContent, {
38196
- headers: { 'Content-Type': 'text/plain' },
38371
+ const axios = await createAxios(options);
38372
+ const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`, json, {
38373
+ headers: { 'Content-Type': 'application/json' },
38197
38374
  });
38198
38375
  const data = res.data;
38199
- if (data.code !== 200)
38200
- throw new Error(data.message);
38201
38376
  return data.result;
38202
38377
  }
38203
38378
 
@@ -38237,14 +38412,19 @@ const transformFns = {
38237
38412
  const projectRoot = getProjectRoot();
38238
38413
  logger.info(`项目根目录: ${projectRoot}`);
38239
38414
  logger.info(`源代码目录: ${config.srcDir}`);
38415
+ if (!libExports.existsSync(config.srcDir)) {
38416
+ logger.error(`当前目录下 ${config.srcDir} 目录不存在,请先创建`);
38417
+ logger.exit(1);
38418
+ }
38240
38419
  let jsonContent = '';
38241
38420
  if (!entry) {
38242
38421
  logger.warn('没有指定 JSON 文件路径,按照默认 IDE 版本的基础模板转换');
38243
38422
  }
38244
38423
  else {
38245
38424
  jsonContent = libExports.readFileSync(entry, 'utf-8');
38425
+ logger.info(`读取到 JSON 文件: ${entry}`);
38246
38426
  }
38247
- const files = await transformJson2FilesApi(jsonContent, {
38427
+ const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, {
38248
38428
  serverBaseURL: config.serverBaseURL,
38249
38429
  ideVersion: config.ideVersion,
38250
38430
  });
@@ -38276,7 +38456,7 @@ async function transform(transformType, entry, options) {
38276
38456
  await transformFn(entry, options);
38277
38457
  }
38278
38458
 
38279
- var version = "0.1.16";
38459
+ var version = "0.1.17";
38280
38460
  var pkg = {
38281
38461
  version: version};
38282
38462
 
@@ -38385,8 +38565,8 @@ program
38385
38565
  // 如果不是 quiet 模式,询问用户确认
38386
38566
  if (!options?.quiet) {
38387
38567
  defaultLogger.newLine();
38388
- defaultLogger.info('即将在 IDE 中创建应用,此操作将调用远程服务。');
38389
- const confirmed = await askForConfirmation('是否继续?(y/n): ');
38568
+ defaultLogger.info('即将在 IDE 中创建新的应用,此操作将调用远程接口。');
38569
+ const confirmed = await askForConfirmation('请确认是否继续?(y/N): ');
38390
38570
  if (!confirmed) {
38391
38571
  defaultLogger.info('已取消操作');
38392
38572
  process.exit(0);
@@ -38402,7 +38582,7 @@ program
38402
38582
  });
38403
38583
  program
38404
38584
  .command('transform <transformType> [entry]')
38405
- .description('转换文件格式\n transformType: files2full (将 src 文件组合成 fullNaturalTS), json2files (将 JSON 转换为文件, 待实现), files2json (将 src 文件转换为 JSON)')
38585
+ .description('转换文件格式\n transformType: files2full (将 src 文件组合成 fullNaturalTS), json2files (将 JSON 转换为文件), files2json (将 src 文件转换为 JSON)')
38406
38586
  .option('-o, --output <outputPath>', '指定输出路径')
38407
38587
  .option('-v, --verbose', '显示详细信息,如依赖分析树')
38408
38588
  .action(async (transformType, entry, options) => {