@nasl/cli 0.2.2 → 0.3.0

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 (72) hide show
  1. package/dist/bin/nasl.mjs +591 -127
  2. package/dist/bin/nasl.mjs.map +1 -1
  3. package/dist/bin/naslc.mjs +322 -59
  4. package/dist/bin/naslc.mjs.map +1 -1
  5. package/dist/index.mjs +11683 -11254
  6. package/dist/index.mjs.map +1 -1
  7. package/out/apis/compileApi.d.ts.map +1 -1
  8. package/out/apis/compileApi.js +3 -2
  9. package/out/apis/compileApi.js.map +1 -1
  10. package/out/apis/dependencyApi.d.ts +29 -0
  11. package/out/apis/dependencyApi.d.ts.map +1 -0
  12. package/out/apis/dependencyApi.js +17 -0
  13. package/out/apis/dependencyApi.js.map +1 -0
  14. package/out/apis/index.d.ts +1 -0
  15. package/out/apis/index.d.ts.map +1 -1
  16. package/out/apis/index.js +1 -0
  17. package/out/apis/index.js.map +1 -1
  18. package/out/apis/openapi.d.ts +12 -0
  19. package/out/apis/openapi.d.ts.map +1 -1
  20. package/out/apis/openapi.js +15 -0
  21. package/out/apis/openapi.js.map +1 -1
  22. package/out/apis/transformApi.d.ts.map +1 -1
  23. package/out/apis/transformApi.js +2 -0
  24. package/out/apis/transformApi.js.map +1 -1
  25. package/out/bin/nasl.js +38 -2
  26. package/out/bin/nasl.js.map +1 -1
  27. package/out/commands/check.d.ts.map +1 -1
  28. package/out/commands/check.js +10 -1
  29. package/out/commands/check.js.map +1 -1
  30. package/out/commands/compile.d.ts.map +1 -1
  31. package/out/commands/compile.js +3 -2
  32. package/out/commands/compile.js.map +1 -1
  33. package/out/commands/dep.d.ts +4 -2
  34. package/out/commands/dep.d.ts.map +1 -1
  35. package/out/commands/dep.js +44 -2
  36. package/out/commands/dep.js.map +1 -1
  37. package/out/commands/index.d.ts +1 -0
  38. package/out/commands/index.d.ts.map +1 -1
  39. package/out/commands/index.js +1 -0
  40. package/out/commands/index.js.map +1 -1
  41. package/out/commands/install.d.ts +9 -0
  42. package/out/commands/install.d.ts.map +1 -0
  43. package/out/commands/install.js +123 -0
  44. package/out/commands/install.js.map +1 -0
  45. package/out/commands/transform.d.ts.map +1 -1
  46. package/out/commands/transform.js +3 -2
  47. package/out/commands/transform.js.map +1 -1
  48. package/out/constants/nasl-file-types.d.ts.map +1 -1
  49. package/out/constants/nasl-file-types.js +21 -0
  50. package/out/constants/nasl-file-types.js.map +1 -1
  51. package/out/services/compose.d.ts +8 -0
  52. package/out/services/compose.d.ts.map +1 -1
  53. package/out/services/compose.js +31 -1
  54. package/out/services/compose.js.map +1 -1
  55. package/out/services/resolve.d.ts +18 -0
  56. package/out/services/resolve.d.ts.map +1 -1
  57. package/out/services/resolve.js +208 -9
  58. package/out/services/resolve.js.map +1 -1
  59. package/out/types/api.d.ts +4 -0
  60. package/out/types/api.d.ts.map +1 -1
  61. package/out/types/config.d.ts +2 -0
  62. package/out/types/config.d.ts.map +1 -1
  63. package/out/types/config.js +1 -0
  64. package/out/types/config.js.map +1 -1
  65. package/out/utils/config.d.ts.map +1 -1
  66. package/out/utils/config.js +2 -0
  67. package/out/utils/config.js.map +1 -1
  68. package/out/utils/errorMapper.d.ts +14 -0
  69. package/out/utils/errorMapper.d.ts.map +1 -0
  70. package/out/utils/errorMapper.js +60 -0
  71. package/out/utils/errorMapper.js.map +1 -0
  72. package/package.json +1 -1
package/dist/bin/nasl.mjs CHANGED
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
  import require$$0$1, { EventEmitter } from 'events';
4
3
  import require$$1, { spawn, spawnSync } from 'child_process';
5
- import * as sysPath from 'path';
6
- import sysPath__default, { join } from 'path';
4
+ import * as path$1 from 'path';
5
+ import path__default, { join } from 'path';
7
6
  import require$$0$2, { promises, unwatchFile, watchFile, watch as watch$1, stat as stat$3 } from 'fs';
8
7
  import require$$4 from 'process';
9
8
  import require$$0$3 from 'constants';
@@ -1171,7 +1170,7 @@ function requireCommand () {
1171
1170
  hasRequiredCommand = 1;
1172
1171
  const EventEmitter = require$$0$1.EventEmitter;
1173
1172
  const childProcess = require$$1;
1174
- const path = sysPath__default;
1173
+ const path = path__default;
1175
1174
  const fs = require$$0$2;
1176
1175
  const process = require$$4;
1177
1176
 
@@ -4581,7 +4580,7 @@ var hasRequiredUtils$5;
4581
4580
  function requireUtils$5 () {
4582
4581
  if (hasRequiredUtils$5) return utils$7;
4583
4582
  hasRequiredUtils$5 = 1;
4584
- const path = sysPath__default;
4583
+ const path = path__default;
4585
4584
 
4586
4585
  // https://github.com/nodejs/node/issues/8987
4587
4586
  // https://github.com/libuv/libuv/pull/1088
@@ -4727,7 +4726,7 @@ function requireStat () {
4727
4726
  hasRequiredStat = 1;
4728
4727
 
4729
4728
  const fs = /*@__PURE__*/ requireFs$4();
4730
- const path = sysPath__default;
4729
+ const path = path__default;
4731
4730
  const u = requireUniversalify().fromPromise;
4732
4731
 
4733
4732
  function getStats (src, dest, opts) {
@@ -4931,7 +4930,7 @@ function requireCopy$1 () {
4931
4930
  hasRequiredCopy$1 = 1;
4932
4931
 
4933
4932
  const fs = /*@__PURE__*/ requireFs$4();
4934
- const path = sysPath__default;
4933
+ const path = path__default;
4935
4934
  const { mkdirs } = /*@__PURE__*/ requireMkdirs();
4936
4935
  const { pathExists } = /*@__PURE__*/ requirePathExists();
4937
4936
  const { utimesMillis } = /*@__PURE__*/ requireUtimes();
@@ -5114,7 +5113,7 @@ function requireCopySync () {
5114
5113
  hasRequiredCopySync = 1;
5115
5114
 
5116
5115
  const fs = requireGracefulFs();
5117
- const path = sysPath__default;
5116
+ const path = path__default;
5118
5117
  const mkdirsSync = /*@__PURE__*/ requireMkdirs().mkdirsSync;
5119
5118
  const utimesMillisSync = /*@__PURE__*/ requireUtimes().utimesMillisSync;
5120
5119
  const stat = /*@__PURE__*/ requireStat();
@@ -5334,7 +5333,7 @@ function requireEmpty () {
5334
5333
 
5335
5334
  const u = requireUniversalify().fromPromise;
5336
5335
  const fs = /*@__PURE__*/ requireFs$4();
5337
- const path = sysPath__default;
5336
+ const path = path__default;
5338
5337
  const mkdir = /*@__PURE__*/ requireMkdirs();
5339
5338
  const remove = /*@__PURE__*/ requireRemove();
5340
5339
 
@@ -5380,7 +5379,7 @@ function requireFile () {
5380
5379
  hasRequiredFile = 1;
5381
5380
 
5382
5381
  const u = requireUniversalify().fromPromise;
5383
- const path = sysPath__default;
5382
+ const path = path__default;
5384
5383
  const fs = /*@__PURE__*/ requireFs$4();
5385
5384
  const mkdir = /*@__PURE__*/ requireMkdirs();
5386
5385
 
@@ -5454,7 +5453,7 @@ function requireLink () {
5454
5453
  hasRequiredLink = 1;
5455
5454
 
5456
5455
  const u = requireUniversalify().fromPromise;
5457
- const path = sysPath__default;
5456
+ const path = path__default;
5458
5457
  const fs = /*@__PURE__*/ requireFs$4();
5459
5458
  const mkdir = /*@__PURE__*/ requireMkdirs();
5460
5459
  const { pathExists } = /*@__PURE__*/ requirePathExists();
@@ -5525,7 +5524,7 @@ function requireSymlinkPaths () {
5525
5524
  if (hasRequiredSymlinkPaths) return symlinkPaths_1;
5526
5525
  hasRequiredSymlinkPaths = 1;
5527
5526
 
5528
- const path = sysPath__default;
5527
+ const path = path__default;
5529
5528
  const fs = /*@__PURE__*/ requireFs$4();
5530
5529
  const { pathExists } = /*@__PURE__*/ requirePathExists();
5531
5530
 
@@ -5677,7 +5676,7 @@ function requireSymlink () {
5677
5676
  hasRequiredSymlink = 1;
5678
5677
 
5679
5678
  const u = requireUniversalify().fromPromise;
5680
- const path = sysPath__default;
5679
+ const path = path__default;
5681
5680
  const fs = /*@__PURE__*/ requireFs$4();
5682
5681
 
5683
5682
  const { mkdirs, mkdirsSync } = /*@__PURE__*/ requireMkdirs();
@@ -5923,7 +5922,7 @@ function requireOutputFile () {
5923
5922
 
5924
5923
  const u = requireUniversalify().fromPromise;
5925
5924
  const fs = /*@__PURE__*/ requireFs$4();
5926
- const path = sysPath__default;
5925
+ const path = path__default;
5927
5926
  const mkdir = /*@__PURE__*/ requireMkdirs();
5928
5927
  const pathExists = /*@__PURE__*/ requirePathExists().pathExists;
5929
5928
 
@@ -6025,7 +6024,7 @@ function requireMove$1 () {
6025
6024
  hasRequiredMove$1 = 1;
6026
6025
 
6027
6026
  const fs = /*@__PURE__*/ requireFs$4();
6028
- const path = sysPath__default;
6027
+ const path = path__default;
6029
6028
  const { copy } = /*@__PURE__*/ requireCopy();
6030
6029
  const { remove } = /*@__PURE__*/ requireRemove();
6031
6030
  const { mkdirp } = /*@__PURE__*/ requireMkdirs();
@@ -6092,7 +6091,7 @@ function requireMoveSync () {
6092
6091
  hasRequiredMoveSync = 1;
6093
6092
 
6094
6093
  const fs = requireGracefulFs();
6095
- const path = sysPath__default;
6094
+ const path = path__default;
6096
6095
  const copySync = /*@__PURE__*/ requireCopy().copySync;
6097
6096
  const removeSync = /*@__PURE__*/ requireRemove().removeSync;
6098
6097
  const mkdirpSync = /*@__PURE__*/ requireMkdirs().mkdirpSync;
@@ -6198,6 +6197,7 @@ const DEFAULT_CONFIG = {
6198
6197
  ideVersion: '4.4',
6199
6198
  srcDir: 'src',
6200
6199
  outDir: 'out',
6200
+ tenantName: 'defaulttenant',
6201
6201
  };
6202
6202
  /**
6203
6203
  * 配置文件名称
@@ -8192,15 +8192,15 @@ var dayjs = /*@__PURE__*/getDefaultExportFromCjs(dayjs_minExports);
8192
8192
 
8193
8193
  function fastLogToFile(entry, suffix, content) {
8194
8194
  if (process.env.NASL_CLI_LOG_DIR) {
8195
- const logDir = sysPath.resolve(process.env.NASL_CLI_LOG_DIR);
8195
+ const logDir = path$1.resolve(process.env.NASL_CLI_LOG_DIR);
8196
8196
  libExports.ensureDirSync(logDir);
8197
8197
  const timeInDir = (process.env.NASL_CLI_LOG_DIR.match(/\d{6,8}_(\d{6})-/)?.[1] || '00');
8198
8198
  const now = dayjs();
8199
8199
  const hourInDir = parseInt(timeInDir.slice(0, 2), 10);
8200
8200
  // 跨天则累加 24 小时
8201
8201
  const hourStr = (now.hour() >= hourInDir ? now.hour() : Math.ceil(hourInDir / 24) * 24 + now.hour()).toString().padStart(2, '0');
8202
- const entryName = sysPath.basename(Array.isArray(entry) ? entry[0] || '*' : entry).replace(/[\[\]\(\)\{\}\+\-\*\?\|\^\$\#\:\,\\\/\s]+/g, '_');
8203
- const filePath = sysPath.resolve(logDir, `${hourStr}${now.format('mmss_SSS')}-${entryName}-${suffix}`);
8202
+ const entryName = path$1.basename(Array.isArray(entry) ? entry[0] || '*' : entry).replace(/[\[\]\(\)\{\}\+\-\*\?\|\^\$\#\:\,\\\/\s]+/g, '_');
8203
+ const filePath = path$1.resolve(logDir, `${hourStr}${now.format('mmss_SSS')}-${entryName}-${suffix}`);
8204
8204
  libExports.outputFileSync(filePath, content);
8205
8205
  }
8206
8206
  }
@@ -8231,16 +8231,16 @@ class BaseLogger {
8231
8231
  }
8232
8232
  debugToFile(topic, ...args) {
8233
8233
  if (process.env.DEBUG_TO_FILE) {
8234
- const baseDir = sysPath.join(process.cwd(), '.nasl');
8234
+ const baseDir = path$1.join(process.cwd(), '.nasl');
8235
8235
  const currentHour = dayjs().format('YYYYMMDD_HH');
8236
8236
  const prevHour = dayjs().subtract(1, 'hour').format('YYYYMMDD_HH');
8237
8237
  let subdir = `${topic}_${currentHour}`;
8238
8238
  const prevSubdir = `${topic}_${prevHour}`;
8239
8239
  // 判断如果有上一个小时的 subdir,则自己汇聚到上一个小时的 subdir 中
8240
- if (libExports.existsSync(sysPath.join(baseDir, prevSubdir)))
8240
+ if (libExports.existsSync(path$1.join(baseDir, prevSubdir)))
8241
8241
  subdir = prevSubdir;
8242
8242
  const fileName = `${topic}_${dayjs().format('YYYYMMDD_HHmmss')}.log`;
8243
- const filePath = sysPath.join(baseDir, subdir, fileName);
8243
+ const filePath = path$1.join(baseDir, subdir, fileName);
8244
8244
  libExports.outputFileSync(filePath, args.join(' '));
8245
8245
  }
8246
8246
  }
@@ -8312,11 +8312,11 @@ function findConfigDir(startDir = process.cwd()) {
8312
8312
  let currentDir = startDir;
8313
8313
  // eslint-disable-next-line no-constant-condition
8314
8314
  while (true) {
8315
- const configPath = sysPath.join(currentDir, CONFIG_FILE_NAME);
8315
+ const configPath = path$1.join(currentDir, CONFIG_FILE_NAME);
8316
8316
  if (libExports.existsSync(configPath)) {
8317
8317
  return currentDir;
8318
8318
  }
8319
- const parentDir = sysPath.dirname(currentDir);
8319
+ const parentDir = path$1.dirname(currentDir);
8320
8320
  // 已经到达根目录
8321
8321
  if (parentDir === currentDir) {
8322
8322
  return null;
@@ -8333,7 +8333,7 @@ function loadConfig(configDir) {
8333
8333
  defaultLogger.error(`未找到配置文件 ${CONFIG_FILE_NAME},请先运行 nasl-init 初始化配置`);
8334
8334
  return defaultLogger.exit(1);
8335
8335
  }
8336
- const configPath = sysPath.join(dir, CONFIG_FILE_NAME);
8336
+ const configPath = path$1.join(dir, CONFIG_FILE_NAME);
8337
8337
  try {
8338
8338
  const content = libExports.readFileSync(configPath, 'utf-8');
8339
8339
  const config = JSON.parse(content);
@@ -8364,6 +8364,8 @@ function loadConfig(configDir) {
8364
8364
  config.OPENAPI_AK = process.env.LCAP_OPENAPI_AK;
8365
8365
  if (process.env.LCAP_OPENAPI_SK)
8366
8366
  config.OPENAPI_SK = process.env.LCAP_OPENAPI_SK;
8367
+ if (process.env.LCAP_TENANT_NAME)
8368
+ config.tenantName = process.env.LCAP_TENANT_NAME;
8367
8369
  // 如果启用了 OpenAPI,验证必需的 AK 和 SK
8368
8370
  if (config.useOPENAPI) {
8369
8371
  if (!config.OPENAPI_AK || !config.OPENAPI_SK) {
@@ -8410,7 +8412,7 @@ function readFileWithLog(filePath, logger) {
8410
8412
  */
8411
8413
  function writeFileWithLog(filePath, content, logger) {
8412
8414
  try {
8413
- const dir = sysPath.dirname(filePath);
8415
+ const dir = path$1.dirname(filePath);
8414
8416
  libExports.ensureDirSync(dir);
8415
8417
  libExports.writeFileSync(filePath, content, 'utf-8');
8416
8418
  }
@@ -8425,7 +8427,7 @@ function writeFileWithLog(filePath, content, logger) {
8425
8427
  */
8426
8428
  function init() {
8427
8429
  const cwd = process.cwd();
8428
- const configPath = sysPath.join(cwd, CONFIG_FILE_NAME);
8430
+ const configPath = path$1.join(cwd, CONFIG_FILE_NAME);
8429
8431
  // 检查配置文件是否已存在
8430
8432
  if (libExports.existsSync(configPath)) {
8431
8433
  defaultLogger.warn(`配置文件已存在: ${configPath}`);
@@ -8439,7 +8441,7 @@ function init() {
8439
8441
  defaultLogger.info('\n配置内容:');
8440
8442
  defaultLogger.info(JSON.stringify(DEFAULT_CONFIG, null, 2));
8441
8443
  // 创建源代码目录
8442
- const srcDirPath = sysPath.join(cwd, DEFAULT_CONFIG.srcDir);
8444
+ const srcDirPath = path$1.join(cwd, DEFAULT_CONFIG.srcDir);
8443
8445
  libExports.ensureDirSync(srcDirPath);
8444
8446
  defaultLogger.success(`源代码目录已创建: ${srcDirPath}`);
8445
8447
  defaultLogger.info('\n提示:');
@@ -20431,7 +20433,7 @@ function requireMimeTypes () {
20431
20433
  */
20432
20434
 
20433
20435
  var db = requireMimeDb();
20434
- var extname = sysPath__default.extname;
20436
+ var extname = path__default.extname;
20435
20437
 
20436
20438
  /**
20437
20439
  * Module variables.
@@ -22172,7 +22174,7 @@ function requireForm_data () {
22172
22174
 
22173
22175
  var CombinedStream = requireCombined_stream();
22174
22176
  var util = require$$0$4;
22175
- var path = sysPath__default;
22177
+ var path = path__default;
22176
22178
  var http = require$$3;
22177
22179
  var https = require$$4$1;
22178
22180
  var parseUrl = require$$0$6.parse;
@@ -29116,6 +29118,20 @@ async function generateCompleteHeaders(options) {
29116
29118
  }
29117
29119
  return headers;
29118
29120
  }
29121
+ /**
29122
+ * 构建请求 headers
29123
+ * 如果 ServerOptions.useOPENAPI 为 true, 意味着接口内部是走的集群,反之则需要走 openapi 调用(本地或者server的场景,透传options相关配置)
29124
+ */
29125
+ function buildNaslHeaders(options) {
29126
+ return {
29127
+ 'Content-Type': 'text/plain',
29128
+ 'X-Server-Base-URL': options.serverBaseURL,
29129
+ ...(options.OPENAPI_AK && { 'X-OPENAPI-AK': options.OPENAPI_AK }),
29130
+ ...(options.OPENAPI_SK && { 'X-OPENAPI-SK': options.OPENAPI_SK }),
29131
+ ...(options.tenantName && { 'X-Tenant-Name': options.tenantName }),
29132
+ ...(options.useOPENAPI !== undefined && { 'X-Use-OPENAPI': String(!options.useOPENAPI) }),
29133
+ };
29134
+ }
29119
29135
 
29120
29136
  /**
29121
29137
  * 创建 Axios 实例
@@ -29167,7 +29183,7 @@ async function compileApi(fullNaturalTS, options) {
29167
29183
  // 示例实现:
29168
29184
  const axios = await createAxios(options);
29169
29185
  const res = await axios.post(`/compile/tsx?ideVersion=${options.ideVersion}&needAnnotation=true`, fullNaturalTS, {
29170
- headers: { 'Content-Type': 'text/plain' },
29186
+ headers: buildNaslHeaders(options),
29171
29187
  });
29172
29188
  const data = res.data;
29173
29189
  const { bundle } = data.result;
@@ -29199,7 +29215,7 @@ window.backendApp = app;
29199
29215
  async function checkApi(fullNaturalTS, options) {
29200
29216
  const axios = await createAxios(options);
29201
29217
  const res = await axios.post(`/check/tsx?ideVersion=${options.ideVersion}`, fullNaturalTS, {
29202
- headers: { 'Content-Type': 'text/plain' },
29218
+ headers: buildNaslHeaders(options),
29203
29219
  });
29204
29220
  const result = res.data.result;
29205
29221
  const errors = (result.errors || []);
@@ -29248,6 +29264,17 @@ async function createAppSyncApi(fullNaturalTS, options) {
29248
29264
  }
29249
29265
  }
29250
29266
 
29267
+ async function installDependenciesApi(dependenciesJSON, options) {
29268
+ const axios = await createAxios(options);
29269
+ const res = await axios.post(`/load/dependencies?ideVersion=${options.ideVersion}`, dependenciesJSON, {
29270
+ headers: buildNaslHeaders(options),
29271
+ });
29272
+ const data = res.data;
29273
+ if (data.code !== 200)
29274
+ throw new Error(data.message);
29275
+ return data.result;
29276
+ }
29277
+
29251
29278
  function createSorter() {
29252
29279
  const priorityOrder = ['app.dataSources', 'app.enums', 'app.structures', 'app.logics', 'app.frontendTypes'];
29253
29280
  // 获取优先级索引
@@ -29326,7 +29353,10 @@ function validateNormalFile(file, nameFromPath, namespace, errors) {
29326
29353
  function composeToString(files) {
29327
29354
  files.sort((a, b) => sorter(a.path, b.path));
29328
29355
  const errors = [];
29356
+ let currentLine = 1;
29329
29357
  const result = files.map((file) => {
29358
+ // 记录这个文件的开始行号
29359
+ file.startLine = currentLine;
29330
29360
  const arr = file.path.split('.');
29331
29361
  const ext = arr.pop();
29332
29362
  const nameFromPath = arr.pop();
@@ -29352,7 +29382,14 @@ function composeToString(files) {
29352
29382
  else if (isThemeCss) {
29353
29383
  content = ` $theme\`${content}\`;`;
29354
29384
  }
29355
- return `namespace ${namespace} {\n${content}\n}\n`;
29385
+ const fileContent = `namespace ${namespace} {\n${content}\n}\n`;
29386
+ // 计算这个文件占用的行数(末尾 \n 导致 split 多一个空元素,减 1 得到实际行数)
29387
+ const lineCount = fileContent.split('\n').length - 1;
29388
+ // 记录这个文件的结束行号
29389
+ file.endLine = currentLine + lineCount - 1;
29390
+ // +1 是 join('\n') 在文件之间插入的换行符
29391
+ currentLine = file.endLine + 2;
29392
+ return fileContent;
29356
29393
  })
29357
29394
  .join('\n');
29358
29395
  if (errors.length > 0) {
@@ -29360,6 +29397,25 @@ function composeToString(files) {
29360
29397
  }
29361
29398
  return result;
29362
29399
  }
29400
+ /**
29401
+ * 将依赖信息拼接到 fullNaturalTS 顶部
29402
+ * @param fullNaturalTS 组合后的 NASL 代码
29403
+ * @param dependencies mergedDependencies 对象或 JSON 字符串
29404
+ * @returns 拼接后的完整内容
29405
+ */
29406
+ function prependDependencies(fullNaturalTS, dependencies) {
29407
+ if (!dependencies)
29408
+ return fullNaturalTS;
29409
+ const jsonStr = JSON.stringify(dependencies, null, 2);
29410
+ const header = `/*
29411
+ -----------app.dependencies.json7xdhjutehm.start
29412
+ ${jsonStr}
29413
+ -----------app.dependencies.json7xdhjutehm.end
29414
+ */
29415
+
29416
+ `;
29417
+ return header + fullNaturalTS;
29418
+ }
29363
29419
 
29364
29420
  var globby$1 = {exports: {}};
29365
29421
 
@@ -29617,7 +29673,7 @@ function requirePath () {
29617
29673
  Object.defineProperty(path, "__esModule", { value: true });
29618
29674
  path.convertPosixPathToPattern = path.convertWindowsPathToPattern = path.convertPathToPattern = path.escapePosixPath = path.escapeWindowsPath = path.escape = path.removeLeadingDotSegment = path.makeAbsolute = path.unixify = void 0;
29619
29675
  const os = require$$0$5;
29620
- const path$1 = sysPath__default;
29676
+ const path$1 = path__default;
29621
29677
  const IS_WINDOWS_PLATFORM = os.platform() === 'win32';
29622
29678
  const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\
29623
29679
  /**
@@ -29882,7 +29938,7 @@ function requireGlobParent () {
29882
29938
  hasRequiredGlobParent = 1;
29883
29939
 
29884
29940
  var isGlob = requireIsGlob();
29885
- var pathPosixDirname = sysPath__default.posix.dirname;
29941
+ var pathPosixDirname = path__default.posix.dirname;
29886
29942
  var isWin32 = require$$0$5.platform() === 'win32';
29887
29943
 
29888
29944
  var slash = '/';
@@ -31454,7 +31510,7 @@ function requireConstants$1 () {
31454
31510
  if (hasRequiredConstants$1) return constants$1;
31455
31511
  hasRequiredConstants$1 = 1;
31456
31512
 
31457
- const path = sysPath__default;
31513
+ const path = path__default;
31458
31514
  const WIN_SLASH = '\\\\/';
31459
31515
  const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
31460
31516
 
@@ -31641,7 +31697,7 @@ function requireUtils$2 () {
31641
31697
  hasRequiredUtils$2 = 1;
31642
31698
  (function (exports$1) {
31643
31699
 
31644
- const path = sysPath__default;
31700
+ const path = path__default;
31645
31701
  const win32 = process.platform === 'win32';
31646
31702
  const {
31647
31703
  REGEX_BACKSLASH,
@@ -33212,7 +33268,7 @@ function requirePicomatch$1 () {
33212
33268
  if (hasRequiredPicomatch$1) return picomatch_1;
33213
33269
  hasRequiredPicomatch$1 = 1;
33214
33270
 
33215
- const path = sysPath__default;
33271
+ const path = path__default;
33216
33272
  const scan = requireScan();
33217
33273
  const parse = requireParse();
33218
33274
  const utils = requireUtils$2();
@@ -34055,7 +34111,7 @@ function requirePattern () {
34055
34111
  hasRequiredPattern = 1;
34056
34112
  Object.defineProperty(pattern, "__esModule", { value: true });
34057
34113
  pattern.isAbsolute = pattern.partitionAbsoluteAndRelative = pattern.removeDuplicateSlashes = pattern.matchAny = pattern.convertPatternsToRe = pattern.makeRe = pattern.getPatternParts = pattern.expandBraceExpansion = pattern.expandPatternsWithBraceExpansion = pattern.isAffectDepthOfReadingPattern = pattern.endsWithSlashGlobStar = pattern.hasGlobStar = pattern.getBaseDirectory = pattern.isPatternRelatedToParentDirectory = pattern.getPatternsOutsideCurrentDirectory = pattern.getPatternsInsideCurrentDirectory = pattern.getPositivePatterns = pattern.getNegativePatterns = pattern.isPositivePattern = pattern.isNegativePattern = pattern.convertToNegativePattern = pattern.convertToPositivePattern = pattern.isDynamicPattern = pattern.isStaticPattern = void 0;
34058
- const path = sysPath__default;
34114
+ const path = path__default;
34059
34115
  const globParent = requireGlobParent();
34060
34116
  const micromatch = requireMicromatch();
34061
34117
  const GLOBSTAR = '**';
@@ -35009,7 +35065,7 @@ function requireSettings$2 () {
35009
35065
  if (hasRequiredSettings$2) return settings$2;
35010
35066
  hasRequiredSettings$2 = 1;
35011
35067
  Object.defineProperty(settings$2, "__esModule", { value: true });
35012
- const path = sysPath__default;
35068
+ const path = path__default;
35013
35069
  const fsStat = requireOut$3();
35014
35070
  const fs = requireFs();
35015
35071
  class Settings {
@@ -35771,7 +35827,7 @@ function requireSettings$1 () {
35771
35827
  if (hasRequiredSettings$1) return settings$1;
35772
35828
  hasRequiredSettings$1 = 1;
35773
35829
  Object.defineProperty(settings$1, "__esModule", { value: true });
35774
- const path = sysPath__default;
35830
+ const path = path__default;
35775
35831
  const fsScandir = requireOut$2();
35776
35832
  class Settings {
35777
35833
  constructor(_options = {}) {
@@ -35847,7 +35903,7 @@ function requireReader () {
35847
35903
  if (hasRequiredReader) return reader;
35848
35904
  hasRequiredReader = 1;
35849
35905
  Object.defineProperty(reader, "__esModule", { value: true });
35850
- const path = sysPath__default;
35906
+ const path = path__default;
35851
35907
  const fsStat = requireOut$3();
35852
35908
  const utils = requireUtils$1();
35853
35909
  class Reader {
@@ -36320,7 +36376,7 @@ function requireProvider () {
36320
36376
  if (hasRequiredProvider) return provider;
36321
36377
  hasRequiredProvider = 1;
36322
36378
  Object.defineProperty(provider, "__esModule", { value: true });
36323
- const path = sysPath__default;
36379
+ const path = path__default;
36324
36380
  const deep_1 = requireDeep();
36325
36381
  const entry_1 = requireEntry$1();
36326
36382
  const error_1 = requireError();
@@ -36760,7 +36816,7 @@ var hasRequiredDirGlob;
36760
36816
  function requireDirGlob () {
36761
36817
  if (hasRequiredDirGlob) return dirGlob.exports;
36762
36818
  hasRequiredDirGlob = 1;
36763
- const path = sysPath__default;
36819
+ const path = path__default;
36764
36820
  const pathType = requirePathType();
36765
36821
 
36766
36822
  const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];
@@ -37510,7 +37566,7 @@ function requireGitignore () {
37510
37566
  hasRequiredGitignore = 1;
37511
37567
  const {promisify} = require$$0$4;
37512
37568
  const fs = require$$0$2;
37513
- const path = sysPath__default;
37569
+ const path = path__default;
37514
37570
  const fastGlob = requireOut();
37515
37571
  const gitIgnore = requireIgnore();
37516
37572
  const slash = requireSlash();
@@ -37942,6 +37998,27 @@ const NASL_FILE_TYPES = [
37942
37998
  codeRefPattern: 'extensions\\.\\w+(?:\\.\\w+)*',
37943
37999
  extension: 'ts',
37944
38000
  },
38001
+ {
38002
+ name: 'apis',
38003
+ description: 'API',
38004
+ fileNamePattern: 'apis\\.\\w+\\.ts',
38005
+ codeRefPattern: 'apis\\.\\w+(?:\\.\\w+)*',
38006
+ extension: 'ts',
38007
+ },
38008
+ {
38009
+ name: 'connectors',
38010
+ description: '连接器',
38011
+ fileNamePattern: 'connectors\\.\\w+\\.ts',
38012
+ codeRefPattern: 'connectors\\.\\w+(?:\\.\\w+)*',
38013
+ extension: 'ts',
38014
+ },
38015
+ {
38016
+ name: 'uilibs',
38017
+ description: 'UI 库',
38018
+ fileNamePattern: 'uilibs\\.\\w+\\.ts',
38019
+ codeRefPattern: 'uilibs\\.\\w+(?:\\.\\w+)*',
38020
+ extension: 'ts',
38021
+ },
37945
38022
  ];
37946
38023
  /**
37947
38024
  * 获取用于验证文件名的正则表达式数组
@@ -37974,10 +38051,15 @@ const codeRefPatterns = getCodeRefPatterns();
37974
38051
  */
37975
38052
  function isKnownFileType(filePath) {
37976
38053
  // 提取文件名
37977
- const fileName = sysPath.basename(filePath);
38054
+ const fileName = path$1.basename(filePath);
37978
38055
  return fileNamePatterns.some((pattern) => pattern.test(fileName));
37979
38056
  }
37980
38057
 
38058
+ /** 这些前缀的依赖不再向下递归查找 */
38059
+ const EXTERNAL_DEP_PREFIXES = ['extensions.', 'connectors.', 'apis.', 'uilibs.'];
38060
+ function shouldSkipDependencyTraversal(depPath) {
38061
+ return EXTERNAL_DEP_PREFIXES.some((prefix) => depPath.startsWith(prefix));
38062
+ }
37981
38063
  /**
37982
38064
  * 扫描目录下的所有 NASL 文件
37983
38065
  */
@@ -38043,6 +38125,15 @@ function extractDeps(content) {
38043
38125
  if (/^extensions\.\w+\./.test(dep)) {
38044
38126
  dep = dep.replace(/^(extensions\.\w+)\..+$/, '$1');
38045
38127
  }
38128
+ if (/^apis\.\w+\./.test(dep)) {
38129
+ dep = dep.replace(/^(apis\.\w+)\..+$/, '$1');
38130
+ }
38131
+ if (/^connectors\.\w+\./.test(dep)) {
38132
+ dep = dep.replace(/^(connectors\.\w+)\..+$/, '$1');
38133
+ }
38134
+ if (/^uilibs\.\w+\./.test(dep)) {
38135
+ dep = dep.replace(/^(uilibs\.\w+)\..+$/, '$1');
38136
+ }
38046
38137
  // 跳过不合法的实体引用(实体后还有字段的情况)
38047
38138
  if (/app\.dataSources\.\w+\.entities\.\w+\.\w+$/.test(dep)) {
38048
38139
  continue;
@@ -38054,6 +38145,152 @@ function extractDeps(content) {
38054
38145
  }
38055
38146
  return Array.from(deps);
38056
38147
  }
38148
+ /**
38149
+ * 从文件内容中提取外部依赖引用(extensions/connectors/apis/uilibs)
38150
+ * 用于构建 externalDependencies
38151
+ */
38152
+ function extractExternalRefs(content) {
38153
+ const refs = {
38154
+ extensions: new Set(),
38155
+ connectors: new Set(),
38156
+ uilibs: new Set(),
38157
+ apis: new Map(),
38158
+ };
38159
+ const processedContent = content
38160
+ .replace(/\/\/.*$/gm, '')
38161
+ .replace(/\/\*[\s\S]*?\*\//g, '')
38162
+ .replace(/'(?:[^'\\]|\\.)*'/g, '')
38163
+ .replace(/"(?:[^"\\]|\\.)*"/g, '');
38164
+ // extensions.xxx, connectors.xxx, uilibs.xxx
38165
+ for (const m of processedContent.matchAll(/\b(extensions|connectors|uilibs)\.(\w+)/g)) {
38166
+ const [, kind, name] = m;
38167
+ if (kind === 'extensions')
38168
+ refs.extensions.add(name);
38169
+ else if (kind === 'connectors')
38170
+ refs.connectors.add(name);
38171
+ else
38172
+ refs.uilibs.add(name);
38173
+ }
38174
+ // apis.xxx.interfaces.yyy
38175
+ for (const m of processedContent.matchAll(/\bapis\.(\w+)\.interfaces\.(\w+)/g)) {
38176
+ const [, apiName, ifaceName] = m;
38177
+ if (!refs.apis.has(apiName))
38178
+ refs.apis.set(apiName, new Set());
38179
+ refs.apis.get(apiName).add(ifaceName);
38180
+ }
38181
+ return refs;
38182
+ }
38183
+ function mergeExternalRefs(into, from) {
38184
+ from.extensions.forEach((x) => into.extensions.add(x));
38185
+ from.connectors.forEach((x) => into.connectors.add(x));
38186
+ from.uilibs.forEach((x) => into.uilibs.add(x));
38187
+ from.apis.forEach((interfaces, apiName) => {
38188
+ if (!into.apis.has(apiName))
38189
+ into.apis.set(apiName, new Set());
38190
+ interfaces.forEach((i) => into.apis.get(apiName).add(i));
38191
+ });
38192
+ }
38193
+ /**
38194
+ * 加载 app.dependencies.json(不存在则返回空对象)
38195
+ */
38196
+ function loadAppDependencies(srcDir) {
38197
+ const p = path$1.join(srcDir, 'app.dependencies.json');
38198
+ if (!libExports.existsSync(p))
38199
+ return {};
38200
+ try {
38201
+ return libExports.readJsonSync(p);
38202
+ }
38203
+ catch {
38204
+ return {};
38205
+ }
38206
+ }
38207
+ /**
38208
+ * 加载并合并 app.dependencies.json 与 potential.dependencies.json
38209
+ * 用于版本号查找:先查 app,再查 potential
38210
+ */
38211
+ function loadMergedDependencies(srcDir) {
38212
+ const load = (file) => {
38213
+ const p = path$1.join(srcDir, file);
38214
+ if (!libExports.existsSync(p))
38215
+ return null;
38216
+ try {
38217
+ return libExports.readJsonSync(p);
38218
+ }
38219
+ catch {
38220
+ return null;
38221
+ }
38222
+ };
38223
+ const app = load('app.dependencies.json') ?? {};
38224
+ const potential = load('potential.dependencies.json') ?? {};
38225
+ const merged = {};
38226
+ for (const key of ['extensions', 'uilibs', 'connectors', 'apis']) {
38227
+ merged[key] = { ...(potential[key] ?? {}), ...(app[key] ?? {}) };
38228
+ }
38229
+ return merged;
38230
+ }
38231
+ /**
38232
+ * 将 externalDependencies 补充到 app.dependencies.json(只增不减)
38233
+ */
38234
+ function mergeDependenciesIntoApp(existing, incoming) {
38235
+ const result = {};
38236
+ for (const key of ['extensions', 'uilibs', 'connectors']) {
38237
+ const existingRecord = existing[key] ?? {};
38238
+ const incomingRecord = incoming[key] ?? {};
38239
+ result[key] = { ...incomingRecord, ...existingRecord };
38240
+ }
38241
+ result.apis = {};
38242
+ if (existing.apis || incoming.apis) {
38243
+ const allApiNames = new Set([...Object.keys(existing.apis ?? {}), ...Object.keys(incoming.apis ?? {})]);
38244
+ for (const apiName of allApiNames) {
38245
+ const existingInterfaces = existing.apis?.[apiName] ?? [];
38246
+ const incomingInterfaces = incoming.apis?.[apiName] ?? [];
38247
+ result.apis[apiName] = [...new Set([...existingInterfaces, ...incomingInterfaces])].sort();
38248
+ }
38249
+ }
38250
+ return result;
38251
+ }
38252
+ /**
38253
+ * 根据收集的外部引用和版本配置,构建 DependenciesJSON
38254
+ * extensions/connectors/uilibs 需要版本号,apis 只需 interfaces 数组
38255
+ */
38256
+ function buildExternalDependencies(refs, mergedDeps, logger) {
38257
+ const result = {};
38258
+ const errors = [];
38259
+ for (const name of refs.extensions) {
38260
+ const ver = mergedDeps.extensions?.[name];
38261
+ if (!ver) {
38262
+ errors.push(`extensions.${name} 未在 app.dependencies.json 或 potential.dependencies.json 中找到版本号`);
38263
+ }
38264
+ else {
38265
+ (result.extensions ?? (result.extensions = {}))[name] = ver;
38266
+ }
38267
+ }
38268
+ for (const name of refs.connectors) {
38269
+ const ver = mergedDeps.connectors?.[name];
38270
+ if (!ver) {
38271
+ errors.push(`connectors.${name} 未在 app.dependencies.json 或 potential.dependencies.json 中找到版本号`);
38272
+ }
38273
+ else {
38274
+ (result.connectors ?? (result.connectors = {}))[name] = ver;
38275
+ }
38276
+ }
38277
+ for (const name of refs.uilibs) {
38278
+ const ver = mergedDeps.uilibs?.[name];
38279
+ if (!ver) {
38280
+ errors.push(`uilibs.${name} 未在 app.dependencies.json 或 potential.dependencies.json 中找到版本号`);
38281
+ }
38282
+ else {
38283
+ (result.uilibs ?? (result.uilibs = {}))[name] = ver;
38284
+ }
38285
+ }
38286
+ // result.uilibs = mergedDeps.uilibs; // 临时先都加上去
38287
+ refs.apis.forEach((interfaces, apiName) => {
38288
+ (result.apis ?? (result.apis = {}))[apiName] = Array.from(interfaces).sort();
38289
+ });
38290
+ if (errors.length > 0)
38291
+ throw new Error(errors.join('\n'));
38292
+ return result;
38293
+ }
38057
38294
  /**
38058
38295
  * 提取页面文件的签名,移除函数体
38059
38296
  * @param content 页面文件内容
@@ -38076,7 +38313,7 @@ function replaceViewAsSignature(content, hasSubViews = false) {
38076
38313
  * @returns 文件信息和新发现的依赖文件列表
38077
38314
  */
38078
38315
  function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFileMap, depNotFoundList, logger, verbose) {
38079
- const absoluteFilePath = sysPath.join(srcDir, pathRelativeToSrc);
38316
+ const absoluteFilePath = path$1.join(srcDir, pathRelativeToSrc);
38080
38317
  const fileInfo = { path: pathRelativeToSrc, content: '' };
38081
38318
  try {
38082
38319
  fileInfo.content = readFileWithLog(absoluteFilePath, logger);
@@ -38106,7 +38343,9 @@ function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFil
38106
38343
  }
38107
38344
  processedFileMap.set(pathRelativeToSrc, fileInfo);
38108
38345
  // 提取依赖
38109
- const deps = extractDeps(fileInfo.content);
38346
+ // extensions/connectors/apis/uilibs 作为叶子节点,不再向下递归查找依赖
38347
+ const isExternalDep = shouldSkipDependencyTraversal(pathRelativeToSrc);
38348
+ const deps = isExternalDep ? [] : extractDeps(fileInfo.content);
38110
38349
  // 查找依赖文件
38111
38350
  if (isView) {
38112
38351
  const pathArr = pathRelativeToSrc.split('.');
@@ -38121,24 +38360,30 @@ function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFil
38121
38360
  } while (true);
38122
38361
  }
38123
38362
  if (verbose || process.env.DEBUG) {
38124
- console.log(`${isEntryFile ? chalk.magenta('[Entry]') : chalk.green('[ Dep ]')} ${pathRelativeToSrc}${deps.map((dep) => `\n├── ${dep}`).join('')}`);
38363
+ console.log(`${isEntryFile ? chalk.magenta('[Entry]') : isExternalDep ? chalk.blue('[ External Dep ]') : chalk.green('[ Dep ]')} ${pathRelativeToSrc}${deps.map((dep) => `\n├── ${dep}`).join('')}`);
38125
38364
  }
38126
38365
  return {
38127
38366
  fileInfo,
38128
38367
  newDeps: deps.filter((dep) => !processedFileMap.has(dep)),
38368
+ isExternalDep,
38129
38369
  };
38130
38370
  }
38131
38371
  /**
38132
38372
  * 收集入口文件及其依赖
38133
38373
  * @param patterns 入口文件的 glob 模式数组
38134
38374
  * @param srcDir 源代码目录绝对路径
38135
- * @param representation NASL 表示形式
38136
- * @returns 文件信息列表
38375
+ * @returns 文件信息列表和外部依赖引用
38137
38376
  */
38138
38377
  async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38139
38378
  const processedFileMap = new Map(); // 已处理的文件(相对路径)
38140
38379
  const filesToProcess = []; // 待处理的文件队列
38141
38380
  const result = [];
38381
+ const externalRefs = {
38382
+ extensions: new Set(),
38383
+ connectors: new Set(),
38384
+ uilibs: new Set(),
38385
+ apis: new Map(),
38386
+ };
38142
38387
  // 1. 使用 glob 匹配入口文件
38143
38388
  logger.newLine();
38144
38389
  logger.info(`匹配入口文件: ${patterns.join(', ')}`);
@@ -38148,15 +38393,15 @@ async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38148
38393
  throw new Error('未找到匹配的入口文件');
38149
38394
  }
38150
38395
  logger.info(`找到 ${matchedFiles.length} 个入口文件`);
38151
- const absoluteSrcDir = sysPath.resolve(srcDir);
38396
+ const absoluteSrcDir = path$1.resolve(srcDir);
38152
38397
  const matchedFileSet = new Set();
38153
38398
  matchedFiles.forEach((pathRelativeToRoot) => {
38154
38399
  // 统一使用相对于 src 的路径
38155
- const absoluteFilePath = sysPath.resolve(projectRoot, pathRelativeToRoot);
38400
+ const absoluteFilePath = path$1.resolve(projectRoot, pathRelativeToRoot);
38156
38401
  // 判断 file 是否超出 srcDir 目录(支持相对路径和绝对路径)
38157
38402
  if (!absoluteFilePath.startsWith(absoluteSrcDir))
38158
38403
  throw new Error(`入口文件 ${absoluteFilePath} 超出了源代码目录 ${srcDir}`);
38159
- const pathRelativeToSrc = sysPath.relative(srcDir, absoluteFilePath);
38404
+ const pathRelativeToSrc = path$1.relative(srcDir, absoluteFilePath);
38160
38405
  filesToProcess.push(pathRelativeToSrc);
38161
38406
  matchedFileSet.add(pathRelativeToSrc);
38162
38407
  });
@@ -38174,8 +38419,9 @@ async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38174
38419
  continue;
38175
38420
  }
38176
38421
  try {
38177
- const { fileInfo, newDeps } = processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFileMap, depNotFoundList, logger, verbose);
38178
- result.push(fileInfo);
38422
+ const { fileInfo, newDeps, isExternalDep } = processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFileMap, depNotFoundList, logger, verbose);
38423
+ !isExternalDep && result.push(fileInfo);
38424
+ mergeExternalRefs(externalRefs, extractExternalRefs(fileInfo.content));
38179
38425
  filesToProcess.push(...newDeps);
38180
38426
  }
38181
38427
  catch (error) {
@@ -38197,7 +38443,7 @@ ${depNotFoundList.map((dep) => `- ${dep}\n`).join('')}
38197
38443
  }
38198
38444
  if (errorMessage)
38199
38445
  throw new Error(errorMessage);
38200
- return result;
38446
+ return { files: result, externalRefs };
38201
38447
  }
38202
38448
  /**
38203
38449
  * 解析需要处理的文件(包含配置加载和目录设置)
@@ -38205,12 +38451,13 @@ ${depNotFoundList.map((dep) => `- ${dep}\n`).join('')}
38205
38451
  * @returns 文件信息、配置和目录信息
38206
38452
  */
38207
38453
  async function resolveNASLFiles(entry, logger, depMode, verbose) {
38454
+ depMode = true; // !!ensure depMode is true
38208
38455
  // 加载配置
38209
38456
  const config = loadConfig();
38210
38457
  const projectRoot = getProjectRoot();
38211
38458
  logger.info(`项目根目录: ${projectRoot}`);
38212
38459
  logger.info(`源代码目录: ${config.srcDir}`);
38213
- const srcDir = sysPath.join(projectRoot, config.srcDir);
38460
+ const srcDir = path$1.join(projectRoot, config.srcDir);
38214
38461
  // 收集需要处理的文件
38215
38462
  let collectedFiles = [];
38216
38463
  if (Array.isArray(entry) && !entry.length) {
@@ -38219,10 +38466,12 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38219
38466
  config,
38220
38467
  projectRoot,
38221
38468
  srcDir,
38469
+ externalDependencies: undefined,
38222
38470
  };
38223
38471
  }
38472
+ let externalRefs = null;
38224
38473
  if (!entry && depMode)
38225
- entry = 'src/**/*.{ts,tsx}';
38474
+ entry = 'src/**/app.*.{ts,tsx,css}';
38226
38475
  if (entry) {
38227
38476
  // 检查入口路径是否在源代码目录外面
38228
38477
  // if (entry.startsWith('..')) throw new Error('入口路径不能在源代码目录外面');
@@ -38230,7 +38479,9 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38230
38479
  // 具体路径也转换为 glob 模式统一处理
38231
38480
  // 使用依赖分析收集文件
38232
38481
  try {
38233
- collectedFiles = await collectDeps(Array.isArray(entry) ? entry : [entry], projectRoot, srcDir, logger, depMode || verbose);
38482
+ const { files, externalRefs: refs } = await collectDeps(Array.isArray(entry) ? entry : [entry], projectRoot, srcDir, logger, depMode || verbose);
38483
+ collectedFiles = files;
38484
+ externalRefs = refs;
38234
38485
  }
38235
38486
  catch (error) {
38236
38487
  logger.error(`依赖分析失败:\n${error.message}`);
@@ -38244,13 +38495,21 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38244
38495
  filePaths.sort(sorter);
38245
38496
  collectedFiles = filePaths.map((filePath) => ({
38246
38497
  path: filePath,
38247
- content: readFileWithLog(sysPath.join(srcDir, filePath), logger),
38498
+ content: readFileWithLog(path$1.join(srcDir, filePath), logger),
38248
38499
  }));
38249
38500
  if (collectedFiles.length === 0) {
38250
38501
  logger.warn('未找到 NASL 文件');
38251
38502
  logger.exit(1);
38252
38503
  }
38253
38504
  logger.info(`找到 ${collectedFiles.length} 个 NASL 文件`);
38505
+ // 全量扫描时也从文件中提取外部依赖引用
38506
+ externalRefs = {
38507
+ extensions: new Set(),
38508
+ connectors: new Set(),
38509
+ uilibs: new Set(),
38510
+ apis: new Map(),
38511
+ };
38512
+ collectedFiles.forEach((f) => mergeExternalRefs(externalRefs, extractExternalRefs(f.content)));
38254
38513
  }
38255
38514
  // 统一过滤掉不支持的文件类型
38256
38515
  const filteredFiles = [];
@@ -38262,11 +38521,24 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38262
38521
  logger.warn(`跳过不支持的文件类型: ${file.path}`);
38263
38522
  }
38264
38523
  });
38524
+ // 从分析中构建 externalDependencies(版本号从 app.dependencies.json / potential.dependencies.json 获取)
38525
+ let externalDependencies;
38526
+ let mergedDependencies;
38527
+ if (externalRefs && (externalRefs.extensions.size > 0 || externalRefs.connectors.size > 0 || externalRefs.uilibs.size > 0 || externalRefs.apis.size > 0)) {
38528
+ const mergedDeps = loadMergedDependencies(srcDir);
38529
+ externalDependencies = buildExternalDependencies(externalRefs, mergedDeps);
38530
+ const appDeps = loadAppDependencies(srcDir);
38531
+ mergedDependencies = mergeDependenciesIntoApp(appDeps, externalDependencies);
38532
+ logger.debug('已从分析构建 externalDependencies', externalDependencies);
38533
+ logger.debug('已从分析构建 mergedDependencies', mergedDependencies);
38534
+ }
38265
38535
  return {
38266
38536
  collectedFiles: filteredFiles,
38267
38537
  config,
38268
38538
  projectRoot,
38269
38539
  srcDir,
38540
+ externalDependencies,
38541
+ mergedDependencies,
38270
38542
  };
38271
38543
  }
38272
38544
 
@@ -38277,19 +38549,20 @@ async function compile(entry, options) {
38277
38549
  const logger = options?.logger || defaultLogger;
38278
38550
  logger.info('开始编译 NASL 代码...');
38279
38551
  // 收集需要编译的文件
38280
- const { collectedFiles, config, projectRoot } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38552
+ const { collectedFiles, config, projectRoot, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38281
38553
  logger.info(`输出目录: ${config.outDir}`);
38282
- const outDir = sysPath.join(projectRoot, config.outDir);
38554
+ const outDir = path$1.join(projectRoot, config.outDir);
38283
38555
  // 调用编译 API
38284
38556
  logger.newLine();
38285
38557
  logger.info('正在调用编译服务...');
38286
38558
  try {
38287
- const fullNaturalTS = composeToString(collectedFiles);
38559
+ let fullNaturalTS = composeToString(collectedFiles);
38560
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38288
38561
  const outputFiles = await compileApi(fullNaturalTS, config);
38289
38562
  logger.success('编译成功!');
38290
38563
  // 写入输出文件
38291
38564
  for (const file of outputFiles) {
38292
- const outputPath = sysPath.join(outDir, file.path);
38565
+ const outputPath = path$1.join(outDir, file.path);
38293
38566
  writeFileWithLog(outputPath, file.content, logger);
38294
38567
  }
38295
38568
  logger.info(`输出 ${outputFiles.length} 个文件`);
@@ -38312,6 +38585,63 @@ async function tryCompile(entry, options) {
38312
38585
  }
38313
38586
  }
38314
38587
 
38588
+ /**
38589
+ * 将错误信息中的行号映射回原始文件
38590
+ * 直接替换错误头中的文件路径和行号,并调整代码片段中的行号
38591
+ */
38592
+ function mapErrorToSourceFile(options) {
38593
+ const { errorMessage, collectedFiles } = options;
38594
+ // 构建行号到文件的映射
38595
+ const lineToFileMap = new Map();
38596
+ collectedFiles.forEach((file) => {
38597
+ if (file.startLine !== undefined && file.endLine !== undefined) {
38598
+ for (let i = file.startLine; i <= file.endLine; i++) {
38599
+ const lineInFile = i - file.startLine;
38600
+ lineToFileMap.set(i, { file, lineInFile });
38601
+ }
38602
+ }
38603
+ });
38604
+ // 处理单个错误块:替换路径、行号,调整代码片段行号
38605
+ function processBlock(block) {
38606
+ // 匹配错误头: 可选的 "N. " 前缀 + "filepath: message (line:col)"
38607
+ const headerMatch = block.match(/^((?:\d+\.\s+)?)(.*?):\s+(.*?)\((\d+):(\d+)\)/);
38608
+ if (!headerMatch)
38609
+ return block;
38610
+ const [fullHeader, prefix, , message, lineStr, colStr] = headerMatch;
38611
+ const originalLine = parseInt(lineStr, 10);
38612
+ const fileInfo = lineToFileMap.get(originalLine);
38613
+ if (!fileInfo)
38614
+ return block;
38615
+ const { file, lineInFile } = fileInfo;
38616
+ const lineOffset = originalLine - lineInFile;
38617
+ // 替换错误头中的路径和行号
38618
+ let mapped = block.replace(fullHeader, `${prefix}${file.path}: ${message}(${lineInFile}:${colStr})`);
38619
+ // 收集代码片段中所有行号并计算映射后的值
38620
+ const snippetNumbers = [];
38621
+ const collectRegex = /^([> ]*?)(\d+)(\s*\|)/gm;
38622
+ let m;
38623
+ while ((m = collectRegex.exec(mapped)) !== null) {
38624
+ snippetNumbers.push(parseInt(m[2], 10) - lineOffset);
38625
+ }
38626
+ // 替换代码片段中的行号,保持对齐
38627
+ if (snippetNumbers.length > 0) {
38628
+ const maxWidth = Math.max(...snippetNumbers.map((n) => String(n).length));
38629
+ let idx = 0;
38630
+ mapped = mapped.replace(/^([> ]*?)(\d+)(\s*\|)/gm, (fullMatch, lead) => {
38631
+ const newNum = snippetNumbers[idx++];
38632
+ if (newNum <= 0)
38633
+ return fullMatch;
38634
+ const paddedNum = String(newNum).padStart(maxWidth);
38635
+ return lead.includes('>') ? `> ${paddedNum} |` : ` ${paddedNum} |`;
38636
+ });
38637
+ }
38638
+ return mapped;
38639
+ }
38640
+ // 按编号前缀分割为独立错误块,分别处理
38641
+ const parts = errorMessage.split(/(?=^\d+\.\s)/m);
38642
+ return parts.map(processBlock).join('');
38643
+ }
38644
+
38315
38645
  /**
38316
38646
  * 检查命令 - 检查 NASL 代码的语法和语义
38317
38647
  */
@@ -38319,7 +38649,7 @@ async function check(entry, options) {
38319
38649
  const logger = options?.logger || defaultLogger;
38320
38650
  logger.info('开始检查 NASL 代码...');
38321
38651
  // 收集需要检查的文件
38322
- const { collectedFiles, config } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38652
+ const { collectedFiles, config, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38323
38653
  // 调用检查 API
38324
38654
  logger.newLine();
38325
38655
  logger.info('正在调用检查服务,对语法和语义进行检查...');
@@ -38327,12 +38657,20 @@ async function check(entry, options) {
38327
38657
  let result = '';
38328
38658
  try {
38329
38659
  fullNaturalTS = composeToString(collectedFiles);
38660
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38330
38661
  }
38331
38662
  catch (error) {
38332
38663
  result = error.message.trim();
38333
38664
  }
38334
38665
  if (!result && fullNaturalTS) {
38335
38666
  result = (await checkApi(fullNaturalTS, config)).trim();
38667
+ // 如果有错误,尝试映射回原始文件
38668
+ if (result) {
38669
+ result = mapErrorToSourceFile({
38670
+ errorMessage: result,
38671
+ collectedFiles,
38672
+ });
38673
+ }
38336
38674
  }
38337
38675
  const checkResult = {
38338
38676
  success: !result,
@@ -38348,12 +38686,19 @@ async function check(entry, options) {
38348
38686
  }
38349
38687
 
38350
38688
  /**
38351
- * 检查命令 - 检查 NASL 代码的语法和语义
38689
+ * 依赖分析命令 - 从入口文件开始进行依赖分析
38352
38690
  */
38353
38691
  async function dep(entry, options) {
38354
- const logger = defaultLogger;
38692
+ const logger = options?.logger || defaultLogger;
38355
38693
  logger.info('开始进行依赖分析...');
38356
- return resolveNASLFiles(entry, logger, true, true);
38694
+ const result = await resolveNASLFiles(entry, logger, true, options?.verbose ?? true);
38695
+ if (options?.save && result.mergedDependencies) {
38696
+ const srcDir = path$1.join(result.projectRoot, result.config.srcDir);
38697
+ const appDepsPath = path$1.join(srcDir, 'app.dependencies.json');
38698
+ await libExports.writeJson(appDepsPath, result.mergedDependencies, { spaces: 2 });
38699
+ logger.success(`已将 externalDependencies 补充到 ${appDepsPath}`);
38700
+ }
38701
+ return result;
38357
38702
  }
38358
38703
 
38359
38704
  /**
@@ -38363,15 +38708,15 @@ async function dev(entry, options) {
38363
38708
  const logger = options?.logger || new ConsoleLoggerWithoutExit();
38364
38709
  // 获取项目根目录和配置
38365
38710
  const projectRoot = process.cwd();
38366
- const configPath = sysPath.join(projectRoot, 'nasl.config.json');
38711
+ const configPath = path$1.join(projectRoot, 'nasl.config.json');
38367
38712
  if (!libExports.existsSync(configPath)) {
38368
38713
  logger.error('未找到 nasl.config.json 配置文件,请先初始化项目');
38369
38714
  process.exit(1);
38370
38715
  }
38371
38716
  const configContent = libExports.readFileSync(configPath, 'utf-8');
38372
38717
  const config = JSON.parse(configContent);
38373
- const srcDir = sysPath.join(projectRoot, config.srcDir);
38374
- const outDir = sysPath.join(projectRoot, config.outDir);
38718
+ const srcDir = path$1.join(projectRoot, config.srcDir);
38719
+ const outDir = path$1.join(projectRoot, config.outDir);
38375
38720
  // 检查是否存在 src 目录
38376
38721
  const hasSrcDir = libExports.existsSync(srcDir) && libExports.statSync(srcDir).isDirectory();
38377
38722
  let lastCompileSuccess = false;
@@ -38421,7 +38766,7 @@ async function dev(entry, options) {
38421
38766
  // 过滤非目标文件类型
38422
38767
  if (!shouldHandleFile(filePath))
38423
38768
  return;
38424
- logger.info(`检测到文件变化: ${sysPath.relative(projectRoot, filePath)}`);
38769
+ logger.info(`检测到文件变化: ${path$1.relative(projectRoot, filePath)}`);
38425
38770
  if (isCompiling) {
38426
38771
  pendingCompile = true;
38427
38772
  return;
@@ -38538,7 +38883,7 @@ async function dev(entry, options) {
38538
38883
  async function startWebpackDevServer(outDir, options, logger) {
38539
38884
  logger?.newLine();
38540
38885
  logger?.info('正在启动开发服务...');
38541
- const configRelativePath = sysPath.relative(outDir, sysPath.resolve(__dirname, '../../build/webpack.config.js'));
38886
+ const configRelativePath = path$1.relative(outDir, path$1.resolve(__dirname, '../../build/webpack.config.js'));
38542
38887
  // 构建 webpack-cli 参数
38543
38888
  let webpackArgs = `${require.resolve('.bin/webpack-cli')} serve --config ${configRelativePath}`;
38544
38889
  if (options?.port)
@@ -38582,7 +38927,7 @@ async function build(entry, options) {
38582
38927
  const { outDir } = await compile(entry);
38583
38928
  logger.newLine();
38584
38929
  logger.info('正在构建项目...');
38585
- const configRelativePath = sysPath.relative(outDir, sysPath.resolve(__dirname, '../../build/webpack.config.js'));
38930
+ const configRelativePath = path$1.relative(outDir, path$1.resolve(__dirname, '../../build/webpack.config.js'));
38586
38931
  const mode = options?.mode || 'production';
38587
38932
  // 构建 webpack-cli 参数
38588
38933
  let webpackArgs = `${require.resolve('.bin/webpack-cli')} build --config ${configRelativePath} --mode ${mode}`;
@@ -38593,8 +38938,8 @@ async function build(entry, options) {
38593
38938
  * 获取 specs 下第1个文件夹的名字
38594
38939
  */
38595
38940
  function getFirstSpecFolderName(projectRoot) {
38596
- const dirname = sysPath.basename(projectRoot);
38597
- const specsDir = sysPath.join(projectRoot, 'specs');
38941
+ const dirname = path$1.basename(projectRoot);
38942
+ const specsDir = path$1.join(projectRoot, 'specs');
38598
38943
  if (!libExports.existsSync(specsDir))
38599
38944
  return dirname;
38600
38945
  const entries = libExports.readdirSync(specsDir, { withFileTypes: true });
@@ -38685,6 +39030,8 @@ async function transformJson2FilesApi(json, options) {
38685
39030
  headers: { 'Content-Type': 'application/json' },
38686
39031
  });
38687
39032
  const data = res.data;
39033
+ if (data.code !== 200)
39034
+ throw new Error(data.message);
38688
39035
  return data.result;
38689
39036
  }
38690
39037
 
@@ -38695,7 +39042,7 @@ const transformFns = {
38695
39042
  async files2full(entry, options) {
38696
39043
  const logger = options?.logger || defaultLogger;
38697
39044
  // 收集需要处理的文件
38698
- const { collectedFiles, projectRoot } = await resolveNASLFiles(entry, logger, false, options?.verbose);
39045
+ const { collectedFiles, projectRoot, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38699
39046
  if (collectedFiles.length === 0) {
38700
39047
  logger.error('未找到需要转换的文件');
38701
39048
  logger.exit(1);
@@ -38704,11 +39051,12 @@ const transformFns = {
38704
39051
  // 组合成 fullNaturalTS
38705
39052
  logger.newLine();
38706
39053
  logger.info('正在组合文件...');
38707
- const fullNaturalTS = composeToString(collectedFiles);
39054
+ let fullNaturalTS = composeToString(collectedFiles);
39055
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38708
39056
  // 确定输出路径
38709
39057
  const outputPath = options?.output
38710
- ? sysPath.resolve(projectRoot, options.output)
38711
- : sysPath.join(projectRoot, './full-natural.ts');
39058
+ ? path$1.resolve(projectRoot, options.output)
39059
+ : path$1.join(projectRoot, './full-natural.ts');
38712
39060
  // 写入文件
38713
39061
  writeFileWithLog(outputPath, fullNaturalTS, logger);
38714
39062
  logger.success(`文件已输出到: ${outputPath}`);
@@ -38738,7 +39086,7 @@ const transformFns = {
38738
39086
  }
38739
39087
  const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, config);
38740
39088
  await Promise.all(files.map(async (file) => {
38741
- const outputPath = sysPath.join(projectRoot, config.srcDir, file.path);
39089
+ const outputPath = path$1.join(projectRoot, config.srcDir, file.path);
38742
39090
  await libExports.writeFile(outputPath, file.content);
38743
39091
  }));
38744
39092
  logger.success(`JSON 文件已转换为 ${files.length} 个文件,输出到 ${config.srcDir}`);
@@ -38765,7 +39113,87 @@ async function transform(transformType, entry, options) {
38765
39113
  await transformFn(entry, options);
38766
39114
  }
38767
39115
 
38768
- var version = "0.2.2";
39116
+ async function installAuto(options) {
39117
+ const logger = options?.logger || defaultLogger;
39118
+ const config = loadConfig();
39119
+ const projectRoot = getProjectRoot();
39120
+ const srcDir = path$1.join(projectRoot, config.srcDir);
39121
+ const appDependenciesJsonPath = path$1.join(srcDir, 'app.dependencies.json');
39122
+ const appDependenciesJson = libExports.readJsonSync(appDependenciesJsonPath);
39123
+ logger.info(`开始按照 ${appDependenciesJsonPath} 安装依赖`);
39124
+ return installByJSON(appDependenciesJson, options);
39125
+ }
39126
+ async function installByKind(kind, deps, options) {
39127
+ const logger = options?.logger || defaultLogger;
39128
+ if (!deps || deps.length === 0) {
39129
+ logger.error(`请至少指定一个要安装的 ${kind},例如:nasl install ${kind} aaa@0.1.0`);
39130
+ return logger.exit(1);
39131
+ }
39132
+ const dependencyMap = {};
39133
+ for (const dep of deps) {
39134
+ if (kind === 'api') {
39135
+ const [service, interfaces] = dep.split(':');
39136
+ if (!service || !interfaces) {
39137
+ logger.error(`无效的依赖格式:${dep},请使用 service:api1,api2 格式,例如:some_service:api1,api2`);
39138
+ return logger.exit(1);
39139
+ }
39140
+ dependencyMap[service] = interfaces.split(',');
39141
+ }
39142
+ else {
39143
+ const [name, version] = dep.split('@');
39144
+ if (!name || !version) {
39145
+ logger.error(`无效的依赖格式:${dep},请使用 name@version 格式,例如:aaa@0.1.0`);
39146
+ return logger.exit(1);
39147
+ }
39148
+ dependencyMap[name] = version;
39149
+ }
39150
+ }
39151
+ return installByJSON({ [kind + 's']: dependencyMap }, options);
39152
+ }
39153
+ async function installByJSON(json, options) {
39154
+ const logger = options?.logger || defaultLogger;
39155
+ if (!Object.keys(json).length) {
39156
+ logger.error('没有需要安装的依赖');
39157
+ return;
39158
+ }
39159
+ const config = loadConfig();
39160
+ const projectRoot = getProjectRoot();
39161
+ const srcDir = path$1.join(projectRoot, config.srcDir);
39162
+ const result = await installDependenciesApi(json, config);
39163
+ if (!result.files || result.files.length <= 1)
39164
+ throw new Error(`安装依赖失败,没有生成任何文件:\n${JSON.stringify(result)}`);
39165
+ if (result.errors.length > 0) {
39166
+ logger.error(`某些依赖安装失败:`);
39167
+ for (const error of result.errors)
39168
+ logger.error(error);
39169
+ }
39170
+ // const appDepsFile = result.files.find((f) => f.path === 'app.dependencies.json');
39171
+ const otherFiles = result.files.filter((f) => f.path !== 'app.dependencies.json');
39172
+ const jsonToSave = JSON.parse(JSON.stringify(json));
39173
+ for (const err of result.errors) {
39174
+ const { name, category } = err;
39175
+ const record = jsonToSave[category];
39176
+ if (record && typeof record === 'object') {
39177
+ delete record[name];
39178
+ if (Object.keys(record).length === 0)
39179
+ delete jsonToSave[category];
39180
+ }
39181
+ }
39182
+ if (options?.savePotential) {
39183
+ const potentialPath = path$1.join(srcDir, 'potential.dependencies.json');
39184
+ await libExports.writeJson(potentialPath, jsonToSave, { spaces: 2 });
39185
+ logger.success(`依赖信息已写入: ${path$1.relative(projectRoot, potentialPath)}`);
39186
+ }
39187
+ await Promise.all(otherFiles.map(async (file) => {
39188
+ const filePath = path$1.join(srcDir, file.path);
39189
+ await libExports.outputFile(filePath, file.content, 'utf-8');
39190
+ logger.success(`依赖文件已写入: ${path$1.relative(projectRoot, filePath)}`);
39191
+ }));
39192
+ const writtenCount = otherFiles.length;
39193
+ logger.success(`成功写入 ${writtenCount} 个依赖文件到 ${config.srcDir} 目录`);
39194
+ }
39195
+
39196
+ var version = "0.3.0";
38769
39197
  var pkg = {
38770
39198
  version: version};
38771
39199
 
@@ -38825,15 +39253,51 @@ program
38825
39253
  program
38826
39254
  .command('dep [entry]')
38827
39255
  .description('从入口文件开始进行依赖分析')
38828
- .action(async (entry) => {
39256
+ .option('--save', '将计算出的 externalDependencies 补充到 src/app.dependencies.json')
39257
+ .action(async (entry, options) => {
38829
39258
  try {
38830
- await dep(entry);
39259
+ await dep(entry, options);
38831
39260
  }
38832
39261
  catch (error) {
38833
39262
  defaultLogger.error(`查找依赖过程发生错误:${error.message}`);
38834
39263
  process.exit(1);
38835
39264
  }
38836
39265
  });
39266
+ program
39267
+ .command('install [kind|by-json] [deps...]')
39268
+ .option('--save-potential', '将 app.dependencies.json 写入 potential.dependencies.json')
39269
+ .description(`安装一个或多个 uilib, extension, api 或 connector 依赖,例如:
39270
+ - nasl install uilib some_component@0.1.0 some_component@0.2.0
39271
+ - nasl install extension some_encryption@0.1.0 some_interceptor@0.2.0
39272
+ - nasl install api some_service:api1,api2 some_service:api3,api4
39273
+ - nasl install connector some_connector@0.1.0 some_connector@0.2.0
39274
+ - nasl install by-json '{"uilibs": {"some_component": "0.1.0"}, "extensions": {"some_encryption": "0.1.0", "some_interceptor": "0.2.0"}}'
39275
+ `)
39276
+ .action(async (kind, deps, options) => {
39277
+ try {
39278
+ if (kind === 'by-json') {
39279
+ if (deps.length < 1)
39280
+ throw new Error('请提供一个 JSON 字符串');
39281
+ else if (deps.length > 1)
39282
+ throw new Error('参数过多,JSON 字符串只能有一个');
39283
+ const jsonStr = deps[0];
39284
+ await installByJSON(JSON.parse(jsonStr), options);
39285
+ }
39286
+ else if (kind) {
39287
+ if (!['uilib', 'extension', 'api', 'connector'].includes(kind)) {
39288
+ throw new Error(`无效的依赖类型: ${kind}。\n支持的类型有: uilib, extension, api, connector`);
39289
+ }
39290
+ await installByKind(kind, deps, options);
39291
+ }
39292
+ else {
39293
+ await installAuto(options);
39294
+ }
39295
+ }
39296
+ catch (error) {
39297
+ defaultLogger.error(`安装过程发生错误:${error.message}`);
39298
+ process.exit(1);
39299
+ }
39300
+ });
38837
39301
  program
38838
39302
  .command('dev [entry]')
38839
39303
  .description('启动开发服务')
@@ -39217,7 +39681,7 @@ const binaryExtensions = new Set([
39217
39681
  'xmind', 'xpi', 'xpm', 'xwd', 'xz',
39218
39682
  'z', 'zip', 'zipx',
39219
39683
  ]);
39220
- const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
39684
+ const isBinaryPath = (filePath) => binaryExtensions.has(path$1.extname(filePath).slice(1).toLowerCase());
39221
39685
  // TODO: emit errors properly. Example: EMFILE on Macos.
39222
39686
  const foreach = (val, fn) => {
39223
39687
  if (val instanceof Set) {
@@ -39270,7 +39734,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
39270
39734
  // emit based on events occurring for files from a directory's watcher in
39271
39735
  // case the file's watcher misses it (and rely on throttling to de-dupe)
39272
39736
  if (evPath && path !== evPath) {
39273
- fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
39737
+ fsWatchBroadcast(path$1.resolve(path, evPath), KEY_LISTENERS, path$1.join(path, evPath));
39274
39738
  }
39275
39739
  };
39276
39740
  try {
@@ -39453,11 +39917,11 @@ class NodeFsHandler {
39453
39917
  */
39454
39918
  _watchWithNodeFs(path, listener) {
39455
39919
  const opts = this.fsw.options;
39456
- const directory = sysPath.dirname(path);
39457
- const basename = sysPath.basename(path);
39920
+ const directory = path$1.dirname(path);
39921
+ const basename = path$1.basename(path);
39458
39922
  const parent = this.fsw._getWatchedDir(directory);
39459
39923
  parent.add(basename);
39460
- const absolutePath = sysPath.resolve(path);
39924
+ const absolutePath = path$1.resolve(path);
39461
39925
  const options = {
39462
39926
  persistent: opts.persistent,
39463
39927
  };
@@ -39489,8 +39953,8 @@ class NodeFsHandler {
39489
39953
  if (this.fsw.closed) {
39490
39954
  return;
39491
39955
  }
39492
- const dirname = sysPath.dirname(file);
39493
- const basename = sysPath.basename(file);
39956
+ const dirname = path$1.dirname(file);
39957
+ const basename = path$1.basename(file);
39494
39958
  const parent = this.fsw._getWatchedDir(dirname);
39495
39959
  // stats is always present
39496
39960
  let prevStats = stats;
@@ -39597,7 +40061,7 @@ class NodeFsHandler {
39597
40061
  }
39598
40062
  _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
39599
40063
  // Normalize the directory name on Windows
39600
- directory = sysPath.join(directory, '');
40064
+ directory = path$1.join(directory, '');
39601
40065
  throttler = this.fsw._throttle('readdir', directory, 1000);
39602
40066
  if (!throttler)
39603
40067
  return;
@@ -39616,7 +40080,7 @@ class NodeFsHandler {
39616
40080
  return;
39617
40081
  }
39618
40082
  const item = entry.path;
39619
- let path = sysPath.join(directory, item);
40083
+ let path = path$1.join(directory, item);
39620
40084
  current.add(item);
39621
40085
  if (entry.stats.isSymbolicLink() &&
39622
40086
  (await this._handleSymlink(entry, directory, path, item))) {
@@ -39632,7 +40096,7 @@ class NodeFsHandler {
39632
40096
  if (item === target || (!target && !previous.has(item))) {
39633
40097
  this.fsw._incrReadyCount();
39634
40098
  // ensure relativeness of path is preserved in case of watcher reuse
39635
- path = sysPath.join(dir, sysPath.relative(dir, path));
40099
+ path = path$1.join(dir, path$1.relative(dir, path));
39636
40100
  this._addToNodeFs(path, initialAdd, wh, depth + 1);
39637
40101
  }
39638
40102
  })
@@ -39677,13 +40141,13 @@ class NodeFsHandler {
39677
40141
  * @returns closer for the watcher instance.
39678
40142
  */
39679
40143
  async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
39680
- const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
39681
- const tracked = parentDir.has(sysPath.basename(dir));
40144
+ const parentDir = this.fsw._getWatchedDir(path$1.dirname(dir));
40145
+ const tracked = parentDir.has(path$1.basename(dir));
39682
40146
  if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
39683
40147
  this.fsw._emit(EV.ADD_DIR, dir, stats);
39684
40148
  }
39685
40149
  // ensure dir is tracked (harmless if redundant)
39686
- parentDir.add(sysPath.basename(dir));
40150
+ parentDir.add(path$1.basename(dir));
39687
40151
  this.fsw._getWatchedDir(dir);
39688
40152
  let throttler;
39689
40153
  let closer;
@@ -39735,7 +40199,7 @@ class NodeFsHandler {
39735
40199
  const follow = this.fsw.options.followSymlinks;
39736
40200
  let closer;
39737
40201
  if (stats.isDirectory()) {
39738
- const absPath = sysPath.resolve(path);
40202
+ const absPath = path$1.resolve(path);
39739
40203
  const targetPath = follow ? await realpath$1(path) : path;
39740
40204
  if (this.fsw.closed)
39741
40205
  return;
@@ -39751,7 +40215,7 @@ class NodeFsHandler {
39751
40215
  const targetPath = follow ? await realpath$1(path) : path;
39752
40216
  if (this.fsw.closed)
39753
40217
  return;
39754
- const parent = sysPath.dirname(wh.watchPath);
40218
+ const parent = path$1.dirname(wh.watchPath);
39755
40219
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
39756
40220
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
39757
40221
  closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
@@ -39759,7 +40223,7 @@ class NodeFsHandler {
39759
40223
  return;
39760
40224
  // preserve this symlink's target path
39761
40225
  if (targetPath !== undefined) {
39762
- this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
40226
+ this.fsw._symlinkPaths.set(path$1.resolve(path), targetPath);
39763
40227
  }
39764
40228
  }
39765
40229
  else {
@@ -39805,11 +40269,11 @@ function createPattern(matcher) {
39805
40269
  if (matcher.path === string)
39806
40270
  return true;
39807
40271
  if (matcher.recursive) {
39808
- const relative = sysPath.relative(matcher.path, string);
40272
+ const relative = path$1.relative(matcher.path, string);
39809
40273
  if (!relative) {
39810
40274
  return false;
39811
40275
  }
39812
- return !relative.startsWith('..') && !sysPath.isAbsolute(relative);
40276
+ return !relative.startsWith('..') && !path$1.isAbsolute(relative);
39813
40277
  }
39814
40278
  return false;
39815
40279
  };
@@ -39819,7 +40283,7 @@ function createPattern(matcher) {
39819
40283
  function normalizePath(path) {
39820
40284
  if (typeof path !== 'string')
39821
40285
  throw new Error('string expected');
39822
- path = sysPath.normalize(path);
40286
+ path = path$1.normalize(path);
39823
40287
  path = path.replace(/\\/g, '/');
39824
40288
  let prepend = false;
39825
40289
  if (path.startsWith('//'))
@@ -39879,21 +40343,21 @@ const toUnix = (string) => {
39879
40343
  };
39880
40344
  // Our version of upath.normalize
39881
40345
  // TODO: this is not equal to path-normalize module - investigate why
39882
- const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
40346
+ const normalizePathToUnix = (path) => toUnix(path$1.normalize(toUnix(path)));
39883
40347
  // TODO: refactor
39884
40348
  const normalizeIgnored = (cwd = '') => (path) => {
39885
40349
  if (typeof path === 'string') {
39886
- return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
40350
+ return normalizePathToUnix(path$1.isAbsolute(path) ? path : path$1.join(cwd, path));
39887
40351
  }
39888
40352
  else {
39889
40353
  return path;
39890
40354
  }
39891
40355
  };
39892
40356
  const getAbsolutePath = (path, cwd) => {
39893
- if (sysPath.isAbsolute(path)) {
40357
+ if (path$1.isAbsolute(path)) {
39894
40358
  return path;
39895
40359
  }
39896
- return sysPath.join(cwd, path);
40360
+ return path$1.join(cwd, path);
39897
40361
  };
39898
40362
  const EMPTY_SET = Object.freeze(new Set());
39899
40363
  /**
@@ -39925,7 +40389,7 @@ class DirEntry {
39925
40389
  }
39926
40390
  catch (err) {
39927
40391
  if (this._removeWatcher) {
39928
- this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
40392
+ this._removeWatcher(path$1.dirname(dir), path$1.basename(dir));
39929
40393
  }
39930
40394
  }
39931
40395
  }
@@ -39957,7 +40421,7 @@ class WatchHelper {
39957
40421
  const watchPath = path;
39958
40422
  this.path = path = path.replace(REPLACER_RE, '');
39959
40423
  this.watchPath = watchPath;
39960
- this.fullWatchPath = sysPath.resolve(watchPath);
40424
+ this.fullWatchPath = path$1.resolve(watchPath);
39961
40425
  this.dirParts = [];
39962
40426
  this.dirParts.forEach((parts) => {
39963
40427
  if (parts.length > 1)
@@ -39967,7 +40431,7 @@ class WatchHelper {
39967
40431
  this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
39968
40432
  }
39969
40433
  entryPath(entry) {
39970
- return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));
40434
+ return path$1.join(this.watchPath, path$1.relative(this.watchPath, entry.fullPath));
39971
40435
  }
39972
40436
  filterPath(entry) {
39973
40437
  const { stats } = entry;
@@ -40123,7 +40587,7 @@ class FSWatcher extends EventEmitter {
40123
40587
  return;
40124
40588
  results.forEach((item) => {
40125
40589
  if (item)
40126
- this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
40590
+ this.add(path$1.dirname(item), path$1.basename(_origAdd || item));
40127
40591
  });
40128
40592
  });
40129
40593
  return this;
@@ -40138,10 +40602,10 @@ class FSWatcher extends EventEmitter {
40138
40602
  const { cwd } = this.options;
40139
40603
  paths.forEach((path) => {
40140
40604
  // convert to absolute path unless relative path already matches
40141
- if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
40605
+ if (!path$1.isAbsolute(path) && !this._closers.has(path)) {
40142
40606
  if (cwd)
40143
- path = sysPath.join(cwd, path);
40144
- path = sysPath.resolve(path);
40607
+ path = path$1.join(cwd, path);
40608
+ path = path$1.resolve(path);
40145
40609
  }
40146
40610
  this._closePath(path);
40147
40611
  this._addIgnoredPath(path);
@@ -40195,7 +40659,7 @@ class FSWatcher extends EventEmitter {
40195
40659
  getWatched() {
40196
40660
  const watchList = {};
40197
40661
  this._watched.forEach((entry, dir) => {
40198
- const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
40662
+ const key = this.options.cwd ? path$1.relative(this.options.cwd, dir) : dir;
40199
40663
  const index = key || ONE_DOT;
40200
40664
  watchList[index] = entry.getChildren().sort();
40201
40665
  });
@@ -40221,9 +40685,9 @@ class FSWatcher extends EventEmitter {
40221
40685
  return;
40222
40686
  const opts = this.options;
40223
40687
  if (isWindows)
40224
- path = sysPath.normalize(path);
40688
+ path = path$1.normalize(path);
40225
40689
  if (opts.cwd)
40226
- path = sysPath.relative(opts.cwd, path);
40690
+ path = path$1.relative(opts.cwd, path);
40227
40691
  const args = [path];
40228
40692
  if (stats != null)
40229
40693
  args.push(stats);
@@ -40279,7 +40743,7 @@ class FSWatcher extends EventEmitter {
40279
40743
  if (opts.alwaysStat &&
40280
40744
  stats === undefined &&
40281
40745
  (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
40282
- const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
40746
+ const fullPath = opts.cwd ? path$1.join(opts.cwd, path) : path;
40283
40747
  let stats;
40284
40748
  try {
40285
40749
  stats = await stat$2(fullPath);
@@ -40362,8 +40826,8 @@ class FSWatcher extends EventEmitter {
40362
40826
  const pollInterval = awf.pollInterval;
40363
40827
  let timeoutHandler;
40364
40828
  let fullPath = path;
40365
- if (this.options.cwd && !sysPath.isAbsolute(path)) {
40366
- fullPath = sysPath.join(this.options.cwd, path);
40829
+ if (this.options.cwd && !path$1.isAbsolute(path)) {
40830
+ fullPath = path$1.join(this.options.cwd, path);
40367
40831
  }
40368
40832
  const now = new Date();
40369
40833
  const writes = this._pendingWrites;
@@ -40434,7 +40898,7 @@ class FSWatcher extends EventEmitter {
40434
40898
  * @param directory path of the directory
40435
40899
  */
40436
40900
  _getWatchedDir(directory) {
40437
- const dir = sysPath.resolve(directory);
40901
+ const dir = path$1.resolve(directory);
40438
40902
  if (!this._watched.has(dir))
40439
40903
  this._watched.set(dir, new DirEntry(dir, this._boundRemove));
40440
40904
  return this._watched.get(dir);
@@ -40460,8 +40924,8 @@ class FSWatcher extends EventEmitter {
40460
40924
  // if what is being deleted is a directory, get that directory's paths
40461
40925
  // for recursive deleting and cleaning of watched object
40462
40926
  // if it is not a directory, nestedDirectoryChildren will be empty array
40463
- const path = sysPath.join(directory, item);
40464
- const fullPath = sysPath.resolve(path);
40927
+ const path = path$1.join(directory, item);
40928
+ const fullPath = path$1.resolve(path);
40465
40929
  isDirectory =
40466
40930
  isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
40467
40931
  // prevent duplicate handling in case of arriving here nearly simultaneously
@@ -40493,7 +40957,7 @@ class FSWatcher extends EventEmitter {
40493
40957
  // If we wait for this file to be fully written, cancel the wait.
40494
40958
  let relPath = path;
40495
40959
  if (this.options.cwd)
40496
- relPath = sysPath.relative(this.options.cwd, path);
40960
+ relPath = path$1.relative(this.options.cwd, path);
40497
40961
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
40498
40962
  const event = this._pendingWrites.get(relPath).cancelWait();
40499
40963
  if (event === EVENTS.ADD)
@@ -40514,8 +40978,8 @@ class FSWatcher extends EventEmitter {
40514
40978
  */
40515
40979
  _closePath(path) {
40516
40980
  this._closeFile(path);
40517
- const dir = sysPath.dirname(path);
40518
- this._getWatchedDir(dir).remove(sysPath.basename(path));
40981
+ const dir = path$1.dirname(path);
40982
+ this._getWatchedDir(dir).remove(path$1.basename(path));
40519
40983
  }
40520
40984
  /**
40521
40985
  * Closes only file-specific watchers