@dsh-plugin/dsh-loader 1.0.0 → 1.1.0-dev.32287576957

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.
Files changed (74) hide show
  1. package/LICENSE +160 -0
  2. package/README.md +251 -226
  3. package/{README.zh-CN.md → README.zh_CN.md} +227 -202
  4. package/bin/dshloader.mjs +42 -42
  5. package/cordis.patch.yml +8 -8
  6. package/dist/adapters/dsh-1-x.d.ts +23 -0
  7. package/dist/adapters/dsh-1-x.js +223 -0
  8. package/dist/adapters/dsh-1-x.js.map +1 -0
  9. package/dist/adapters/index.d.ts +22 -0
  10. package/dist/adapters/index.js +57 -0
  11. package/dist/adapters/index.js.map +1 -0
  12. package/dist/api.d.ts +13 -0
  13. package/dist/api.js +46 -0
  14. package/dist/api.js.map +1 -0
  15. package/dist/client.d.ts +157 -0
  16. package/dist/client.js +295 -0
  17. package/dist/client.js.map +1 -0
  18. package/dist/index.d.ts +52 -0
  19. package/dist/index.js +89 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/registry.d.ts +35 -0
  22. package/dist/registry.js +229 -0
  23. package/dist/registry.js.map +1 -0
  24. package/dist/services/services.d.ts +4 -0
  25. package/dist/services/services.js +28 -0
  26. package/dist/services/services.js.map +1 -0
  27. package/dist/services/settings.d.ts +41 -0
  28. package/dist/services/settings.js +161 -0
  29. package/dist/services/settings.js.map +1 -0
  30. package/dist/services/web.d.ts +10 -0
  31. package/dist/services/web.js +63 -0
  32. package/dist/services/web.js.map +1 -0
  33. package/dist/setup.d.ts +32 -0
  34. package/dist/setup.js +119 -0
  35. package/dist/setup.js.map +1 -0
  36. package/dist/types.d.ts +111 -0
  37. package/dist/types.js +12 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/version.d.ts +2 -0
  40. package/{src → dist}/version.js +5 -5
  41. package/dist/version.js.map +1 -0
  42. package/lib/client.js +283 -0
  43. package/lib/client.js.map +1 -0
  44. package/package.json +75 -59
  45. package/src/stable/agent.d.ts +1 -1
  46. package/src/stable/agent.js +2 -2
  47. package/src/stable/llm.d.ts +1 -1
  48. package/src/stable/llm.js +2 -2
  49. package/src/stable/runtime.d.ts +1 -1
  50. package/src/stable/runtime.js +5 -5
  51. package/src/stable/schema-form.d.ts +1 -1
  52. package/src/stable/schema-form.js +2 -2
  53. package/src/stable/settings.d.ts +1 -1
  54. package/src/stable/settings.js +2 -2
  55. package/src/stable/tools.d.ts +1 -1
  56. package/src/stable/tools.js +5 -5
  57. package/src/stable/ui-primitives.d.ts +4 -4
  58. package/src/stable/ui-primitives.js +6 -6
  59. package/src/stable/ui-settings.d.ts +6 -6
  60. package/src/stable/ui-settings.js +4 -4
  61. package/src/stable/ui-slots.d.ts +1 -1
  62. package/src/stable/ui-slots.js +2 -2
  63. package/src/stable/web-react.d.ts +1 -1
  64. package/src/stable/web-react.js +2 -2
  65. package/src/adapters/dsh-1-x.js +0 -236
  66. package/src/adapters/index.js +0 -59
  67. package/src/api.js +0 -56
  68. package/src/client.js +0 -330
  69. package/src/index.js +0 -105
  70. package/src/registry.js +0 -242
  71. package/src/services/services.js +0 -28
  72. package/src/services/settings.js +0 -174
  73. package/src/services/web.js +0 -71
  74. package/src/setup.mjs +0 -125
@@ -1,202 +1,227 @@
1
- # dshloader
2
-
3
- [English](README.md) | [中文](#中文)
4
-
5
- ---
6
-
7
- ## 中文
8
-
9
- **dsh**(DeepSeek Harness)cordis bundle 插件的运行时兼容层。dshloader 通过版本感知的**适配器注册表**,把第三方插件与 dsh 的内部服务名、模块路径、包名、RPC 细节解耦——dsh 升级改了内部 API 时,只需升级 dshloader,插件不用改。
10
-
11
- ### 为什么需要
12
-
13
- dsh 迭代很快,内部 API 在版本间会变:
14
-
15
- - `httpServer` 被重命名为 `webServer`——旧插件注入 `httpServer` 会永远挂起。
16
- - 深层源码导入如
17
- `@deepseek-ai/dsh-client-runtime/src/client/sessions/context-provenance.ts`
18
- dsh 不再发布 `src/` 时直接报错。
19
- - 客户端 UI 包如 `@deepseek-ai/dsh-client-ui-primitives` 在未来 dsh 版本中可能改名,直接 import 的插件全部会坏。
20
- - 官方 `dsh-host-apiproxy` 硬编码了 settings namespace 白名单,第三方设置卡片无法出现在 Web UI 中。
21
-
22
- dshloader 把这些(以及未来的)破坏性变更吸收到**稳定 API** 后面:host 侧的 `ctx.dshLoader`、浏览器侧的 `window.__dshLoader__`、以及包导入的 `@dsh-plugin/dsh-loader/*` 稳定 subpath。
23
-
24
- ### 快速上手
25
-
26
- #### 1. 安装 dshloader profile
27
-
28
- ```sh
29
- dsh plugin --profile <name> add /path/to/dshloader
30
- #
31
- DSH_HOME=~/.dsh npx dshloader setup <name>
32
- ```
33
-
34
- #### 2. 插件 `package.json`——只依赖 dshloader
35
-
36
- ```json
37
- {
38
- "dependencies": {
39
- "@dsh-plugin/dsh-loader": "link:..."
40
- }
41
- }
42
- ```
43
-
44
- > **插件不允许声明任何 `@deepseek-ai/*` 依赖。** 所有 dsh 包都通过 dshloader 的稳定 subpath 访问。
45
-
46
- #### 3. Host 侧——用 `ctx.dshLoader`
47
-
48
- ```js
49
- export const inject = ['dshLoader'];
50
-
51
- export async function apply(ctx) {
52
- // Settings:注册 namespace
53
- const scope = ctx.dshLoader.settings.register('my-plugin', schema);
54
-
55
- // Web:注册路由和 WebSocket upgrade
56
- ctx.dshLoader.web.get('/api/my-plugin/status', (req, res) => res.json({ ok: true }));
57
- ctx.dshLoader.web.registerUpgrade({ path: '/ws/my-plugin', handler: fn });
58
-
59
- // Services:读取 cordis 服务
60
- const sessions = ctx.dshLoader.services.get('sessions');
61
- }
62
- ```
63
-
64
- #### 4. 通过稳定 subpath 导入 dsh 包
65
-
66
- ```js
67
- // Host 包
68
- const { defineTool } = require('@dsh-plugin/dsh-loader/tools');
69
-
70
- // Client UI 包(在 client bundle 源码中)
71
- import { IconCloseFill14 } from '@dsh-plugin/dsh-loader/ui-primitives';
72
- ```
73
-
74
- **稳定 subpath dsh 真实包名映射(dsh 1.x):**
75
-
76
- | 稳定 subpath | dsh 真实包名 |
77
- |---|---|
78
- | `@dsh-plugin/dsh-loader/tools` | `@deepseek-ai/dsh-tools` |
79
- | `@dsh-plugin/dsh-loader/llm` | `@deepseek-ai/dsh-llm` |
80
- | `@dsh-plugin/dsh-loader/agent` | `@deepseek-ai/dsh-agent` |
81
- | `@dsh-plugin/dsh-loader/settings` | `@deepseek-ai/dsh-settings` |
82
- | `@dsh-plugin/dsh-loader/ui-primitives` | `@deepseek-ai/dsh-client-ui-primitives` |
83
- | `@dsh-plugin/dsh-loader/ui-slots` | `@deepseek-ai/dsh-client-ui-slots` |
84
- | `@dsh-plugin/dsh-loader/ui-settings` | `@deepseek-ai/dsh-client-ui-settings/client` |
85
- | `@dsh-plugin/dsh-loader/web-react` | `@deepseek-ai/dsh-client-web-react` |
86
- | `@dsh-plugin/dsh-loader/schema-form` | `@deepseek-ai/dsh-client-schema-form` |
87
- | `@dsh-plugin/dsh-loader/runtime` | `@deepseek-ai/dsh-client-runtime/client` |
88
-
89
- dsh 改包名时,只需改 dshloader 适配器——插件源码和 bundle 不用动。
90
-
91
- #### 5. Client 侧——用 `window.__dshLoader__`
92
-
93
- ```js
94
- // 读取 cordis client 服务
95
- const conv = window.__dshLoader__.services.get('conversation');
96
-
97
- // 运行时注册包名别名(兜底用)
98
- window.__dshLoader__.registerPackageAlias('@old/pkg', '@new/pkg');
99
- ```
100
-
101
- #### 6. 构建配置——把稳定 subpath 加入 external
102
-
103
- ```ts
104
- const CLIENT_EXTERNALS = [
105
- 'react', 'react/jsx-runtime', 'react-dom', 'react-dom/client', 'cordis',
106
- '@dsh-plugin/dsh-loader/ui-primitives',
107
- '@dsh-plugin/dsh-loader/ui-slots',
108
- '@dsh-plugin/dsh-loader/ui-settings',
109
- '@dsh-plugin/dsh-loader/web-react',
110
- '@dsh-plugin/dsh-loader/schema-form',
111
- '@dsh-plugin/dsh-loader/runtime',
112
- ]
113
- ```
114
-
115
- ### 工作原理
116
-
117
- ```
118
- plugin ──▶ ctx.dshLoader.{settings,web,services} ──▶ dshloader 适配器
119
-
120
-
121
- 真实 dsh(当前版本)
122
-
123
- plugin bundle ──▶ require('@dsh-plugin/dsh-loader/ui-primitives')
124
-
125
- ▼(__ModuleLoader__ wrapper 映射稳定名)
126
- require('@deepseek-ai/dsh-client-ui-primitives')
127
-
128
-
129
- dsh 模块表
130
- ```
131
-
132
- 1. **版本探测** 读取 `node_modules/@deepseek-ai/dsh/package.json`(或 `DSHLOADER_DSH_VERSION`)。
133
- 2. **适配器注册表** 选择最适合当前版本的适配器(精确 → 范围 → 最近低版本回退 → 报错)。
134
- 3. 选中的**适配器** 注册服务别名、安装包名映射钩子(host: `Module._resolveFilename`;client: `__ModuleLoader__.load` wrapper)、以及(仅在开启时)settings 白名单绕过桥接。所有注册通过 `ctx.reflect.provide` / `ctx.effect`,cordis 在 fiber 卸载时自动回收。
135
-
136
- > **加载顺序无关。** cordis 是响应式依赖注入:声明了 `inject: [...]` 的插件会停在 `PENDING` 状态,直到依赖的服务出现,与 dshloader 在 `cordis.patch.yml` 中的位置无关。
137
-
138
- ### Settings 白名单绕过(`exposeAllNamespaces`)
139
-
140
- 默认**不绕过**官方 settings namespace 白名单。需要时显式开启:
141
-
142
- - 环境变量:`DSHLOADER_EXPOSE_ALL_SETTINGS=1`
143
- - profile `package.json`:`dsh.dshloader.exposeAllNamespaces: true`
144
-
145
- > **安全权衡**:开启后会移除官方对浏览器 settings 访问的默认拒绝边界。仅在信任所有已安装插件的 profile 中开启。
146
-
147
- ### CLI
148
-
149
- ```
150
- dshloader setup <profile> 注入 dshloader profile(依赖 + patch)。
151
- dshloader dump-config <profile> 运行 `dsh --profile <name> --dump-config`。
152
- dshloader info [profile] 打印 loader 版本、探测到的 dsh 版本、选中的适配器。
153
- ```
154
-
155
- ### 回滚 / 禁用
156
-
157
- - 单次启动禁用:`DSHLOADER_DISABLE=1 dsh web`
158
- - 移除:`dsh plugin --profile <name> rm @dsh-plugin/dsh-loader`
159
-
160
- ### 项目结构
161
-
162
- ```
163
- src/
164
- index.js host bundle 入口(name / inject / apply)
165
- client.js client bundle 入口(immediately tier)
166
- api.js DshLoaderHostAPI 构造
167
- registry.js 适配器注册表 + 版本探测
168
- version.js loader 版本 + 日志前缀
169
- stable/ 稳定 subpath re-export(ui-primitives、tools 等)
170
- services/
171
- settings.js settings 稳定 API
172
- web.js web 稳定 API
173
- services.js services 稳定 API(get / alias)
174
- adapters/
175
- dsh-1-x.js dsh 1.x 适配器
176
- index.js 适配器注册
177
- setup.mjs profile 注入 + dump-config + info
178
- bin/dshloader.mjs CLI 入口
179
- docs/
180
- api.md 完整 API 参考
181
- design.md 设计文档
182
- tests/ L1(单元)/ module(L2)/ integration(L3
183
- examples/
184
- sample-plugin/ 最小示例插件
185
- dsh-aux-state/ 仅用 ctx.dshLoader 的示例
186
- ```
187
-
188
- ### 开发
189
-
190
- ```sh
191
- pnpm install
192
- npm test # 全部测试
193
- npm run test:l1 # 单元测试
194
- npm run test:l2 # 模块测试
195
- npm run test:l3 # 集成测试
196
- ```
197
-
198
- Node.js >= 18,`node --test`,无额外测试框架。
199
-
200
- ### 许可证
201
-
202
- BSD-3-Clause
1
+ <div align="center">
2
+
3
+ ![Banner](./docs/banner.png)
4
+
5
+ # dshloader
6
+
7
+ **面向 dsh(DeepSeek Harness)的版本感知运行时兼容层:通过适配器注册表,让第三方插件在 dsh 升级改版后无需改动即可继续工作。**
8
+
9
+ [English](README.md) | [简体中文](#中文)
10
+
11
+ [![DSH Plugin](https://img.shields.io/badge/DeepSeek%20Harness-plugin-4f7cff)](https://github.com/topics/dsh-plugin)
12
+ <a href="https://github.com/dsh-plugins/dsh-loader/actions/workflows/npm-publish.yml">
13
+ <img src="https://github.com/dsh-plugins/dsh-loader/actions/workflows/npm-publish.yml/badge.svg" alt="Build Status">
14
+ </a>
15
+ <a href="https://www.npmjs.com/package/@dsh-plugin/dsh-loader">
16
+ <img src="https://img.shields.io/npm/v/@dsh-plugin/dsh-loader.svg?sanitize=true" alt="Version">
17
+ </a>
18
+ <a href="https://www.npmjs.com/package/@dsh-plugin/dsh-loader">
19
+ <img src="https://img.shields.io/npm/l/@dsh-plugin/dsh-loader.svg?sanitize=true" alt="License">
20
+ </a>
21
+
22
+ </div>
23
+
24
+ ## 中文
25
+
26
+ **dsh**(DeepSeek Harness)cordis bundle 插件的运行时兼容层。dshloader 通过版本感知的**适配器注册表**,把第三方插件与 dsh 的内部服务名、模块路径、包名、RPC 细节解耦——dsh 升级改了内部 API 时,只需升级 dshloader,插件不用改。
27
+
28
+ ### 为什么需要
29
+
30
+ dsh 迭代很快,内部 API 在版本间会变:
31
+
32
+ - `httpServer` 被重命名为 `webServer`——旧插件注入 `httpServer` 会永远挂起。
33
+ - 深层源码导入如
34
+ `@deepseek-ai/dsh-client-runtime/src/client/sessions/context-provenance.ts`
35
+ 在 dsh 不再发布 `src/` 时直接报错。
36
+ - 客户端 UI 包如 `@deepseek-ai/dsh-client-ui-primitives` 在未来 dsh 版本中可能改名,直接 import 的插件全部会坏。
37
+ - 官方 `dsh-host-apiproxy` 硬编码了 settings namespace 白名单,第三方设置卡片无法出现在 Web UI 中。
38
+
39
+ dshloader 把这些(以及未来的)破坏性变更吸收到**稳定 API** 后面:host 侧的 `ctx.dshLoader`、浏览器侧的 `window.__dshLoader__`、以及包导入的 `@dsh-plugin/dsh-loader/*` 稳定 subpath。
40
+
41
+ ### 快速上手
42
+
43
+ #### 1. 安装 dshloader 到 profile
44
+
45
+ ```sh
46
+ dsh plugin --profile <name> add /path/to/dshloader
47
+ # 或
48
+ DSH_HOME=~/.dsh npx dshloader setup <name>
49
+ ```
50
+
51
+ #### 2. 插件 `package.json`——只依赖 dshloader
52
+
53
+ ```json
54
+ {
55
+ "dependencies": {
56
+ "@dsh-plugin/dsh-loader": "link:..."
57
+ }
58
+ }
59
+ ```
60
+
61
+ > **插件不允许声明任何 `@deepseek-ai/*` 依赖。** 所有 dsh 包都通过 dshloader 的稳定 subpath 访问。
62
+
63
+ #### 3. Host 侧——用 `ctx.dshLoader`
64
+
65
+ ```js
66
+ export const inject = ['dshLoader'];
67
+
68
+ export async function apply(ctx) {
69
+ // Settings:注册 namespace
70
+ const scope = ctx.dshLoader.settings.register('my-plugin', schema);
71
+
72
+ // Web:注册路由和 WebSocket upgrade
73
+ ctx.dshLoader.web.get('/api/my-plugin/status', (req, res) => res.json({ ok: true }));
74
+ ctx.dshLoader.web.registerUpgrade({ path: '/ws/my-plugin', handler: fn });
75
+
76
+ // Services:读取 cordis 服务
77
+ const sessions = ctx.dshLoader.services.get('sessions');
78
+ }
79
+ ```
80
+
81
+ #### 4. 通过稳定 subpath 导入 dsh
82
+
83
+ ```js
84
+ // Host
85
+ const { defineTool } = require('@dsh-plugin/dsh-loader/tools');
86
+
87
+ // Client UI 包(在 client bundle 源码中)
88
+ import { IconCloseFill14 } from '@dsh-plugin/dsh-loader/ui-primitives';
89
+ ```
90
+
91
+ **稳定 subpath dsh 真实包名映射(dsh 1.x):**
92
+
93
+ | 稳定 subpath | dsh 真实包名 |
94
+ |---|---|
95
+ | `@dsh-plugin/dsh-loader/tools` | `@deepseek-ai/dsh-tools` |
96
+ | `@dsh-plugin/dsh-loader/llm` | `@deepseek-ai/dsh-llm` |
97
+ | `@dsh-plugin/dsh-loader/agent` | `@deepseek-ai/dsh-agent` |
98
+ | `@dsh-plugin/dsh-loader/settings` | `@deepseek-ai/dsh-settings` |
99
+ | `@dsh-plugin/dsh-loader/ui-primitives` | `@deepseek-ai/dsh-client-ui-primitives` |
100
+ | `@dsh-plugin/dsh-loader/ui-slots` | `@deepseek-ai/dsh-client-ui-slots` |
101
+ | `@dsh-plugin/dsh-loader/ui-settings` | `@deepseek-ai/dsh-client-ui-settings/client` |
102
+ | `@dsh-plugin/dsh-loader/web-react` | `@deepseek-ai/dsh-client-web-react` |
103
+ | `@dsh-plugin/dsh-loader/schema-form` | `@deepseek-ai/dsh-client-schema-form` |
104
+ | `@dsh-plugin/dsh-loader/runtime` | `@deepseek-ai/dsh-client-runtime/client` |
105
+
106
+ dsh 改包名时,只需改 dshloader 适配器——插件源码和 bundle 不用动。
107
+
108
+ #### 5. Client 侧——用 `window.__dshLoader__`
109
+
110
+ ```js
111
+ // 读取 cordis client 服务
112
+ const conv = window.__dshLoader__.services.get('conversation');
113
+
114
+ // 运行时注册包名别名(兜底用)
115
+ window.__dshLoader__.registerPackageAlias('@old/pkg', '@new/pkg');
116
+ ```
117
+
118
+ #### 6. 构建配置——把稳定 subpath 加入 external
119
+
120
+ ```ts
121
+ const CLIENT_EXTERNALS = [
122
+ 'react', 'react/jsx-runtime', 'react-dom', 'react-dom/client', 'cordis',
123
+ '@dsh-plugin/dsh-loader/ui-primitives',
124
+ '@dsh-plugin/dsh-loader/ui-slots',
125
+ '@dsh-plugin/dsh-loader/ui-settings',
126
+ '@dsh-plugin/dsh-loader/web-react',
127
+ '@dsh-plugin/dsh-loader/schema-form',
128
+ '@dsh-plugin/dsh-loader/runtime',
129
+ ]
130
+ ```
131
+
132
+ ### 工作原理
133
+
134
+ ```
135
+ plugin ──▶ ctx.dshLoader.{settings,web,services} ──▶ dshloader 适配器
136
+
137
+
138
+ 真实 dsh(当前版本)
139
+
140
+ plugin bundle ──▶ require('@dsh-plugin/dsh-loader/ui-primitives')
141
+
142
+ ▼(__ModuleLoader__ wrapper 映射稳定名)
143
+ require('@deepseek-ai/dsh-client-ui-primitives')
144
+
145
+
146
+ dsh 模块表
147
+ ```
148
+
149
+ 1. **版本探测** 读取 `node_modules/@deepseek-ai/dsh/package.json`(或 `DSHLOADER_DSH_VERSION`)。
150
+ 2. **适配器注册表** 选择最适合当前版本的适配器(精确 范围 最近低版本回退 → 报错)。
151
+ 3. 选中的**适配器** 注册服务别名、安装包名映射钩子(host: `Module._resolveFilename`;client: `__ModuleLoader__.load` wrapper)、以及(仅在开启时)settings 白名单绕过桥接。所有注册通过 `ctx.reflect.provide` / `ctx.effect`,cordis 在 fiber 卸载时自动回收。
152
+
153
+ > **加载顺序无关。** cordis 是响应式依赖注入:声明了 `inject: [...]` 的插件会停在 `PENDING` 状态,直到依赖的服务出现,与 dshloader 在 `cordis.patch.yml` 中的位置无关。
154
+
155
+ ### Settings 白名单绕过(`exposeAllNamespaces`)
156
+
157
+ 默认**不绕过**官方 settings namespace 白名单。需要时显式开启:
158
+
159
+ - 环境变量:`DSHLOADER_EXPOSE_ALL_SETTINGS=1`
160
+ - profile `package.json`:`dsh.dshloader.exposeAllNamespaces: true`
161
+
162
+ > **安全权衡**:开启后会移除官方对浏览器 settings 访问的默认拒绝边界。仅在信任所有已安装插件的 profile 中开启。
163
+
164
+ ### CLI
165
+
166
+ ```
167
+ dshloader setup <profile> 注入 dshloader 到 profile(依赖 + patch)。
168
+ dshloader dump-config <profile> 运行 `dsh --profile <name> --dump-config`。
169
+ dshloader info [profile] 打印 loader 版本、探测到的 dsh 版本、选中的适配器。
170
+ ```
171
+
172
+ ### 回滚 / 禁用
173
+
174
+ - 单次启动禁用:`DSHLOADER_DISABLE=1 dsh web`
175
+ - 移除:`dsh plugin --profile <name> rm @dsh-plugin/dsh-loader`
176
+
177
+ ### 项目结构
178
+
179
+ ```
180
+ src/
181
+ index.ts host bundle 入口(name / inject / apply)
182
+ client.ts client bundle 入口(immediately tier
183
+ api.ts DshLoaderHostAPI 构造
184
+ registry.ts 适配器注册表 + 版本探测
185
+ types.ts 共享 host/client TypeScript 类型
186
+ version.ts loader 版本 + 日志前缀
187
+ stable/ 稳定 subpath re-export(ui-primitives、tools 等)
188
+ services/
189
+ settings.ts settings 稳定 API
190
+ web.ts web 稳定 API
191
+ services.ts services 稳定 API(get / alias)
192
+ adapters/
193
+ dsh-1-x.ts dsh 1.x 适配器
194
+ index.ts 适配器注册
195
+ setup.ts profile 注入 + dump-config + info
196
+ bin/dshloader.mjs CLI 入口
197
+ dist/ 编译后的 host 产物(tsc 输出,已 git-ignore)
198
+ lib/ 编译后的 client bundle(tsdown 输出,已 git-ignore)
199
+ tsconfig.json typecheck 配置
200
+ tsconfig.build.json host 构建配置(产出 dist/)
201
+ tsdown.client.config.mjs client bundle 构建配置
202
+ docs/
203
+ api.md 完整 API 参考
204
+ design.md 设计文档
205
+ tests/ L1(单元)/ module(L2)/ integration(L3)
206
+ examples/
207
+ sample-plugin/ 最小示例插件
208
+ dsh-aux-state/ 仅用 ctx.dshLoader 的示例
209
+ ```
210
+
211
+ ### 开发
212
+
213
+ ```sh
214
+ pnpm install
215
+ npm run typecheck # 类型检查 src/**/*.ts
216
+ npm run build # 编译 host(dist/)+ client bundle(lib/)
217
+ npm test # 全部测试
218
+ npm run test:l1 # 单元测试
219
+ npm run test:l2 # 模块测试
220
+ npm run test:l3 # 集成测试
221
+ ```
222
+
223
+ Node.js >= 18,`node --test`,无额外测试框架。
224
+
225
+ ### 许可证
226
+
227
+ LGPL-3.0-only(GNU 宽通用公共许可证第 3 版)。参见 [LICENSE](./LICENSE)。
package/bin/dshloader.mjs CHANGED
@@ -1,42 +1,42 @@
1
- #!/usr/bin/env node
2
- // dshloader CLI entry (M6). Subcommands: setup, dump-config, info.
3
- import { setupProfile, dumpConfig, info } from '../src/setup.mjs';
4
-
5
- const [cmd, ...rest] = process.argv.slice(2);
6
-
7
- function usage() {
8
- console.log(`dshloader <command> [args]
9
-
10
- Commands:
11
- setup <profile> Inject dshloader into a profile (dependency + patch).
12
- dump-config <profile> Run \`dsh --profile <name> --dump-config\` to validate.
13
- info [profile] Print dshloader version, detected dsh version, adapter.`);
14
- }
15
-
16
- try {
17
- switch (cmd) {
18
- case 'setup': {
19
- const profile = rest[0];
20
- if (!profile) throw new Error('setup requires a profile name');
21
- setupProfile(profile);
22
- break;
23
- }
24
- case 'dump-config': {
25
- const profile = rest[0];
26
- if (!profile) throw new Error('dump-config requires a profile name');
27
- const { ok, output } = dumpConfig(profile);
28
- process.stdout.write(output);
29
- process.exit(ok ? 0 : 1);
30
- }
31
- case 'info': {
32
- info(rest[0]);
33
- break;
34
- }
35
- default:
36
- usage();
37
- process.exit(cmd ? 1 : 0);
38
- }
39
- } catch (error) {
40
- console.error(error.message);
41
- process.exit(1);
42
- }
1
+ #!/usr/bin/env node
2
+ // dshloader CLI entry (M6). Subcommands: setup, dump-config, info.
3
+ import { setupProfile, dumpConfig, info } from '../dist/setup.js';
4
+
5
+ const [cmd, ...rest] = process.argv.slice(2);
6
+
7
+ function usage() {
8
+ console.log(`dshloader <command> [args]
9
+
10
+ Commands:
11
+ setup <profile> Inject dshloader into a profile (dependency + patch).
12
+ dump-config <profile> Run \`dsh --profile <name> --dump-config\` to validate.
13
+ info [profile] Print dshloader version, detected dsh version, adapter.`);
14
+ }
15
+
16
+ try {
17
+ switch (cmd) {
18
+ case 'setup': {
19
+ const profile = rest[0];
20
+ if (!profile) throw new Error('setup requires a profile name');
21
+ setupProfile(profile);
22
+ break;
23
+ }
24
+ case 'dump-config': {
25
+ const profile = rest[0];
26
+ if (!profile) throw new Error('dump-config requires a profile name');
27
+ const { ok, output } = dumpConfig(profile);
28
+ process.stdout.write(output);
29
+ process.exit(ok ? 0 : 1);
30
+ }
31
+ case 'info': {
32
+ info(rest[0]);
33
+ break;
34
+ }
35
+ default:
36
+ usage();
37
+ process.exit(cmd ? 1 : 0);
38
+ }
39
+ } catch (error) {
40
+ console.error(error.message);
41
+ process.exit(1);
42
+ }
package/cordis.patch.yml CHANGED
@@ -1,8 +1,8 @@
1
- # dsh bundle patch: mounts dshloader into a profile's cordis layer stack.
2
- # Position in the `insert` list does NOT affect whether service aliases /
3
- # module redirects take effect — cordis is reactive dependency injection,
4
- # so downstream plugins declaring `inject: [...]` stay PENDING until the
5
- # alias is provided, regardless of file order. See docs/design.md §1.2/§6.2.
6
- - insert:
7
- - id: dsh-loader
8
- name: '@dsh-plugin/dsh-loader'
1
+ # dsh bundle patch: mounts dshloader into a profile's cordis layer stack.
2
+ # Position in the `insert` list does NOT affect whether service aliases /
3
+ # module redirects take effect — cordis is reactive dependency injection,
4
+ # so downstream plugins declaring `inject: [...]` stay PENDING until the
5
+ # alias is provided, regardless of file order. See docs/design.md §1.2/§6.2.
6
+ - insert:
7
+ - id: dsh-loader
8
+ name: '@dsh-plugin/dsh-loader'
@@ -0,0 +1,23 @@
1
+ import type { CordisContext, HostAdapterConfig } from '../types.js';
2
+ export declare const supports = ">=0.1.0-rc.1 <2.0.0";
3
+ export declare const name = "dsh-1-x";
4
+ export declare const BRIDGE_PREFIX = "/api/dshloader";
5
+ export declare const hostPackageAliases: Record<string, string>;
6
+ /**
7
+ * Install a Module._resolveFilename hook that maps old package names to
8
+ * new ones for CJS require() calls. Returns a dispose function that
9
+ * removes the hook.
10
+ */
11
+ export declare function installHostPackageAliases(aliases: Record<string, string>): Promise<() => void>;
12
+ /**
13
+ * @param ctx cordis context
14
+ * @param config
15
+ */
16
+ export declare function create(ctx: CordisContext, config?: HostAdapterConfig): HostAdapterType;
17
+ interface HostAdapterType {
18
+ supports: string;
19
+ name: string;
20
+ apply: () => Promise<void>;
21
+ dispose: () => void;
22
+ }
23
+ export {};