@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.
- package/dist/bin/nasl.mjs +591 -127
- package/dist/bin/nasl.mjs.map +1 -1
- package/dist/bin/naslc.mjs +322 -59
- package/dist/bin/naslc.mjs.map +1 -1
- package/dist/index.mjs +11683 -11254
- package/dist/index.mjs.map +1 -1
- package/out/apis/compileApi.d.ts.map +1 -1
- package/out/apis/compileApi.js +3 -2
- package/out/apis/compileApi.js.map +1 -1
- package/out/apis/dependencyApi.d.ts +29 -0
- package/out/apis/dependencyApi.d.ts.map +1 -0
- package/out/apis/dependencyApi.js +17 -0
- package/out/apis/dependencyApi.js.map +1 -0
- package/out/apis/index.d.ts +1 -0
- package/out/apis/index.d.ts.map +1 -1
- package/out/apis/index.js +1 -0
- package/out/apis/index.js.map +1 -1
- package/out/apis/openapi.d.ts +12 -0
- package/out/apis/openapi.d.ts.map +1 -1
- package/out/apis/openapi.js +15 -0
- package/out/apis/openapi.js.map +1 -1
- package/out/apis/transformApi.d.ts.map +1 -1
- package/out/apis/transformApi.js +2 -0
- package/out/apis/transformApi.js.map +1 -1
- package/out/bin/nasl.js +38 -2
- package/out/bin/nasl.js.map +1 -1
- package/out/commands/check.d.ts.map +1 -1
- package/out/commands/check.js +10 -1
- package/out/commands/check.js.map +1 -1
- package/out/commands/compile.d.ts.map +1 -1
- package/out/commands/compile.js +3 -2
- package/out/commands/compile.js.map +1 -1
- package/out/commands/dep.d.ts +4 -2
- package/out/commands/dep.d.ts.map +1 -1
- package/out/commands/dep.js +44 -2
- package/out/commands/dep.js.map +1 -1
- package/out/commands/index.d.ts +1 -0
- package/out/commands/index.d.ts.map +1 -1
- package/out/commands/index.js +1 -0
- package/out/commands/index.js.map +1 -1
- package/out/commands/install.d.ts +9 -0
- package/out/commands/install.d.ts.map +1 -0
- package/out/commands/install.js +123 -0
- package/out/commands/install.js.map +1 -0
- package/out/commands/transform.d.ts.map +1 -1
- package/out/commands/transform.js +3 -2
- package/out/commands/transform.js.map +1 -1
- package/out/constants/nasl-file-types.d.ts.map +1 -1
- package/out/constants/nasl-file-types.js +21 -0
- package/out/constants/nasl-file-types.js.map +1 -1
- package/out/services/compose.d.ts +8 -0
- package/out/services/compose.d.ts.map +1 -1
- package/out/services/compose.js +31 -1
- package/out/services/compose.js.map +1 -1
- package/out/services/resolve.d.ts +18 -0
- package/out/services/resolve.d.ts.map +1 -1
- package/out/services/resolve.js +208 -9
- package/out/services/resolve.js.map +1 -1
- package/out/types/api.d.ts +4 -0
- package/out/types/api.d.ts.map +1 -1
- package/out/types/config.d.ts +2 -0
- package/out/types/config.d.ts.map +1 -1
- package/out/types/config.js +1 -0
- package/out/types/config.js.map +1 -1
- package/out/utils/config.d.ts.map +1 -1
- package/out/utils/config.js +2 -0
- package/out/utils/config.js.map +1 -1
- package/out/utils/errorMapper.d.ts +14 -0
- package/out/utils/errorMapper.d.ts.map +1 -0
- package/out/utils/errorMapper.js +60 -0
- package/out/utils/errorMapper.js.map +1 -0
- 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
|
|
6
|
-
import
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
8203
|
-
const filePath =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
* @
|
|
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 =
|
|
38396
|
+
const absoluteSrcDir = path$1.resolve(srcDir);
|
|
38152
38397
|
const matchedFileSet = new Set();
|
|
38153
38398
|
matchedFiles.forEach((pathRelativeToRoot) => {
|
|
38154
38399
|
// 统一使用相对于 src 的路径
|
|
38155
|
-
const absoluteFilePath =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
38554
|
+
const outDir = path$1.join(projectRoot, config.outDir);
|
|
38283
38555
|
// 调用编译 API
|
|
38284
38556
|
logger.newLine();
|
|
38285
38557
|
logger.info('正在调用编译服务...');
|
|
38286
38558
|
try {
|
|
38287
|
-
|
|
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 =
|
|
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
|
-
*
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
38374
|
-
const 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(`检测到文件变化: ${
|
|
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 =
|
|
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 =
|
|
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 =
|
|
38597
|
-
const specsDir =
|
|
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
|
-
|
|
39054
|
+
let fullNaturalTS = composeToString(collectedFiles);
|
|
39055
|
+
fullNaturalTS = prependDependencies(fullNaturalTS, mergedDependencies);
|
|
38708
39056
|
// 确定输出路径
|
|
38709
39057
|
const outputPath = options?.output
|
|
38710
|
-
?
|
|
38711
|
-
:
|
|
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 =
|
|
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
|
-
|
|
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
|
-
.
|
|
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(
|
|
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(
|
|
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 =
|
|
39457
|
-
const basename =
|
|
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 =
|
|
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 =
|
|
39493
|
-
const basename =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
39681
|
-
const tracked = parentDir.has(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
40272
|
+
const relative = path$1.relative(matcher.path, string);
|
|
39809
40273
|
if (!relative) {
|
|
39810
40274
|
return false;
|
|
39811
40275
|
}
|
|
39812
|
-
return !relative.startsWith('..') && !
|
|
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 =
|
|
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(
|
|
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(
|
|
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 (
|
|
40357
|
+
if (path$1.isAbsolute(path)) {
|
|
39894
40358
|
return path;
|
|
39895
40359
|
}
|
|
39896
|
-
return
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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 (!
|
|
40605
|
+
if (!path$1.isAbsolute(path) && !this._closers.has(path)) {
|
|
40142
40606
|
if (cwd)
|
|
40143
|
-
path =
|
|
40144
|
-
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 ?
|
|
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 =
|
|
40688
|
+
path = path$1.normalize(path);
|
|
40225
40689
|
if (opts.cwd)
|
|
40226
|
-
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 ?
|
|
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 && !
|
|
40366
|
-
fullPath =
|
|
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 =
|
|
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 =
|
|
40464
|
-
const fullPath =
|
|
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 =
|
|
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 =
|
|
40518
|
-
this._getWatchedDir(dir).remove(
|
|
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
|