@maptec/cli 1.0.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/LICENSE +21 -0
- package/README.md +284 -0
- package/bin/maptec.js +2 -0
- package/dist/chunk-K574OFFK.js +122 -0
- package/dist/chunk-K574OFFK.js.map +1 -0
- package/dist/cli.js +899 -0
- package/dist/cli.js.map +1 -0
- package/dist/store-ZU7HLXCV.js +18 -0
- package/dist/store-ZU7HLXCV.js.map +1 -0
- package/package.json +47 -0
- package/skills/README.md +30 -0
- package/skills/jsapi-skills/README.md +60 -0
- package/skills/jsapi-skills/SKILL.md +145 -0
- package/skills/jsapi-skills/package.json +31 -0
- package/skills/jsapi-skills/references/controls.md +195 -0
- package/skills/jsapi-skills/references/events.md +222 -0
- package/skills/jsapi-skills/references/geocoding.md +184 -0
- package/skills/jsapi-skills/references/map-style.md +123 -0
- package/skills/jsapi-skills/references/map.md +154 -0
- package/skills/jsapi-skills/references/marker.md +136 -0
- package/skills/jsapi-skills/references/operate.md +138 -0
- package/skills/jsapi-skills/references/overlay.md +311 -0
- package/skills/jsapi-skills/references/place-search.md +411 -0
- package/skills/jsapi-skills/references/poi-categories.md +123 -0
- package/skills/jsapi-skills/references/popup.md +146 -0
- package/skills/jsapi-skills/references/re-geocoding.md +183 -0
- package/skills/jsapi-skills/references/routing.md +347 -0
- package/skills/jsapi-skills/references/track.md +240 -0
- package/skills/jsapi-skills/scripts/validate_jsapi_skill.py +160 -0
- package/skills/webapi-skills/README.md +73 -0
- package/skills/webapi-skills/SKILL.md +63 -0
- package/skills/webapi-skills/package.json +32 -0
- package/skills/webapi-skills/references/direction-api.md +175 -0
- package/skills/webapi-skills/references/geocoding.md +195 -0
- package/skills/webapi-skills/references/ip-location.md +87 -0
- package/skills/webapi-skills/references/matrix-api.md +149 -0
- package/skills/webapi-skills/references/nearby-search.md +223 -0
- package/skills/webapi-skills/references/places.md +239 -0
- package/skills/webapi-skills/references/quick-start-cn.md +219 -0
- package/skills/webapi-skills/references/reverse-geocoding.md +157 -0
- package/skills/webapi-skills/references/suggest.md +111 -0
- package/skills/webapi-skills/references/text-search.md +282 -0
- package/skills/webapi-skills/scripts/validate_webapi_skill.py +158 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maptec
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# @maptec/cli
|
|
2
|
+
|
|
3
|
+
Maptec 地图服务命令行工具。面向开发者与 AI Agent,提供地理编码、地点检索与路线规划能力,并以结构化 JSON 输出结果。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @maptec/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
也可通过 `npx` 临时运行:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @maptec/cli --help
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
要求 Node.js ≥ 18。
|
|
18
|
+
|
|
19
|
+
## 快速开始
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
maptec init
|
|
23
|
+
maptec config get
|
|
24
|
+
maptec geocode --address "Orchard Road" --region SG --format json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`maptec init` 将引导配置 API Key 与 Base URL,并写入 `~/.maptec/config.json`。
|
|
28
|
+
|
|
29
|
+
## 配置
|
|
30
|
+
|
|
31
|
+
### 配置文件
|
|
32
|
+
|
|
33
|
+
路径:`~/.maptec/config.json`
|
|
34
|
+
|
|
35
|
+
| 字段 | 说明 | 默认值 |
|
|
36
|
+
|------|------|--------|
|
|
37
|
+
| `apiKey` | Maptec API Key | 必填 |
|
|
38
|
+
| `baseUrl` | WebAPI 根地址 | 必填 |
|
|
39
|
+
| `defaultFormat` | 输出格式:`json` \| `table` | `json` |
|
|
40
|
+
| `timeoutMs` | 请求超时(毫秒) | `30000` |
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"apiKey": "YOUR_API_KEY",
|
|
45
|
+
"baseUrl": "https://api.maptec.com",
|
|
46
|
+
"defaultFormat": "json",
|
|
47
|
+
"timeoutMs": 30000
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 环境变量
|
|
52
|
+
|
|
53
|
+
| 变量 | 说明 |
|
|
54
|
+
|------|------|
|
|
55
|
+
| `MAPTEC_API_KEY` | 覆盖配置文件中的 API Key |
|
|
56
|
+
| `MAPTEC_BASE_URL` | 覆盖 Base URL |
|
|
57
|
+
| `MAPTEC_API_URL` | `MAPTEC_BASE_URL` 的兼容别名 |
|
|
58
|
+
|
|
59
|
+
Base URL 解析顺序:`MAPTEC_BASE_URL` → `MAPTEC_API_URL` → 配置文件 `baseUrl`。
|
|
60
|
+
|
|
61
|
+
### 命令行配置
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
maptec config get
|
|
65
|
+
maptec config set api-key YOUR_API_KEY
|
|
66
|
+
maptec config set base-url https://api.maptec.com
|
|
67
|
+
maptec config set default-format json
|
|
68
|
+
maptec config set timeout 60000
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`config set` 支持的键:`api-key`、`base-url`、`default-format`、`timeout`(及其驼峰别名)。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 全局选项
|
|
76
|
+
|
|
77
|
+
| 选项 | 说明 | 默认值 |
|
|
78
|
+
|------|------|--------|
|
|
79
|
+
| `--format <json\|table>` | 输出格式 | `json` |
|
|
80
|
+
| `--out <file>` | 将结果写入文件 | — |
|
|
81
|
+
| `--quiet` | 减少 stderr 提示信息 | `false` |
|
|
82
|
+
| `--timeout <ms>` | 覆盖请求超时 | 配置文件值 |
|
|
83
|
+
| `--fields <list>` | 裁剪输出字段(逗号分隔) | — |
|
|
84
|
+
| `-V, --version` | 显示版本号 | — |
|
|
85
|
+
|
|
86
|
+
### 成功输出
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"ok": true,
|
|
91
|
+
"command": "geocode",
|
|
92
|
+
"data": {}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 退出码
|
|
97
|
+
|
|
98
|
+
| 码 | 含义 |
|
|
99
|
+
|----|------|
|
|
100
|
+
| `0` | 成功 |
|
|
101
|
+
| `1` | 参数错误 |
|
|
102
|
+
| `2` | 未配置 `apiKey` 或 `baseUrl` |
|
|
103
|
+
| `3` | API 业务错误 |
|
|
104
|
+
| `4` | 网络错误或超时 |
|
|
105
|
+
| `5` | 内部错误 |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 命令
|
|
110
|
+
|
|
111
|
+
### `maptec geocode`
|
|
112
|
+
|
|
113
|
+
地址 → 坐标。
|
|
114
|
+
|
|
115
|
+
| 选项 | 必填 | 说明 |
|
|
116
|
+
|------|------|------|
|
|
117
|
+
| `--address <text>` | 是 | 地址 |
|
|
118
|
+
| `--language <code>` | 否 | 语言,如 `en`、`zh-CN` |
|
|
119
|
+
| `--region <code>` | 否 | 地区偏向,如 `SG`、`CN` |
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
maptec geocode --address "Orchard Road" --language en --region SG --format json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `maptec reverse-geocode`
|
|
126
|
+
|
|
127
|
+
坐标 → 地址。
|
|
128
|
+
|
|
129
|
+
| 选项 | 必填 | 说明 |
|
|
130
|
+
|------|------|------|
|
|
131
|
+
| `--lat <number>` | 是 | 纬度 |
|
|
132
|
+
| `--lng <number>` | 是 | 经度 |
|
|
133
|
+
| `--language <code>` | 否 | 语言 |
|
|
134
|
+
| `--region <code>` | 否 | 地区偏向 |
|
|
135
|
+
| `--result-type <types>` | 否 | 结果类型过滤(`|` 分隔) |
|
|
136
|
+
| `--location-type <types>` | 否 | 精度类型过滤 |
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
maptec reverse-geocode --lat 1.3048 --lng 103.8318 --language en --format json
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### `maptec search text`
|
|
143
|
+
|
|
144
|
+
关键词检索。
|
|
145
|
+
|
|
146
|
+
| 选项 | 必填 | 说明 |
|
|
147
|
+
|------|------|------|
|
|
148
|
+
| `--query <text>` | 是 | 关键词 |
|
|
149
|
+
| `--location <lng,lat>` | 否 | 位置偏向:`lng,lat` 或 `lng,lat,radius` |
|
|
150
|
+
| `--language <code>` | 否 | 语言(默认 `en`) |
|
|
151
|
+
| `--region <code>` | 否 | 地区 |
|
|
152
|
+
| `--page-size <n>` | 否 | 每页条数(默认 `20`) |
|
|
153
|
+
| `--type <category>` | 否 | POI 类别 |
|
|
154
|
+
| `--rank <mode>` | 否 | `RELEVANCE` \| `DISTANCE` \| `POPULARITY` |
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
maptec search text \
|
|
158
|
+
--query "cafe" \
|
|
159
|
+
--location "103.83,1.30,3000" \
|
|
160
|
+
--language en \
|
|
161
|
+
--region SG \
|
|
162
|
+
--page-size 10 \
|
|
163
|
+
--format json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `maptec search nearby`
|
|
167
|
+
|
|
168
|
+
周边检索。
|
|
169
|
+
|
|
170
|
+
| 选项 | 必填 | 说明 |
|
|
171
|
+
|------|------|------|
|
|
172
|
+
| `--lat <number>` | 是 | 圆心纬度 |
|
|
173
|
+
| `--lng <number>` | 是 | 圆心经度 |
|
|
174
|
+
| `--radius <meters>` | 否 | 半径,米(默认 `500`) |
|
|
175
|
+
| `--types <list>` | 否 | POI 类型,逗号分隔 |
|
|
176
|
+
| `--limit <n>` | 否 | 结果数量上限(默认 `20`) |
|
|
177
|
+
| `--language <code>` | 否 | 语言(默认 `en`) |
|
|
178
|
+
| `--region <code>` | 否 | 地区 |
|
|
179
|
+
| `--rank <mode>` | 否 | 排序(默认 `DISTANCE`) |
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
maptec search nearby \
|
|
183
|
+
--lat 1.3048 \
|
|
184
|
+
--lng 103.8318 \
|
|
185
|
+
--radius 1000 \
|
|
186
|
+
--types "restaurant,cafe" \
|
|
187
|
+
--limit 10 \
|
|
188
|
+
--format json
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `maptec search suggest`
|
|
192
|
+
|
|
193
|
+
输入提示。
|
|
194
|
+
|
|
195
|
+
| 选项 | 必填 | 说明 |
|
|
196
|
+
|------|------|------|
|
|
197
|
+
| `--query <text>` | 是 | 输入文本 |
|
|
198
|
+
| `--location <lng,lat>` | 否 | 位置偏向 |
|
|
199
|
+
| `--language <code>` | 否 | 语言(默认 `en`) |
|
|
200
|
+
| `--region <code>` | 否 | 地区 |
|
|
201
|
+
| `--limit <n>` | 否 | 结果数量上限(默认 `20`) |
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
maptec search suggest --query "Orch" --location "103.83,1.30" --limit 5 --format json
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### `maptec search place`
|
|
208
|
+
|
|
209
|
+
地点详情。
|
|
210
|
+
|
|
211
|
+
| 选项 | 必填 | 说明 |
|
|
212
|
+
|------|------|------|
|
|
213
|
+
| `--id <placeId>` | 是 | 地点 ID |
|
|
214
|
+
| `--language <code>` | 否 | 语言 |
|
|
215
|
+
| `--region <code>` | 否 | 地区 |
|
|
216
|
+
| `--session-token <token>` | 否 | 会话令牌 |
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
maptec search place --id "<placeId>" --language en --format json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `maptec route driving` / `maptec route truck`
|
|
223
|
+
|
|
224
|
+
路线规划。起终点任选一种写法:
|
|
225
|
+
|
|
226
|
+
- `--from` / `--to`:地址、`lng,lat` 或 place ID
|
|
227
|
+
- `--from-lat` + `--from-lng` / `--to-lat` + `--to-lng`:坐标分量
|
|
228
|
+
|
|
229
|
+
文本地址会自动进行地理编码。
|
|
230
|
+
|
|
231
|
+
| 选项 | 说明 |
|
|
232
|
+
|------|------|
|
|
233
|
+
| `--strategy <name>` | `fastest` \| `shortest` \| `eco` \| `balanced` |
|
|
234
|
+
| `--language <code>` | 导航语言 |
|
|
235
|
+
| `--height <meters>` | 车高(仅 `truck`) |
|
|
236
|
+
| `--weight <tons>` | 总重(仅 `truck`) |
|
|
237
|
+
| `--length <meters>` | 车长(仅 `truck`) |
|
|
238
|
+
|
|
239
|
+
默认输出 `distance`、`duration`、`summary`。需要路径几何时增加 `--fields polyline`。
|
|
240
|
+
|
|
241
|
+
可选字段:`distance`、`duration`、`summary`、`polyline`、`warnings`、`legs`。
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
maptec route driving \
|
|
245
|
+
--from "Orchard Road" \
|
|
246
|
+
--to "North Bridge Rd" \
|
|
247
|
+
--fields distance,duration,summary \
|
|
248
|
+
--format json
|
|
249
|
+
|
|
250
|
+
maptec route driving \
|
|
251
|
+
--from-lat 1.2966 --from-lng 103.7764 \
|
|
252
|
+
--to-lat 1.3048 --to-lng 103.8318 \
|
|
253
|
+
--strategy fastest \
|
|
254
|
+
--format json
|
|
255
|
+
|
|
256
|
+
maptec route truck \
|
|
257
|
+
--from "103.85,1.29" \
|
|
258
|
+
--to "103.83,1.30" \
|
|
259
|
+
--height 4.2 \
|
|
260
|
+
--weight 10 \
|
|
261
|
+
--length 12 \
|
|
262
|
+
--fields distance,duration,summary \
|
|
263
|
+
--format json
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 示例
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# 将结果写入文件
|
|
272
|
+
maptec geocode --address "Orchard Road" --region SG --format json --out result.json
|
|
273
|
+
|
|
274
|
+
# 检索后查询地点详情
|
|
275
|
+
maptec search suggest --query "Orchard" --limit 1 --format json
|
|
276
|
+
maptec search place --id "<placeId>" --format json
|
|
277
|
+
|
|
278
|
+
# 人类可读配置
|
|
279
|
+
maptec config get --format table
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## License
|
|
283
|
+
|
|
284
|
+
[MIT](./LICENSE) © 2026 Maptec
|
package/bin/maptec.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config/store.ts
|
|
4
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
|
|
8
|
+
// src/config/env.ts
|
|
9
|
+
var DEFAULT_CONFIG = {
|
|
10
|
+
defaultFormat: "json",
|
|
11
|
+
timeoutMs: 3e4
|
|
12
|
+
};
|
|
13
|
+
var API_VERSION = "v1";
|
|
14
|
+
function normalizeBaseUrl(value) {
|
|
15
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
16
|
+
if (!trimmed) {
|
|
17
|
+
throw new Error("baseUrl \u4E0D\u80FD\u4E3A\u7A7A");
|
|
18
|
+
}
|
|
19
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
20
|
+
throw new Error(`\u65E0\u6548 baseUrl "${value}"\uFF0C\u9700\u4EE5 http:// \u6216 https:// \u5F00\u5934`);
|
|
21
|
+
}
|
|
22
|
+
return trimmed;
|
|
23
|
+
}
|
|
24
|
+
function resolveBaseUrl(config) {
|
|
25
|
+
const fromBase = process.env.MAPTEC_BASE_URL?.trim();
|
|
26
|
+
if (fromBase) {
|
|
27
|
+
return normalizeBaseUrl(fromBase);
|
|
28
|
+
}
|
|
29
|
+
const fromApiUrl = process.env.MAPTEC_API_URL?.trim();
|
|
30
|
+
if (fromApiUrl) {
|
|
31
|
+
return normalizeBaseUrl(fromApiUrl);
|
|
32
|
+
}
|
|
33
|
+
const fromConfig = config.baseUrl?.trim();
|
|
34
|
+
if (fromConfig) {
|
|
35
|
+
return normalizeBaseUrl(fromConfig);
|
|
36
|
+
}
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
function resolveApiKey(config) {
|
|
40
|
+
const fromEnv = process.env.MAPTEC_API_KEY?.trim();
|
|
41
|
+
if (fromEnv) return fromEnv;
|
|
42
|
+
return config.apiKey?.trim() || void 0;
|
|
43
|
+
}
|
|
44
|
+
function maskApiKey(key) {
|
|
45
|
+
if (key.length <= 8) return "****";
|
|
46
|
+
return `${key.slice(0, 3)}...${key.slice(-4)}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/config/store.ts
|
|
50
|
+
var CONFIG_DIR = join(homedir(), ".maptec");
|
|
51
|
+
var CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
52
|
+
function getConfigPath() {
|
|
53
|
+
return CONFIG_PATH;
|
|
54
|
+
}
|
|
55
|
+
async function loadConfig() {
|
|
56
|
+
try {
|
|
57
|
+
const raw = await readFile(CONFIG_PATH, "utf8");
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
const { env: _legacyEnv, ...rest } = parsed;
|
|
60
|
+
return {
|
|
61
|
+
...DEFAULT_CONFIG,
|
|
62
|
+
...rest
|
|
63
|
+
};
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err.code === "ENOENT") {
|
|
66
|
+
return { ...DEFAULT_CONFIG };
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function saveConfig(config) {
|
|
72
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
73
|
+
const { env: _legacyEnv, ...rest } = config;
|
|
74
|
+
await writeFile(CONFIG_PATH, `${JSON.stringify(rest, null, 2)}
|
|
75
|
+
`, "utf8");
|
|
76
|
+
}
|
|
77
|
+
async function setConfigValue(key, value) {
|
|
78
|
+
const config = await loadConfig();
|
|
79
|
+
switch (key) {
|
|
80
|
+
case "apiKey":
|
|
81
|
+
config.apiKey = String(value);
|
|
82
|
+
break;
|
|
83
|
+
case "baseUrl":
|
|
84
|
+
config.baseUrl = normalizeBaseUrl(String(value));
|
|
85
|
+
break;
|
|
86
|
+
case "defaultFormat":
|
|
87
|
+
if (value !== "json" && value !== "table") {
|
|
88
|
+
throw new Error("defaultFormat \u4EC5\u652F\u6301 json \u6216 table");
|
|
89
|
+
}
|
|
90
|
+
config.defaultFormat = value;
|
|
91
|
+
break;
|
|
92
|
+
case "timeoutMs":
|
|
93
|
+
config.timeoutMs = Number(value);
|
|
94
|
+
if (!Number.isFinite(config.timeoutMs) || config.timeoutMs <= 0) {
|
|
95
|
+
throw new Error("timeoutMs \u5FC5\u987B\u4E3A\u6B63\u6574\u6570");
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
await saveConfig(config);
|
|
100
|
+
return config;
|
|
101
|
+
}
|
|
102
|
+
async function setApiKey(value) {
|
|
103
|
+
return setConfigValue("apiKey", value);
|
|
104
|
+
}
|
|
105
|
+
async function setBaseUrl(value) {
|
|
106
|
+
return setConfigValue("baseUrl", value);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
API_VERSION,
|
|
111
|
+
normalizeBaseUrl,
|
|
112
|
+
resolveBaseUrl,
|
|
113
|
+
resolveApiKey,
|
|
114
|
+
maskApiKey,
|
|
115
|
+
getConfigPath,
|
|
116
|
+
loadConfig,
|
|
117
|
+
saveConfig,
|
|
118
|
+
setConfigValue,
|
|
119
|
+
setApiKey,
|
|
120
|
+
setBaseUrl
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=chunk-K574OFFK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/store.ts","../src/config/env.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport {\n DEFAULT_CONFIG,\n normalizeBaseUrl,\n type MaptecConfig,\n} from './env.js';\n\nconst CONFIG_DIR = join(homedir(), '.maptec');\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.json');\n\nexport function getConfigPath(): string {\n return CONFIG_PATH;\n}\n\nexport async function loadConfig(): Promise<MaptecConfig> {\n try {\n const raw = await readFile(CONFIG_PATH, 'utf8');\n const parsed = JSON.parse(raw) as Partial<MaptecConfig> & { env?: string };\n const { env: _legacyEnv, ...rest } = parsed;\n return {\n ...DEFAULT_CONFIG,\n ...rest,\n };\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ...DEFAULT_CONFIG };\n }\n throw err;\n }\n}\n\nexport async function saveConfig(config: MaptecConfig): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n const { env: _legacyEnv, ...rest } = config as MaptecConfig & { env?: string };\n await writeFile(CONFIG_PATH, `${JSON.stringify(rest, null, 2)}\\n`, 'utf8');\n}\n\nexport async function setConfigValue(\n key: 'apiKey' | 'baseUrl' | 'defaultFormat' | 'timeoutMs',\n value: string | number,\n): Promise<MaptecConfig> {\n const config = await loadConfig();\n switch (key) {\n case 'apiKey':\n config.apiKey = String(value);\n break;\n case 'baseUrl':\n config.baseUrl = normalizeBaseUrl(String(value));\n break;\n case 'defaultFormat':\n if (value !== 'json' && value !== 'table') {\n throw new Error('defaultFormat 仅支持 json 或 table');\n }\n config.defaultFormat = value;\n break;\n case 'timeoutMs':\n config.timeoutMs = Number(value);\n if (!Number.isFinite(config.timeoutMs) || config.timeoutMs <= 0) {\n throw new Error('timeoutMs 必须为正整数');\n }\n break;\n }\n await saveConfig(config);\n return config;\n}\n\nexport async function setApiKey(value: string): Promise<MaptecConfig> {\n return setConfigValue('apiKey', value);\n}\n\nexport async function setBaseUrl(value: string): Promise<MaptecConfig> {\n return setConfigValue('baseUrl', value);\n}\n","export interface MaptecConfig {\n apiKey?: string;\n baseUrl?: string;\n defaultFormat: 'json' | 'table';\n timeoutMs: number;\n}\n\nexport const DEFAULT_CONFIG: MaptecConfig = {\n defaultFormat: 'json',\n timeoutMs: 30_000,\n};\n\nexport const API_VERSION = 'v1';\n\n/** 去掉尾部斜杠,校验非空 URL 形态 */\nexport function normalizeBaseUrl(value: string): string {\n const trimmed = value.trim().replace(/\\/+$/, '');\n if (!trimmed) {\n throw new Error('baseUrl 不能为空');\n }\n if (!/^https?:\\/\\//i.test(trimmed)) {\n throw new Error(`无效 baseUrl \"${value}\",需以 http:// 或 https:// 开头`);\n }\n return trimmed;\n}\n\n/**\n * 解析 API 根地址。优先级:\n * 1. MAPTEC_BASE_URL\n * 2. MAPTEC_API_URL(兼容别名)\n * 3. 配置文件 baseUrl\n */\nexport function resolveBaseUrl(config: MaptecConfig): string | undefined {\n const fromBase = process.env.MAPTEC_BASE_URL?.trim();\n if (fromBase) {\n return normalizeBaseUrl(fromBase);\n }\n const fromApiUrl = process.env.MAPTEC_API_URL?.trim();\n if (fromApiUrl) {\n return normalizeBaseUrl(fromApiUrl);\n }\n const fromConfig = config.baseUrl?.trim();\n if (fromConfig) {\n return normalizeBaseUrl(fromConfig);\n }\n return undefined;\n}\n\nexport function resolveApiKey(config: MaptecConfig): string | undefined {\n const fromEnv = process.env.MAPTEC_API_KEY?.trim();\n if (fromEnv) return fromEnv;\n return config.apiKey?.trim() || undefined;\n}\n\nexport function maskApiKey(key: string): string {\n if (key.length <= 8) return '****';\n return `${key.slice(0, 3)}...${key.slice(-4)}`;\n}\n"],"mappings":";;;AAAA,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,eAAe;AACxB,SAAS,YAAY;;;ACKd,IAAM,iBAA+B;AAAA,EAC1C,eAAe;AAAA,EACf,WAAW;AACb;AAEO,IAAM,cAAc;AAGpB,SAAS,iBAAiB,OAAuB;AACtD,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,QAAQ,EAAE;AAC/C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,kCAAc;AAAA,EAChC;AACA,MAAI,CAAC,gBAAgB,KAAK,OAAO,GAAG;AAClC,UAAM,IAAI,MAAM,yBAAe,KAAK,0DAA4B;AAAA,EAClE;AACA,SAAO;AACT;AAQO,SAAS,eAAe,QAA0C;AACvE,QAAM,WAAW,QAAQ,IAAI,iBAAiB,KAAK;AACnD,MAAI,UAAU;AACZ,WAAO,iBAAiB,QAAQ;AAAA,EAClC;AACA,QAAM,aAAa,QAAQ,IAAI,gBAAgB,KAAK;AACpD,MAAI,YAAY;AACd,WAAO,iBAAiB,UAAU;AAAA,EACpC;AACA,QAAM,aAAa,OAAO,SAAS,KAAK;AACxC,MAAI,YAAY;AACd,WAAO,iBAAiB,UAAU;AAAA,EACpC;AACA,SAAO;AACT;AAEO,SAAS,cAAc,QAA0C;AACtE,QAAM,UAAU,QAAQ,IAAI,gBAAgB,KAAK;AACjD,MAAI,QAAS,QAAO;AACpB,SAAO,OAAO,QAAQ,KAAK,KAAK;AAClC;AAEO,SAAS,WAAW,KAAqB;AAC9C,MAAI,IAAI,UAAU,EAAG,QAAO;AAC5B,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;AAC9C;;;ADhDA,IAAM,aAAa,KAAK,QAAQ,GAAG,SAAS;AAC5C,IAAM,cAAc,KAAK,YAAY,aAAa;AAE3C,SAAS,gBAAwB;AACtC,SAAO;AACT;AAEA,eAAsB,aAAoC;AACxD,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,aAAa,MAAM;AAC9C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAM,EAAE,KAAK,YAAY,GAAG,KAAK,IAAI;AACrC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,UAAU;AACpD,aAAO,EAAE,GAAG,eAAe;AAAA,IAC7B;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WAAW,QAAqC;AACpE,QAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,QAAM,EAAE,KAAK,YAAY,GAAG,KAAK,IAAI;AACrC,QAAM,UAAU,aAAa,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC3E;AAEA,eAAsB,eACpB,KACA,OACuB;AACvB,QAAM,SAAS,MAAM,WAAW;AAChC,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,SAAS,OAAO,KAAK;AAC5B;AAAA,IACF,KAAK;AACH,aAAO,UAAU,iBAAiB,OAAO,KAAK,CAAC;AAC/C;AAAA,IACF,KAAK;AACH,UAAI,UAAU,UAAU,UAAU,SAAS;AACzC,cAAM,IAAI,MAAM,oDAAgC;AAAA,MAClD;AACA,aAAO,gBAAgB;AACvB;AAAA,IACF,KAAK;AACH,aAAO,YAAY,OAAO,KAAK;AAC/B,UAAI,CAAC,OAAO,SAAS,OAAO,SAAS,KAAK,OAAO,aAAa,GAAG;AAC/D,cAAM,IAAI,MAAM,gDAAkB;AAAA,MACpC;AACA;AAAA,EACJ;AACA,QAAM,WAAW,MAAM;AACvB,SAAO;AACT;AAEA,eAAsB,UAAU,OAAsC;AACpE,SAAO,eAAe,UAAU,KAAK;AACvC;AAEA,eAAsB,WAAW,OAAsC;AACrE,SAAO,eAAe,WAAW,KAAK;AACxC;","names":[]}
|