@morlay/dsh-desktop-shell 0.0.1-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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 morlay
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,34 @@
1
+ # @morlay/dsh-desktop-shell
2
+
3
+ dsh 桌面应用的 **Electron 壳**:服务应用自己的 `<name>://` 协议,经字节管道(FD 3/4)把 desktop profile 交给
4
+ host 子进程 [`@morlay/dsh-desktop-host`](../dsh-desktop-host/README.md) 启动,并在首次启动 / 种子指纹变化时把
5
+ profile 种进 `DSH_HOME`。
6
+
7
+ 它**不单独跑**——启动与打包它的是 [`@morlay/dsh-desktopify`](../dsh-desktopify/README.md):
8
+
9
+ - `dsh-desktopify dev` 以**本包目录**为 Electron app 启动(Electron 按本包清单的 `main` 找到 `dist/index.mjs`);
10
+ - `dsh-desktopify bundle` 把本包的 `dist/` 复制成最小壳 app 目录再交给 electron-builder。
11
+
12
+ 边界与拆分理由见[设计 壳独立成包](./.agents/designs/20260924-壳独立成包.md)。
13
+
14
+ ## 出口
15
+
16
+ | 出口 | 用途 |
17
+ | ------------------- | ------------------------------------------------------------------- |
18
+ | `.` | 壳入口(`dist/index.mjs`,Electron 主进程),由 `main` 与它一起指到 |
19
+ | `./appconfig` | `appconfig.json` 读写与 profile patch 文件名 |
20
+ | `./dshhome` | `dshHome` 语义解析(`xdg` / `env` / 路径) |
21
+ | `./official` | 官方包清单与 host 变体包名(壳与工具的同一份事实) |
22
+ | `./profile-project` | profile 工程(`pnpm-workspace.yaml`、overrides、清单) |
23
+ | `./seed` | 种子布局与指纹 |
24
+
25
+ 后五个是工具侧复用同一份实现的入口——种子、官方包清单、home 解析都只有这一份,壳与 CLI 都引它。
26
+
27
+ ## 依赖边界
28
+
29
+ 壳产物整份进 `app.asar`,那里只有壳自己的字节(`@local/*` 与 `@morlay/dsh-desktop-host` 构建期内联),上游包
30
+ 一律留在产物外。因此**壳入口可达的模块只能 import node 内建、`electron` 与那两个内联面**——上游裸引用能过类型
31
+ 检查、能打出产物,但装进 asar 后解析不到,只在真机启动时炸。守卫:
32
+ [`shell-import-boundary.spec.ts`](./src/__tests__/shell-import-boundary.spec.ts)。
33
+
34
+ preload 必须是 CJS(sandboxed preload 的约束),所以它单独一遍构建;壳主进程与它产在同一次 `pnpm build`。
@@ -0,0 +1,43 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ //#region src/appconfig.ts
4
+ const PROFILE_NAME = "desktop";
5
+ /**
6
+ * profile 自己的 patch 文档名(上游 `PROFILE_PATCH_FILENAME` 的同值)。
7
+ * 常量放在这里而不是 import 上游:`seed.ts` 会被打进壳产物(`app.asar`),
8
+ * 那里解析不到 `@deepseek-ai/*`——上游裸引用会让应用启动即 `ERR_MODULE_NOT_FOUND`。
9
+ */
10
+ const PROFILE_PATCH_NAME = "cordis.patch.yml";
11
+ function isRecord(value) {
12
+ return typeof value === "object" && value !== null;
13
+ }
14
+ function windowConfig(value) {
15
+ const record = isRecord(value) ? value : {};
16
+ return {
17
+ width: numberOr(record.width, 1280),
18
+ height: numberOr(record.height, 800),
19
+ minWidth: numberOr(record.minWidth, 800),
20
+ minHeight: numberOr(record.minHeight, 600)
21
+ };
22
+ }
23
+ function numberOr(value, fallback) {
24
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
25
+ }
26
+ async function loadAppConfig(exeDir) {
27
+ const path = join(exeDir, "appconfig.json");
28
+ const value = JSON.parse(await readFile(path, "utf8"));
29
+ if (!isRecord(value) || typeof value.name !== "string" || value.name === "" || typeof value.id !== "string" || value.id === "" || typeof value.version !== "string" || value.version === "" || value.profile !== "desktop" || value.dshHome !== "xdg" && value.dshHome !== "env" && typeof value.dshHome !== "string") throw new Error(`dsh desktop: invalid shell configuration ${path}`);
30
+ return {
31
+ name: value.name,
32
+ id: value.id,
33
+ version: value.version,
34
+ profile: PROFILE_NAME,
35
+ dshHome: value.dshHome,
36
+ window: windowConfig(value.window)
37
+ };
38
+ }
39
+ async function writeAppConfig(exeDir, config) {
40
+ await writeFile(join(exeDir, "appconfig.json"), `${JSON.stringify(config, void 0, 2)}\n`, { mode: 384 });
41
+ }
42
+ //#endregion
43
+ export { writeAppConfig as i, PROFILE_PATCH_NAME as n, loadAppConfig as r, PROFILE_NAME as t };
@@ -0,0 +1,2 @@
1
+ import { i as writeAppConfig, n as PROFILE_PATCH_NAME, r as loadAppConfig, t as PROFILE_NAME } from "./appconfig-B4kozO2F.mjs";
2
+ export { PROFILE_NAME, PROFILE_PATCH_NAME, loadAppConfig, writeAppConfig };
@@ -0,0 +1,26 @@
1
+ import { isAbsolute, join, resolve } from "node:path";
2
+ import { homedir } from "node:os";
3
+ //#region src/dshhome.ts
4
+ function xdgDataHome() {
5
+ if (process.platform === "darwin") return join(homedir(), "Library", "Application Support");
6
+ const configured = process.env.XDG_DATA_HOME;
7
+ if (configured !== void 0 && configured.trim() !== "") return resolve(configured);
8
+ return join(homedir(), ".local", "share");
9
+ }
10
+ /**
11
+ * 解析 `dshHome` 的三态:`xdg`(平台数据目录 + app 名)、`env`(交给环境,这里没有具体路径)、
12
+ * 绝对路径。打包壳与 dev CLI(`--home`)共用这一份,措辞与校验只写在这里。
13
+ */
14
+ function resolveConfiguredHome(name, spec) {
15
+ if (spec === "env") return void 0;
16
+ if (spec === "xdg") return join(xdgDataHome(), name);
17
+ if (!isAbsolute(spec)) throw new Error(`dsh desktop: dshHome must be xdg, env, or an absolute path, got ${JSON.stringify(spec)}`);
18
+ return spec;
19
+ }
20
+ function resolveDshHome(config) {
21
+ const override = process.env.DSH_APP_DSH_HOME;
22
+ if (override !== void 0 && override.trim() !== "") return resolve(override);
23
+ return resolveConfiguredHome(config.name, config.dshHome);
24
+ }
25
+ //#endregion
26
+ export { resolveDshHome as n, xdgDataHome as r, resolveConfiguredHome as t };
@@ -0,0 +1,2 @@
1
+ import { n as resolveDshHome, r as xdgDataHome, t as resolveConfiguredHome } from "./dshhome-C_iyJzc8.mjs";
2
+ export { resolveConfiguredHome, resolveDshHome, xdgDataHome };