dsh-code-server-app 0.1.42 → 0.2.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/lib/vendor.js CHANGED
@@ -1,15 +1,17 @@
1
- // lib/vendor.js — 内置 code-server 产物的路径工具(host 与脚本共用)。
1
+ // lib/vendor.js — 内置 VS Code 产物的路径工具(host 与脚本共用)。
2
2
  //
3
- // 模型(0.1.37 起):
4
- // - code-server 本体 + 它自己的运行时依赖(约 232MB 解包)打成**平台专属子包**发布:
5
- // @<scope>/dshcs-code-server-<platform>-<arch>@<code-server 版本>
6
- // (os/cpu 限定,挂在插件 optionalDependencies 上 → pnpm 按架构自动选中);
7
- // 子包内布局:<pkg>/code-server/{out,lib/vscode,node_modules,…};
3
+ // 模型(重构后,0.2.0 起):
4
+ // - VS Code + 少量浏览器静态资源打成**平台无关子包**发布:
5
+ // @<scope>/dshcs-vscode-server@<code-server 版本>
6
+ // 子包内布局:<pkg>/vscode/{lib/vscode,out/browser,src/browser,…};
7
+ // 旧的全量树 @<scope>/dshcs-code-server@<版本> 仍然可作回退(0.1.43 及更早)。
8
+ // - code-server 的 Node 服务层(out/node/** + 136 个依赖)不再随包发布:
9
+ // 由插件自带的 lib/launcher.mjs 取代(见 docs/analysis-code-server-as-dsh-plugin.md)。
8
10
  // - VS Code 内部依赖(约 1GB)与需编译的原生模块仍由包管理器安装:
9
- // 纯 JS 部分写在插件 package.json 的 dependencies;
10
- // pnpm 拒绝安装的原生包由 scripts/vendor-repacks.mjs 重打包成 @<scope>/dshcs-*,
11
- // 再由平台聚合包 @<scope>/dsh-code-server-runtime-<platform>-<arch> 用 npm: 别名装回原名字;
12
- // - 插件包内 `vendor/code-server/` 只作为**开发期/兼容**回退(0.1.37 起不再随包发布)。
11
+ // 纯 JS 部分写在插件 package.json 的 dependencies;
12
+ // pnpm 拒绝安装的原生包由 scripts/vendor-repacks.mjs 重打包成 @<scope>/dshcs-*,
13
+ // 再由平台聚合包 @<scope>/dsh-code-server-runtime-<platform>-<arch> 用 npm: 别名装回原名字;
14
+ // - 插件包内 `vendor/vscode/` 只作为**开发期/兼容**回退(发布包不含 vendor)。
13
15
  import { createRequire } from 'node:module';
14
16
  import { existsSync, readFileSync } from 'node:fs';
15
17
  import { dirname, join, resolve } from 'node:path';
@@ -18,8 +20,10 @@ import { fileURLToPath } from 'node:url';
18
20
  const here = dirname(fileURLToPath(import.meta.url)); // <pkg>/lib
19
21
  const require_ = createRequire(import.meta.url);
20
22
  export const PACKAGE_ROOT = resolve(here, '..');
21
- /** 包内 code-server 树(0.1.36 及更早随包发布;现在仅开发期/兼容回退)。 */
22
- export const VENDOR_TREE = join(PACKAGE_ROOT, 'vendor', 'code-server');
23
+ /** 包内 VS Code 树(新模型;发布包不含,仅开发期/兼容回退)。 */
24
+ export const VENDOR_TREE = join(PACKAGE_ROOT, 'vendor', 'vscode');
25
+ /** 包内旧全量 code-server 树(0.1.43 及更早;仅兼容回退)。 */
26
+ export const LEGACY_VENDOR_TREE = join(PACKAGE_ROOT, 'vendor', 'code-server');
23
27
  const VENDOR_META = join(PACKAGE_ROOT, 'vendor', 'VENDOR.json');
24
28
  /** 旧版安装根目录名(0.1.35 及更早);仅用于迁移提示。 */
25
29
  export const APP_DIR_NAME = '.code-server-app';
@@ -37,14 +41,31 @@ export function legacyInstallRoot() {
37
41
  return profileRoot !== null ? join(profileRoot, APP_DIR_NAME) : null;
38
42
  }
39
43
 
40
- /** code-server 本体包名(0.1.38+ 平台无关):取插件 dependencies 里的 @<scope>/dshcs-code-server。 */
41
- export function codeServerPackageName() {
44
+ function declaredDependencyNames() {
42
45
  try {
43
46
  const manifest = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
44
- const declared = { ...(manifest.dependencies ?? {}), ...(manifest.optionalDependencies ?? {}) };
45
- const hit = Object.keys(declared).find((name) => /^@[^/]+\/dshcs-code-server$/.test(name));
46
- if (hit !== undefined) return hit;
47
- } catch { /* 回退默认 scope */ }
47
+ return {
48
+ ...(manifest.dependencies ?? {}),
49
+ ...(manifest.optionalDependencies ?? {}),
50
+ };
51
+ } catch {
52
+ return {};
53
+ }
54
+ }
55
+
56
+ /** VS Code 树包名(0.2.0+ 平台无关):取插件 dependencies 里的 @<scope>/dshcs-vscode-server。 */
57
+ export function vscodeServerPackageName() {
58
+ const declared = declaredDependencyNames();
59
+ const hit = Object.keys(declared).find((name) => /^@[^/]+\/dshcs-vscode-server$/.test(name));
60
+ if (hit !== undefined) return hit;
61
+ return '@jinsiyu/dshcs-vscode-server';
62
+ }
63
+
64
+ /** 旧 code-server 全量树包名(0.1.43 及更早):@<scope>/dshcs-code-server。 */
65
+ export function codeServerPackageName() {
66
+ const declared = declaredDependencyNames();
67
+ const hit = Object.keys(declared).find((name) => /^@[^/]+\/dshcs-code-server$/.test(name));
68
+ if (hit !== undefined) return hit;
48
69
  return '@jinsiyu/dshcs-code-server';
49
70
  }
50
71
 
@@ -53,34 +74,73 @@ export function legacyCodeServerPackageName(platform = process.platform, arch =
53
74
  return `@jinsiyu/dshcs-code-server-${platform}-${arch}`;
54
75
  }
55
76
 
56
- /** 解析某个包目录下的 code-server 运行根(包内布局:<pkg>/code-server/**)。 */
77
+ /** 解析某个包目录下的 VS Code 树根。
78
+ * 新布局:<pkg>/vscode/lib/vscode/out/server-main.js;旧布局:<pkg>/code-server/out/node/entry.js。 */
57
79
  function rootOfPackage(name) {
58
80
  try {
59
81
  const manifest = require_.resolve(`${name}/package.json`);
60
- const root = join(dirname(manifest), 'code-server');
61
- if (existsSync(join(root, 'out', 'node', 'entry.js'))) return root;
82
+ const base = dirname(manifest);
83
+ const slim = join(base, 'vscode');
84
+ if (existsSync(join(slim, 'lib', 'vscode', 'out', 'server-main.js'))) return slim;
85
+ const legacy = join(base, 'code-server');
86
+ if (existsSync(join(legacy, 'out', 'node', 'entry.js'))) return legacy;
62
87
  } catch { /* 未安装 */ }
63
88
  return null;
64
89
  }
65
90
 
66
- /** code-server 运行根:① 本体包(0.1.38+ 平台无关)> ② 旧平台子包(0.1.37)> 包内 vendor(开发期)。
67
- * @returns {string|null} 绝对路径,如 <profile>\node_modules\@jinsiyu\dshcs-code-server\code-server */
68
- export function codeServerRoot() {
69
- const root = rootOfPackage(codeServerPackageName()) ?? rootOfPackage(legacyCodeServerPackageName());
91
+ /** 是否是一棵「精简 VS Code 树」( lib/vscode/out/server-main.js,不含 code-server 服务层)。 */
92
+ export function isVscodeOnlyTree(root) {
93
+ return root !== null && existsSync(join(root, 'lib', 'vscode', 'out', 'server-main.js'));
94
+ }
95
+
96
+ /** VS Code 树根(新包 > 旧包 > 旧平台子包 > 包内 vendor/vscode > 包内 vendor/code-server)。
97
+ * @returns {string|null} 绝对路径,如 <profile>\node_modules\@jinsiyu\dshcs-vscode-server\vscode */
98
+ export function vsRoot() {
99
+ const root = rootOfPackage(vscodeServerPackageName())
100
+ ?? rootOfPackage(codeServerPackageName())
101
+ ?? rootOfPackage(legacyCodeServerPackageName());
70
102
  if (root !== null) return root;
71
- if (existsSync(join(VENDOR_TREE, 'out', 'node', 'entry.js'))) return VENDOR_TREE;
103
+ if (existsSync(join(VENDOR_TREE, 'lib', 'vscode', 'out', 'server-main.js'))) return VENDOR_TREE;
104
+ if (existsSync(join(LEGACY_VENDOR_TREE, 'out', 'node', 'entry.js'))) return LEGACY_VENDOR_TREE;
72
105
  return null;
73
106
  }
74
107
 
75
- /** code-server 入口脚本(out/node/entry.js);不可用时返回 null。 */
108
+ /** VS Code server 入口(<树根>/lib/vscode/out/server-main.js);不可用时返回 null。 */
109
+ export function vsServerEntry() {
110
+ const root = vsRoot();
111
+ if (root === null) return null;
112
+ const entry = join(root, 'lib', 'vscode', 'out', 'server-main.js');
113
+ return existsSync(entry) ? entry : null;
114
+ }
115
+
116
+ /** VS Code 树根(兼容别名:0.1.43 及更早的调用点用这个名字)。 */
117
+ export function codeServerRoot() {
118
+ return vsRoot();
119
+ }
120
+
121
+ /** code-server 入口脚本(旧全量树的 out/node/entry.js);精简树下返回 null。 */
76
122
  export function codeServerEntry() {
77
- const root = codeServerRoot();
78
- return root !== null ? join(root, 'out', 'node', 'entry.js') : null;
123
+ const root = vsRoot();
124
+ if (root === null) return null;
125
+ const entry = join(root, 'out', 'node', 'entry.js');
126
+ return existsSync(entry) ? entry : null;
79
127
  }
80
128
 
81
129
  /** code-server 运行根(旧名,脚本/调用方沿用)。 */
82
130
  export function codeServerTarget() {
83
- return codeServerRoot();
131
+ return vsRoot();
132
+ }
133
+
134
+ /** VS Code 客户端约定的产品路径(quality-commit);从 product.json 现算,禁止硬编码。 */
135
+ export function productPath(root = vsRoot()) {
136
+ if (root !== null) {
137
+ try {
138
+ const product = JSON.parse(readFileSync(join(root, 'lib', 'vscode', 'product.json'), 'utf8'));
139
+ return `${product.quality ?? 'oss'}-${product.commit ?? 'dev'}`;
140
+ } catch { /* 回退 VENDOR.json */ }
141
+ }
142
+ const meta = readVendorMeta();
143
+ return typeof meta?.productPath === 'string' && meta.productPath !== '' ? meta.productPath : null;
84
144
  }
85
145
 
86
146
  export function readTreeVersion(dir) {
@@ -108,10 +168,11 @@ export function vendoredVersion() {
108
168
  if (meta !== null && typeof meta.codeServerVersion === 'string' && meta.codeServerVersion !== '') {
109
169
  return meta.codeServerVersion;
110
170
  }
111
- return readTreeVersion(VENDOR_TREE);
171
+ return readTreeVersion(VENDOR_TREE) ?? readTreeVersion(LEGACY_VENDOR_TREE);
112
172
  }
113
173
 
114
- /** code-server 是否可用(平台子包已安装或包内 vendor 在位)。 */
174
+ /** VS Code 树是否可用(包已安装或包内 vendor 在位)。 */
115
175
  export function vendorReady() {
116
- return codeServerRoot() !== null;
176
+ return vsRoot() !== null;
117
177
  }
178
+
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-code-server-app",
3
- "version": "0.1.42",
4
- "description": "Integrate code-server (VS Code in the browser) into DSH Web and Desktop: right-sidebar tab (DSH >= 0.1.5-alpha.1) with a floating-ball fallback for older hosts, over the Connection /api channel (ctx.connection.fetch; no webServer dependency) with host-side process lifecycle.",
3
+ "version": "0.2.0",
4
+ "description": "VS Code (from a code-server release) inside DSH Web and Desktop: right-sidebar tab with a floating-ball fallback, driven by the plugin's own launcher over the in-process VS Code server (lib/launcher.mjs). Two serving modes: loopback port (default) or same-origin mount on DSH's own webServer (/code-server, protected by ctx.connection.requestRejection). No code-server Node layer, no argon2, no C++ toolchain.",
5
5
  "homepage": "https://github.com/jinsiyu/dsh-code-server-app",
6
6
  "repository": {
7
7
  "type": "git",
@@ -40,11 +40,14 @@
40
40
  "files": [
41
41
  "lib/index.js",
42
42
  "lib/client.js",
43
+ "lib/launcher.mjs",
44
+ "lib/serve-dsh.mjs",
43
45
  "lib/vendor.js",
44
46
  "lib/native.js",
45
47
  "assets/favicon.ico",
46
48
  "assets/favicon.svg",
47
49
  "assets/extensions/dshcs-open-file",
50
+ "scripts/vendor-vscode-server.mjs",
48
51
  "scripts/vendor-code-server.mjs",
49
52
  "scripts/vendor-repacks.mjs",
50
53
  "vendor/VENDOR.json",
@@ -59,7 +62,7 @@
59
62
  },
60
63
  "license": "MIT",
61
64
  "dependencies": {
62
- "@jinsiyu/dshcs-code-server": "4.136.2",
65
+ "@jinsiyu/dshcs-vscode-server": "4.136.2",
63
66
  "@microsoft/1ds-core-js": "3.2.13",
64
67
  "@microsoft/1ds-post-js": "3.2.13",
65
68
  "@vscode/iconv-lite-umd": "0.7.1",
@@ -97,13 +100,14 @@
97
100
  "zod": "4.4.3"
98
101
  },
99
102
  "optionalDependencies": {
100
- "@jinsiyu/dsh-code-server-runtime-win32-arm64": "^0.1.38",
101
- "@jinsiyu/dsh-code-server-runtime-win32-x64": "^0.1.38"
103
+ "@jinsiyu/dsh-code-server-runtime-win32-arm64": "^0.2.0",
104
+ "@jinsiyu/dsh-code-server-runtime-win32-x64": "^0.2.0"
102
105
  },
103
106
  "scripts": {
107
+ "vendor:vscode": "node scripts/vendor-vscode-server.mjs",
108
+ "vendor:latest": "node scripts/vendor-vscode-server.mjs --force",
109
+ "vendor:check": "node scripts/vendor-vscode-server.mjs --check",
104
110
  "vendor:code-server": "node scripts/vendor-code-server.mjs",
105
- "vendor:latest": "node scripts/vendor-code-server.mjs --force",
106
- "vendor:check": "node scripts/vendor-code-server.mjs --check",
107
111
  "repack:build": "node scripts/vendor-repacks.mjs",
108
112
  "publish:repacks": "node scripts/publish-repacks.mjs",
109
113
  "publish:plugin": "node scripts/publish-plugin.mjs",
@@ -1,20 +1,20 @@
1
- // scripts/vendor-repacks.mjs — 打包期把 code-server 本体与「pnpm 拒绝安装」的原生包全部打成可安装的预编译包。
1
+ // scripts/vendor-repacks.mjs — 打包期把「VS Code 树」与「pnpm 拒绝安装」的原生包全部打成可安装的预编译包。
2
2
  //
3
3
  // 为什么:pnpm 认为「含安装脚本」或「含 binding.gyp / .hooks」的包需要构建,必须由宿主
4
- // pnpm-workspace.yaml 的 allowBuilds 批准,否则 dsh plugin add 直接 exit 1。code-server 本体、
5
- // argon2 VS Code 内部依赖里的一批原生包都属于这一类。
4
+ // pnpm-workspace.yaml 的 allowBuilds 批准,否则 dsh plugin add 直接 exit 1。VS Code 内部依赖里
5
+ // 的一批原生包都属于这一类;树本身则因为 npm 打包永远排除**包根** node_modules 而必须重打包。
6
6
  //
7
7
  // 产物(全部由本脚本统一生成,再由 scripts/publish-repacks.mjs 统一发布):
8
- // ① @<scope>/dshcs-code-server@<code-server 版本> 平台无关:vendor/code-server 的树
9
- // (out/ + lib/vscode + 自带运行时依赖),**去掉 node_modules/argon2**;
10
- // @<scope>/dshcs-argon2-<platform>-<arch>@<argon2 版本> 平台专属:argon2 + 该架构编译好的 .node
11
- // (与其它原生包同一套规则:删 scripts/files/binding.gyp、删 prebuilds 统一走 build/Release);
12
- // ③ @<scope>/dshcs-<名字>[-<platform>-<arch>]@<版本> VS Code 内部依赖里需要构建的包
8
+ // ① @<scope>/dshcs-vscode-server@<code-server 版本> 平台无关:vendor/vscode 的树
9
+ // (lib/vscode + out/browser + src/browser);**不含** code-server 的 out/node 与其 136 个依赖
10
+ // —— 那层由插件自带的 lib/launcher.mjs 取代(见 docs/analysis-code-server-as-dsh-plugin.md);
11
+ // @<scope>/dshcs-<名字>[-<platform>-<arch>]@<版本> VS Code 内部依赖里需要构建的包
13
12
  // (node-pty / @vscode/sqlite3 / kerberos / koffi / ssh2 / …),
14
13
  // 依赖链上命中它们的包也一并重打包(含 optionalDependencies,如 @vscode/proxy-agent → windows-ca-certs);
15
- // @<scope>/dsh-code-server-runtime-<platform>-<arch>@<插件版本> 平台聚合包:
16
- // dependencies 用 npm: 别名把 ②③ 装回**原始名字**(argon2 / node-pty / @vscode/sqlite3 / …),
17
- // 这样 code-server 与 VS Code 的 require 不用改,插件只需按 os/cpu 声明 ①(常规依赖)+ (可选依赖)。
14
+ // @<scope>/dsh-code-server-runtime-<platform>-<arch>@<插件版本> 平台聚合包:
15
+ // dependencies 用 npm: 别名把 装回**原始名字**(node-pty / @vscode/sqlite3 / …),
16
+ // 这样 VS Code 的 require/import 不用改,插件只需按 os/cpu 声明 ①(常规依赖)+ (可选依赖)。
17
+ // (argon2 已随 code-server 服务层一起移除:auth=none 不再需要口令哈希。)
18
18
  //
19
19
  // 结果:pnpm install 不再遇到任何带构建信号的包 → 无需 allowBuilds、无需「安装环境」步骤。
20
20
  //
@@ -50,7 +50,7 @@ const FROM = argValue('--from');
50
50
  const SCOPE = argValue('--scope') ?? '@jinsiyu';
51
51
  const DO_PACK = process.argv.includes('--pack');
52
52
  // --reuse:复用 repack/build 里已有的原生包(不重新 analyze/交叉编译),只重建
53
- // code-server 本体包、argon2 平台包、平台聚合包与插件 package.json。
53
+ // VS Code 树包、平台聚合包与插件 package.json。
54
54
  // 适用于「原生包没变、只调整打包结构」的场景(本机已无可分析的完整源树时也用它)。
55
55
  const REUSE = process.argv.includes('--reuse');
56
56
  const TARGETS = argValues('--target');
@@ -277,12 +277,13 @@ function prepareCrossTree(specs, target) {
277
277
  * 1) npm install code-server@<内置版本> --ignore-scripts(只解包);
278
278
  * 2) 在 lib/vscode 与 lib/vscode/extensions 里 npm install --ignore-scripts(解包内部依赖,约 1GB);
279
279
  * 3) 缺 Spectre 库时先降级 gyp,再 npm rebuild(编译本机原生包)。
280
+ * 注意:只有 lib/vscode 的依赖会被 analyze 用到 —— code-server 自己的 136 个依赖已随服务层移除。
280
281
  * @returns {string} 源树根 */
281
282
  function prepareSourceTree() {
282
- const vendorVersion = readJson(join(pkgRoot, 'vendor', 'VENDOR.json'))?.codeServerVersion
283
+ const vendorVersion = readJson(join(pkgRoot, 'vendor', 'vscode', 'package.json'))?.version
283
284
  ?? readJson(join(pkgRoot, 'vendor', 'code-server', 'package.json'))?.version;
284
285
  if (typeof vendorVersion !== 'string' || vendorVersion === '') {
285
- throw new Error('缺少 vendor/code-server;先运行 `node scripts/vendor-code-server.mjs`');
286
+ throw new Error('缺少 vendor/vscode;先运行 `node scripts/vendor-vscode-server.mjs`');
286
287
  }
287
288
  const tmp = join(pkgRoot, '.vendor-tmp', `repack-src-${process.pid}`);
288
289
  rmSync(tmp, { recursive: true, force: true });
@@ -325,86 +326,48 @@ function peMachine(file) {
325
326
  } catch { return null; }
326
327
  }
327
328
 
328
- function nodeGypCli() {
329
- const cli = join(process.env.APPDATA ?? '', 'npm', 'node_modules', 'node-gyp', 'bin', 'node-gyp.js');
330
- if (!existsSync(cli)) throw new Error('找不到 node-gyp(需全局安装 node-gyp)');
331
- return cli;
332
- }
333
-
334
- /** code-server 本体(平台无关):vendor/code-server repack/build/code-server/。
335
- * 去掉平台专属的 node_modules/argon2 —— 它由 @<scope>/dshcs-argon2-<platform>-<arch> 按架构提供。 */
336
- function buildCodeServerPackage() {
337
- const vendorTree = join(pkgRoot, 'vendor', 'code-server');
338
- if (!existsSync(join(vendorTree, 'out', 'node', 'entry.js'))) {
339
- throw new Error('缺少 vendor/code-server;先运行 `node scripts/vendor-code-server.mjs`');
329
+ /** ① VS Code 树(平台无关):vendor/vscode → repack/build/vscode/vscode/。
330
+ * 排除 VS Code 的「内部依赖目录」(lib/vscode/node_modules、lib/vscode/extensions/node_modules)
331
+ * —— 它们由包管理器安装 + 平台聚合包按架构提供,树里只留 lib/vscode 本体与静态资源。
332
+ * 不含 code-server 的 out/node 与服务层依赖(已由 lib/launcher.mjs 取代)。 */
333
+ function buildVscodeServerPackage() {
334
+ const vendorTree = join(pkgRoot, 'vendor', 'vscode');
335
+ if (!existsSync(join(vendorTree, 'lib', 'vscode', 'out', 'server-main.js'))) {
336
+ throw new Error('缺少 vendor/vscode;先运行 `node scripts/vendor-vscode-server.mjs`');
340
337
  }
341
338
  const version = readJson(join(vendorTree, 'package.json'))?.version;
342
- if (typeof version !== 'string') throw new Error('读不到 code-server 版本');
343
- const dir = join(OUT, 'build', 'code-server');
339
+ if (typeof version !== 'string') throw new Error('读不到树版本(vendor/vscode/package.json)');
340
+ const dir = join(OUT, 'build', 'vscode');
344
341
  rmSync(dir, { recursive: true, force: true });
345
342
  mkdirSync(dir, { recursive: true });
346
- console.log(`[repack] code-server 本体(平台无关)→ ${relative(pkgRoot, join(dir, 'code-server'))}(argon2 由平台包提供)`);
347
- cpSync(vendorTree, join(dir, 'code-server'), {
343
+ const inner = [
344
+ join('lib', 'vscode', 'node_modules'),
345
+ join('lib', 'vscode', 'extensions', 'node_modules'),
346
+ ].map((p) => p.replaceAll('\\', '/'));
347
+ console.log(`[repack] VS Code 树(平台无关)→ ${relative(pkgRoot, join(dir, 'vscode'))}`);
348
+ cpSync(vendorTree, join(dir, 'vscode'), {
348
349
  recursive: true,
349
350
  dereference: false,
350
351
  maxRetries: 6,
351
352
  retryDelay: 250,
353
+ filter: (source) => {
354
+ const rel = source.slice(vendorTree.length + 1).replaceAll('\\', '/');
355
+ return !inner.some((p) => rel === p || rel.startsWith(`${p}/`));
356
+ },
352
357
  });
353
- // 删掉平台专属的 argon2(整目录,避免嵌套解析遮蔽 <profile>/node_modules/argon2)
354
- rmSync(join(dir, 'code-server', 'node_modules', 'argon2'), { recursive: true, force: true });
358
+ const name = `${SCOPE}/dshcs-vscode-server`;
355
359
  writeFileSync(join(dir, 'package.json'), JSON.stringify({
356
- name: `${SCOPE}/dshcs-code-server`,
360
+ name,
357
361
  version,
358
- description: `code-server ${version} (out/ + lib/vscode + its runtime dependencies), repacked so pnpm installs it `
359
- + `without any build script. The platform-specific argon2 binary is provided by ${SCOPE}/dshcs-argon2-<platform>-<arch>.`,
360
- files: ['code-server'],
362
+ description: `The VS Code server tree from code-server ${version} (lib/vscode + browser assets), repacked so pnpm `
363
+ + 'installs it without any build script. The code-server Node layer is replaced by the plugin launcher.',
364
+ files: ['vscode'],
361
365
  license: 'MIT',
362
366
  repository: readJson(join(pkgRoot, 'package.json'))?.repository ?? undefined,
363
367
  }, null, 2) + '\n', 'utf8');
364
- const name = `${SCOPE}/dshcs-code-server`;
365
368
  return { dir, name, version, file: tgzName(name, version) };
366
369
  }
367
370
 
368
- /** ② argon2 平台二进制包(每个目标一个):@<scope>/dshcs-argon2-<target>@<argon2 版本>。
369
- * 与其它原生包同一套规则:删 scripts/files/binding.gyp,保留 build/Release 里的 .node;
370
- * prebuilds/ 一律删掉(统一走 build/Release,避免 node-gyp-build 在 win32-x64 选到上游 .glibc 命名文件)。 */
371
- function buildArgon2Package(target) {
372
- const [platform, arch] = target.split('-');
373
- const src = join(pkgRoot, 'vendor', 'code-server', 'node_modules', 'argon2');
374
- if (!existsSync(join(src, 'package.json'))) throw new Error('缺少 vendor/code-server/node_modules/argon2');
375
- const version = readJson(join(src, 'package.json')).version;
376
- const dir = join(OUT, 'build', `argon2-${target}`);
377
- rmSync(dir, { recursive: true, force: true });
378
- mkdirSync(dirname(dir), { recursive: true });
379
- cpSync(src, dir, { recursive: true, maxRetries: 6, retryDelay: 250 }); // dest 不存在 → 内容平铺到 dir
380
- rmSync(join(dir, 'build'), { recursive: true, force: true }); // 重新编译,避免带走 host 架构产物
381
-
382
- console.log(`[repack] argon2 ${target}: node-gyp rebuild --arch=${arch} …`);
383
- const res = spawnSync(process.execPath, [nodeGypCli(), 'rebuild', `--arch=${arch}`], { cwd: dir, stdio: 'inherit' });
384
- if ((res.status ?? 1) !== 0) throw new Error(`argon2 ${target} 编译失败 (${res.status})`);
385
- // 编译完成后才剥掉构建信号:删 prebuilds(统一走 build/Release)、binding.gyp、中间产物
386
- rmSync(join(dir, 'prebuilds'), { recursive: true, force: true });
387
- rmSync(join(dir, 'binding.gyp'), { force: true });
388
- rmSync(join(dir, '.npmignore'), { force: true });
389
- rmSync(join(dir, 'build', 'gyp'), { recursive: true, force: true }); // 中间产物,别进包
390
- const bin = join(dir, 'build', 'Release', 'argon2.node');
391
- if (!existsSync(bin)) throw new Error(`argon2 ${target} 缺 build/Release/argon2.node`);
392
- const want = arch === 'x64' ? '0x8664' : arch === 'arm64' ? '0xaa64' : null;
393
- const machine = peMachine(bin);
394
- if (want !== null && machine !== want) throw new Error(`argon2 ${target} PE machine=${machine},期望 ${want}`);
395
-
396
- const manifest = readJson(join(dir, 'package.json'));
397
- delete manifest.scripts;
398
- delete manifest.files;
399
- manifest.name = `${SCOPE}/dshcs-argon2-${target}`;
400
- manifest.version = version;
401
- manifest.os = [platform];
402
- manifest.cpu = [arch];
403
- writeFileSync(join(dir, 'package.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8');
404
- console.log(` ✓ argon2 ${target} → ${machine} (${manifest.name}@${version})`);
405
- return { dir, name: manifest.name, version, file: tgzName(manifest.name, version) };
406
- }
407
-
408
371
  /** 从已安装的 profile 的 node_modules 还原 host 平台映射(别名目录名 = 原始包名,清单名 = 重打包名)。
409
372
  * 聚合包清单丢失时的兜底(例如上次构建中途失败)。 */
410
373
  function hostMapFromProfile() {
@@ -425,7 +388,9 @@ function hostMapFromProfile() {
425
388
  if (ent.name.startsWith('@')) { visit(full, prefix + ent.name + '/'); continue; }
426
389
  const m = readJson(join(full, 'package.json'));
427
390
  if (m === null || typeof m.name !== 'string') continue;
428
- if (!/^@[^/]+\/dshcs-/.test(m.name) || /dshcs-code-server/.test(m.name)) continue;
391
+ // argon2 已随 code-server 服务层移除:旧 profile 的别名表里可能仍有它
392
+ if (ent.name === 'argon2' || /dshcs-argon2/.test(m.name)) continue;
393
+ if (!/^@[^/]+\/dshcs-/.test(m.name) || /dshcs-(code-server|vscode-server)/.test(m.name)) continue;
429
394
  map.set(`${prefix}${ent.name}`, { pkgName: m.name, version: m.version });
430
395
  }
431
396
  };
@@ -449,7 +414,8 @@ function reuseExisting(targets, hostKey) {
449
414
  if (agg === null) continue;
450
415
  const map = new Map();
451
416
  for (const [orig, spec] of Object.entries(agg.dependencies ?? {})) {
452
- if (orig === 'argon2') continue; // argon2 由本脚本重建
417
+ // 旧的聚合包清单里可能仍带 argon2(已随 code-server 服务层移除)
418
+ if (orig === 'argon2') continue;
453
419
  const hit = /^npm:(.+)@([^@]+)$/.exec(spec);
454
420
  if (hit === null) throw new Error(`无法解析聚合包依赖 ${orig}: ${spec}`);
455
421
  map.set(orig, { pkgName: hit[1], version: hit[2] });
@@ -495,10 +461,10 @@ function reuseExisting(targets, hostKey) {
495
461
  for (const [orig, info] of hostSet) {
496
462
  repack.set(orig, { pkg: { version: info.version }, platformSpecific: info.pkgName.endsWith(`-${knownTarget}`) });
497
463
  }
498
- // 已有原生包目录 → plan 项;顺带清掉将被重建的 code-server / argon2 目录
464
+ // 已有原生包目录 → plan 项;顺带清掉将被重建的树目录(旧 code-server / argon2 目录一并清理)
499
465
  const reusedItems = [];
500
466
  for (const ent of readdirSync(buildRoot)) {
501
- if (/^code-server/.test(ent) || /^argon2-/.test(ent)) {
467
+ if (ent === 'vscode' || /^code-server/.test(ent) || /^argon2-/.test(ent)) {
502
468
  rmSync(join(buildRoot, ent), { recursive: true, force: true });
503
469
  continue;
504
470
  }
@@ -573,6 +539,21 @@ function main() {
573
539
  const [platform, arch] = pkg.pkgName.match(/-(win32|darwin|linux)-(arm64|x64)$/).slice(1);
574
540
  m.os = [platform];
575
541
  m.cpu = [arch];
542
+ if (platform === 'win32') {
543
+ // 交叉编译产物静态校验:.node 的 PE machine 必须是目标架构(0x8664=x64 / 0xaa64=arm64)
544
+ const want = arch === 'x64' ? '0x8664' : '0xaa64';
545
+ const files = nodeFilesOf(dir);
546
+ const wrong = files
547
+ .map((file) => [file, peMachine(file)])
548
+ .filter(([, machine]) => machine !== null && machine !== want);
549
+ if (files.length > 0 && wrong.length === files.length) {
550
+ throw new Error(`${pkg.pkgName}: 所有 .node 架构都不是 ${want}`
551
+ + `(${wrong.map(([file, machine]) => `${relative(dir, file)}=${machine}`).join(', ')})`);
552
+ }
553
+ if (wrong.length > 0) {
554
+ console.warn(` ⚠ ${pkg.pkgName}: ${wrong.length} 个 .node 架构不符(期望 ${want})`);
555
+ }
556
+ }
576
557
  }
577
558
  for (const fld of ['dependencies', 'optionalDependencies']) {
578
559
  if (!m[fld]) continue;
@@ -588,15 +569,9 @@ function main() {
588
569
  const plan = [];
589
570
  // 0) 已打包的原生包(--reuse 模式)
590
571
  for (const item of reusedItems) plan.push(item);
591
- // 1) code-server 本体(平台无关,1 个包)+ argon2 平台二进制包(每目标 1 个,与其它原生包同一套规则)
592
- const codeServerPkg = buildCodeServerPackage();
593
- plan.push({ dir: codeServerPkg.dir, file: codeServerPkg.file });
594
- const argon2ByTarget = new Map();
595
- for (const target of targets) {
596
- const pkg = buildArgon2Package(target);
597
- argon2ByTarget.set(target, pkg);
598
- plan.push({ dir: pkg.dir, file: pkg.file });
599
- }
572
+ // 1) VS Code 树(平台无关,1 个包)
573
+ const vscodePkg = buildVscodeServerPackage();
574
+ plan.push({ dir: vscodePkg.dir, file: vscodePkg.file });
600
575
  // 2) 全平台重打包包(从 host 树;--reuse 时用已打包目录)
601
576
  if (!REUSE) {
602
577
  for (const [name, r] of repack) {
@@ -624,7 +599,7 @@ function main() {
624
599
  }
625
600
  if (crossTree !== null) rmSync(crossTree, { recursive: true, force: true });
626
601
  }
627
- // 3) 聚合包(每平台一个):dependencies 用 npm: 别名把重打包包装回原名(含 argon2)
602
+ // 3) 聚合包(每平台一个):dependencies 用 npm: 别名把重打包包装回原名
628
603
  for (const target of targets) {
629
604
  const map = byTarget.get(target);
630
605
  const aggName = `${SCOPE}/dsh-code-server-runtime-${target}`;
@@ -632,13 +607,11 @@ function main() {
632
607
  mkdirSync(aggDir, { recursive: true });
633
608
  const deps = {};
634
609
  for (const [name] of repack) deps[name] = `npm:${map.get(name).pkgName}@${map.get(name).version}`;
635
- // argon2:code-server 本体包不带原生二进制,由这里按平台装回原名 "argon2"
636
- const argon2 = argon2ByTarget.get(target);
637
- if (argon2 !== undefined) deps.argon2 = `npm:${argon2.name}@${argon2.version}`;
638
610
  writeFileSync(join(aggDir, 'package.json'), JSON.stringify({
639
611
  name: aggName,
640
612
  version: pluginVersion,
641
- description: `Prebuilt native modules for code-server on ${target} (argon2, node-pty, @vscode/sqlite3, kerberos, …), `
613
+ description: `Prebuilt native modules for the VS Code server tree on ${target} `
614
+ + '(node-pty, @vscode/sqlite3, kerberos, @vscode/spdlog, …), '
642
615
  + 'so that installing the VS Code inner dependencies needs no build approval or C++ toolchain.',
643
616
  os: [target.split('-')[0]],
644
617
  cpu: [target.split('-')[1]],
@@ -652,19 +625,19 @@ function main() {
652
625
  writeFileSync(join(OUT, 'pack-plan.json'), JSON.stringify(plan, null, 2) + '\n', 'utf8');
653
626
  console.log(`[repack] 生成 ${plan.length} 个待打包目录 → repack/ (计划:repack/pack-plan.json)`);
654
627
 
655
- // 4) 改写插件 package.json 的依赖:纯 JS 直装集 + code-server 本体包(平台无关);
656
- // 平台专属的(16 个原生包 + argon2)通过聚合包按 os/cpu 自动选。
628
+ // 4) 改写插件 package.json 的依赖:纯 JS 直装集 + VS Code 树包(平台无关);
629
+ // 平台专属的(原生包)通过聚合包按 os/cpu 自动选。
657
630
  const pkgFile = join(pkgRoot, 'package.json');
658
631
  const pluginPkg = readJson(pkgFile);
659
632
  pluginPkg.dependencies = Object.fromEntries([
660
- [codeServerPkg.name, codeServerPkg.version],
633
+ [vscodePkg.name, vscodePkg.version],
661
634
  ...declare.map((d) => [d.name, d.version]),
662
635
  ].sort(([a], [b]) => a.localeCompare(b)));
663
636
  pluginPkg.optionalDependencies = Object.fromEntries(targets
664
637
  .map((t) => [`${SCOPE}/dsh-code-server-runtime-${t}`, `^${pluginVersion}`]));
665
638
  writeFileSync(pkgFile, JSON.stringify(pluginPkg, null, 2) + '\n', 'utf8');
666
639
  console.log(`[repack] 已写入 package.json:dependencies ${pluginPkg.dependencies ? Object.keys(pluginPkg.dependencies).length : 0} 个`
667
- + `(code-server 本体 + 纯 JS),optionalDependencies ${targets.length} 个平台聚合包`);
640
+ + `(VS Code + 纯 JS),optionalDependencies ${targets.length} 个平台聚合包`);
668
641
 
669
642
  // 5) 可选:直接打包
670
643
  if (DO_PACK) {