@nasl/cli 0.1.17 → 0.1.18
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/README.md +113 -11
- package/dist/bin/nasl.mjs +151 -34
- package/dist/bin/nasl.mjs.map +1 -1
- package/dist/bin/naslc.mjs +143 -27
- package/dist/bin/naslc.mjs.map +1 -1
- package/dist/index.mjs +150 -33
- package/dist/index.mjs.map +1 -1
- package/out/apis/cachable.d.ts +16 -0
- package/out/apis/cachable.d.ts.map +1 -0
- package/out/apis/cachable.js +142 -0
- package/out/apis/cachable.js.map +1 -0
- package/out/apis/createAxios.d.ts.map +1 -1
- package/out/apis/createAxios.js +2 -3
- package/out/apis/createAxios.js.map +1 -1
- package/out/apis/openapi.d.ts +5 -2
- package/out/apis/openapi.d.ts.map +1 -1
- package/out/apis/openapi.js +21 -25
- package/out/apis/openapi.js.map +1 -1
- package/out/commands/createAppInIde.d.ts.map +1 -1
- package/out/commands/createAppInIde.js +4 -0
- package/out/commands/createAppInIde.js.map +1 -1
- package/out/commands/transform.d.ts.map +1 -1
- package/out/commands/transform.js +1 -4
- package/out/commands/transform.js.map +1 -1
- package/out/utils/config.d.ts.map +1 -1
- package/out/utils/config.js +31 -2
- package/out/utils/config.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,12 +7,12 @@ NASL 语言的命令行工具,提供编译、检查、开发服务等功能。
|
|
|
7
7
|
## 安装
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
npm install -g @nasl/cli
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## 使用
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### 初始化配置(nasl init)
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
nasl init
|
|
@@ -22,16 +22,15 @@ nasl init
|
|
|
22
22
|
|
|
23
23
|
```json
|
|
24
24
|
{
|
|
25
|
-
"serverBaseURL": "https://nasl.lcap.163yun.com
|
|
25
|
+
"serverBaseURL": "https://nasl.lcap.163yun.com", // NASL 编译服务的基础 URL
|
|
26
26
|
"representation": "NaturalTS", // NASL 语言的表示
|
|
27
27
|
"namespaceResolution": "filename-as-namespace", // 命名空间解析策略
|
|
28
|
-
"ideVersion": "4.
|
|
28
|
+
"ideVersion": "4.4", // IDE 版本
|
|
29
29
|
"srcDir": "src", // 源代码目录
|
|
30
30
|
"outDir": "out" // 输出目录
|
|
31
31
|
}
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
### 入口文件说明
|
|
36
35
|
|
|
37
36
|
下面的命令中均支持 [entry] 参数,表示入口文件:
|
|
@@ -47,7 +46,7 @@ nasl init
|
|
|
47
46
|
- 会自动进行依赖分析,收集所有依赖的文件
|
|
48
47
|
- 依赖的页面文件(.tsx)不会继续进行依赖分析,而是直接提取签名,以提高性能
|
|
49
48
|
|
|
50
|
-
### 编译 NASL
|
|
49
|
+
### 编译 NASL 代码(nasl compile 或 naslc)
|
|
51
50
|
|
|
52
51
|
```bash
|
|
53
52
|
# 编译整个 src 目录
|
|
@@ -63,7 +62,7 @@ naslc "src/app.logics.*.ts"
|
|
|
63
62
|
naslc "src/*.tsx"
|
|
64
63
|
```
|
|
65
64
|
|
|
66
|
-
### 检查 NASL
|
|
65
|
+
### 检查 NASL 代码(nasl check)
|
|
67
66
|
|
|
68
67
|
```bash
|
|
69
68
|
# 检查整个 src 目录
|
|
@@ -77,7 +76,7 @@ nasl check "src/app.logics.*.ts"
|
|
|
77
76
|
nasl check "src/*.tsx"
|
|
78
77
|
```
|
|
79
78
|
|
|
80
|
-
###
|
|
79
|
+
### 依赖分析(nasl dep)
|
|
81
80
|
|
|
82
81
|
建议指定入口文件,否则会扫描整个 src 目录,输出量较大。
|
|
83
82
|
|
|
@@ -89,13 +88,19 @@ nasl dep "src/*.tsx"
|
|
|
89
88
|
nasl dep
|
|
90
89
|
```
|
|
91
90
|
|
|
92
|
-
###
|
|
91
|
+
### 启动开发服务(nasl dev)
|
|
93
92
|
|
|
94
93
|
```bash
|
|
95
94
|
nasl dev
|
|
96
95
|
```
|
|
97
96
|
|
|
98
|
-
|
|
97
|
+
启动开发服务后,默认访问 http://localhost:3100 查看预览效果。
|
|
98
|
+
|
|
99
|
+
可以用 --port 和 --host 更换端口号和主机名。
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
nasl dev --port 4900 --host 0.0.0.0
|
|
103
|
+
```
|
|
99
104
|
|
|
100
105
|
dev 进程始终保持运行,规则如下:
|
|
101
106
|
|
|
@@ -109,7 +114,104 @@ dev 进程始终保持运行,规则如下:
|
|
|
109
114
|
2. src 被创建:自动编译生成 out 目录
|
|
110
115
|
3. src 被删除: 使用缓存的 out 目录
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
### 构建项目(nasl build)
|
|
118
|
+
|
|
119
|
+
与 nasl dev 对应,构建成最终用于浏览器的 dist 产物。
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# 使用生产模式构建(默认)
|
|
123
|
+
nasl build
|
|
124
|
+
|
|
125
|
+
# 使用开发模式构建
|
|
126
|
+
nasl build --mode development
|
|
127
|
+
|
|
128
|
+
# 构建指定入口文件及其依赖
|
|
129
|
+
nasl build src/app.frontendTypes.pc.frontends.pc.views.dashboard.tsx
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 转换文件格式(nasl transform)
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# files2full: 将 src 中的文件组合成 fullNaturalTS
|
|
136
|
+
nasl transform files2full [entry] --output [outputPath]
|
|
137
|
+
# 默认输出到 ./full-natural.ts
|
|
138
|
+
|
|
139
|
+
# json2files: 将 JSON 文件转换成 src 的 files
|
|
140
|
+
nasl transform json2files [jsonFile] --output [outputPath]
|
|
141
|
+
# 如果不指定 jsonFile,将按照默认 IDE 版本的基础模板转换
|
|
142
|
+
|
|
143
|
+
# files2json: 将 src 中的文件转换成一个 JSON(待实现)
|
|
144
|
+
nasl transform files2json [entry] --output [outputPath]
|
|
145
|
+
# 默认输出到 ./files.json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 在 IDE 中直接创建应用(nasl create-app-in-ide)
|
|
149
|
+
|
|
150
|
+
**注意**:目前该命令不支持 useOPENAPI 模式,只在测试环境使用。
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# 会询问确认(默认)
|
|
154
|
+
nasl create-app-in-ide [entry]
|
|
155
|
+
|
|
156
|
+
# 跳过确认,直接执行
|
|
157
|
+
nasl create-app-in-ide [entry] --quiet
|
|
158
|
+
|
|
159
|
+
# 显示详细信息
|
|
160
|
+
nasl create-app-in-ide [entry] --verbose
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
此命令会将当前项目的 NASL 代码上传到远程服务,在 IDE 中创建新的应用。默认会询问用户确认,使用 `--quiet` 选项可以跳过确认。
|
|
164
|
+
|
|
165
|
+
## 环境变量配置
|
|
166
|
+
|
|
167
|
+
除了在 `nasl.config.json` 中配置外,也可以通过环境变量来配置部分选项。环境变量的优先级低于配置文件。
|
|
168
|
+
|
|
169
|
+
### 支持的环境变量
|
|
170
|
+
|
|
171
|
+
- `NASL_IDE_VERSION`: IDE 版本号,对应配置`ideVersion`字段
|
|
172
|
+
```bash
|
|
173
|
+
export NASL_IDE_VERSION=4.4
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- `NASL_SERVER_BASE_URL`: NASL 编译服务的基础 URL,对应配置`serverBaseURL`字段
|
|
177
|
+
```bash
|
|
178
|
+
export NASL_SERVER_BASE_URL=https://nasl.lcap.163yun.com
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- `USE_LCAP_OPENAPI`: 是否使用 OpenAPI 方式调用(值为 `'true'` 时启用),对应配置`useOPENAPI`字段
|
|
182
|
+
```bash
|
|
183
|
+
export USE_LCAP_OPENAPI=true
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- `LCAP_OPENAPI_AK`: LCAP OpenAPI Access Key(使用 OpenAPI 时必需),对应配置`OPENAPI_AK`字段
|
|
187
|
+
```bash
|
|
188
|
+
export LCAP_OPENAPI_AK=your_access_key
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
- `LCAP_OPENAPI_SK`: LCAP OpenAPI Secret Key(使用 OpenAPI 时必需),对应配置`OPENAPI_SK`字段
|
|
192
|
+
```bash
|
|
193
|
+
export LCAP_OPENAPI_SK=your_secret_key
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 配置文件示例(包含 OpenAPI 配置)
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"serverBaseURL": "https://sometenant.codewave.163.com",
|
|
201
|
+
"representation": "NaturalTS",
|
|
202
|
+
"namespaceResolution": "filename-as-namespace",
|
|
203
|
+
"ideVersion": "4.4",
|
|
204
|
+
"srcDir": "src",
|
|
205
|
+
"outDir": "out",
|
|
206
|
+
"useOPENAPI": true,
|
|
207
|
+
"OPENAPI_AK": "your_access_key",
|
|
208
|
+
"OPENAPI_SK": "your_secret_key"
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
注意:如果配置了 `useOPENAPI: true`,则必须同时配置 `OPENAPI_AK` 和 `OPENAPI_SK`(可在配置文件中配置,或通过环境变量 `LCAP_OPENAPI_AK` 和 `LCAP_OPENAPI_SK` 配置)。
|
|
213
|
+
|
|
214
|
+
## DEVELOPMENT
|
|
113
215
|
|
|
114
216
|
```bash
|
|
115
217
|
# 安装依赖
|
package/dist/bin/nasl.mjs
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import require$$0$1, { EventEmitter } from 'events';
|
|
4
4
|
import require$$1, { spawn, spawnSync } from 'child_process';
|
|
5
5
|
import * as sysPath from 'path';
|
|
6
|
-
import sysPath__default from 'path';
|
|
7
|
-
import require$$0$2, { unwatchFile, watchFile, watch as watch$1, stat as stat$3 } from 'fs';
|
|
6
|
+
import sysPath__default, { join } from 'path';
|
|
7
|
+
import require$$0$2, { promises, unwatchFile, watchFile, watch as watch$1, stat as stat$3 } from 'fs';
|
|
8
8
|
import require$$4 from 'process';
|
|
9
9
|
import require$$0$3 from 'constants';
|
|
10
10
|
import stream$4, { Readable } from 'stream';
|
|
@@ -15,14 +15,14 @@ import require$$1$1 from 'tty';
|
|
|
15
15
|
import require$$3 from 'http';
|
|
16
16
|
import require$$4$1 from 'https';
|
|
17
17
|
import require$$0$6 from 'url';
|
|
18
|
-
import crypto$1 from 'crypto';
|
|
18
|
+
import crypto$1, { createHash } from 'crypto';
|
|
19
19
|
import http2 from 'http2';
|
|
20
20
|
import zlib from 'zlib';
|
|
21
21
|
import * as readline from 'readline';
|
|
22
22
|
import { realpath as realpath$1, stat as stat$2, lstat as lstat$1, open, readdir as readdir$1 } from 'fs/promises';
|
|
23
23
|
import { lstat, stat as stat$1, readdir, realpath } from 'node:fs/promises';
|
|
24
24
|
import { Readable as Readable$1 } from 'node:stream';
|
|
25
|
-
import { resolve, join, relative, sep } from 'node:path';
|
|
25
|
+
import { resolve, join as join$1, relative, sep } from 'node:path';
|
|
26
26
|
|
|
27
27
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
28
28
|
|
|
@@ -8338,10 +8338,39 @@ function loadConfig(configDir) {
|
|
|
8338
8338
|
const content = libExports.readFileSync(configPath, 'utf-8');
|
|
8339
8339
|
const config = JSON.parse(content);
|
|
8340
8340
|
// 验证必需字段
|
|
8341
|
-
if (!config.
|
|
8342
|
-
defaultLogger.error('
|
|
8341
|
+
if (!config.srcDir || !config.outDir) {
|
|
8342
|
+
defaultLogger.error('配置文件格式不正确,缺少必需的 srcDir 或 outDir 字段');
|
|
8343
8343
|
return defaultLogger.exit(1);
|
|
8344
8344
|
}
|
|
8345
|
+
if (!config.ideVersion) {
|
|
8346
|
+
config.ideVersion = process.env.NASL_IDE_VERSION || '';
|
|
8347
|
+
if (!config.ideVersion) {
|
|
8348
|
+
defaultLogger.error('缺少配置 ideVersion,请在配置文件中添加,或在环境变量中配置 NASL_IDE_VERSION');
|
|
8349
|
+
return defaultLogger.exit(1);
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
if (!config.serverBaseURL) {
|
|
8353
|
+
config.serverBaseURL = process.env.NASL_SERVER_BASE_URL || '';
|
|
8354
|
+
if (!config.serverBaseURL) {
|
|
8355
|
+
defaultLogger.error('缺少配置 serverBaseURL,请在配置文件中添加,或在环境变量中配置 NASL_SERVER_BASE_URL');
|
|
8356
|
+
return defaultLogger.exit(1);
|
|
8357
|
+
}
|
|
8358
|
+
}
|
|
8359
|
+
if (!config.useOPENAPI)
|
|
8360
|
+
config.useOPENAPI = process.env.USE_LCAP_OPENAPI === 'true';
|
|
8361
|
+
if (!config.OPENAPI_AK)
|
|
8362
|
+
config.OPENAPI_AK = process.env.LCAP_OPENAPI_AK;
|
|
8363
|
+
if (!config.OPENAPI_SK)
|
|
8364
|
+
config.OPENAPI_SK = process.env.LCAP_OPENAPI_SK;
|
|
8365
|
+
if (config.useOPENAPI) {
|
|
8366
|
+
if (!config.OPENAPI_AK || !config.OPENAPI_SK) {
|
|
8367
|
+
defaultLogger.error(`配置了 useOPENAPI,但缺少配置 OPENAPI_AK 和 OPENAPI_SK:
|
|
8368
|
+
- 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK
|
|
8369
|
+
- 或将 useOPENAPI 配置为 false
|
|
8370
|
+
`);
|
|
8371
|
+
return defaultLogger.exit(1);
|
|
8372
|
+
}
|
|
8373
|
+
}
|
|
8345
8374
|
return config;
|
|
8346
8375
|
}
|
|
8347
8376
|
catch (error) {
|
|
@@ -28895,18 +28924,99 @@ function v4(options, buf, offset) {
|
|
|
28895
28924
|
return unsafeStringify(rnds);
|
|
28896
28925
|
}
|
|
28897
28926
|
|
|
28927
|
+
function generateHash(params) {
|
|
28928
|
+
const hash = createHash('sha256');
|
|
28929
|
+
hash.update(JSON.stringify(params));
|
|
28930
|
+
return hash.digest('hex');
|
|
28931
|
+
}
|
|
28932
|
+
async function getCachePathWithTimestamp(hash) {
|
|
28933
|
+
const cacheDir = join(process.cwd(), '.cache');
|
|
28934
|
+
await promises.mkdir(cacheDir, { recursive: true });
|
|
28935
|
+
return join(cacheDir, `${hash}_${Date.now()}.json`);
|
|
28936
|
+
}
|
|
28898
28937
|
/**
|
|
28899
|
-
*
|
|
28938
|
+
* 查找指定 hash 的有效缓存文件
|
|
28939
|
+
* @param hash 缓存标识
|
|
28940
|
+
* @param ttl 缓存有效期(毫秒)
|
|
28941
|
+
* @returns 缓存文件路径和缓存内容,如果没有有效缓存则返回 null
|
|
28900
28942
|
*/
|
|
28901
|
-
function
|
|
28902
|
-
|
|
28943
|
+
async function findValidCache(hash, ttl) {
|
|
28944
|
+
const cacheDir = join(process.cwd(), '.cache');
|
|
28945
|
+
try {
|
|
28946
|
+
await promises.mkdir(cacheDir, { recursive: true });
|
|
28947
|
+
const files = await promises.readdir(cacheDir);
|
|
28948
|
+
const now = Date.now();
|
|
28949
|
+
// 查找所有匹配的缓存文件
|
|
28950
|
+
const matchingFiles = files
|
|
28951
|
+
.filter((file) => file.startsWith(`${hash}_`) && file.endsWith('.json'))
|
|
28952
|
+
.map((file) => {
|
|
28953
|
+
const match = file.match(/_(\d+)\.json$/);
|
|
28954
|
+
if (!match)
|
|
28955
|
+
return null;
|
|
28956
|
+
const timestamp = parseInt(match[1], 10);
|
|
28957
|
+
return {
|
|
28958
|
+
path: join(cacheDir, file),
|
|
28959
|
+
timestamp,
|
|
28960
|
+
isExpired: now - timestamp > ttl,
|
|
28961
|
+
};
|
|
28962
|
+
})
|
|
28963
|
+
.filter((item) => item !== null);
|
|
28964
|
+
// 删除过期的缓存文件
|
|
28965
|
+
const expiredFiles = matchingFiles.filter((item) => item.isExpired);
|
|
28966
|
+
await Promise.all(expiredFiles.map((item) => promises.unlink(item.path).catch(() => { })));
|
|
28967
|
+
// 查找有效的缓存文件(按时间戳降序排序,获取最新的)
|
|
28968
|
+
const validFiles = matchingFiles.filter((item) => !item.isExpired).sort((a, b) => b.timestamp - a.timestamp);
|
|
28969
|
+
if (validFiles.length > 0) {
|
|
28970
|
+
const cacheFile = validFiles[0];
|
|
28971
|
+
const cacheContent = await promises.readFile(cacheFile.path, 'utf-8');
|
|
28972
|
+
const cachedResult = JSON.parse(cacheContent);
|
|
28973
|
+
return { path: cacheFile.path, data: cachedResult };
|
|
28974
|
+
}
|
|
28975
|
+
return null;
|
|
28976
|
+
}
|
|
28977
|
+
catch (error) {
|
|
28978
|
+
return null;
|
|
28979
|
+
}
|
|
28903
28980
|
}
|
|
28904
28981
|
/**
|
|
28905
|
-
*
|
|
28982
|
+
* 高阶函数,为异步函数添加带时间戳的缓存功能
|
|
28983
|
+
* @param fn 需要添加缓存的函数
|
|
28984
|
+
* @param ttl 缓存有效期(毫秒),默认 1 小时
|
|
28985
|
+
* @param getCacheKey 可选的自定义缓存 key 生成函数,如果不提供则使用整个 params
|
|
28986
|
+
* @returns 带缓存的函数版本
|
|
28906
28987
|
*/
|
|
28907
|
-
function
|
|
28908
|
-
|
|
28988
|
+
function cachableWithTTL(fn, ttl = 3600 * 1000, // 默认 1 小时
|
|
28989
|
+
getCacheKey) {
|
|
28990
|
+
return async (params, extraParams) => {
|
|
28991
|
+
const functionName = fn.name;
|
|
28992
|
+
const logPrefix = functionName ? `[${functionName}]` : '[cachableWithTTL]';
|
|
28993
|
+
// 检查是否启用缓存
|
|
28994
|
+
if (process.env.NO_AI_CACHE) {
|
|
28995
|
+
return fn(params, extraParams);
|
|
28996
|
+
}
|
|
28997
|
+
// 使用自定义的 getCacheKey 或默认使用整个 params
|
|
28998
|
+
const cacheKey = getCacheKey ? getCacheKey(params) : params;
|
|
28999
|
+
const hash = generateHash(cacheKey);
|
|
29000
|
+
// 查找有效的缓存
|
|
29001
|
+
const validCache = await findValidCache(hash, ttl);
|
|
29002
|
+
if (validCache) {
|
|
29003
|
+
console.log(`${logPrefix} ✓ 使用缓存`);
|
|
29004
|
+
return validCache.data;
|
|
29005
|
+
}
|
|
29006
|
+
// 调用原函数
|
|
29007
|
+
const result = await fn(params, extraParams);
|
|
29008
|
+
// 保存结果到缓存(带时间戳)
|
|
29009
|
+
try {
|
|
29010
|
+
const cachePath = await getCachePathWithTimestamp(hash);
|
|
29011
|
+
await promises.writeFile(cachePath, JSON.stringify(result, null, 2), 'utf-8');
|
|
29012
|
+
}
|
|
29013
|
+
catch (error) {
|
|
29014
|
+
// 缓存写入失败,但不影响返回结果
|
|
29015
|
+
}
|
|
29016
|
+
return result;
|
|
29017
|
+
};
|
|
28909
29018
|
}
|
|
29019
|
+
|
|
28910
29020
|
/**
|
|
28911
29021
|
* 生成客户端签名信息
|
|
28912
29022
|
* @param appKey AppKey
|
|
@@ -28916,8 +29026,8 @@ function generateSignature(plainText) {
|
|
|
28916
29026
|
function generateClientSignature(appKey, secretKey) {
|
|
28917
29027
|
const timestamp = Math.floor(Date.now() / 1000).toString();
|
|
28918
29028
|
const nonce = v4();
|
|
28919
|
-
const plainText =
|
|
28920
|
-
const signature =
|
|
29029
|
+
const plainText = `${appKey}&${nonce}&${timestamp}&${secretKey}`;
|
|
29030
|
+
const signature = crypto$1.createHash('md5').update(plainText).digest('hex');
|
|
28921
29031
|
return {
|
|
28922
29032
|
appKey,
|
|
28923
29033
|
timestamp,
|
|
@@ -28942,12 +29052,12 @@ function generateBaseHeaders(ak, sk) {
|
|
|
28942
29052
|
};
|
|
28943
29053
|
}
|
|
28944
29054
|
/**
|
|
28945
|
-
* 获取租户的 signInfo
|
|
29055
|
+
* 获取租户的 signInfo(内部实现)
|
|
28946
29056
|
* @param options 服务器选项
|
|
28947
29057
|
* @param baseHeaders 基础认证头
|
|
28948
29058
|
* @returns x-signInfo 值
|
|
28949
29059
|
*/
|
|
28950
|
-
async function
|
|
29060
|
+
async function _fetchSignInfo({ options, baseHeaders }) {
|
|
28951
29061
|
const tenantName = options.tenantName || 'defaulttenant';
|
|
28952
29062
|
const userName = tenantName === 'defaulttenant' ? 'admin' : `${tenantName}-admin`;
|
|
28953
29063
|
const data = {
|
|
@@ -28969,6 +29079,14 @@ async function fetchSignInfo(options, baseHeaders) {
|
|
|
28969
29079
|
return null;
|
|
28970
29080
|
}
|
|
28971
29081
|
}
|
|
29082
|
+
/**
|
|
29083
|
+
* 获取租户的 signInfo(带缓存,1 小时过期)
|
|
29084
|
+
* @param options 服务器选项
|
|
29085
|
+
* @param baseHeaders 基础认证头
|
|
29086
|
+
* @returns x-signInfo 值
|
|
29087
|
+
*/
|
|
29088
|
+
const fetchSignInfo = cachableWithTTL(_fetchSignInfo, 3600 * 1000, // 1 小时
|
|
29089
|
+
(params) => params.options);
|
|
28972
29090
|
/**
|
|
28973
29091
|
* 生成完整的认证头(包含 x-signInfo)
|
|
28974
29092
|
* @param options 服务器选项
|
|
@@ -28978,19 +29096,18 @@ async function generateCompleteHeaders(options) {
|
|
|
28978
29096
|
const headers = {
|
|
28979
29097
|
'Content-Type': 'application/json',
|
|
28980
29098
|
};
|
|
28981
|
-
const OPENAPI_AK = options.OPENAPI_AK || process.env.LCAP_OPENAPI_AK;
|
|
28982
|
-
const OPENAPI_SK = options.OPENAPI_SK || process.env.LCAP_OPENAPI_SK;
|
|
28983
29099
|
// 如果没有提供 ak 和 sk,返回基础 headers
|
|
28984
|
-
if (!OPENAPI_AK || !OPENAPI_SK) {
|
|
28985
|
-
throw new Error(`配置了 useOPENAPI
|
|
28986
|
-
-
|
|
28987
|
-
-
|
|
29100
|
+
if (!options.OPENAPI_AK || !options.OPENAPI_SK) {
|
|
29101
|
+
throw new Error(`配置了 useOPENAPI,但缺少配置 OPENAPI_AK 和 OPENAPI_SK:
|
|
29102
|
+
- 在 nasl.config.json 中配置 OPENAPI_AK 和 OPENAPI_SK,或者在环境变量中配置 LCAP_OPENAPI_AK 和 LCAP_OPENAPI_SK
|
|
29103
|
+
- 或将 useOPENAPI 配置为 false
|
|
29104
|
+
`);
|
|
28988
29105
|
}
|
|
28989
29106
|
// 生成基础认证头
|
|
28990
|
-
const baseHeaders = generateBaseHeaders(OPENAPI_AK, OPENAPI_SK);
|
|
29107
|
+
const baseHeaders = generateBaseHeaders(options.OPENAPI_AK, options.OPENAPI_SK);
|
|
28991
29108
|
Object.assign(headers, baseHeaders);
|
|
28992
29109
|
// 获取 signInfo
|
|
28993
|
-
const signInfo = await fetchSignInfo(options, headers);
|
|
29110
|
+
const signInfo = await fetchSignInfo({ options, baseHeaders: headers });
|
|
28994
29111
|
if (signInfo) {
|
|
28995
29112
|
headers['x-signInfo'] = signInfo;
|
|
28996
29113
|
}
|
|
@@ -29005,10 +29122,9 @@ async function generateCompleteHeaders(options) {
|
|
|
29005
29122
|
async function createAxios(options) {
|
|
29006
29123
|
// 如果需要鉴权,拼接 /openapi/v3/nasl;否则使用原始 URL
|
|
29007
29124
|
const serverBaseURL = new URL(options.serverBaseURL).origin;
|
|
29008
|
-
const
|
|
29009
|
-
const baseURL = useOPENAPI ? `${serverBaseURL}/openapi/v3/nasl` : `${serverBaseURL}/api/v1/nasl`;
|
|
29125
|
+
const baseURL = options.useOPENAPI ? `${serverBaseURL}/openapi/v3/nasl` : `${serverBaseURL}/api/v1/nasl`;
|
|
29010
29126
|
// 如果需要鉴权,生成完整的认证头;否则只使用基础 headers
|
|
29011
|
-
const headers = useOPENAPI ? await generateCompleteHeaders(options) : { 'Content-Type': 'application/json' };
|
|
29127
|
+
const headers = options.useOPENAPI ? await generateCompleteHeaders(options) : { 'Content-Type': 'application/json' };
|
|
29012
29128
|
console.log('本次服务调用方为:', baseURL);
|
|
29013
29129
|
const instance = axios.create({
|
|
29014
29130
|
baseURL,
|
|
@@ -29096,7 +29212,7 @@ async function checkApi(fullNaturalTS, options) {
|
|
|
29096
29212
|
async function createAppSyncApi(fullNaturalTS, options) {
|
|
29097
29213
|
const url = new URL(options.serverBaseURL);
|
|
29098
29214
|
const origin = url.origin + '/app-ai-creator';
|
|
29099
|
-
const axios = await createAxios({ serverBaseURL: origin});
|
|
29215
|
+
const axios = await createAxios({ serverBaseURL: origin, ideVersion: options.ideVersion });
|
|
29100
29216
|
try {
|
|
29101
29217
|
const res = await axios.post('/api/createAppSync', {
|
|
29102
29218
|
fullNaturalTS,
|
|
@@ -38305,6 +38421,10 @@ async function createAppInIde(entry, options) {
|
|
|
38305
38421
|
logger.info('开始创建应用在 IDE 中...');
|
|
38306
38422
|
// 收集需要处理的文件
|
|
38307
38423
|
const { collectedFiles, config } = await resolveNASLFiles(entry, logger, false, options?.verbose);
|
|
38424
|
+
if (config.useOPENAPI) {
|
|
38425
|
+
logger.error('create-app-in-ide 暂不支持 useOPENAPI 模式');
|
|
38426
|
+
logger.exit(1);
|
|
38427
|
+
}
|
|
38308
38428
|
// 生成 fullNaturalTS
|
|
38309
38429
|
logger.newLine();
|
|
38310
38430
|
logger.info('正在生成 NaturalTS 代码...');
|
|
@@ -38424,10 +38544,7 @@ const transformFns = {
|
|
|
38424
38544
|
jsonContent = libExports.readFileSync(entry, 'utf-8');
|
|
38425
38545
|
logger.info(`读取到 JSON 文件: ${entry}`);
|
|
38426
38546
|
}
|
|
38427
|
-
const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {},
|
|
38428
|
-
serverBaseURL: config.serverBaseURL,
|
|
38429
|
-
ideVersion: config.ideVersion,
|
|
38430
|
-
});
|
|
38547
|
+
const files = await transformJson2FilesApi(jsonContent ? JSON.parse(jsonContent) : {}, config);
|
|
38431
38548
|
await Promise.all(files.map(async (file) => {
|
|
38432
38549
|
const outputPath = sysPath.join(projectRoot, config.srcDir, file.path);
|
|
38433
38550
|
await libExports.writeFile(outputPath, file.content);
|
|
@@ -38456,7 +38573,7 @@ async function transform(transformType, entry, options) {
|
|
|
38456
38573
|
await transformFn(entry, options);
|
|
38457
38574
|
}
|
|
38458
38575
|
|
|
38459
|
-
var version = "0.1.
|
|
38576
|
+
var version = "0.1.18";
|
|
38460
38577
|
var pkg = {
|
|
38461
38578
|
version: version};
|
|
38462
38579
|
|
|
@@ -38760,7 +38877,7 @@ class ReaddirpStream extends Readable$1 {
|
|
|
38760
38877
|
let entry;
|
|
38761
38878
|
const basename = this._isDirent ? dirent.name : dirent;
|
|
38762
38879
|
try {
|
|
38763
|
-
const fullPath = resolve(join(path, basename));
|
|
38880
|
+
const fullPath = resolve(join$1(path, basename));
|
|
38764
38881
|
entry = { path: relative(this._root, fullPath), fullPath, basename };
|
|
38765
38882
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
38766
38883
|
}
|