@deepseek-ai/dsh-host-frontend-static 0.1.1-rc.2 → 0.1.2-alpha.2
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.i18n.yaml +2 -2
- package/README.md +100 -5
- package/README.zh.md +101 -6
- package/lib/index.js +14 -8
- package/lib/types/index.d.ts +6 -4
- package/package.json +12 -9
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/host/frontend-static/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: e80dd44220ec9c29625581a8b833672834523720
|
|
6
|
+
README.zh.md: f3014deacca04f88f1750e5912f84d32562e4ba5
|
package/README.md
CHANGED
|
@@ -1,14 +1,94 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "SPA dist server for the Web shell: claims the webserver fallback seat and serves the built frontend with traversal rejection and SPA index fallback."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-host-frontend-static
|
|
2
7
|
|
|
3
8
|
English | [中文](README.zh.md)
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Browsers get the built Web shell from `dsh-host-frontend-static`: it claims the [webserver](../webserver/README.md) fallback seat and serves the built frontend directory with locked semantics — only the dist root and the configured index path render `index.html` (HTTP 200), other existing files are served directly, an absent or non-file target inside the dist root — including a missing configured index — returns an empty 404, traversal outside the dist root is 403, unknown extensions ship as `application/octet-stream`, and non-GET/HEAD without a matching named route is 405. Every successful index response is rendered through the webserver's `renderIndex`, which is how the boot manifest reaches the page. The fallback seat is single-owner: a second claim throws, and unloading the plugin releases the seat.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Compose this plugin in a browser-facing host that serves the built Web shell: it claims the webserver's fallback seat and answers every request no named route matches. It needs one config value — where the built frontend's `index.html` lives.
|
|
29
|
+
|
|
30
|
+
### Minimal configuration
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
- name: '@deepseek-ai/dsh-host-frontend-static'
|
|
34
|
+
config:
|
|
35
|
+
distIndex: /absolute/path/to/dist/index.html
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`distIndex` is an assembly fact of the composing application: [`dsh-web-app`](../../bundle/web-app/README.md) resolves it through the frontend package's exports and mounts this plugin; a deployment never hardcodes it.
|
|
39
|
+
|
|
40
|
+
### What the server enforces
|
|
41
|
+
|
|
42
|
+
Requests are served from the dist root (the directory containing `distIndex`). The dist root and the configured index path render `index.html` with HTTP 200; any other existing file is served directly with its MIME type, and unknown extensions ship as `application/octet-stream`. A path that resolves outside the root is rejected with 403, so a crafted path cannot read files above the dist. An absent or non-file target inside the dist root — a missing file, a directory, or a missing configured index — returns an empty 404. Non-GET/HEAD requests without a matching named route are answered 405. Every successful index response is rendered through the webserver's `renderIndex`, so the boot manifest reaches the page on `/` and on the configured index path.
|
|
43
|
+
|
|
44
|
+
Root and configured-index responses call `ctx.connection.authorizeIndex` before reading HTML. A valid process token receives a 303 redirect plus the persistent browser cookie; an existing valid cookie serves the index; every other index request receives the Connection-owned 401 response. Non-index files remain public static assets. Connection owns the token, cookie, expiry, and signing-record semantics.
|
|
45
|
+
|
|
46
|
+
### Observable failures
|
|
47
|
+
|
|
48
|
+
Traversal returns 403 rather than an error page. An absent or non-file target inside the dist root returns an empty 404, so a stale link or a mistyped pathname is an explicit failure rather than a silent SPA fallback. Claiming the seat twice throws, and while the seat is unclaimed the webserver answers 404 — which is what a browser sees if this plugin's fiber is disposed.
|
|
49
|
+
|
|
50
|
+
-----
|
|
51
|
+
|
|
52
|
+
<a id="understand-the-implementation"></a>
|
|
53
|
+
## Understand the implementation
|
|
54
|
+
|
|
55
|
+
<details>
|
|
56
|
+
<summary>Implementation internals — click to expand</summary>
|
|
6
57
|
|
|
7
|
-
|
|
58
|
+
### Design concept
|
|
8
59
|
|
|
60
|
+
The package is one function plugin around `serveStatic`: `apply` resolves the dist root from `distIndex`, builds a `renderIndex` closure that runs `ctx.webServer.renderIndex` over the raw `index.html`, and registers the fallback handler under an effect scope. The seat is single-owner by the webserver's contract — a second registration throws — and effect-scoped, so disposing the fiber releases the seat.
|
|
61
|
+
|
|
62
|
+
### The traversal fence
|
|
63
|
+
|
|
64
|
+
`serveStatic` normalizes the requested pathname and joins it to the dist root, then requires the target to be the root itself or stay under it. The check uses `sep` rather than `/` because `resolve()` emits backslash paths on Windows, where a `/` suffix would reject every legitimate subpath as traversal.
|
|
65
|
+
|
|
66
|
+
### Source map
|
|
67
|
+
|
|
68
|
+
| File | Role |
|
|
69
|
+
|---|---|
|
|
70
|
+
| [`src/index.ts`](src/index.ts) | `serveStatic` and `apply`: fallback claim, traversal rejection, index rendering, MIME table |
|
|
71
|
+
|
|
72
|
+
</details>
|
|
73
|
+
|
|
74
|
+
-----
|
|
75
|
+
|
|
76
|
+
<a id="further-exploration"></a>
|
|
77
|
+
## Further Exploration
|
|
78
|
+
|
|
79
|
+
Read these when the serving contract is not enough: the seat owner's contract, then the composition that resolves the dist and the subsystem reference.
|
|
80
|
+
|
|
81
|
+
- [Webserver](../webserver/README.md) — the fallback seat this plugin claims and the index taps it runs.
|
|
82
|
+
- [dsh-web-app bundle](../../bundle/web-app/README.md) — the application that resolves `distIndex` and mounts this plugin.
|
|
83
|
+
- [HTTP server subsystem](../../../docs/subsystems/web-server.md) — how the fallback seat fits the route tables.
|
|
84
|
+
- [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-host-frontend-static) — every accepted config field and its source declaration.
|
|
85
|
+
|
|
86
|
+
-----
|
|
87
|
+
|
|
88
|
+
<a id="model-experience"></a>
|
|
9
89
|
## Model Experience
|
|
10
90
|
|
|
11
|
-
None, as the
|
|
91
|
+
None, as the SPA dist server answers browser asset requests and registers nothing model-facing.
|
|
12
92
|
|
|
13
93
|
#### KV Cache effect
|
|
14
94
|
|
|
@@ -16,5 +96,20 @@ None; this package neither assembles nor sends a provider request.
|
|
|
16
96
|
|
|
17
97
|
## Known Limitations and Deferred Work
|
|
18
98
|
|
|
19
|
-
|
|
99
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
These limits define when a served asset class is not yet covered. They are current package constraints, not a task backlog.
|
|
103
|
+
|
|
104
|
+
- **The starter MIME table is minimal** — it covers the Vite-emitted asset set plus the shipped PWA manifest; other extensions fall back to `application/octet-stream` until an asset class ships.
|
|
20
105
|
- **Pathname routing is explicit** — the current client enters through the root or configured index path and has no History API pathname routes. Adding one requires an explicit server rule and real-composition coverage rather than a broad fallback for every miss.
|
|
106
|
+
|
|
107
|
+
<a id="dev-note"></a>
|
|
108
|
+
### Dev Note
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
112
|
+
|
|
113
|
+
None.
|
|
114
|
+
|
|
115
|
+
</details>
|
package/README.zh.md
CHANGED
|
@@ -1,14 +1,94 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Web 壳的 SPA dist 服务器:占据 webserver 回退席位,以遍历拒绝与 SPA index 回退服务已构建的前端。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-host-frontend-static
|
|
2
7
|
|
|
3
8
|
[English](README.md) | 中文
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
浏览器从 `dsh-host-frontend-static` 获取已构建的 Web 壳:它占据 [webserver](../webserver/README.zh.md) 回退席位,并按锁定语义服务已构建前端目录——只有 dist 根目录与配置的 index 路径以 HTTP 200 渲染 `index.html`,其他已有文件直接提供,dist 根目录内缺失或非文件的 target(包括配置的 index 缺失)返回空 404,越出 dist 根目录的遍历返回 403,未知扩展名按 `application/octet-stream` 提供,GET/HEAD 之外的方法在没有匹配的具名路由时返回 405。每个成功的 index 响应都经 webserver 的 `renderIndex` 渲染,启动 manifest(元数据清单)就是经这条路径送达页面的。回退席位只有单一所有者:第二次占据会抛错,卸载插件即释放席位。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
在服务已构建 Web 壳的浏览器宿主中组合本插件:它占据 webserver 的回退席位,并应答所有未被具名路由命中的请求。它只需要一个配置值——已构建前端的 `index.html` 位于何处。
|
|
29
|
+
|
|
30
|
+
### 最小配置
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
- name: '@deepseek-ai/dsh-host-frontend-static'
|
|
34
|
+
config:
|
|
35
|
+
distIndex: /absolute/path/to/dist/index.html
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`distIndex` 是组合应用的组装事实:[`dsh-web-app`](../../bundle/web-app/README.zh.md) 通过前端包的 exports 解析它并挂载本插件;部署绝不硬编码它。
|
|
39
|
+
|
|
40
|
+
### 服务器强制什么
|
|
41
|
+
|
|
42
|
+
请求从 dist 根目录(包含 `distIndex` 的目录)提供。dist 根目录与配置的 index 路径以 HTTP 200 渲染 `index.html`;任何其他已有文件按自身 MIME 类型直接提供,未知扩展名按 `application/octet-stream` 提供。解析到根目录之外的路径以 403 拒绝,因此精心构造的路径无法读取 dist 之上的文件。dist 根目录内缺失或非文件的 target——文件缺失、目录或配置的 index 缺失——返回空 404。没有匹配具名路由的非 GET/HEAD 请求回答 405。每个成功的 index 响应都经 webserver 的 `renderIndex` 渲染,因此启动 manifest 在 `/` 与配置的 index 路径上到达页面。
|
|
43
|
+
|
|
44
|
+
根路径与配置的 index 响应会在读取 HTML 前调用 `ctx.connection.authorizeIndex`。有效进程 token 会得到 303 重定向与持久浏览器 cookie;已有有效 cookie 时直接提供 index;其他 index 请求得到 Connection 所有的 401 响应。非 index 文件仍是公开静态资源。Token、cookie、过期时间与签名记录语义都归 Connection 所有。
|
|
45
|
+
|
|
46
|
+
### 可观察的失败
|
|
47
|
+
|
|
48
|
+
遍历返回 403 而不是错误页。dist 根目录内缺失或非文件的 target 返回空 404,因此失效链接或拼错的 pathname 是显式失败,而不是静默的 SPA 回退。第二次占据席位会抛错,而席位无人占据时 webserver 回答 404——本插件 fiber 被 dispose 后浏览器看到的就是它。
|
|
49
|
+
|
|
50
|
+
-----
|
|
51
|
+
|
|
52
|
+
<a id="understand-the-implementation"></a>
|
|
53
|
+
## 理解实现
|
|
54
|
+
|
|
55
|
+
<details>
|
|
56
|
+
<summary>实现细节——点击展开</summary>
|
|
6
57
|
|
|
7
|
-
|
|
58
|
+
### 设计理念
|
|
8
59
|
|
|
60
|
+
本包是围绕 `serveStatic` 的一个函数插件:`apply` 从 `distIndex` 解析出 dist 根目录,构建一个对原始 `index.html` 运行 `ctx.webServer.renderIndex` 的 `renderIndex` 闭包,并在 effect 作用域下注册回退 handler。按 webserver 的约定,席位只有单一所有者——第二次注册会抛错——且受 effect 作用域约束,因此 dispose fiber 即释放席位。
|
|
61
|
+
|
|
62
|
+
### 遍历栅栏
|
|
63
|
+
|
|
64
|
+
`serveStatic` 规范化请求的 pathname 并拼接到 dist 根目录,然后要求目标就是根目录本身或保持在它之下。检查使用 `sep` 而非 `/`,因为 `resolve()` 在 Windows 上输出反斜杠路径,此时 `/` 后缀会把每个合法子路径都当作遍历拒绝。
|
|
65
|
+
|
|
66
|
+
### 源码地图
|
|
67
|
+
|
|
68
|
+
| 文件 | 职责 |
|
|
69
|
+
|---|---|
|
|
70
|
+
| [`src/index.ts`](src/index.ts) | `serveStatic` 与 `apply`:回退占据、遍历拒绝、index 渲染、MIME 表 |
|
|
71
|
+
|
|
72
|
+
</details>
|
|
73
|
+
|
|
74
|
+
-----
|
|
75
|
+
|
|
76
|
+
<a id="further-exploration"></a>
|
|
77
|
+
## 进一步探索
|
|
78
|
+
|
|
79
|
+
当服务约定不够用时阅读以下内容:先看席位所有者的约定,再看解析 dist 的组合与子系统参考。
|
|
80
|
+
|
|
81
|
+
- [Webserver](../webserver/README.zh.md)——本插件占据的回退席位与它运行的 index 转换器。
|
|
82
|
+
- [dsh-web-app 组合包](../../bundle/web-app/README.zh.md)——解析 `distIndex` 并挂载本插件的应用。
|
|
83
|
+
- [HTTP 服务器子系统](../../../docs/subsystems/web-server.zh.md)——回退席位如何融入路由表。
|
|
84
|
+
- [生成配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-host-frontend-static)——每个受支持配置字段及其源声明。
|
|
85
|
+
|
|
86
|
+
-----
|
|
87
|
+
|
|
88
|
+
<a id="model-experience"></a>
|
|
9
89
|
## 模型体验
|
|
10
90
|
|
|
11
|
-
|
|
91
|
+
无。该 SPA dist 服务器只应答浏览器资产请求,不注册任何面向模型的内容。
|
|
12
92
|
|
|
13
93
|
#### KV Cache 影响
|
|
14
94
|
|
|
@@ -16,5 +96,20 @@ Web 壳的 SPA dist 服务器:一个函数插件(配置为 `{distIndex}`)
|
|
|
16
96
|
|
|
17
97
|
## 已知限制与延期工作
|
|
18
98
|
|
|
19
|
-
|
|
20
|
-
|
|
99
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
这些限制说明某个资产类别何时尚未被覆盖。它们是当前包约束,不是任务积压。
|
|
103
|
+
|
|
104
|
+
- **初始 MIME 表很精简**:它覆盖 Vite 输出的资产集合及实际交付的 PWA manifest;其他扩展名在相应资产类别发布前都会回退到 `application/octet-stream`。
|
|
105
|
+
- **Pathname 路由是显式声明**——当前客户端从根目录或配置的 index 路径进入,没有 History API pathname 路由。新增一条需要显式服务器规则与真实组合覆盖,而不是对每次未命中做宽泛回退。
|
|
106
|
+
|
|
107
|
+
<a id="dev-note"></a>
|
|
108
|
+
### 开发备注
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
112
|
+
|
|
113
|
+
无。
|
|
114
|
+
|
|
115
|
+
</details>
|
package/lib/index.js
CHANGED
|
@@ -8,16 +8,17 @@ import z from "@deepseek-ai/schemastery";
|
|
|
8
8
|
* entry points. A readable index renders at the dist root and configured index
|
|
9
9
|
* path; missing paths return 404, traversal outside the dist root is 403,
|
|
10
10
|
* unknown extensions ship as octet-stream, and non-GET/HEAD is 405. Every
|
|
11
|
-
* index response
|
|
12
|
-
* injection rows, then raw taps).
|
|
11
|
+
* index response first passes Connection's browser authentication, then the
|
|
12
|
+
* webserver's index render (structured injection rows, then raw taps).
|
|
13
|
+
* Non-index assets stay public. The dist location is workspace knowledge of
|
|
13
14
|
* the composing application, so `distIndex` is typically supplied through a
|
|
14
15
|
* `!!js` expression, never hardcoded by a deployment.
|
|
15
16
|
* @module @deepseek-ai/dsh-host-frontend-static
|
|
16
17
|
*/
|
|
17
18
|
/** Stable Cordis plugin name. */
|
|
18
19
|
const name = "frontend-static";
|
|
19
|
-
/**
|
|
20
|
-
const inject = ["webServer"];
|
|
20
|
+
/** Services required before the authenticated fallback seat can be claimed. */
|
|
21
|
+
const inject = ["webServer", "connection"];
|
|
21
22
|
const Config = z.object({ distIndex: z.string().required() });
|
|
22
23
|
const HTML_MIME = "text/html; charset=utf-8";
|
|
23
24
|
const MIME = {
|
|
@@ -27,7 +28,8 @@ const MIME = {
|
|
|
27
28
|
".svg": "image/svg+xml",
|
|
28
29
|
".json": "application/json",
|
|
29
30
|
".map": "application/json",
|
|
30
|
-
".webmanifest": "application/manifest+json"
|
|
31
|
+
".webmanifest": "application/manifest+json",
|
|
32
|
+
".gz": "application/gzip"
|
|
31
33
|
};
|
|
32
34
|
const STATIC_MISS_CODES = new Set([
|
|
33
35
|
"ENOENT",
|
|
@@ -40,10 +42,11 @@ const STATIC_MISS_CODES = new Set([
|
|
|
40
42
|
* @param res - the node:http response to write.
|
|
41
43
|
* @param distRoot - absolute dist root directory (resolved by the caller).
|
|
42
44
|
* @param distIndex - absolute path of index.html inside distRoot.
|
|
45
|
+
* @param authorizeIndex - authenticates an index response before its bytes are read.
|
|
43
46
|
* @param renderIndex - produces the index.html body (structured injection
|
|
44
47
|
* rendering) for the dist root and configured index path.
|
|
45
48
|
*/
|
|
46
|
-
async function serveStatic(pathname, res, distRoot, distIndex, renderIndex) {
|
|
49
|
+
async function serveStatic(pathname, res, distRoot, distIndex, authorizeIndex, renderIndex) {
|
|
47
50
|
const target = resolve(normalize(join(distRoot, pathname)));
|
|
48
51
|
if (target !== distRoot && !target.startsWith(distRoot + sep)) {
|
|
49
52
|
res.writeHead(403);
|
|
@@ -54,6 +57,7 @@ async function serveStatic(pathname, res, distRoot, distIndex, renderIndex) {
|
|
|
54
57
|
let type;
|
|
55
58
|
try {
|
|
56
59
|
if (target === distRoot || target === distIndex) {
|
|
60
|
+
if (!authorizeIndex()) return;
|
|
57
61
|
body = await renderIndex();
|
|
58
62
|
type = HTML_MIME;
|
|
59
63
|
} else {
|
|
@@ -77,7 +81,9 @@ async function serveStatic(pathname, res, distRoot, distIndex, renderIndex) {
|
|
|
77
81
|
function apply(ctx, config) {
|
|
78
82
|
const distIndex = config.distIndex;
|
|
79
83
|
const distRoot = dirname(distIndex);
|
|
80
|
-
const renderIndex = async () =>
|
|
84
|
+
const renderIndex = async () => {
|
|
85
|
+
return ctx.webServer.renderIndex(await readFile(distIndex, "utf8")).replace(/<head(?:\s[^>]*)?>/i, (open) => `${open}<base href="/">`);
|
|
86
|
+
};
|
|
81
87
|
ctx.effect(() => ctx.webServer.registerFallback(async (req, res) => {
|
|
82
88
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
83
89
|
res.writeHead(405);
|
|
@@ -86,7 +92,7 @@ function apply(ctx, config) {
|
|
|
86
92
|
}
|
|
87
93
|
/* v8 ignore next -- node:http always sets url on server requests */
|
|
88
94
|
const rawPath = new URL(req.url ?? "/", "http://x").pathname;
|
|
89
|
-
await serveStatic(decodeURIComponent(rawPath), res, distRoot, distIndex, renderIndex);
|
|
95
|
+
await serveStatic(decodeURIComponent(rawPath), res, distRoot, distIndex, () => ctx.connection.authorizeIndex(req, res), renderIndex);
|
|
90
96
|
}), "frontend-static: fallback seat");
|
|
91
97
|
}
|
|
92
98
|
//#endregion
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* entry points. A readable index renders at the dist root and configured index
|
|
5
5
|
* path; missing paths return 404, traversal outside the dist root is 403,
|
|
6
6
|
* unknown extensions ship as octet-stream, and non-GET/HEAD is 405. Every
|
|
7
|
-
* index response
|
|
8
|
-
* injection rows, then raw taps).
|
|
7
|
+
* index response first passes Connection's browser authentication, then the
|
|
8
|
+
* webserver's index render (structured injection rows, then raw taps).
|
|
9
|
+
* Non-index assets stay public. The dist location is workspace knowledge of
|
|
9
10
|
* the composing application, so `distIndex` is typically supplied through a
|
|
10
11
|
* `!!js` expression, never hardcoded by a deployment.
|
|
11
12
|
* @module @deepseek-ai/dsh-host-frontend-static
|
|
@@ -15,7 +16,7 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
15
16
|
import z from '@deepseek-ai/schemastery';
|
|
16
17
|
/** Stable Cordis plugin name. */
|
|
17
18
|
export declare const name = "frontend-static";
|
|
18
|
-
/**
|
|
19
|
+
/** Services required before the authenticated fallback seat can be claimed. */
|
|
19
20
|
export declare const inject: string[];
|
|
20
21
|
/** Plugin config: the dist anchor. */
|
|
21
22
|
export interface Config {
|
|
@@ -29,10 +30,11 @@ export declare const Config: z<Config>;
|
|
|
29
30
|
* @param res - the node:http response to write.
|
|
30
31
|
* @param distRoot - absolute dist root directory (resolved by the caller).
|
|
31
32
|
* @param distIndex - absolute path of index.html inside distRoot.
|
|
33
|
+
* @param authorizeIndex - authenticates an index response before its bytes are read.
|
|
32
34
|
* @param renderIndex - produces the index.html body (structured injection
|
|
33
35
|
* rendering) for the dist root and configured index path.
|
|
34
36
|
*/
|
|
35
|
-
export declare function serveStatic(pathname: string, res: ServerResponse, distRoot: string, distIndex: string, renderIndex: () => Promise<string>): Promise<void>;
|
|
37
|
+
export declare function serveStatic(pathname: string, res: ServerResponse, distRoot: string, distIndex: string, authorizeIndex: () => boolean, renderIndex: () => Promise<string>): Promise<void>;
|
|
36
38
|
/**
|
|
37
39
|
* Claim the webserver fallback seat and serve the dist.
|
|
38
40
|
* @param ctx - plugin context carrying the webServer service.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-host-frontend-static",
|
|
3
3
|
"description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving explicit index entries and static assets with traversal rejection and 404 misses",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -32,17 +32,20 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@deepseek-ai/dsh-
|
|
36
|
-
"@deepseek-ai/
|
|
37
|
-
"@deepseek-ai/dsh-
|
|
35
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.2",
|
|
36
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
37
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.2",
|
|
38
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
41
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@deepseek-ai/
|
|
44
|
-
"@deepseek-ai/
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/
|
|
44
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.2",
|
|
45
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
46
|
+
"@deepseek-ai/dsh-credentials-local": "^0.1.2-alpha.2",
|
|
47
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.2",
|
|
48
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
49
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
47
50
|
}
|
|
48
51
|
}
|