@nasl/cli 0.2.3 → 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 (66) hide show
  1. package/dist/bin/nasl.mjs +516 -126
  2. package/dist/bin/nasl.mjs.map +1 -1
  3. package/dist/bin/naslc.mjs +311 -58
  4. package/dist/bin/naslc.mjs.map +1 -1
  5. package/dist/index.mjs +11610 -11255
  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 +2 -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 +20 -0
  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/config.d.ts +2 -0
  60. package/out/types/config.d.ts.map +1 -1
  61. package/out/types/config.js +1 -0
  62. package/out/types/config.js.map +1 -1
  63. package/out/utils/config.d.ts.map +1 -1
  64. package/out/utils/config.js +2 -0
  65. package/out/utils/config.js.map +1 -1
  66. 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
  // 获取优先级索引
@@ -29370,6 +29397,25 @@ function composeToString(files) {
29370
29397
  }
29371
29398
  return result;
29372
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
+ }
29373
29419
 
29374
29420
  var globby$1 = {exports: {}};
29375
29421
 
@@ -29627,7 +29673,7 @@ function requirePath () {
29627
29673
  Object.defineProperty(path, "__esModule", { value: true });
29628
29674
  path.convertPosixPathToPattern = path.convertWindowsPathToPattern = path.convertPathToPattern = path.escapePosixPath = path.escapeWindowsPath = path.escape = path.removeLeadingDotSegment = path.makeAbsolute = path.unixify = void 0;
29629
29675
  const os = require$$0$5;
29630
- const path$1 = sysPath__default;
29676
+ const path$1 = path__default;
29631
29677
  const IS_WINDOWS_PLATFORM = os.platform() === 'win32';
29632
29678
  const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\
29633
29679
  /**
@@ -29892,7 +29938,7 @@ function requireGlobParent () {
29892
29938
  hasRequiredGlobParent = 1;
29893
29939
 
29894
29940
  var isGlob = requireIsGlob();
29895
- var pathPosixDirname = sysPath__default.posix.dirname;
29941
+ var pathPosixDirname = path__default.posix.dirname;
29896
29942
  var isWin32 = require$$0$5.platform() === 'win32';
29897
29943
 
29898
29944
  var slash = '/';
@@ -31464,7 +31510,7 @@ function requireConstants$1 () {
31464
31510
  if (hasRequiredConstants$1) return constants$1;
31465
31511
  hasRequiredConstants$1 = 1;
31466
31512
 
31467
- const path = sysPath__default;
31513
+ const path = path__default;
31468
31514
  const WIN_SLASH = '\\\\/';
31469
31515
  const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
31470
31516
 
@@ -31651,7 +31697,7 @@ function requireUtils$2 () {
31651
31697
  hasRequiredUtils$2 = 1;
31652
31698
  (function (exports$1) {
31653
31699
 
31654
- const path = sysPath__default;
31700
+ const path = path__default;
31655
31701
  const win32 = process.platform === 'win32';
31656
31702
  const {
31657
31703
  REGEX_BACKSLASH,
@@ -33222,7 +33268,7 @@ function requirePicomatch$1 () {
33222
33268
  if (hasRequiredPicomatch$1) return picomatch_1;
33223
33269
  hasRequiredPicomatch$1 = 1;
33224
33270
 
33225
- const path = sysPath__default;
33271
+ const path = path__default;
33226
33272
  const scan = requireScan();
33227
33273
  const parse = requireParse();
33228
33274
  const utils = requireUtils$2();
@@ -34065,7 +34111,7 @@ function requirePattern () {
34065
34111
  hasRequiredPattern = 1;
34066
34112
  Object.defineProperty(pattern, "__esModule", { value: true });
34067
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;
34068
- const path = sysPath__default;
34114
+ const path = path__default;
34069
34115
  const globParent = requireGlobParent();
34070
34116
  const micromatch = requireMicromatch();
34071
34117
  const GLOBSTAR = '**';
@@ -35019,7 +35065,7 @@ function requireSettings$2 () {
35019
35065
  if (hasRequiredSettings$2) return settings$2;
35020
35066
  hasRequiredSettings$2 = 1;
35021
35067
  Object.defineProperty(settings$2, "__esModule", { value: true });
35022
- const path = sysPath__default;
35068
+ const path = path__default;
35023
35069
  const fsStat = requireOut$3();
35024
35070
  const fs = requireFs();
35025
35071
  class Settings {
@@ -35781,7 +35827,7 @@ function requireSettings$1 () {
35781
35827
  if (hasRequiredSettings$1) return settings$1;
35782
35828
  hasRequiredSettings$1 = 1;
35783
35829
  Object.defineProperty(settings$1, "__esModule", { value: true });
35784
- const path = sysPath__default;
35830
+ const path = path__default;
35785
35831
  const fsScandir = requireOut$2();
35786
35832
  class Settings {
35787
35833
  constructor(_options = {}) {
@@ -35857,7 +35903,7 @@ function requireReader () {
35857
35903
  if (hasRequiredReader) return reader;
35858
35904
  hasRequiredReader = 1;
35859
35905
  Object.defineProperty(reader, "__esModule", { value: true });
35860
- const path = sysPath__default;
35906
+ const path = path__default;
35861
35907
  const fsStat = requireOut$3();
35862
35908
  const utils = requireUtils$1();
35863
35909
  class Reader {
@@ -36330,7 +36376,7 @@ function requireProvider () {
36330
36376
  if (hasRequiredProvider) return provider;
36331
36377
  hasRequiredProvider = 1;
36332
36378
  Object.defineProperty(provider, "__esModule", { value: true });
36333
- const path = sysPath__default;
36379
+ const path = path__default;
36334
36380
  const deep_1 = requireDeep();
36335
36381
  const entry_1 = requireEntry$1();
36336
36382
  const error_1 = requireError();
@@ -36770,7 +36816,7 @@ var hasRequiredDirGlob;
36770
36816
  function requireDirGlob () {
36771
36817
  if (hasRequiredDirGlob) return dirGlob.exports;
36772
36818
  hasRequiredDirGlob = 1;
36773
- const path = sysPath__default;
36819
+ const path = path__default;
36774
36820
  const pathType = requirePathType();
36775
36821
 
36776
36822
  const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];
@@ -37520,7 +37566,7 @@ function requireGitignore () {
37520
37566
  hasRequiredGitignore = 1;
37521
37567
  const {promisify} = require$$0$4;
37522
37568
  const fs = require$$0$2;
37523
- const path = sysPath__default;
37569
+ const path = path__default;
37524
37570
  const fastGlob = requireOut();
37525
37571
  const gitIgnore = requireIgnore();
37526
37572
  const slash = requireSlash();
@@ -37952,6 +37998,27 @@ const NASL_FILE_TYPES = [
37952
37998
  codeRefPattern: 'extensions\\.\\w+(?:\\.\\w+)*',
37953
37999
  extension: 'ts',
37954
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
+ },
37955
38022
  ];
37956
38023
  /**
37957
38024
  * 获取用于验证文件名的正则表达式数组
@@ -37984,10 +38051,15 @@ const codeRefPatterns = getCodeRefPatterns();
37984
38051
  */
37985
38052
  function isKnownFileType(filePath) {
37986
38053
  // 提取文件名
37987
- const fileName = sysPath.basename(filePath);
38054
+ const fileName = path$1.basename(filePath);
37988
38055
  return fileNamePatterns.some((pattern) => pattern.test(fileName));
37989
38056
  }
37990
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
+ }
37991
38063
  /**
37992
38064
  * 扫描目录下的所有 NASL 文件
37993
38065
  */
@@ -38053,6 +38125,15 @@ function extractDeps(content) {
38053
38125
  if (/^extensions\.\w+\./.test(dep)) {
38054
38126
  dep = dep.replace(/^(extensions\.\w+)\..+$/, '$1');
38055
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
+ }
38056
38137
  // 跳过不合法的实体引用(实体后还有字段的情况)
38057
38138
  if (/app\.dataSources\.\w+\.entities\.\w+\.\w+$/.test(dep)) {
38058
38139
  continue;
@@ -38064,6 +38145,152 @@ function extractDeps(content) {
38064
38145
  }
38065
38146
  return Array.from(deps);
38066
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
+ }
38067
38294
  /**
38068
38295
  * 提取页面文件的签名,移除函数体
38069
38296
  * @param content 页面文件内容
@@ -38086,7 +38313,7 @@ function replaceViewAsSignature(content, hasSubViews = false) {
38086
38313
  * @returns 文件信息和新发现的依赖文件列表
38087
38314
  */
38088
38315
  function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFileMap, depNotFoundList, logger, verbose) {
38089
- const absoluteFilePath = sysPath.join(srcDir, pathRelativeToSrc);
38316
+ const absoluteFilePath = path$1.join(srcDir, pathRelativeToSrc);
38090
38317
  const fileInfo = { path: pathRelativeToSrc, content: '' };
38091
38318
  try {
38092
38319
  fileInfo.content = readFileWithLog(absoluteFilePath, logger);
@@ -38116,7 +38343,9 @@ function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFil
38116
38343
  }
38117
38344
  processedFileMap.set(pathRelativeToSrc, fileInfo);
38118
38345
  // 提取依赖
38119
- const deps = extractDeps(fileInfo.content);
38346
+ // extensions/connectors/apis/uilibs 作为叶子节点,不再向下递归查找依赖
38347
+ const isExternalDep = shouldSkipDependencyTraversal(pathRelativeToSrc);
38348
+ const deps = isExternalDep ? [] : extractDeps(fileInfo.content);
38120
38349
  // 查找依赖文件
38121
38350
  if (isView) {
38122
38351
  const pathArr = pathRelativeToSrc.split('.');
@@ -38131,24 +38360,30 @@ function processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFil
38131
38360
  } while (true);
38132
38361
  }
38133
38362
  if (verbose || process.env.DEBUG) {
38134
- 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('')}`);
38135
38364
  }
38136
38365
  return {
38137
38366
  fileInfo,
38138
38367
  newDeps: deps.filter((dep) => !processedFileMap.has(dep)),
38368
+ isExternalDep,
38139
38369
  };
38140
38370
  }
38141
38371
  /**
38142
38372
  * 收集入口文件及其依赖
38143
38373
  * @param patterns 入口文件的 glob 模式数组
38144
38374
  * @param srcDir 源代码目录绝对路径
38145
- * @param representation NASL 表示形式
38146
- * @returns 文件信息列表
38375
+ * @returns 文件信息列表和外部依赖引用
38147
38376
  */
38148
38377
  async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38149
38378
  const processedFileMap = new Map(); // 已处理的文件(相对路径)
38150
38379
  const filesToProcess = []; // 待处理的文件队列
38151
38380
  const result = [];
38381
+ const externalRefs = {
38382
+ extensions: new Set(),
38383
+ connectors: new Set(),
38384
+ uilibs: new Set(),
38385
+ apis: new Map(),
38386
+ };
38152
38387
  // 1. 使用 glob 匹配入口文件
38153
38388
  logger.newLine();
38154
38389
  logger.info(`匹配入口文件: ${patterns.join(', ')}`);
@@ -38158,15 +38393,15 @@ async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38158
38393
  throw new Error('未找到匹配的入口文件');
38159
38394
  }
38160
38395
  logger.info(`找到 ${matchedFiles.length} 个入口文件`);
38161
- const absoluteSrcDir = sysPath.resolve(srcDir);
38396
+ const absoluteSrcDir = path$1.resolve(srcDir);
38162
38397
  const matchedFileSet = new Set();
38163
38398
  matchedFiles.forEach((pathRelativeToRoot) => {
38164
38399
  // 统一使用相对于 src 的路径
38165
- const absoluteFilePath = sysPath.resolve(projectRoot, pathRelativeToRoot);
38400
+ const absoluteFilePath = path$1.resolve(projectRoot, pathRelativeToRoot);
38166
38401
  // 判断 file 是否超出 srcDir 目录(支持相对路径和绝对路径)
38167
38402
  if (!absoluteFilePath.startsWith(absoluteSrcDir))
38168
38403
  throw new Error(`入口文件 ${absoluteFilePath} 超出了源代码目录 ${srcDir}`);
38169
- const pathRelativeToSrc = sysPath.relative(srcDir, absoluteFilePath);
38404
+ const pathRelativeToSrc = path$1.relative(srcDir, absoluteFilePath);
38170
38405
  filesToProcess.push(pathRelativeToSrc);
38171
38406
  matchedFileSet.add(pathRelativeToSrc);
38172
38407
  });
@@ -38184,8 +38419,9 @@ async function collectDeps(patterns, projectRoot, srcDir, logger, verbose) {
38184
38419
  continue;
38185
38420
  }
38186
38421
  try {
38187
- const { fileInfo, newDeps } = processFileDeps(pathRelativeToSrc, srcDir, matchedFileSet, processedFileMap, depNotFoundList, logger, verbose);
38188
- 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));
38189
38425
  filesToProcess.push(...newDeps);
38190
38426
  }
38191
38427
  catch (error) {
@@ -38207,7 +38443,7 @@ ${depNotFoundList.map((dep) => `- ${dep}\n`).join('')}
38207
38443
  }
38208
38444
  if (errorMessage)
38209
38445
  throw new Error(errorMessage);
38210
- return result;
38446
+ return { files: result, externalRefs };
38211
38447
  }
38212
38448
  /**
38213
38449
  * 解析需要处理的文件(包含配置加载和目录设置)
@@ -38215,12 +38451,13 @@ ${depNotFoundList.map((dep) => `- ${dep}\n`).join('')}
38215
38451
  * @returns 文件信息、配置和目录信息
38216
38452
  */
38217
38453
  async function resolveNASLFiles(entry, logger, depMode, verbose) {
38454
+ depMode = true; // !!ensure depMode is true
38218
38455
  // 加载配置
38219
38456
  const config = loadConfig();
38220
38457
  const projectRoot = getProjectRoot();
38221
38458
  logger.info(`项目根目录: ${projectRoot}`);
38222
38459
  logger.info(`源代码目录: ${config.srcDir}`);
38223
- const srcDir = sysPath.join(projectRoot, config.srcDir);
38460
+ const srcDir = path$1.join(projectRoot, config.srcDir);
38224
38461
  // 收集需要处理的文件
38225
38462
  let collectedFiles = [];
38226
38463
  if (Array.isArray(entry) && !entry.length) {
@@ -38229,10 +38466,12 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38229
38466
  config,
38230
38467
  projectRoot,
38231
38468
  srcDir,
38469
+ externalDependencies: undefined,
38232
38470
  };
38233
38471
  }
38472
+ let externalRefs = null;
38234
38473
  if (!entry && depMode)
38235
- entry = 'src/**/*.{ts,tsx}';
38474
+ entry = 'src/**/app.*.{ts,tsx,css}';
38236
38475
  if (entry) {
38237
38476
  // 检查入口路径是否在源代码目录外面
38238
38477
  // if (entry.startsWith('..')) throw new Error('入口路径不能在源代码目录外面');
@@ -38240,7 +38479,9 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38240
38479
  // 具体路径也转换为 glob 模式统一处理
38241
38480
  // 使用依赖分析收集文件
38242
38481
  try {
38243
- 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;
38244
38485
  }
38245
38486
  catch (error) {
38246
38487
  logger.error(`依赖分析失败:\n${error.message}`);
@@ -38254,13 +38495,21 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38254
38495
  filePaths.sort(sorter);
38255
38496
  collectedFiles = filePaths.map((filePath) => ({
38256
38497
  path: filePath,
38257
- content: readFileWithLog(sysPath.join(srcDir, filePath), logger),
38498
+ content: readFileWithLog(path$1.join(srcDir, filePath), logger),
38258
38499
  }));
38259
38500
  if (collectedFiles.length === 0) {
38260
38501
  logger.warn('未找到 NASL 文件');
38261
38502
  logger.exit(1);
38262
38503
  }
38263
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)));
38264
38513
  }
38265
38514
  // 统一过滤掉不支持的文件类型
38266
38515
  const filteredFiles = [];
@@ -38272,11 +38521,24 @@ async function resolveNASLFiles(entry, logger, depMode, verbose) {
38272
38521
  logger.warn(`跳过不支持的文件类型: ${file.path}`);
38273
38522
  }
38274
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
+ }
38275
38535
  return {
38276
38536
  collectedFiles: filteredFiles,
38277
38537
  config,
38278
38538
  projectRoot,
38279
38539
  srcDir,
38540
+ externalDependencies,
38541
+ mergedDependencies,
38280
38542
  };
38281
38543
  }
38282
38544
 
@@ -38287,19 +38549,20 @@ async function compile(entry, options) {
38287
38549
  const logger = options?.logger || defaultLogger;
38288
38550
  logger.info('开始编译 NASL 代码...');
38289
38551
  // 收集需要编译的文件
38290
- const { collectedFiles, config, projectRoot } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38552
+ const { collectedFiles, config, projectRoot, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38291
38553
  logger.info(`输出目录: ${config.outDir}`);
38292
- const outDir = sysPath.join(projectRoot, config.outDir);
38554
+ const outDir = path$1.join(projectRoot, config.outDir);
38293
38555
  // 调用编译 API
38294
38556
  logger.newLine();
38295
38557
  logger.info('正在调用编译服务...');
38296
38558
  try {
38297
- const fullNaturalTS = composeToString(collectedFiles);
38559
+ let fullNaturalTS = composeToString(collectedFiles);
38560
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38298
38561
  const outputFiles = await compileApi(fullNaturalTS, config);
38299
38562
  logger.success('编译成功!');
38300
38563
  // 写入输出文件
38301
38564
  for (const file of outputFiles) {
38302
- const outputPath = sysPath.join(outDir, file.path);
38565
+ const outputPath = path$1.join(outDir, file.path);
38303
38566
  writeFileWithLog(outputPath, file.content, logger);
38304
38567
  }
38305
38568
  logger.info(`输出 ${outputFiles.length} 个文件`);
@@ -38386,7 +38649,7 @@ async function check(entry, options) {
38386
38649
  const logger = options?.logger || defaultLogger;
38387
38650
  logger.info('开始检查 NASL 代码...');
38388
38651
  // 收集需要检查的文件
38389
- const { collectedFiles, config } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38652
+ const { collectedFiles, config, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38390
38653
  // 调用检查 API
38391
38654
  logger.newLine();
38392
38655
  logger.info('正在调用检查服务,对语法和语义进行检查...');
@@ -38394,6 +38657,7 @@ async function check(entry, options) {
38394
38657
  let result = '';
38395
38658
  try {
38396
38659
  fullNaturalTS = composeToString(collectedFiles);
38660
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38397
38661
  }
38398
38662
  catch (error) {
38399
38663
  result = error.message.trim();
@@ -38422,12 +38686,19 @@ async function check(entry, options) {
38422
38686
  }
38423
38687
 
38424
38688
  /**
38425
- * 检查命令 - 检查 NASL 代码的语法和语义
38689
+ * 依赖分析命令 - 从入口文件开始进行依赖分析
38426
38690
  */
38427
38691
  async function dep(entry, options) {
38428
- const logger = defaultLogger;
38692
+ const logger = options?.logger || defaultLogger;
38429
38693
  logger.info('开始进行依赖分析...');
38430
- 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;
38431
38702
  }
38432
38703
 
38433
38704
  /**
@@ -38437,15 +38708,15 @@ async function dev(entry, options) {
38437
38708
  const logger = options?.logger || new ConsoleLoggerWithoutExit();
38438
38709
  // 获取项目根目录和配置
38439
38710
  const projectRoot = process.cwd();
38440
- const configPath = sysPath.join(projectRoot, 'nasl.config.json');
38711
+ const configPath = path$1.join(projectRoot, 'nasl.config.json');
38441
38712
  if (!libExports.existsSync(configPath)) {
38442
38713
  logger.error('未找到 nasl.config.json 配置文件,请先初始化项目');
38443
38714
  process.exit(1);
38444
38715
  }
38445
38716
  const configContent = libExports.readFileSync(configPath, 'utf-8');
38446
38717
  const config = JSON.parse(configContent);
38447
- const srcDir = sysPath.join(projectRoot, config.srcDir);
38448
- 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);
38449
38720
  // 检查是否存在 src 目录
38450
38721
  const hasSrcDir = libExports.existsSync(srcDir) && libExports.statSync(srcDir).isDirectory();
38451
38722
  let lastCompileSuccess = false;
@@ -38495,7 +38766,7 @@ async function dev(entry, options) {
38495
38766
  // 过滤非目标文件类型
38496
38767
  if (!shouldHandleFile(filePath))
38497
38768
  return;
38498
- logger.info(`检测到文件变化: ${sysPath.relative(projectRoot, filePath)}`);
38769
+ logger.info(`检测到文件变化: ${path$1.relative(projectRoot, filePath)}`);
38499
38770
  if (isCompiling) {
38500
38771
  pendingCompile = true;
38501
38772
  return;
@@ -38612,7 +38883,7 @@ async function dev(entry, options) {
38612
38883
  async function startWebpackDevServer(outDir, options, logger) {
38613
38884
  logger?.newLine();
38614
38885
  logger?.info('正在启动开发服务...');
38615
- 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'));
38616
38887
  // 构建 webpack-cli 参数
38617
38888
  let webpackArgs = `${require.resolve('.bin/webpack-cli')} serve --config ${configRelativePath}`;
38618
38889
  if (options?.port)
@@ -38656,7 +38927,7 @@ async function build(entry, options) {
38656
38927
  const { outDir } = await compile(entry);
38657
38928
  logger.newLine();
38658
38929
  logger.info('正在构建项目...');
38659
- 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'));
38660
38931
  const mode = options?.mode || 'production';
38661
38932
  // 构建 webpack-cli 参数
38662
38933
  let webpackArgs = `${require.resolve('.bin/webpack-cli')} build --config ${configRelativePath} --mode ${mode}`;
@@ -38667,8 +38938,8 @@ async function build(entry, options) {
38667
38938
  * 获取 specs 下第1个文件夹的名字
38668
38939
  */
38669
38940
  function getFirstSpecFolderName(projectRoot) {
38670
- const dirname = sysPath.basename(projectRoot);
38671
- const specsDir = sysPath.join(projectRoot, 'specs');
38941
+ const dirname = path$1.basename(projectRoot);
38942
+ const specsDir = path$1.join(projectRoot, 'specs');
38672
38943
  if (!libExports.existsSync(specsDir))
38673
38944
  return dirname;
38674
38945
  const entries = libExports.readdirSync(specsDir, { withFileTypes: true });
@@ -38759,6 +39030,8 @@ async function transformJson2FilesApi(json, options) {
38759
39030
  headers: { 'Content-Type': 'application/json' },
38760
39031
  });
38761
39032
  const data = res.data;
39033
+ if (data.code !== 200)
39034
+ throw new Error(data.message);
38762
39035
  return data.result;
38763
39036
  }
38764
39037
 
@@ -38769,7 +39042,7 @@ const transformFns = {
38769
39042
  async files2full(entry, options) {
38770
39043
  const logger = options?.logger || defaultLogger;
38771
39044
  // 收集需要处理的文件
38772
- const { collectedFiles, projectRoot } = await resolveNASLFiles(entry, logger, false, options?.verbose);
39045
+ const { collectedFiles, projectRoot, mergedDependencies } = await resolveNASLFiles(entry, logger, false, options?.verbose);
38773
39046
  if (collectedFiles.length === 0) {
38774
39047
  logger.error('未找到需要转换的文件');
38775
39048
  logger.exit(1);
@@ -38778,11 +39051,12 @@ const transformFns = {
38778
39051
  // 组合成 fullNaturalTS
38779
39052
  logger.newLine();
38780
39053
  logger.info('正在组合文件...');
38781
- const fullNaturalTS = composeToString(collectedFiles);
39054
+ let fullNaturalTS = composeToString(collectedFiles);
39055
+ fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
38782
39056
  // 确定输出路径
38783
39057
  const outputPath = options?.output
38784
- ? sysPath.resolve(projectRoot, options.output)
38785
- : sysPath.join(projectRoot, './full-natural.ts');
39058
+ ? path$1.resolve(projectRoot, options.output)
39059
+ : path$1.join(projectRoot, './full-natural.ts');
38786
39060
  // 写入文件
38787
39061
  writeFileWithLog(outputPath, fullNaturalTS, logger);
38788
39062
  logger.success(`文件已输出到: ${outputPath}`);
@@ -38812,7 +39086,7 @@ const transformFns = {
38812
39086
  }
38813
39087
  const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, config);
38814
39088
  await Promise.all(files.map(async (file) => {
38815
- const outputPath = sysPath.join(projectRoot, config.srcDir, file.path);
39089
+ const outputPath = path$1.join(projectRoot, config.srcDir, file.path);
38816
39090
  await libExports.writeFile(outputPath, file.content);
38817
39091
  }));
38818
39092
  logger.success(`JSON 文件已转换为 ${files.length} 个文件,输出到 ${config.srcDir}`);
@@ -38839,7 +39113,87 @@ async function transform(transformType, entry, options) {
38839
39113
  await transformFn(entry, options);
38840
39114
  }
38841
39115
 
38842
- var version = "0.2.3";
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";
38843
39197
  var pkg = {
38844
39198
  version: version};
38845
39199
 
@@ -38899,15 +39253,51 @@ program
38899
39253
  program
38900
39254
  .command('dep [entry]')
38901
39255
  .description('从入口文件开始进行依赖分析')
38902
- .action(async (entry) => {
39256
+ .option('--save', '将计算出的 externalDependencies 补充到 src/app.dependencies.json')
39257
+ .action(async (entry, options) => {
38903
39258
  try {
38904
- await dep(entry);
39259
+ await dep(entry, options);
38905
39260
  }
38906
39261
  catch (error) {
38907
39262
  defaultLogger.error(`查找依赖过程发生错误:${error.message}`);
38908
39263
  process.exit(1);
38909
39264
  }
38910
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
+ });
38911
39301
  program
38912
39302
  .command('dev [entry]')
38913
39303
  .description('启动开发服务')
@@ -39291,7 +39681,7 @@ const binaryExtensions = new Set([
39291
39681
  'xmind', 'xpi', 'xpm', 'xwd', 'xz',
39292
39682
  'z', 'zip', 'zipx',
39293
39683
  ]);
39294
- const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
39684
+ const isBinaryPath = (filePath) => binaryExtensions.has(path$1.extname(filePath).slice(1).toLowerCase());
39295
39685
  // TODO: emit errors properly. Example: EMFILE on Macos.
39296
39686
  const foreach = (val, fn) => {
39297
39687
  if (val instanceof Set) {
@@ -39344,7 +39734,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
39344
39734
  // emit based on events occurring for files from a directory's watcher in
39345
39735
  // case the file's watcher misses it (and rely on throttling to de-dupe)
39346
39736
  if (evPath && path !== evPath) {
39347
- 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));
39348
39738
  }
39349
39739
  };
39350
39740
  try {
@@ -39527,11 +39917,11 @@ class NodeFsHandler {
39527
39917
  */
39528
39918
  _watchWithNodeFs(path, listener) {
39529
39919
  const opts = this.fsw.options;
39530
- const directory = sysPath.dirname(path);
39531
- const basename = sysPath.basename(path);
39920
+ const directory = path$1.dirname(path);
39921
+ const basename = path$1.basename(path);
39532
39922
  const parent = this.fsw._getWatchedDir(directory);
39533
39923
  parent.add(basename);
39534
- const absolutePath = sysPath.resolve(path);
39924
+ const absolutePath = path$1.resolve(path);
39535
39925
  const options = {
39536
39926
  persistent: opts.persistent,
39537
39927
  };
@@ -39563,8 +39953,8 @@ class NodeFsHandler {
39563
39953
  if (this.fsw.closed) {
39564
39954
  return;
39565
39955
  }
39566
- const dirname = sysPath.dirname(file);
39567
- const basename = sysPath.basename(file);
39956
+ const dirname = path$1.dirname(file);
39957
+ const basename = path$1.basename(file);
39568
39958
  const parent = this.fsw._getWatchedDir(dirname);
39569
39959
  // stats is always present
39570
39960
  let prevStats = stats;
@@ -39671,7 +40061,7 @@ class NodeFsHandler {
39671
40061
  }
39672
40062
  _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
39673
40063
  // Normalize the directory name on Windows
39674
- directory = sysPath.join(directory, '');
40064
+ directory = path$1.join(directory, '');
39675
40065
  throttler = this.fsw._throttle('readdir', directory, 1000);
39676
40066
  if (!throttler)
39677
40067
  return;
@@ -39690,7 +40080,7 @@ class NodeFsHandler {
39690
40080
  return;
39691
40081
  }
39692
40082
  const item = entry.path;
39693
- let path = sysPath.join(directory, item);
40083
+ let path = path$1.join(directory, item);
39694
40084
  current.add(item);
39695
40085
  if (entry.stats.isSymbolicLink() &&
39696
40086
  (await this._handleSymlink(entry, directory, path, item))) {
@@ -39706,7 +40096,7 @@ class NodeFsHandler {
39706
40096
  if (item === target || (!target && !previous.has(item))) {
39707
40097
  this.fsw._incrReadyCount();
39708
40098
  // ensure relativeness of path is preserved in case of watcher reuse
39709
- path = sysPath.join(dir, sysPath.relative(dir, path));
40099
+ path = path$1.join(dir, path$1.relative(dir, path));
39710
40100
  this._addToNodeFs(path, initialAdd, wh, depth + 1);
39711
40101
  }
39712
40102
  })
@@ -39751,13 +40141,13 @@ class NodeFsHandler {
39751
40141
  * @returns closer for the watcher instance.
39752
40142
  */
39753
40143
  async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
39754
- const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
39755
- 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));
39756
40146
  if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
39757
40147
  this.fsw._emit(EV.ADD_DIR, dir, stats);
39758
40148
  }
39759
40149
  // ensure dir is tracked (harmless if redundant)
39760
- parentDir.add(sysPath.basename(dir));
40150
+ parentDir.add(path$1.basename(dir));
39761
40151
  this.fsw._getWatchedDir(dir);
39762
40152
  let throttler;
39763
40153
  let closer;
@@ -39809,7 +40199,7 @@ class NodeFsHandler {
39809
40199
  const follow = this.fsw.options.followSymlinks;
39810
40200
  let closer;
39811
40201
  if (stats.isDirectory()) {
39812
- const absPath = sysPath.resolve(path);
40202
+ const absPath = path$1.resolve(path);
39813
40203
  const targetPath = follow ? await realpath$1(path) : path;
39814
40204
  if (this.fsw.closed)
39815
40205
  return;
@@ -39825,7 +40215,7 @@ class NodeFsHandler {
39825
40215
  const targetPath = follow ? await realpath$1(path) : path;
39826
40216
  if (this.fsw.closed)
39827
40217
  return;
39828
- const parent = sysPath.dirname(wh.watchPath);
40218
+ const parent = path$1.dirname(wh.watchPath);
39829
40219
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
39830
40220
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
39831
40221
  closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
@@ -39833,7 +40223,7 @@ class NodeFsHandler {
39833
40223
  return;
39834
40224
  // preserve this symlink's target path
39835
40225
  if (targetPath !== undefined) {
39836
- this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
40226
+ this.fsw._symlinkPaths.set(path$1.resolve(path), targetPath);
39837
40227
  }
39838
40228
  }
39839
40229
  else {
@@ -39879,11 +40269,11 @@ function createPattern(matcher) {
39879
40269
  if (matcher.path === string)
39880
40270
  return true;
39881
40271
  if (matcher.recursive) {
39882
- const relative = sysPath.relative(matcher.path, string);
40272
+ const relative = path$1.relative(matcher.path, string);
39883
40273
  if (!relative) {
39884
40274
  return false;
39885
40275
  }
39886
- return !relative.startsWith('..') && !sysPath.isAbsolute(relative);
40276
+ return !relative.startsWith('..') && !path$1.isAbsolute(relative);
39887
40277
  }
39888
40278
  return false;
39889
40279
  };
@@ -39893,7 +40283,7 @@ function createPattern(matcher) {
39893
40283
  function normalizePath(path) {
39894
40284
  if (typeof path !== 'string')
39895
40285
  throw new Error('string expected');
39896
- path = sysPath.normalize(path);
40286
+ path = path$1.normalize(path);
39897
40287
  path = path.replace(/\\/g, '/');
39898
40288
  let prepend = false;
39899
40289
  if (path.startsWith('//'))
@@ -39953,21 +40343,21 @@ const toUnix = (string) => {
39953
40343
  };
39954
40344
  // Our version of upath.normalize
39955
40345
  // TODO: this is not equal to path-normalize module - investigate why
39956
- const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
40346
+ const normalizePathToUnix = (path) => toUnix(path$1.normalize(toUnix(path)));
39957
40347
  // TODO: refactor
39958
40348
  const normalizeIgnored = (cwd = '') => (path) => {
39959
40349
  if (typeof path === 'string') {
39960
- return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
40350
+ return normalizePathToUnix(path$1.isAbsolute(path) ? path : path$1.join(cwd, path));
39961
40351
  }
39962
40352
  else {
39963
40353
  return path;
39964
40354
  }
39965
40355
  };
39966
40356
  const getAbsolutePath = (path, cwd) => {
39967
- if (sysPath.isAbsolute(path)) {
40357
+ if (path$1.isAbsolute(path)) {
39968
40358
  return path;
39969
40359
  }
39970
- return sysPath.join(cwd, path);
40360
+ return path$1.join(cwd, path);
39971
40361
  };
39972
40362
  const EMPTY_SET = Object.freeze(new Set());
39973
40363
  /**
@@ -39999,7 +40389,7 @@ class DirEntry {
39999
40389
  }
40000
40390
  catch (err) {
40001
40391
  if (this._removeWatcher) {
40002
- this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
40392
+ this._removeWatcher(path$1.dirname(dir), path$1.basename(dir));
40003
40393
  }
40004
40394
  }
40005
40395
  }
@@ -40031,7 +40421,7 @@ class WatchHelper {
40031
40421
  const watchPath = path;
40032
40422
  this.path = path = path.replace(REPLACER_RE, '');
40033
40423
  this.watchPath = watchPath;
40034
- this.fullWatchPath = sysPath.resolve(watchPath);
40424
+ this.fullWatchPath = path$1.resolve(watchPath);
40035
40425
  this.dirParts = [];
40036
40426
  this.dirParts.forEach((parts) => {
40037
40427
  if (parts.length > 1)
@@ -40041,7 +40431,7 @@ class WatchHelper {
40041
40431
  this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
40042
40432
  }
40043
40433
  entryPath(entry) {
40044
- 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));
40045
40435
  }
40046
40436
  filterPath(entry) {
40047
40437
  const { stats } = entry;
@@ -40197,7 +40587,7 @@ class FSWatcher extends EventEmitter {
40197
40587
  return;
40198
40588
  results.forEach((item) => {
40199
40589
  if (item)
40200
- this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
40590
+ this.add(path$1.dirname(item), path$1.basename(_origAdd || item));
40201
40591
  });
40202
40592
  });
40203
40593
  return this;
@@ -40212,10 +40602,10 @@ class FSWatcher extends EventEmitter {
40212
40602
  const { cwd } = this.options;
40213
40603
  paths.forEach((path) => {
40214
40604
  // convert to absolute path unless relative path already matches
40215
- if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
40605
+ if (!path$1.isAbsolute(path) && !this._closers.has(path)) {
40216
40606
  if (cwd)
40217
- path = sysPath.join(cwd, path);
40218
- path = sysPath.resolve(path);
40607
+ path = path$1.join(cwd, path);
40608
+ path = path$1.resolve(path);
40219
40609
  }
40220
40610
  this._closePath(path);
40221
40611
  this._addIgnoredPath(path);
@@ -40269,7 +40659,7 @@ class FSWatcher extends EventEmitter {
40269
40659
  getWatched() {
40270
40660
  const watchList = {};
40271
40661
  this._watched.forEach((entry, dir) => {
40272
- 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;
40273
40663
  const index = key || ONE_DOT;
40274
40664
  watchList[index] = entry.getChildren().sort();
40275
40665
  });
@@ -40295,9 +40685,9 @@ class FSWatcher extends EventEmitter {
40295
40685
  return;
40296
40686
  const opts = this.options;
40297
40687
  if (isWindows)
40298
- path = sysPath.normalize(path);
40688
+ path = path$1.normalize(path);
40299
40689
  if (opts.cwd)
40300
- path = sysPath.relative(opts.cwd, path);
40690
+ path = path$1.relative(opts.cwd, path);
40301
40691
  const args = [path];
40302
40692
  if (stats != null)
40303
40693
  args.push(stats);
@@ -40353,7 +40743,7 @@ class FSWatcher extends EventEmitter {
40353
40743
  if (opts.alwaysStat &&
40354
40744
  stats === undefined &&
40355
40745
  (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
40356
- const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
40746
+ const fullPath = opts.cwd ? path$1.join(opts.cwd, path) : path;
40357
40747
  let stats;
40358
40748
  try {
40359
40749
  stats = await stat$2(fullPath);
@@ -40436,8 +40826,8 @@ class FSWatcher extends EventEmitter {
40436
40826
  const pollInterval = awf.pollInterval;
40437
40827
  let timeoutHandler;
40438
40828
  let fullPath = path;
40439
- if (this.options.cwd && !sysPath.isAbsolute(path)) {
40440
- 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);
40441
40831
  }
40442
40832
  const now = new Date();
40443
40833
  const writes = this._pendingWrites;
@@ -40508,7 +40898,7 @@ class FSWatcher extends EventEmitter {
40508
40898
  * @param directory path of the directory
40509
40899
  */
40510
40900
  _getWatchedDir(directory) {
40511
- const dir = sysPath.resolve(directory);
40901
+ const dir = path$1.resolve(directory);
40512
40902
  if (!this._watched.has(dir))
40513
40903
  this._watched.set(dir, new DirEntry(dir, this._boundRemove));
40514
40904
  return this._watched.get(dir);
@@ -40534,8 +40924,8 @@ class FSWatcher extends EventEmitter {
40534
40924
  // if what is being deleted is a directory, get that directory's paths
40535
40925
  // for recursive deleting and cleaning of watched object
40536
40926
  // if it is not a directory, nestedDirectoryChildren will be empty array
40537
- const path = sysPath.join(directory, item);
40538
- const fullPath = sysPath.resolve(path);
40927
+ const path = path$1.join(directory, item);
40928
+ const fullPath = path$1.resolve(path);
40539
40929
  isDirectory =
40540
40930
  isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
40541
40931
  // prevent duplicate handling in case of arriving here nearly simultaneously
@@ -40567,7 +40957,7 @@ class FSWatcher extends EventEmitter {
40567
40957
  // If we wait for this file to be fully written, cancel the wait.
40568
40958
  let relPath = path;
40569
40959
  if (this.options.cwd)
40570
- relPath = sysPath.relative(this.options.cwd, path);
40960
+ relPath = path$1.relative(this.options.cwd, path);
40571
40961
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
40572
40962
  const event = this._pendingWrites.get(relPath).cancelWait();
40573
40963
  if (event === EVENTS.ADD)
@@ -40588,8 +40978,8 @@ class FSWatcher extends EventEmitter {
40588
40978
  */
40589
40979
  _closePath(path) {
40590
40980
  this._closeFile(path);
40591
- const dir = sysPath.dirname(path);
40592
- this._getWatchedDir(dir).remove(sysPath.basename(path));
40981
+ const dir = path$1.dirname(path);
40982
+ this._getWatchedDir(dir).remove(path$1.basename(path));
40593
40983
  }
40594
40984
  /**
40595
40985
  * Closes only file-specific watchers