mock-service-cli 4.5.0 → 4.6.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/README.md +13 -7
- package/dist/file-explorer-login.html +1 -1
- package/dist/file-explorer.html +33 -7
- package/dist/meta.json +7 -7
- package/dist/runtime.js +13 -10
- package/docs/static-server.config.example.json +36 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -76,8 +76,9 @@ npx mock-service-cli [options] [path]
|
|
|
76
76
|
| `-D` 或 `--web-dir` | 启用 Web 服务器,指定 web 目录(SPA 应用) | - |
|
|
77
77
|
| `-P` 或 `--web-port` | Web 服务器端口 | 9090 |
|
|
78
78
|
| `-b` 或 `--web-baseurl` | 指定 SPA Web 服务器的公共路径 | - |
|
|
79
|
-
| `-R` 或 `--static-server` |
|
|
80
|
-
| `--
|
|
79
|
+
| `-R` 或 `--static-server` | 启用单目录静态服务器,指定静态资源目录 | - |
|
|
80
|
+
| `--spa-fallback <path>` | 单目录模式显式启用 SPA 回退 | - |
|
|
81
|
+
| `--static-config <file>` | 使用自包含 JSON 配置启动静态服务器 | - |
|
|
81
82
|
| `-w` 或 `--open` | 自动打开 API 概览页、文件浏览器页 | false |
|
|
82
83
|
| `-e` 或 `--explorer` | 启用文件浏览器服务器,指定要浏览的目录 | ./ |
|
|
83
84
|
| `--edit` | 启用文件浏览器的新建、重命名、删除和上传操作 | false |
|
|
@@ -108,16 +109,21 @@ mock-service-cli -f ./mock.js
|
|
|
108
109
|
# 启动静态服务器
|
|
109
110
|
mock-service-cli -R ./public
|
|
110
111
|
|
|
111
|
-
#
|
|
112
|
-
mock-service-cli -R ./public --
|
|
112
|
+
# 单目录模式启用 SPA 回退
|
|
113
|
+
mock-service-cli -R ./public --spa-fallback /index.html
|
|
114
|
+
|
|
115
|
+
# 使用自包含配置(不需要目录参数)
|
|
116
|
+
mock-service-cli -R --static-config ./static-server.json
|
|
117
|
+
mock-service-cli --static-config ./static-server.json
|
|
113
118
|
```
|
|
114
119
|
|
|
115
120
|
静态服务器会监听资源变化并向 HTML 页面注入热更新客户端:CSS 文件更新时替换样式表,其余变更刷新页面。
|
|
116
121
|
默认不打开浏览器;在配置中设置 `"open": true` 或提供页面路径即可打开。完整配置字段和示例见
|
|
117
122
|
[`docs/static-server.config.example.json`](./docs/static-server.config.example.json):支持忽略规则、SPA 回退、挂载目录、代理、HTTPS、CORS、响应头和自定义浏览器命令。
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
配置文件只在顶层保留服务器级字段。所有应用都放在 `mounts` 中,并可独立设置 `directory`、`spaFallback`、`proxy`、`cors`、`headers` 和 `secure`。mount 未设置 `path` 时默认挂载到 `/`;`directory` 可省略,但该应用必须配置至少一条代理。代理键使用完整公开路径,例如 `/api/app`。
|
|
124
|
+
代理规则使用 `{ "target": "http://...", "rewrite": true }`;`rewrite` 为 true 时只移除匹配的完整代理前缀并保留剩余路径和 query string。应用级 `secure` 控制其代理 HTTPS 目标的证书校验,默认 `false`。配置模式不接受 `--proxy-options`、`--rewrite` 或 `--spa-fallback`。
|
|
125
|
+
未设置 `spaFallback` 时,应用目录会显示可点击的目录索引;可直接访问其中的 HTML 文件。mount 未命中的路由不会继续进入其他应用的 SPA fallback。
|
|
126
|
+
设置了 `spaFallback` 的应用可选配置 `accessLog.success` 与 `accessLog.failure` 文件路径。服务将把每次访问以 JSON Lines 写入对应文件:2xx/3xx 写入 success,4xx/5xx 写入 failure;路径相对配置文件解析。启动后控制台会突出显示每条代理所属的应用、公开前缀、目标和 rewrite 状态。
|
|
121
127
|
|
|
122
128
|
### Web 服务器 (SPA)
|
|
123
129
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>文件浏览器登录</title>
|
|
7
|
-
<link rel="icon" type="image/svg+xml" href="
|
|
7
|
+
<link rel="icon" type="image/svg+xml" href="__FILE_EXPLORER_FAVICON_URL__" />
|
|
8
8
|
<style>
|
|
9
9
|
* { box-sizing: border-box; }
|
|
10
10
|
body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #f4f6f8; color: #202124; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
package/dist/file-explorer.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>文件浏览器 - File Explorer</title>
|
|
7
|
-
<link rel="icon" type="image/svg+xml" href="
|
|
7
|
+
<link rel="icon" type="image/svg+xml" href="__FILE_EXPLORER_FAVICON_URL__" />
|
|
8
8
|
<style>
|
|
9
9
|
* {
|
|
10
10
|
margin: 0;
|
|
@@ -1158,6 +1158,7 @@
|
|
|
1158
1158
|
let explorerLifecycleVersion = 0;
|
|
1159
1159
|
let currentArchiveJobId = null;
|
|
1160
1160
|
let currentArchiveJobOperation = null;
|
|
1161
|
+
let explorerRootId = null;
|
|
1161
1162
|
let archiveCapabilities = { createFormats: [], readExtensions: [] };
|
|
1162
1163
|
|
|
1163
1164
|
const EXPLORER_AUTH_STORAGE_KEY = 'mock-service-cli.file-explorer.password';
|
|
@@ -1281,6 +1282,7 @@
|
|
|
1281
1282
|
const config = await response.json();
|
|
1282
1283
|
if (!response.ok || config.error) throw new Error(config.error || 'Failed to load configuration');
|
|
1283
1284
|
editMode = Boolean(config.editMode);
|
|
1285
|
+
explorerRootId = typeof config.rootId === 'string' ? config.rootId : null;
|
|
1284
1286
|
} catch (error) {
|
|
1285
1287
|
console.warn('Failed to load file explorer configuration:', error);
|
|
1286
1288
|
editMode = false;
|
|
@@ -1413,7 +1415,25 @@
|
|
|
1413
1415
|
}
|
|
1414
1416
|
}
|
|
1415
1417
|
|
|
1416
|
-
|
|
1418
|
+
function getStoredExplorerPath() {
|
|
1419
|
+
try {
|
|
1420
|
+
const stored = JSON.parse(sessionStorage.getItem(EXPLORER_PATH_STORAGE_KEY));
|
|
1421
|
+
if (stored && stored.rootId === explorerRootId && typeof stored.path === 'string' && stored.path.startsWith('/')) {
|
|
1422
|
+
return stored.path;
|
|
1423
|
+
}
|
|
1424
|
+
} catch (error) {
|
|
1425
|
+
// Earlier releases stored the path directly; discard that unscoped value.
|
|
1426
|
+
}
|
|
1427
|
+
sessionStorage.removeItem(EXPLORER_PATH_STORAGE_KEY);
|
|
1428
|
+
return '/';
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
function storeExplorerPath(path) {
|
|
1432
|
+
if (!explorerRootId) return;
|
|
1433
|
+
sessionStorage.setItem(EXPLORER_PATH_STORAGE_KEY, JSON.stringify({ rootId: explorerRootId, path }));
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
async function initializeExplorer() {
|
|
1417
1437
|
if (explorerInitializationPromise) return explorerInitializationPromise;
|
|
1418
1438
|
|
|
1419
1439
|
const lifecycleVersion = explorerLifecycleVersion;
|
|
@@ -1443,7 +1463,7 @@
|
|
|
1443
1463
|
await loadArchiveCapabilities();
|
|
1444
1464
|
if (lifecycleVersion !== explorerLifecycleVersion) return;
|
|
1445
1465
|
startHealthCheck();
|
|
1446
|
-
await loadDirectory(
|
|
1466
|
+
await loadDirectory(getStoredExplorerPath(), { fallbackToRoot: true });
|
|
1447
1467
|
})();
|
|
1448
1468
|
explorerInitializationPromise = initializationPromise;
|
|
1449
1469
|
|
|
@@ -1460,7 +1480,7 @@
|
|
|
1460
1480
|
|
|
1461
1481
|
window.addEventListener('pagehide', handlePageHide);
|
|
1462
1482
|
window.addEventListener('pageshow', event => {
|
|
1463
|
-
if (event.persisted) initializeExplorer(
|
|
1483
|
+
if (event.persisted) initializeExplorer();
|
|
1464
1484
|
});
|
|
1465
1485
|
|
|
1466
1486
|
function showContextMenu(x, y, filePath, isDirectory) {
|
|
@@ -1538,7 +1558,7 @@
|
|
|
1538
1558
|
hideContextMenu();
|
|
1539
1559
|
}
|
|
1540
1560
|
|
|
1541
|
-
async function loadDirectory(path) {
|
|
1561
|
+
async function loadDirectory(path, { fallbackToRoot = false } = {}) {
|
|
1542
1562
|
const fileGrid = document.getElementById('fileGrid');
|
|
1543
1563
|
const oldCurrentPath = currentPath;
|
|
1544
1564
|
const requestId = ++directoryRequestId;
|
|
@@ -1562,12 +1582,14 @@
|
|
|
1562
1582
|
const data = await response.json();
|
|
1563
1583
|
|
|
1564
1584
|
if (!response.ok || data.error) {
|
|
1565
|
-
|
|
1585
|
+
const error = new Error(data.error || 'Failed to load directory');
|
|
1586
|
+
error.status = response.status;
|
|
1587
|
+
throw error;
|
|
1566
1588
|
}
|
|
1567
1589
|
if (requestId !== directoryRequestId) return;
|
|
1568
1590
|
|
|
1569
1591
|
currentPath = data.currentPath;
|
|
1570
|
-
|
|
1592
|
+
storeExplorerPath(currentPath);
|
|
1571
1593
|
allFiles = data.files || [];
|
|
1572
1594
|
|
|
1573
1595
|
if (document.getElementById('searchInput')) {
|
|
@@ -1580,6 +1602,10 @@
|
|
|
1580
1602
|
updateBackButton(data.parentPath);
|
|
1581
1603
|
} catch (error) {
|
|
1582
1604
|
if (error.name === 'AbortError' || requestId !== directoryRequestId) return;
|
|
1605
|
+
if (fallbackToRoot && path !== '/' && error.status === 404) {
|
|
1606
|
+
sessionStorage.removeItem(EXPLORER_PATH_STORAGE_KEY);
|
|
1607
|
+
return loadDirectory('/', { fallbackToRoot: false });
|
|
1608
|
+
}
|
|
1583
1609
|
console.error('Error loading directory:', error);
|
|
1584
1610
|
currentPath = oldCurrentPath;
|
|
1585
1611
|
const parentPath = currentPath === '/' ? null : currentPath.substring(0, currentPath.lastIndexOf('/')) || '/';
|
package/dist/meta.json
CHANGED
|
@@ -1088,7 +1088,7 @@
|
|
|
1088
1088
|
"format": "cjs"
|
|
1089
1089
|
},
|
|
1090
1090
|
"src/bin/mock-service-cli": {
|
|
1091
|
-
"bytes":
|
|
1091
|
+
"bytes": 13264,
|
|
1092
1092
|
"imports": [
|
|
1093
1093
|
{
|
|
1094
1094
|
"path": "node_modules/colors/safe.js",
|
|
@@ -6704,7 +6704,7 @@
|
|
|
6704
6704
|
"format": "cjs"
|
|
6705
6705
|
},
|
|
6706
6706
|
"src/lib/staticServer.js": {
|
|
6707
|
-
"bytes":
|
|
6707
|
+
"bytes": 33699,
|
|
6708
6708
|
"imports": [
|
|
6709
6709
|
{
|
|
6710
6710
|
"path": "node_modules/express/index.js",
|
|
@@ -7484,7 +7484,7 @@
|
|
|
7484
7484
|
"format": "cjs"
|
|
7485
7485
|
},
|
|
7486
7486
|
"src/lib/fileExplorerServer.js": {
|
|
7487
|
-
"bytes":
|
|
7487
|
+
"bytes": 25537,
|
|
7488
7488
|
"imports": [
|
|
7489
7489
|
{
|
|
7490
7490
|
"path": "node_modules/express/index.js",
|
|
@@ -8872,7 +8872,7 @@
|
|
|
8872
8872
|
"bytesInOutput": 429
|
|
8873
8873
|
},
|
|
8874
8874
|
"src/bin/mock-service-cli": {
|
|
8875
|
-
"bytesInOutput":
|
|
8875
|
+
"bytesInOutput": 10204
|
|
8876
8876
|
},
|
|
8877
8877
|
"node_modules/depd/index.js": {
|
|
8878
8878
|
"bytesInOutput": 6779
|
|
@@ -9856,7 +9856,7 @@
|
|
|
9856
9856
|
"bytesInOutput": 10974
|
|
9857
9857
|
},
|
|
9858
9858
|
"src/lib/staticServer.js": {
|
|
9859
|
-
"bytesInOutput":
|
|
9859
|
+
"bytesInOutput": 26622
|
|
9860
9860
|
},
|
|
9861
9861
|
"node_modules/busboy/lib/utils.js": {
|
|
9862
9862
|
"bytesInOutput": 8707
|
|
@@ -9979,13 +9979,13 @@
|
|
|
9979
9979
|
"bytesInOutput": 7774
|
|
9980
9980
|
},
|
|
9981
9981
|
"src/lib/fileExplorerServer.js": {
|
|
9982
|
-
"bytesInOutput":
|
|
9982
|
+
"bytesInOutput": 19066
|
|
9983
9983
|
},
|
|
9984
9984
|
"src/runtime.js": {
|
|
9985
9985
|
"bytesInOutput": 507
|
|
9986
9986
|
}
|
|
9987
9987
|
},
|
|
9988
|
-
"bytes":
|
|
9988
|
+
"bytes": 1631230
|
|
9989
9989
|
}
|
|
9990
9990
|
}
|
|
9991
9991
|
}
|