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/README.en.md +113 -106
- package/README.md +125 -92
- package/cordis.patch.yml +19 -15
- package/lib/client.js +1 -3
- package/lib/index.js +247 -144
- package/lib/launcher.mjs +313 -0
- package/lib/native.js +44 -12
- package/lib/serve-dsh.mjs +162 -0
- package/lib/vendor.js +94 -33
- package/package.json +11 -7
- package/scripts/vendor-repacks.mjs +72 -99
- package/scripts/vendor-vscode-server.mjs +278 -0
- package/vendor/VENDOR.json +5 -2
package/lib/vendor.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
// lib/vendor.js — 内置
|
|
1
|
+
// lib/vendor.js — 内置 VS Code 产物的路径工具(host 与脚本共用)。
|
|
2
2
|
//
|
|
3
|
-
// 模型(0.
|
|
4
|
-
// -
|
|
5
|
-
// @<scope>/dshcs-
|
|
6
|
-
//
|
|
7
|
-
//
|
|
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
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// - 插件包内 `vendor/
|
|
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
|
-
/** 包内
|
|
22
|
-
export const VENDOR_TREE = join(PACKAGE_ROOT, 'vendor', '
|
|
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
|
-
|
|
41
|
-
export function codeServerPackageName() {
|
|
44
|
+
function declaredDependencyNames() {
|
|
42
45
|
try {
|
|
43
46
|
const manifest = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
/** 解析某个包目录下的
|
|
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
|
|
61
|
-
|
|
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
|
-
/**
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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, '
|
|
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
|
-
/**
|
|
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 =
|
|
78
|
-
|
|
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
|
|
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
|
-
/**
|
|
174
|
+
/** VS Code 树是否可用(包已安装或包内 vendor 在位)。 */
|
|
115
175
|
export function vendorReady() {
|
|
116
|
-
return
|
|
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.
|
|
4
|
-
"description": "
|
|
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-
|
|
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.
|
|
101
|
-
"@jinsiyu/dsh-code-server-runtime-win32-x64": "^0.
|
|
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 —
|
|
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。
|
|
5
|
-
//
|
|
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-
|
|
9
|
-
// (
|
|
10
|
-
//
|
|
11
|
-
//
|
|
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
|
-
//
|
|
16
|
-
// dependencies 用 npm: 别名把
|
|
17
|
-
// 这样
|
|
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
|
-
//
|
|
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', '
|
|
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/
|
|
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
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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('
|
|
343
|
-
const dir = join(OUT, 'build', '
|
|
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
|
-
|
|
347
|
-
|
|
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
|
-
|
|
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
|
|
360
|
+
name,
|
|
357
361
|
version,
|
|
358
|
-
description: `code-server ${version} (
|
|
359
|
-
+
|
|
360
|
-
files: ['
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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)
|
|
592
|
-
const
|
|
593
|
-
plan.push({ dir:
|
|
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: 别名把重打包包装回原名
|
|
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
|
|
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 直装集 +
|
|
656
|
-
// 平台专属的(
|
|
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
|
-
[
|
|
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
|
-
+ `(
|
|
640
|
+
+ `(VS Code 树 + 纯 JS),optionalDependencies ${targets.length} 个平台聚合包`);
|
|
668
641
|
|
|
669
642
|
// 5) 可选:直接打包
|
|
670
643
|
if (DO_PACK) {
|