@nasl/cli 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/nasl.bundle.js +4970 -4941
- package/dist/bin/nasl.mjs +243 -51
- package/dist/bin/nasl.mjs.map +1 -1
- package/dist/bin/naslc.mjs +196 -16
- package/dist/bin/naslc.mjs.map +1 -1
- package/dist/index.mjs +212 -49
- package/dist/index.mjs.map +1 -1
- package/out/apis/compileApi.d.ts.map +1 -1
- package/out/apis/compileApi.js +2 -4
- package/out/apis/compileApi.js.map +1 -1
- package/out/apis/createAppApi.js +1 -1
- package/out/apis/createAppApi.js.map +1 -1
- package/out/apis/createAxios.d.ts +7 -1
- package/out/apis/createAxios.d.ts.map +1 -1
- package/out/apis/createAxios.js +34 -5
- package/out/apis/createAxios.js.map +1 -1
- package/out/apis/openapi.d.ts +34 -0
- package/out/apis/openapi.d.ts.map +1 -0
- package/out/apis/openapi.js +114 -0
- package/out/apis/openapi.js.map +1 -0
- package/out/apis/transformApi.d.ts +1 -1
- package/out/apis/transformApi.d.ts.map +1 -1
- package/out/apis/transformApi.js +4 -6
- package/out/apis/transformApi.js.map +1 -1
- package/out/bin/nasl.js +63 -1
- package/out/bin/nasl.js.map +1 -1
- package/out/commands/check.d.ts.map +1 -1
- package/out/commands/check.js +1 -4
- package/out/commands/check.js.map +1 -1
- package/out/commands/compile.d.ts.map +1 -1
- package/out/commands/compile.js +1 -4
- package/out/commands/compile.js.map +1 -1
- package/out/commands/transform.d.ts.map +1 -1
- package/out/commands/transform.js +7 -19
- package/out/commands/transform.js.map +1 -1
- package/out/types/api.d.ts +8 -0
- package/out/types/api.d.ts.map +1 -1
- package/out/types/command.d.ts +1 -0
- package/out/types/command.d.ts.map +1 -1
- package/out/types/config.d.ts +6 -0
- package/out/types/config.d.ts.map +1 -1
- package/out/types/config.js +2 -2
- package/out/types/config.js.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import require$$5 from 'assert';
|
|
|
11
11
|
import require$$3 from 'http';
|
|
12
12
|
import require$$4 from 'https';
|
|
13
13
|
import require$$0$6 from 'url';
|
|
14
|
-
import
|
|
14
|
+
import crypto$1 from 'crypto';
|
|
15
15
|
import http2 from 'http2';
|
|
16
16
|
import zlib from 'zlib';
|
|
17
17
|
import { spawn, spawnSync } from 'child_process';
|
|
@@ -24,10 +24,10 @@ import { resolve, join, relative, sep } from 'node:path';
|
|
|
24
24
|
* 默认配置
|
|
25
25
|
*/
|
|
26
26
|
const DEFAULT_CONFIG = {
|
|
27
|
-
serverBaseURL: 'https://nasl.lcap.163yun.com
|
|
27
|
+
serverBaseURL: 'https://nasl.lcap.163yun.com',
|
|
28
28
|
representation: 'NaturalTS',
|
|
29
29
|
namespaceResolution: 'filename-as-namespace',
|
|
30
|
-
ideVersion: '4.
|
|
30
|
+
ideVersion: '4.4',
|
|
31
31
|
srcDir: 'src',
|
|
32
32
|
outDir: 'out',
|
|
33
33
|
};
|
|
@@ -27652,7 +27652,7 @@ function requireForm_data () {
|
|
|
27652
27652
|
var parseUrl = require$$0$6.parse;
|
|
27653
27653
|
var fs = require$$0$3;
|
|
27654
27654
|
var Stream = stream$4.Stream;
|
|
27655
|
-
var crypto =
|
|
27655
|
+
var crypto = crypto$1;
|
|
27656
27656
|
var mime = requireMimeTypes();
|
|
27657
27657
|
var asynckit = requireAsynckit();
|
|
27658
27658
|
var setToStringTag = /*@__PURE__*/ requireEsSetTostringtag();
|
|
@@ -28561,7 +28561,7 @@ const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {
|
|
|
28561
28561
|
let str = '';
|
|
28562
28562
|
const {length} = alphabet;
|
|
28563
28563
|
const randomValues = new Uint32Array(size);
|
|
28564
|
-
|
|
28564
|
+
crypto$1.randomFillSync(randomValues);
|
|
28565
28565
|
for (let i = 0; i < size; i++) {
|
|
28566
28566
|
str += alphabet[randomValues[i] % length];
|
|
28567
28567
|
}
|
|
@@ -34346,14 +34346,199 @@ const {
|
|
|
34346
34346
|
mergeConfig
|
|
34347
34347
|
} = axios;
|
|
34348
34348
|
|
|
34349
|
-
|
|
34350
|
-
|
|
34349
|
+
// Unique ID creation requires a high quality random # generator. In the browser we therefore
|
|
34350
|
+
// require the crypto API and do not support built-in fallback to lower quality random number
|
|
34351
|
+
// generators (like Math.random()).
|
|
34352
|
+
let getRandomValues;
|
|
34353
|
+
const rnds8 = new Uint8Array(16);
|
|
34354
|
+
function rng() {
|
|
34355
|
+
// lazy load so that environments that need to polyfill have a chance to do so
|
|
34356
|
+
if (!getRandomValues) {
|
|
34357
|
+
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
|
|
34358
|
+
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
34359
|
+
|
|
34360
|
+
if (!getRandomValues) {
|
|
34361
|
+
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
34362
|
+
}
|
|
34363
|
+
}
|
|
34364
|
+
|
|
34365
|
+
return getRandomValues(rnds8);
|
|
34366
|
+
}
|
|
34367
|
+
|
|
34368
|
+
/**
|
|
34369
|
+
* Convert array of 16 byte values to UUID string format of the form:
|
|
34370
|
+
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
34371
|
+
*/
|
|
34372
|
+
|
|
34373
|
+
const byteToHex = [];
|
|
34374
|
+
|
|
34375
|
+
for (let i = 0; i < 256; ++i) {
|
|
34376
|
+
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
34377
|
+
}
|
|
34378
|
+
|
|
34379
|
+
function unsafeStringify(arr, offset = 0) {
|
|
34380
|
+
// Note: Be careful editing this code! It's been tuned for performance
|
|
34381
|
+
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
|
|
34382
|
+
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
34383
|
+
}
|
|
34384
|
+
|
|
34385
|
+
const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
34386
|
+
var native = {
|
|
34387
|
+
randomUUID
|
|
34388
|
+
};
|
|
34389
|
+
|
|
34390
|
+
function v4(options, buf, offset) {
|
|
34391
|
+
if (native.randomUUID && true && !options) {
|
|
34392
|
+
return native.randomUUID();
|
|
34393
|
+
}
|
|
34394
|
+
|
|
34395
|
+
options = options || {};
|
|
34396
|
+
const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
34397
|
+
|
|
34398
|
+
rnds[6] = rnds[6] & 0x0f | 0x40;
|
|
34399
|
+
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
|
|
34400
|
+
|
|
34401
|
+
return unsafeStringify(rnds);
|
|
34402
|
+
}
|
|
34403
|
+
|
|
34404
|
+
/**
|
|
34405
|
+
* 构建签名字符串
|
|
34406
|
+
*/
|
|
34407
|
+
function buildStringToSign(appKey, nonce, timestamp, secretKey) {
|
|
34408
|
+
return `${appKey}&${nonce}&${timestamp}&${secretKey}`;
|
|
34409
|
+
}
|
|
34410
|
+
/**
|
|
34411
|
+
* 生成 MD5 签名
|
|
34412
|
+
*/
|
|
34413
|
+
function generateSignature(plainText) {
|
|
34414
|
+
return crypto$1.createHash('md5').update(plainText).digest('hex');
|
|
34415
|
+
}
|
|
34416
|
+
/**
|
|
34417
|
+
* 生成客户端签名信息
|
|
34418
|
+
* @param appKey AppKey
|
|
34419
|
+
* @param secretKey SecretKey
|
|
34420
|
+
* @returns 签名信息
|
|
34421
|
+
*/
|
|
34422
|
+
function generateClientSignature(appKey, secretKey) {
|
|
34423
|
+
const timestamp = Math.floor(Date.now() / 1000).toString();
|
|
34424
|
+
const nonce = v4();
|
|
34425
|
+
const plainText = buildStringToSign(appKey, nonce, timestamp, secretKey);
|
|
34426
|
+
const signature = generateSignature(plainText);
|
|
34427
|
+
return {
|
|
34428
|
+
appKey,
|
|
34429
|
+
timestamp,
|
|
34430
|
+
nonce,
|
|
34431
|
+
signature,
|
|
34432
|
+
};
|
|
34433
|
+
}
|
|
34434
|
+
/**
|
|
34435
|
+
* 生成基础认证头
|
|
34436
|
+
* @param ak AppKey
|
|
34437
|
+
* @param sk SecretKey
|
|
34438
|
+
* @returns 基础认证头
|
|
34439
|
+
*/
|
|
34440
|
+
function generateBaseHeaders(ak, sk) {
|
|
34441
|
+
const { timestamp, signature, nonce } = generateClientSignature(ak, sk);
|
|
34442
|
+
return {
|
|
34443
|
+
'Content-Type': 'application/json',
|
|
34444
|
+
'x-appKey': ak,
|
|
34445
|
+
'x-timestamp': timestamp,
|
|
34446
|
+
'x-nonce': nonce,
|
|
34447
|
+
'x-signature': signature,
|
|
34448
|
+
};
|
|
34449
|
+
}
|
|
34450
|
+
/**
|
|
34451
|
+
* 获取租户的 signInfo
|
|
34452
|
+
* @param options 服务器选项
|
|
34453
|
+
* @param baseHeaders 基础认证头
|
|
34454
|
+
* @returns x-signInfo 值
|
|
34455
|
+
*/
|
|
34456
|
+
async function fetchSignInfo(options, baseHeaders) {
|
|
34457
|
+
const tenantName = options.tenantName || 'defaulttenant';
|
|
34458
|
+
const userName = tenantName === 'defaulttenant' ? 'admin' : `${tenantName}-admin`;
|
|
34459
|
+
const data = {
|
|
34460
|
+
tenantName,
|
|
34461
|
+
userName,
|
|
34462
|
+
source: 'Normal',
|
|
34463
|
+
};
|
|
34464
|
+
const url = `${options.serverBaseURL}/openapi/v3/auth/getSignInfo`;
|
|
34465
|
+
try {
|
|
34466
|
+
const tempAxios = axios.create({
|
|
34467
|
+
headers: baseHeaders,
|
|
34468
|
+
timeout: 120000,
|
|
34469
|
+
});
|
|
34470
|
+
const response = await tempAxios.post(url, data);
|
|
34471
|
+
return response?.data?.result || null;
|
|
34472
|
+
}
|
|
34473
|
+
catch (error) {
|
|
34474
|
+
console.error('Error fetching sign info:', error.response?.data);
|
|
34475
|
+
return null;
|
|
34476
|
+
}
|
|
34477
|
+
}
|
|
34478
|
+
/**
|
|
34479
|
+
* 生成完整的认证头(包含 x-signInfo)
|
|
34480
|
+
* @param options 服务器选项
|
|
34481
|
+
* @returns 完整的认证头
|
|
34482
|
+
*/
|
|
34483
|
+
async function generateCompleteHeaders(options) {
|
|
34484
|
+
const headers = {
|
|
34485
|
+
'Content-Type': 'application/json',
|
|
34486
|
+
};
|
|
34487
|
+
const OPENAPI_AK = options.OPENAPI_AK || process.env.LCAP_OPENAPI_AK;
|
|
34488
|
+
const OPENAPI_SK = options.OPENAPI_SK || process.env.LCAP_OPENAPI_SK;
|
|
34489
|
+
// 如果没有提供 ak 和 sk,返回基础 headers
|
|
34490
|
+
if (!OPENAPI_AK || !OPENAPI_SK) {
|
|
34491
|
+
throw new Error(`配置了 useOPENAPI,但没有提供 OPENAPI_AK 和 OPENAPI_SK:
|
|
34492
|
+
- 可取消配置 useOPENAPI
|
|
34493
|
+
- 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK`);
|
|
34494
|
+
}
|
|
34495
|
+
// 生成基础认证头
|
|
34496
|
+
const baseHeaders = generateBaseHeaders(OPENAPI_AK, OPENAPI_SK);
|
|
34497
|
+
Object.assign(headers, baseHeaders);
|
|
34498
|
+
// 获取 signInfo
|
|
34499
|
+
const signInfo = await fetchSignInfo(options, headers);
|
|
34500
|
+
if (signInfo) {
|
|
34501
|
+
headers['x-signInfo'] = signInfo;
|
|
34502
|
+
}
|
|
34503
|
+
return headers;
|
|
34504
|
+
}
|
|
34505
|
+
|
|
34506
|
+
/**
|
|
34507
|
+
* 创建 Axios 实例
|
|
34508
|
+
* @param options 服务器选项,包含认证信息
|
|
34509
|
+
* @returns Axios 实例
|
|
34510
|
+
*/
|
|
34511
|
+
async function createAxios(options) {
|
|
34512
|
+
// 如果需要鉴权,拼接 /openapi/v3/nasl;否则使用原始 URL
|
|
34513
|
+
const serverBaseURL = new URL(options.serverBaseURL).origin;
|
|
34514
|
+
const useOPENAPI = options.useOPENAPI || process.env.USE_LCAP_OPENAPI === 'true';
|
|
34515
|
+
const baseURL = useOPENAPI ? `${serverBaseURL}/openapi/v3/nasl` : `${serverBaseURL}/api/v1/nasl`;
|
|
34516
|
+
// 如果需要鉴权,生成完整的认证头;否则只使用基础 headers
|
|
34517
|
+
const headers = useOPENAPI ? await generateCompleteHeaders(options) : { 'Content-Type': 'application/json' };
|
|
34518
|
+
console.log('本次服务调用方为:', baseURL);
|
|
34519
|
+
const instance = axios.create({
|
|
34351
34520
|
baseURL,
|
|
34352
|
-
headers
|
|
34353
|
-
'Content-Type': 'application/json',
|
|
34354
|
-
},
|
|
34521
|
+
headers,
|
|
34355
34522
|
timeout: 120000,
|
|
34356
34523
|
});
|
|
34524
|
+
const oldPost = instance.post;
|
|
34525
|
+
instance.post = async (url, data, config) => {
|
|
34526
|
+
return oldPost(url, data, config).then((res) => {
|
|
34527
|
+
const data = res.data;
|
|
34528
|
+
if (data.code !== 200)
|
|
34529
|
+
throw new Error(JSON.stringify(data));
|
|
34530
|
+
return res;
|
|
34531
|
+
}).catch((err) => {
|
|
34532
|
+
// console.log(err.response ? err.response.data : err);
|
|
34533
|
+
if (err.response) {
|
|
34534
|
+
throw new Error(JSON.stringify(err.response.data));
|
|
34535
|
+
}
|
|
34536
|
+
else {
|
|
34537
|
+
throw err;
|
|
34538
|
+
}
|
|
34539
|
+
});
|
|
34540
|
+
};
|
|
34541
|
+
return instance;
|
|
34357
34542
|
}
|
|
34358
34543
|
|
|
34359
34544
|
function truncate(str, maxLength) {
|
|
@@ -34367,13 +34552,11 @@ function truncate(str, maxLength) {
|
|
|
34367
34552
|
async function compileApi(fullNaturalTS, options) {
|
|
34368
34553
|
// 这里需要调用实际的编译服务接口
|
|
34369
34554
|
// 示例实现:
|
|
34370
|
-
const axios = createAxios(options
|
|
34555
|
+
const axios = await createAxios(options);
|
|
34371
34556
|
const res = await axios.post(`/compile/tsx?ideVersion=${options.ideVersion}&needAnnotation=true`, fullNaturalTS, {
|
|
34372
34557
|
headers: { 'Content-Type': 'text/plain' },
|
|
34373
34558
|
});
|
|
34374
34559
|
const data = res.data;
|
|
34375
|
-
if (data.code !== 200)
|
|
34376
|
-
throw new Error(data.message);
|
|
34377
34560
|
const { bundle } = data.result;
|
|
34378
34561
|
const fileMap = bundle.frontendBundle.files;
|
|
34379
34562
|
const files = Object.keys(fileMap).map((key) => {
|
|
@@ -34401,7 +34584,7 @@ window.backendApp = app;
|
|
|
34401
34584
|
* TODO: 实现具体的 API 调用逻辑
|
|
34402
34585
|
*/
|
|
34403
34586
|
async function checkApi(fullNaturalTS, options) {
|
|
34404
|
-
const axios = createAxios(options
|
|
34587
|
+
const axios = await createAxios(options);
|
|
34405
34588
|
const res = await axios.post(`/check/tsx?ideVersion=${options.ideVersion}`, fullNaturalTS, {
|
|
34406
34589
|
headers: { 'Content-Type': 'text/plain' },
|
|
34407
34590
|
});
|
|
@@ -34419,7 +34602,7 @@ async function checkApi(fullNaturalTS, options) {
|
|
|
34419
34602
|
async function createAppSyncApi(fullNaturalTS, options) {
|
|
34420
34603
|
const url = new URL(options.serverBaseURL);
|
|
34421
34604
|
const origin = url.origin + '/app-ai-creator';
|
|
34422
|
-
const axios = createAxios(origin);
|
|
34605
|
+
const axios = await createAxios({ serverBaseURL: origin});
|
|
34423
34606
|
try {
|
|
34424
34607
|
const res = await axios.post('/api/createAppSync', {
|
|
34425
34608
|
fullNaturalTS,
|
|
@@ -34466,10 +34649,7 @@ async function compile(entry, options) {
|
|
|
34466
34649
|
logger.info('正在调用编译服务...');
|
|
34467
34650
|
try {
|
|
34468
34651
|
const fullNaturalTS = composeToString(collectedFiles);
|
|
34469
|
-
const outputFiles = await compileApi(fullNaturalTS,
|
|
34470
|
-
serverBaseURL: config.serverBaseURL,
|
|
34471
|
-
ideVersion: config.ideVersion,
|
|
34472
|
-
});
|
|
34652
|
+
const outputFiles = await compileApi(fullNaturalTS, config);
|
|
34473
34653
|
logger.success('编译成功!');
|
|
34474
34654
|
// 写入输出文件
|
|
34475
34655
|
for (const file of outputFiles) {
|
|
@@ -34516,10 +34696,7 @@ async function check(entry, options) {
|
|
|
34516
34696
|
result = error.message.trim();
|
|
34517
34697
|
}
|
|
34518
34698
|
if (!result && fullNaturalTS) {
|
|
34519
|
-
result = (await checkApi(fullNaturalTS,
|
|
34520
|
-
serverBaseURL: config.serverBaseURL,
|
|
34521
|
-
ideVersion: config.ideVersion,
|
|
34522
|
-
})).trim();
|
|
34699
|
+
result = (await checkApi(fullNaturalTS, config)).trim();
|
|
34523
34700
|
}
|
|
34524
34701
|
const checkResult = {
|
|
34525
34702
|
success: !result,
|
|
@@ -34859,15 +35036,13 @@ async function createAppInIde(entry, options) {
|
|
|
34859
35036
|
* 编译 NASL 代码
|
|
34860
35037
|
* TODO: 实现具体的 API 调用逻辑
|
|
34861
35038
|
*/
|
|
34862
|
-
async function transformJson2FilesApi(
|
|
35039
|
+
async function transformJson2FilesApi(json, options) {
|
|
34863
35040
|
// 示例实现:
|
|
34864
|
-
const axios = createAxios(options
|
|
34865
|
-
const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`,
|
|
34866
|
-
headers: { 'Content-Type': '
|
|
35041
|
+
const axios = await createAxios(options);
|
|
35042
|
+
const res = await axios.post(`/transform/json2files?ideVersion=${options.ideVersion}`, json, {
|
|
35043
|
+
headers: { 'Content-Type': 'application/json' },
|
|
34867
35044
|
});
|
|
34868
35045
|
const data = res.data;
|
|
34869
|
-
if (data.code !== 200)
|
|
34870
|
-
throw new Error(data.message);
|
|
34871
35046
|
return data.result;
|
|
34872
35047
|
}
|
|
34873
35048
|
|
|
@@ -34907,14 +35082,19 @@ const transformFns = {
|
|
|
34907
35082
|
const projectRoot = getProjectRoot();
|
|
34908
35083
|
logger.info(`项目根目录: ${projectRoot}`);
|
|
34909
35084
|
logger.info(`源代码目录: ${config.srcDir}`);
|
|
35085
|
+
if (!libExports.existsSync(config.srcDir)) {
|
|
35086
|
+
logger.error(`当前目录下 ${config.srcDir} 目录不存在,请先创建`);
|
|
35087
|
+
logger.exit(1);
|
|
35088
|
+
}
|
|
34910
35089
|
let jsonContent = '';
|
|
34911
35090
|
if (!entry) {
|
|
34912
35091
|
logger.warn('没有指定 JSON 文件路径,按照默认 IDE 版本的基础模板转换');
|
|
34913
35092
|
}
|
|
34914
35093
|
else {
|
|
34915
35094
|
jsonContent = libExports.readFileSync(entry, 'utf-8');
|
|
35095
|
+
logger.info(`读取到 JSON 文件: ${entry}`);
|
|
34916
35096
|
}
|
|
34917
|
-
const files = await transformJson2FilesApi(jsonContent, {
|
|
35097
|
+
const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, {
|
|
34918
35098
|
serverBaseURL: config.serverBaseURL,
|
|
34919
35099
|
ideVersion: config.ideVersion,
|
|
34920
35100
|
});
|
|
@@ -34928,25 +35108,8 @@ const transformFns = {
|
|
|
34928
35108
|
* 将 src 中的文件转换成一个 JSON
|
|
34929
35109
|
*/
|
|
34930
35110
|
async files2json(entry, options) {
|
|
34931
|
-
|
|
34932
|
-
|
|
34933
|
-
const { collectedFiles, projectRoot } = await resolveNASLFiles(entry, logger, false, options?.verbose);
|
|
34934
|
-
if (collectedFiles.length === 0) {
|
|
34935
|
-
logger.error('未找到需要转换的文件');
|
|
34936
|
-
logger.exit(1);
|
|
34937
|
-
}
|
|
34938
|
-
logger.info(`找到 ${collectedFiles.length} 个文件`);
|
|
34939
|
-
// 转换为 JSON
|
|
34940
|
-
logger.newLine();
|
|
34941
|
-
logger.info('正在转换为 JSON...');
|
|
34942
|
-
const jsonContent = JSON.stringify(collectedFiles, null, 2);
|
|
34943
|
-
// 确定输出路径
|
|
34944
|
-
const outputPath = options?.output
|
|
34945
|
-
? sysPath.resolve(projectRoot, options.output)
|
|
34946
|
-
: sysPath.join(projectRoot, './files.json');
|
|
34947
|
-
// 写入文件
|
|
34948
|
-
writeFileWithLog(outputPath, jsonContent, logger);
|
|
34949
|
-
logger.success(`JSON 文件已输出到: ${outputPath}`);
|
|
35111
|
+
options?.logger || defaultLogger;
|
|
35112
|
+
throw new Error('files2json 转换类型尚未实现');
|
|
34950
35113
|
},
|
|
34951
35114
|
};
|
|
34952
35115
|
/**
|