@monotykamary/dsh-host-frontend-static 0.1.0-rc.10

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
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.
@@ -0,0 +1,6 @@
1
+ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
+ # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
+ # after editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/host/frontend-static/README.md
5
+ README.md: a8cba9233a694c4f257c1d7197d7247e80e066ac
6
+ README.zh.md: 2d2a53a49003896fbf19ca571d05b0af4e2d3eb3
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # `@monotykamary/dsh-host-frontend-static`
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ SPA dist server for the Web shell: a function plugin (config `{distIndex}`) that claims the [webserver](../webserver/README.md)'s single fallback seat and serves the built frontend directory with the shell's locked semantics — traversal outside the dist root is 403, any miss falls back to `index.html` with HTTP 200 (SPA routing), unknown extensions ship as `application/octet-stream`, and non-GET/HEAD without a matching named route is 405. Every index response runs through the webserver's registered index taps (`applyIndexTaps`), which is how the boot manifest reaches the page. `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.
6
+
7
+ The fallback seat is single-owner (a second claim throws) and effect-scoped: disposing the plugin's fiber releases the seat, after which the unclaimed webserver answers 404.
8
+
9
+ ## Model Experience
10
+
11
+ None, as the package serves browser assets; nothing here reaches a model request.
12
+
13
+ #### KV Cache effect
14
+
15
+ None; this package neither assembles nor sends a provider request.
16
+
17
+ ## Known Limitations and Deferred Work
18
+
19
+ - **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 actually ships.
package/README.zh.md ADDED
@@ -0,0 +1,19 @@
1
+ # `@monotykamary/dsh-host-frontend-static`
2
+
3
+ [English](README.md) | 中文
4
+
5
+ Web 壳的 SPA dist 服务器:一个函数插件(配置为 `{distIndex}`),占据 [webserver](../webserver/README.md) 的唯一回退席位,并按壳层锁定的语义服务已构建的前端目录——越出 dist 根目录的遍历返回 403,任何未命中项都以 HTTP 200 回退到 `index.html`(SPA 路由),未知扩展名按 `application/octet-stream` 提供,GET/HEAD 之外的方法在没有匹配的具名路由时返回 405。每个 index 响应都会经过 webserver 已注册的 index 转换器(`applyIndexTaps`),启动 manifest(元数据清单)就是经这条路径送达页面的。`distIndex` 是组合应用的组装事实:[`dsh-web-app`](../../bundle/web-app/README.md) 通过前端包的 exports 解析它并挂载本插件;部署绝不硬编码它。
6
+
7
+ 回退席位只有单一所有者(第二次占据会抛错),并受 effect 作用域约束:dispose(资源释放)插件的 fiber 会释放席位,此后无人占据的 webserver 回答 404。
8
+
9
+ ## 模型体验
10
+
11
+ 无。该包只服务浏览器资产;其中没有任何内容会进入模型请求。
12
+
13
+ #### KV Cache 影响
14
+
15
+ 无;该包既不组装也不发送提供方请求。
16
+
17
+ ## 已知限制与延期工作
18
+
19
+ - **初始 MIME 表很精简**:它覆盖 Vite 输出的资产集合及实际交付的 PWA manifest;其他扩展名在相应资产类别实际发布前都会回退到 `application/octet-stream`。
package/lib/index.js ADDED
@@ -0,0 +1,85 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname, extname, join, normalize, resolve, sep } from "node:path";
3
+ import z from "@monotykamary/schemastery";
4
+ //#region lib/types/index.js
5
+ /**
6
+ * @monotykamary/dsh-host-frontend-static — SPA dist server over the webserver
7
+ * fallback seat: serves the built frontend directory with the semantics the
8
+ * Web shell locked at step1 — traversal outside the dist root is 403, any
9
+ * miss falls back to index.html with HTTP 200 (SPA routing), unknown
10
+ * extensions ship as octet-stream, non-GET/HEAD is 405. Every index response
11
+ * runs through the webserver's registered index taps (boot-manifest
12
+ * injection). The dist location is workspace knowledge of the composing
13
+ * application, so `distIndex` is typically supplied through a `!!js`
14
+ * expression, never hardcoded by a deployment.
15
+ * @module @monotykamary/dsh-host-frontend-static
16
+ */
17
+ /** Stable Cordis plugin name. */
18
+ const name = "frontend-static";
19
+ /** Service required before the fallback seat can be claimed. */
20
+ const inject = ["webServer"];
21
+ const Config = z.object({ distIndex: z.string().required() });
22
+ const MIME = {
23
+ ".html": "text/html; charset=utf-8",
24
+ ".js": "text/javascript; charset=utf-8",
25
+ ".css": "text/css; charset=utf-8",
26
+ ".svg": "image/svg+xml",
27
+ ".json": "application/json",
28
+ ".map": "application/json",
29
+ ".webmanifest": "application/manifest+json"
30
+ };
31
+ /**
32
+ * Serve one GET/HEAD static request from the dist root.
33
+ * @param pathname - decoded URL pathname of the request.
34
+ * @param res - the node:http response to write.
35
+ * @param distRoot - absolute dist root directory (resolved by the caller).
36
+ * @param distIndex - absolute path of index.html inside distRoot.
37
+ * @param renderIndex - produces the index.html body (index-tap injection) for
38
+ * `/` and every SPA fallback.
39
+ */
40
+ async function serveStatic(pathname, res, distRoot, distIndex, renderIndex) {
41
+ const target = resolve(normalize(join(distRoot, pathname)));
42
+ if (target !== distRoot && !target.startsWith(distRoot + sep)) {
43
+ res.writeHead(403);
44
+ res.end();
45
+ return;
46
+ }
47
+ const serveIndex = async () => {
48
+ const body = await renderIndex();
49
+ res.writeHead(200, { "content-type": MIME[".html"] });
50
+ res.end(body);
51
+ };
52
+ if (target === distRoot || target === distIndex) {
53
+ await serveIndex();
54
+ return;
55
+ }
56
+ try {
57
+ const body = await readFile(target);
58
+ res.writeHead(200, { "content-type": MIME[extname(target)] ?? "application/octet-stream" });
59
+ res.end(body);
60
+ } catch {
61
+ await serveIndex();
62
+ }
63
+ }
64
+ /**
65
+ * Claim the webserver fallback seat and serve the dist.
66
+ * @param ctx - plugin context carrying the webServer service.
67
+ * @param config - validated {@link Config}.
68
+ */
69
+ function apply(ctx, config) {
70
+ const distIndex = config.distIndex;
71
+ const distRoot = dirname(distIndex);
72
+ const renderIndex = async () => ctx.webServer.applyIndexTaps(await readFile(distIndex, "utf8"));
73
+ ctx.effect(() => ctx.webServer.registerFallback(async (req, res) => {
74
+ if (req.method !== "GET" && req.method !== "HEAD") {
75
+ res.writeHead(405);
76
+ res.end();
77
+ return;
78
+ }
79
+ /* v8 ignore next -- node:http always sets url on server requests */
80
+ const rawPath = new URL(req.url ?? "/", "http://x").pathname;
81
+ await serveStatic(decodeURIComponent(rawPath), res, distRoot, distIndex, renderIndex);
82
+ }), "frontend-static: fallback seat");
83
+ }
84
+ //#endregion
85
+ export { Config, apply, inject, name, serveStatic };
@@ -0,0 +1,29 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@monotykamary/dsh-host-frontend-static`.
4
+ * @module @monotykamary/dsh-host-frontend-static/invariant
5
+ */
6
+ const PACKAGE_NAME = "@monotykamary/dsh-host-frontend-static";
7
+ /** Cordis companion plugin name. */
8
+ const name = "host-frontend-static-invariant";
9
+ /** Service required before the companion can register. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * No runtime invariant: the only owned relation is the single fallback seat,
13
+ * which cannot be probed from the teardown stream — `internal/plugin` fires
14
+ * before the disposing fiber's effects run, so the legitimate owner still
15
+ * holds the seat at notification time and any claim probe would
16
+ * false-positive on every correct disposal (unlike the webserver companion,
17
+ * whose reserved-path probes never collide with a live registration). The
18
+ * seat's register/release symmetry is covered by the package's
19
+ * real-composition HMR-safety test instead.
20
+ */
21
+ const install = () => {};
22
+ /**
23
+ * Register this package's invariant companion.
24
+ * @param ctx - Cordis context carrying the invariant service.
25
+ * @returns the installed registration's disposer after setup succeeds.
26
+ */
27
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
28
+ //#endregion
29
+ export { apply, inject, name };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @monotykamary/dsh-host-frontend-static — SPA dist server over the webserver
3
+ * fallback seat: serves the built frontend directory with the semantics the
4
+ * Web shell locked at step1 — traversal outside the dist root is 403, any
5
+ * miss falls back to index.html with HTTP 200 (SPA routing), unknown
6
+ * extensions ship as octet-stream, non-GET/HEAD is 405. Every index response
7
+ * runs through the webserver's registered index taps (boot-manifest
8
+ * injection). The dist location is workspace knowledge of the composing
9
+ * application, so `distIndex` is typically supplied through a `!!js`
10
+ * expression, never hardcoded by a deployment.
11
+ * @module @monotykamary/dsh-host-frontend-static
12
+ */
13
+ import type { ServerResponse } from 'node:http';
14
+ import type { Context } from '@monotykamary/cordis';
15
+ import z from '@monotykamary/schemastery';
16
+ /** Stable Cordis plugin name. */
17
+ export declare const name = "frontend-static";
18
+ /** Service required before the fallback seat can be claimed. */
19
+ export declare const inject: string[];
20
+ /** Plugin config: the dist anchor. */
21
+ export interface Config {
22
+ /** Absolute path of index.html inside the dist root. */
23
+ distIndex: string;
24
+ }
25
+ export declare const Config: z<Config>;
26
+ /**
27
+ * Serve one GET/HEAD static request from the dist root.
28
+ * @param pathname - decoded URL pathname of the request.
29
+ * @param res - the node:http response to write.
30
+ * @param distRoot - absolute dist root directory (resolved by the caller).
31
+ * @param distIndex - absolute path of index.html inside distRoot.
32
+ * @param renderIndex - produces the index.html body (index-tap injection) for
33
+ * `/` and every SPA fallback.
34
+ */
35
+ export declare function serveStatic(pathname: string, res: ServerResponse, distRoot: string, distIndex: string, renderIndex: () => Promise<string>): Promise<void>;
36
+ /**
37
+ * Claim the webserver fallback seat and serve the dist.
38
+ * @param ctx - plugin context carrying the webServer service.
39
+ * @param config - validated {@link Config}.
40
+ */
41
+ export declare function apply(ctx: Context, config: Config): void;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@monotykamary/dsh-host-frontend-static`.
3
+ * @module @monotykamary/dsh-host-frontend-static/invariant
4
+ */
5
+ import type { Context } from '@monotykamary/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "host-frontend-static-invariant";
8
+ /** Service required before the companion can register. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer after setup succeeds.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@monotykamary/dsh-host-frontend-static",
3
+ "description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving the built frontend with index-tap injection, traversal rejection, and SPA index fallback",
4
+ "version": "0.1.0-rc.10",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/host/frontend-static"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./src/*": "./src/*",
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "lib/index.js",
30
+ "lib/invariant.js",
31
+ "lib/types/**/*.d.ts"
32
+ ],
33
+ "license": "MIT",
34
+ "peerDependencies": {
35
+ "@monotykamary/dsh-host-webserver": "^0.1.0-rc.10",
36
+ "@monotykamary/dsh-invariants": "^0.1.0-rc.10",
37
+ "@monotykamary/cordis": "^4.0.1"
38
+ },
39
+ "dependencies": {
40
+ "@monotykamary/schemastery": "^3.18.1"
41
+ },
42
+ "devDependencies": {
43
+ "@monotykamary/cordis-plugin-loader": "^1.0.2",
44
+ "@monotykamary/dsh-host-webserver": "^0.1.0-rc.10",
45
+ "@monotykamary/dsh-invariants": "^0.1.0-rc.10",
46
+ "@monotykamary/cordis": "^4.0.1"
47
+ }
48
+ }