@dsh-workbench/adapter-probe 1.1.14-beta.2 → 1.1.14
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/dist/bootstrap-run.d.ts +2 -3
- package/dist/bootstrap-run.js +26 -43
- package/dist/browser-wake.d.ts +2 -2
- package/dist/browser-wake.js +11 -15
- package/dist/desktop-runtime.d.ts +14 -0
- package/dist/desktop-runtime.js +59 -0
- package/dist/diy-preset-health.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/preflight-route.d.ts +3 -2
- package/dist/preflight-route.js +12 -6
- package/dist/preflight.d.ts +3 -2
- package/dist/preflight.js +12 -10
- package/dist/probe-cache.js +3 -2
- package/dist/probe-libs.d.ts +2 -3
- package/dist/probe-libs.js +2 -2
- package/dist/probe-units.d.ts +3 -4
- package/dist/probe-units.js +21 -14
- package/dist/release-port.d.ts +3 -3
- package/dist/release-port.js +2 -2
- package/dist/runtime-seed.d.ts +4 -6
- package/dist/runtime-seed.js +31 -61
- package/dist/self-update.d.ts +3 -3
- package/dist/self-update.js +10 -13
- package/dist/supply-port.d.ts +5 -2
- package/dist/supply-port.js +3 -2
- package/dist/toolchain-probe.d.ts +4 -2
- package/dist/toolchain-probe.js +80 -14
- package/dist/toolchain.d.ts +7 -19
- package/dist/toolchain.js +19 -69
- package/package.json +5 -8
package/dist/release-port.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export declare const latestVersion: (options: {
|
|
2
|
-
readonly
|
|
2
|
+
readonly seam: import("@dsh-workbench/shared/host").Seam;
|
|
3
3
|
readonly name: string;
|
|
4
4
|
readonly registry: string;
|
|
5
5
|
readonly force?: boolean;
|
|
6
6
|
}) => Promise<string | undefined>;
|
|
7
7
|
export declare const missingReleaseParts: (options: {
|
|
8
|
-
readonly
|
|
8
|
+
readonly seam: import("@dsh-workbench/shared/host").Seam;
|
|
9
9
|
readonly name: string;
|
|
10
10
|
readonly registry: string;
|
|
11
11
|
readonly version: string;
|
|
12
12
|
readonly force?: boolean;
|
|
13
13
|
}) => Promise<readonly string[]>;
|
|
14
14
|
export declare const probeRelease: (options: {
|
|
15
|
-
readonly
|
|
15
|
+
readonly seam: import("@dsh-workbench/shared/host").Seam;
|
|
16
16
|
readonly package: string;
|
|
17
17
|
readonly registry?: string | undefined;
|
|
18
18
|
readonly force?: boolean;
|
package/dist/release-port.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createReleasePort } from '@dsh-workbench/adapter-profile';
|
|
2
|
-
import {
|
|
3
|
-
const port = createReleasePort({
|
|
2
|
+
import { vendorPrefix } from '@dsh-workbench/adapter-runtime';
|
|
3
|
+
const port = createReleasePort({ prefix: vendorPrefix() });
|
|
4
4
|
export const latestVersion = port.latestVersion;
|
|
5
5
|
export const missingReleaseParts = port.missingReleaseParts;
|
|
6
6
|
export const probeRelease = port.probeRelease;
|
package/dist/runtime-seed.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { spawn } from 'node:child_process';
|
|
2
1
|
import type { DshHostContext } from '@dsh-workbench/shared';
|
|
2
|
+
import type { Seam } from '@dsh-workbench/shared/host';
|
|
3
3
|
export type SeedLog = (message: string) => void;
|
|
4
4
|
export interface RuntimeSeedPaths {
|
|
5
5
|
readonly root: string;
|
|
@@ -21,9 +21,7 @@ export interface RuntimeSeedOptions {
|
|
|
21
21
|
}
|
|
22
22
|
export declare function opencliBinName(platform?: NodeJS.Platform): string;
|
|
23
23
|
export declare function runtimeSeedPaths(root: string, platform?: NodeJS.Platform): RuntimeSeedPaths;
|
|
24
|
-
export declare function runtimeSeedRootOf(
|
|
25
|
-
export declare function coversWritableRoot(workspaceRoot: string, root: string): boolean;
|
|
26
|
-
export declare function warnUnwritableRoot(ctx: DshHostContext): void;
|
|
24
|
+
export declare function runtimeSeedRootOf(_ctx: DshHostContext): string | null;
|
|
27
25
|
export declare function wrapperRootOf(fallbackRoot: string): string;
|
|
28
26
|
export declare function isInstalledCopy(packageRoot: string): boolean;
|
|
29
27
|
export declare function opencliWrapperScript(packageRoot: string, home: string, platform?: NodeJS.Platform): string;
|
|
@@ -38,7 +36,7 @@ export declare function workshopSeedPlan(packageRoot: string, home: string, root
|
|
|
38
36
|
readonly entry: SeedCommand;
|
|
39
37
|
readonly full: SeedCommand;
|
|
40
38
|
};
|
|
41
|
-
export declare function runDetached(command: SeedCommand, onError: SeedLog,
|
|
39
|
+
export declare function runDetached(command: SeedCommand, onError: SeedLog, seam?: Seam | undefined): void;
|
|
42
40
|
export declare function prependPath(entryDir: string, env?: NodeJS.ProcessEnv): boolean;
|
|
43
|
-
export declare function seedWorkbenchToolchain(root: string, log: SeedLog): void
|
|
41
|
+
export declare function seedWorkbenchToolchain(root: string, log: SeedLog, seam?: Seam | undefined): Promise<void>;
|
|
44
42
|
export declare function seedRuntimeFiles(options: RuntimeSeedOptions): readonly string[];
|
package/dist/runtime-seed.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { execa } from 'execa';
|
|
2
1
|
import { toolchainManifestOf } from '@dsh-workbench/adapter-runtime';
|
|
3
2
|
import { createRequire } from 'node:module';
|
|
4
|
-
import
|
|
5
|
-
import { chmodSync, closeSync, mkdirSync, openSync, readFileSync, rmSync, } from 'node:fs';
|
|
3
|
+
import { mkdirSync, readFileSync, rmSync } from 'node:fs';
|
|
6
4
|
import { delimiter, dirname, join, sep } from 'node:path';
|
|
7
|
-
import { quoteShellArg, quoteShellArgFor } from '@dsh-workbench/shared/host';
|
|
8
|
-
import { desktopPnpmPath, desktopPnpmVersion, ensureToolchain, localNpmCache, localPnpmCommand,
|
|
5
|
+
import { pathWithBinsOf, quoteShellArg, quoteShellArgFor, workbenchRoot, writeTextFile } from '@dsh-workbench/shared/host';
|
|
6
|
+
import { desktopBundledBins, desktopNodeExecutable, desktopPnpmPath, desktopPnpmVersion, ensureToolchain, localNpmCache, localPnpmCommand, provisionLocalPnpm, } from './toolchain.js';
|
|
9
7
|
export function opencliBinName(platform = process.platform) {
|
|
10
8
|
return platform === 'win32' ? 'opencli.cmd' : 'opencli';
|
|
11
9
|
}
|
|
@@ -25,32 +23,8 @@ export function runtimeSeedPaths(root, platform = process.platform) {
|
|
|
25
23
|
workshopManifest: join(workshop, 'package.json'),
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
|
-
export function runtimeSeedRootOf(
|
|
29
|
-
|
|
30
|
-
if (configured !== undefined && configured !== '')
|
|
31
|
-
return configured;
|
|
32
|
-
const homePath = ctx.get('dshHomePath');
|
|
33
|
-
if (typeof homePath !== 'function')
|
|
34
|
-
return null;
|
|
35
|
-
try {
|
|
36
|
-
return homePath('workbench');
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
export function coversWritableRoot(workspaceRoot, root) {
|
|
43
|
-
const prefix = workspaceRoot.endsWith(sep) ? workspaceRoot : `${workspaceRoot}${sep}`;
|
|
44
|
-
return root === workspaceRoot || root.startsWith(prefix);
|
|
45
|
-
}
|
|
46
|
-
export function warnUnwritableRoot(ctx) {
|
|
47
|
-
const root = runtimeSeedRootOf(ctx);
|
|
48
|
-
if (root === null)
|
|
49
|
-
return;
|
|
50
|
-
const workspaceRoot = ctx.get('sandboxPolicy')?.workspaceRoot;
|
|
51
|
-
if (workspaceRoot === undefined || coversWritableRoot(workspaceRoot, root))
|
|
52
|
-
return;
|
|
53
|
-
ctx.logger?.warn?.(`[dsh-workbench] 可写根 ${workspaceRoot} 盖不住 ${root}:市场装插件、自举命令可能被沙箱挡(把 profile/sandbox.patch.yml 那一行写进这个 profile 的 cordis.patch.yml 再重启)`);
|
|
26
|
+
export function runtimeSeedRootOf(_ctx) {
|
|
27
|
+
return workbenchRoot();
|
|
54
28
|
}
|
|
55
29
|
export function wrapperRootOf(fallbackRoot) {
|
|
56
30
|
try {
|
|
@@ -88,49 +62,46 @@ export function workshopSeedPlan(packageRoot, home, root, platform = process.pla
|
|
|
88
62
|
full: { file: 'bash', args: [script], env, log },
|
|
89
63
|
};
|
|
90
64
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
65
|
+
export function runDetached(command, onError, seam) {
|
|
66
|
+
if (seam === undefined) {
|
|
67
|
+
onError(`自举脚本没跑起来(${command.file}):宿主没给执行缝`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
94
70
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
71
|
+
const handle = seam.spawn({
|
|
72
|
+
target: { argv: [command.file, ...command.args] },
|
|
73
|
+
intent: { kind: 'host' },
|
|
74
|
+
lifetime: 'host',
|
|
75
|
+
logFile: command.log,
|
|
76
|
+
env: command.env,
|
|
77
|
+
label: 'seed',
|
|
100
78
|
});
|
|
101
|
-
|
|
102
|
-
child.unref();
|
|
79
|
+
handle.onError((error) => onError(`自举脚本没跑起来(${command.file}):${String(error)}`));
|
|
103
80
|
}
|
|
104
81
|
catch (error) {
|
|
105
82
|
onError(`自举脚本没跑起来(${command.file}):${String(error)}`);
|
|
106
83
|
}
|
|
107
|
-
finally {
|
|
108
|
-
if (fd !== null)
|
|
109
|
-
closeQuietly(fd);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function closeQuietly(fd) {
|
|
113
|
-
try {
|
|
114
|
-
closeSync(fd);
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
84
|
}
|
|
120
85
|
export function prependPath(entryDir, env = process.env) {
|
|
121
86
|
const parts = (env.PATH ?? '').split(delimiter).filter((part) => part !== '');
|
|
122
87
|
if (parts.includes(entryDir))
|
|
123
88
|
return false;
|
|
124
|
-
env.PATH = [entryDir
|
|
89
|
+
env.PATH = pathWithBinsOf(env.PATH, [entryDir]);
|
|
125
90
|
return true;
|
|
126
91
|
}
|
|
127
|
-
export function seedWorkbenchToolchain(root, log) {
|
|
92
|
+
export async function seedWorkbenchToolchain(root, log, seam) {
|
|
93
|
+
for (const dir of desktopBundledBins()) {
|
|
94
|
+
if (prependPath(dir))
|
|
95
|
+
log(`PATH 前插 Desktop 自带 ${dir}`);
|
|
96
|
+
}
|
|
128
97
|
const bundledPnpm = desktopPnpmPath();
|
|
129
98
|
const bundledMajor = Number(desktopPnpmVersion()?.split('.')[0] ?? '0');
|
|
130
99
|
const bundledUsable = bundledPnpm !== undefined && bundledMajor >= 10;
|
|
131
100
|
if (bundledPnpm !== undefined && bundledUsable) {
|
|
132
|
-
|
|
133
|
-
|
|
101
|
+
const bundledNode = desktopNodeExecutable();
|
|
102
|
+
const nodePrefix = bundledNode === undefined ? 'node' : quoteShellArgFor(bundledNode, process.platform);
|
|
103
|
+
process.env.DSH_WB_PNPM = `${nodePrefix} ${quoteShellArgFor(bundledPnpm, process.platform)}`;
|
|
104
|
+
log(`pnpm 用 Desktop 自带的:${bundledPnpm}(node: ${nodePrefix})`);
|
|
134
105
|
}
|
|
135
106
|
else if (bundledPnpm !== undefined) {
|
|
136
107
|
log(`Desktop 自带 pnpm 版本低于 10,优先用 PATH 上的 pnpm`);
|
|
@@ -155,7 +126,7 @@ export function seedWorkbenchToolchain(root, log) {
|
|
|
155
126
|
process.env.DSH_WB_PNPM = localPnpmCommand(root);
|
|
156
127
|
}
|
|
157
128
|
else if (!bundledUsable && toolchain.pathDir !== undefined) {
|
|
158
|
-
const installed =
|
|
129
|
+
const installed = await provisionLocalPnpm({ root, seam });
|
|
159
130
|
if (installed.ok && installed.binDir !== undefined) {
|
|
160
131
|
if (prependPath(installed.binDir))
|
|
161
132
|
log(`PATH 前插 ${installed.binDir}`);
|
|
@@ -178,15 +149,14 @@ export function seedRuntimeFiles(options) {
|
|
|
178
149
|
const manifest = join(paths.opencliRoot, 'toolchain', 'package.json');
|
|
179
150
|
mkdirSync(dirname(manifest), { recursive: true });
|
|
180
151
|
if (readText(manifest) !== toolchainManifestOf()) {
|
|
181
|
-
|
|
152
|
+
writeTextFile(manifest, toolchainManifestOf());
|
|
182
153
|
done.push(manifest);
|
|
183
154
|
}
|
|
184
155
|
rmSync(join(paths.opencliRoot, 'toolchain', 'pnpm-workspace.yaml'), { force: true });
|
|
185
156
|
const wanted = opencliWrapperScript(options.packageRoot, options.home, platform);
|
|
186
157
|
if (readText(paths.opencliBin) !== wanted) {
|
|
187
158
|
rmSync(paths.opencliBin, { force: true });
|
|
188
|
-
|
|
189
|
-
chmodSync(paths.opencliBin, 0o755);
|
|
159
|
+
writeTextFile(paths.opencliBin, wanted, { mode: 0o755 });
|
|
190
160
|
done.push(paths.opencliBin);
|
|
191
161
|
}
|
|
192
162
|
}
|
package/dist/self-update.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Seam } from '@dsh-workbench/shared/host';
|
|
2
2
|
import { type SeedCommand } from './runtime-seed.js';
|
|
3
3
|
import { SELF_UPDATE_STATES, type SelfUpdateState, type WorkbenchSelfUpdate } from '@dsh-workbench/shared/contract/protocol/bundle-install';
|
|
4
4
|
export { SELF_UPDATE_STATES, type SelfUpdateState };
|
|
@@ -47,7 +47,7 @@ export interface SelfUpdateStart {
|
|
|
47
47
|
readonly paths: SelfUpdatePaths;
|
|
48
48
|
readonly forward: string;
|
|
49
49
|
}
|
|
50
|
-
export declare function selfUpdatePaths(
|
|
50
|
+
export declare function selfUpdatePaths(_dshHome: string, platform?: NodeJS.Platform): SelfUpdatePaths;
|
|
51
51
|
export declare function recoveryCommand(input: {
|
|
52
52
|
readonly profile: string;
|
|
53
53
|
readonly pkg: string;
|
|
@@ -58,6 +58,6 @@ export declare function selfUpdateMarker(request: SelfUpdateRequest, state: Self
|
|
|
58
58
|
export declare function selfUpdateScript(request: SelfUpdateRequest, paths: SelfUpdatePaths, cli?: SelfUpdateCli): string;
|
|
59
59
|
export declare function selfUpdateNodeScript(request: SelfUpdateRequest, paths: SelfUpdatePaths, cli?: SelfUpdateCli): string;
|
|
60
60
|
export declare function planSelfUpdate(request: SelfUpdateRequest, now?: Date, cli?: SelfUpdateCli, platform?: NodeJS.Platform): SelfUpdatePlan;
|
|
61
|
-
export declare function startSelfUpdate(request: SelfUpdateRequest, onError: (message: string) => void,
|
|
61
|
+
export declare function startSelfUpdate(request: SelfUpdateRequest, onError: (message: string) => void, seam?: Seam | undefined, cli?: SelfUpdateCli): SelfUpdateStart;
|
|
62
62
|
export declare function readSelfUpdateView(home: string, profile?: string): WorkbenchSelfUpdate | undefined;
|
|
63
63
|
export { runningVersionOf } from '@dsh-workbench/shared/host';
|
package/dist/self-update.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { quoteShellArg } from '@dsh-workbench/shared/host';
|
|
1
|
+
import { now as clockNow, quoteShellArg, workbenchRoot, writeJsonFile, writeTextFile } from '@dsh-workbench/shared/host';
|
|
3
2
|
import { hostSurface } from './platform.js';
|
|
4
|
-
import {
|
|
3
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, statSync, } from 'node:fs';
|
|
5
4
|
import { dirname, join } from 'node:path';
|
|
6
5
|
import { runDetached } from './runtime-seed.js';
|
|
7
6
|
import { SELF_UPDATE_STATES, } from '@dsh-workbench/shared/contract/protocol/bundle-install';
|
|
@@ -41,9 +40,8 @@ export function selfUpdateCliFor(profile, proc = process, exists = existsSync) {
|
|
|
41
40
|
return PATH_DSH;
|
|
42
41
|
return desktopSelfUpdateCli(proc, exists) ?? PATH_DSH;
|
|
43
42
|
}
|
|
44
|
-
export function selfUpdatePaths(
|
|
45
|
-
const
|
|
46
|
-
const dir = configured === undefined || configured === '' ? join(dshHome, 'workbench') : configured;
|
|
43
|
+
export function selfUpdatePaths(_dshHome, platform = process.platform) {
|
|
44
|
+
const dir = workbenchRoot();
|
|
47
45
|
return {
|
|
48
46
|
dir,
|
|
49
47
|
script: join(dir, platform === 'win32' ? 'self-update.mjs' : 'self-update.sh'),
|
|
@@ -178,7 +176,7 @@ export function selfUpdateNodeScript(request, paths, cli = selfUpdateCliFor(requ
|
|
|
178
176
|
'',
|
|
179
177
|
].join('\n');
|
|
180
178
|
}
|
|
181
|
-
export function planSelfUpdate(request, now = new Date(), cli = selfUpdateCliFor(request.profile), platform = process.platform) {
|
|
179
|
+
export function planSelfUpdate(request, now = new Date(clockNow()), cli = selfUpdateCliFor(request.profile), platform = process.platform) {
|
|
182
180
|
const paths = selfUpdatePaths(request.dshHome, platform);
|
|
183
181
|
const windows = platform === 'win32';
|
|
184
182
|
return {
|
|
@@ -195,13 +193,12 @@ export function planSelfUpdate(request, now = new Date(), cli = selfUpdateCliFor
|
|
|
195
193
|
: { file: 'bash', args: [paths.script], env: {}, log: paths.log },
|
|
196
194
|
};
|
|
197
195
|
}
|
|
198
|
-
export function startSelfUpdate(request, onError,
|
|
199
|
-
const plan = planSelfUpdate(request, new Date(), cli);
|
|
196
|
+
export function startSelfUpdate(request, onError, seam, cli = selfUpdateCliFor(request.profile)) {
|
|
197
|
+
const plan = planSelfUpdate(request, new Date(clockNow()), cli);
|
|
200
198
|
mkdirSync(plan.paths.dir, { recursive: true });
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
runDetached(plan.command, onError, spawnImpl);
|
|
199
|
+
writeTextFile(plan.paths.script, plan.script, { mode: 0o755 });
|
|
200
|
+
writeJsonFile(plan.paths.marker, plan.marker);
|
|
201
|
+
runDetached(plan.command, onError, seam);
|
|
205
202
|
const forward = recoveryCommand({
|
|
206
203
|
profile: request.profile,
|
|
207
204
|
pkg: request.pkg,
|
package/dist/supply-port.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import type { SupplyPort } from '@dsh-workbench/shared/host';
|
|
2
|
-
export
|
|
1
|
+
import type { Seam, SupplyPort } from '@dsh-workbench/shared/host';
|
|
2
|
+
export interface ProbeSupplyOptions {
|
|
3
|
+
readonly seam?: Seam | undefined;
|
|
4
|
+
}
|
|
5
|
+
export declare function createSupplyPort(options?: ProbeSupplyOptions): SupplyPort;
|
package/dist/supply-port.js
CHANGED
|
@@ -7,7 +7,8 @@ import { startSelfUpdate } from './self-update.js';
|
|
|
7
7
|
import { declarationGaps, declarationRefusalOf, moduleDeclarationOf, packageRouteOf, pathDeclarationOf, pluginInstallPlan, profileDirOf, profileModules, readInstalledModule, readProfilePackage, registryDeclarationOf, resolvePluginSource, splitNpmSpec, } from '@dsh-workbench/adapter-supply';
|
|
8
8
|
import { readBundleManager, refusalReason } from '@dsh-workbench/shared/host';
|
|
9
9
|
import { OPENCLI_MANIFEST_FILE } from '@dsh-workbench/adapter-runtime';
|
|
10
|
-
export function createSupplyPort() {
|
|
10
|
+
export function createSupplyPort(options = {}) {
|
|
11
|
+
const seam = options.seam;
|
|
11
12
|
const port = {
|
|
12
13
|
isolatedRoot,
|
|
13
14
|
isolatedHome,
|
|
@@ -42,7 +43,7 @@ export function createSupplyPort() {
|
|
|
42
43
|
splitNpmSpec,
|
|
43
44
|
libInstallCommand,
|
|
44
45
|
libUninstallCommand,
|
|
45
|
-
startSelfUpdate,
|
|
46
|
+
startSelfUpdate: (request, onError) => startSelfUpdate(request, onError, seam),
|
|
46
47
|
};
|
|
47
48
|
return { ...port, env: port, modules: port };
|
|
48
49
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Seam } from '@dsh-workbench/shared/host';
|
|
2
2
|
export interface ToolchainReport {
|
|
3
3
|
readonly ok: boolean;
|
|
4
4
|
readonly detail: string;
|
|
@@ -6,5 +6,7 @@ export interface ToolchainReport {
|
|
|
6
6
|
readonly npmMissing: boolean;
|
|
7
7
|
readonly pnpmProblem: boolean;
|
|
8
8
|
readonly stalled?: boolean | undefined;
|
|
9
|
+
readonly diagnostics?: readonly string[] | undefined;
|
|
10
|
+
readonly hostBroken?: boolean | undefined;
|
|
9
11
|
}
|
|
10
|
-
export declare function probeDesktopToolchain(
|
|
12
|
+
export declare function probeDesktopToolchain(seam: Seam): Promise<ToolchainReport>;
|
package/dist/toolchain-probe.js
CHANGED
|
@@ -1,28 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { productWrite, quoteShellArg } from '@dsh-workbench/shared/host';
|
|
2
|
+
import { delimiter } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { desktopBundledBins, desktopNodeExecutable, desktopPnpmPath, desktopPnpmVersion, desktopResourcesDir, desktopRuntimeEnv, } from './desktop-runtime.js';
|
|
4
5
|
import { hostSurface } from './platform.js';
|
|
5
|
-
async function toolVersion(
|
|
6
|
+
async function toolVersion(seam, line, extra) {
|
|
6
7
|
try {
|
|
7
|
-
const result = await
|
|
8
|
+
const result = await seam.run({
|
|
9
|
+
command: line,
|
|
10
|
+
intent: productWrite(),
|
|
11
|
+
retry: 'safe',
|
|
12
|
+
timeoutMs: 10_000,
|
|
13
|
+
...(extra?.workdir === undefined ? {} : { workdir: extra.workdir }),
|
|
14
|
+
});
|
|
8
15
|
const text = (result.stdout || result.stderr).trim().split('\n')[0] ?? '';
|
|
9
|
-
|
|
16
|
+
const fact = seam.facts().filter((entry) => entry.command === line).at(-1);
|
|
17
|
+
const sandbox = fact === undefined
|
|
18
|
+
? '(无)'
|
|
19
|
+
: `mode=${fact.mode} root=${fact.workspaceRoot}${fact.denial === undefined ? '' : ` denial=${fact.denial.scope}`}`;
|
|
20
|
+
return {
|
|
21
|
+
ok: result.exitCode === 0 && !result.timedOut,
|
|
22
|
+
text,
|
|
23
|
+
stalled: result.stalled,
|
|
24
|
+
code: result.exitCode,
|
|
25
|
+
raw: `${result.stdout ?? ''}${result.stderr ?? ''}`.trim().split('\n').slice(0, 2).join(' / '),
|
|
26
|
+
sandbox,
|
|
27
|
+
};
|
|
10
28
|
}
|
|
11
|
-
catch {
|
|
12
|
-
return { ok: false, text: '', stalled: false };
|
|
29
|
+
catch (error) {
|
|
30
|
+
return { ok: false, text: '', stalled: false, code: null, raw: String(error), sandbox: '(抛错)' };
|
|
13
31
|
}
|
|
14
32
|
}
|
|
15
|
-
export async function probeDesktopToolchain(
|
|
33
|
+
export async function probeDesktopToolchain(seam) {
|
|
34
|
+
const bundledNode = desktopNodeExecutable();
|
|
16
35
|
const bundledPnpm = desktopPnpmPath();
|
|
17
36
|
const bundledMajor = desktopPnpmVersion()?.split('.')[0];
|
|
18
37
|
const preferBundled = bundledPnpm !== undefined && Number(bundledMajor ?? '0') >= 10;
|
|
38
|
+
const nodeCommand = bundledNode === undefined ? 'node' : quoteShellArg(bundledNode);
|
|
19
39
|
const pnpmLine = preferBundled
|
|
20
|
-
?
|
|
40
|
+
? `${nodeCommand} ${quoteShellArg(bundledPnpm ?? '')} --version`
|
|
21
41
|
: 'pnpm --version';
|
|
42
|
+
const path = desktopRuntimeEnv().PATH;
|
|
22
43
|
const [node, npm, pnpm] = await Promise.all([
|
|
23
|
-
toolVersion(
|
|
24
|
-
toolVersion(
|
|
25
|
-
toolVersion(
|
|
44
|
+
toolVersion(seam, `${nodeCommand} --version`),
|
|
45
|
+
toolVersion(seam, 'npm --version'),
|
|
46
|
+
toolVersion(seam, pnpmLine),
|
|
26
47
|
]);
|
|
27
48
|
if (node.stalled || npm.stalled || pnpm.stalled) {
|
|
28
49
|
return {
|
|
@@ -56,5 +77,50 @@ export async function probeDesktopToolchain(shell) {
|
|
|
56
77
|
? `pnpm ${pnpm.text}(Desktop 自带)`
|
|
57
78
|
: `pnpm ${pnpm.text}`,
|
|
58
79
|
];
|
|
59
|
-
|
|
80
|
+
const control = [];
|
|
81
|
+
if (nodeMissing) {
|
|
82
|
+
for (const [label, file] of [
|
|
83
|
+
['direct bundled node', desktopNodeExecutable()],
|
|
84
|
+
['direct host node', process.execPath],
|
|
85
|
+
]) {
|
|
86
|
+
if (file === undefined) {
|
|
87
|
+
control.push(`control ${label}: (没有可执行文件)`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const out = await seam.run({
|
|
92
|
+
argv: [file, '--version'],
|
|
93
|
+
intent: { kind: 'host' },
|
|
94
|
+
timeoutMs: 10_000,
|
|
95
|
+
});
|
|
96
|
+
control.push(`control ${label}: exit=${String(out.exitCode)} out=${(out.stdout || out.stderr).slice(0, 80)}`);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
control.push(`control ${label}: 起不来 ${String(error).slice(0, 120)}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const [label, workdir] of [
|
|
103
|
+
['default', undefined],
|
|
104
|
+
['home', homedir()],
|
|
105
|
+
['cwd', process.cwd()],
|
|
106
|
+
]) {
|
|
107
|
+
const probe = await toolVersion(seam, 'echo workbench-probe', { workdir });
|
|
108
|
+
control.push(`control ${label}: exit=${String(probe.code)} out=${probe.raw.slice(0, 80) || '(空)'}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const hostBroken = control.some((line) => line.includes('exit=3221225794'));
|
|
112
|
+
const diagnostics = [
|
|
113
|
+
`deployment=${desktop ? 'desktop' : 'host'} · resources=${desktopResourcesDir() ?? '(无)'} · execPath=${process.execPath}`,
|
|
114
|
+
`bundled node=${bundledNode ?? '(找不到)'} · bundled pnpm=${bundledPnpm ?? '(找不到)'} · bins=${desktopBundledBins().join('|') || '(无)'}`,
|
|
115
|
+
`PATH 前两段=${(path ?? '').split(delimiter).slice(0, 2).join('|') || '(空)'}`,
|
|
116
|
+
`node: exit=${String(node.code)} sandbox=${node.sandbox} out=${node.raw.slice(0, 160) || '(空)'} cmd=${nodeCommand}`,
|
|
117
|
+
`pnpm: exit=${String(pnpm.code)} sandbox=${pnpm.sandbox} out=${pnpm.raw.slice(0, 160) || '(空)'} cmd=${pnpmLine}`,
|
|
118
|
+
`npm: exit=${String(npm.code)} sandbox=${npm.sandbox} out=${npm.raw.slice(0, 120) || '(空)'}`,
|
|
119
|
+
...control,
|
|
120
|
+
];
|
|
121
|
+
const base = parts.join(' · ');
|
|
122
|
+
const detail = hostBroken
|
|
123
|
+
? `宿主执行通道起不了子进程(0xC0000142 · DLL 初始化失败)——不是没装 node:${base}`
|
|
124
|
+
: base;
|
|
125
|
+
return { ok: !nodeMissing, detail, nodeMissing, npmMissing, pnpmProblem, diagnostics, hostBroken };
|
|
60
126
|
}
|
package/dist/toolchain.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { Seam } from '@dsh-workbench/shared/host';
|
|
2
|
+
import type { PnpmProcess } from './desktop-runtime.js';
|
|
3
|
+
export { desktopBundledBins, desktopNodeExecutable, desktopPnpmPath, desktopPnpmVersion, desktopResourcesDir, desktopRuntimeEnv, desktopRuntimeEnvPath } from './desktop-runtime.js';
|
|
4
|
+
export type { PnpmProcess } from './desktop-runtime.js';
|
|
1
5
|
export interface ToolchainProcess {
|
|
2
6
|
readonly versions: {
|
|
3
7
|
readonly electron?: string | undefined;
|
|
@@ -6,15 +10,6 @@ export interface ToolchainProcess {
|
|
|
6
10
|
readonly execPath: string;
|
|
7
11
|
readonly resourcesPath?: string | undefined;
|
|
8
12
|
}
|
|
9
|
-
export interface PnpmProcess {
|
|
10
|
-
readonly versions: {
|
|
11
|
-
readonly electron?: string | undefined;
|
|
12
|
-
readonly node?: string | undefined;
|
|
13
|
-
};
|
|
14
|
-
readonly resourcesPath?: string | undefined;
|
|
15
|
-
}
|
|
16
|
-
export declare function desktopPnpmPath(proc?: PnpmProcess, exists?: (path: string) => boolean): string | undefined;
|
|
17
|
-
export declare function desktopPnpmVersion(proc?: PnpmProcess, exists?: (path: string) => boolean): string | undefined;
|
|
18
13
|
export interface ToolchainOptions {
|
|
19
14
|
readonly root: string;
|
|
20
15
|
readonly proc?: ToolchainProcess | undefined;
|
|
@@ -61,10 +56,11 @@ export interface LocalPnpmProvision {
|
|
|
61
56
|
}
|
|
62
57
|
export declare function provisionLocalPnpm(options: {
|
|
63
58
|
readonly root: string;
|
|
64
|
-
readonly
|
|
59
|
+
readonly seam?: Seam | undefined;
|
|
60
|
+
readonly run?: ((command: string) => Promise<{
|
|
65
61
|
ok: boolean;
|
|
66
62
|
detail: string;
|
|
67
|
-
}
|
|
63
|
+
}>) | undefined;
|
|
68
64
|
readonly installed?: (() => boolean) | undefined;
|
|
69
65
|
readonly platform?: NodeJS.Platform | undefined;
|
|
70
66
|
readonly proc?: PnpmProcess | undefined;
|
|
@@ -72,14 +68,6 @@ export declare function provisionLocalPnpm(options: {
|
|
|
72
68
|
readonly pnpm?: string | undefined;
|
|
73
69
|
readonly npm?: string | undefined;
|
|
74
70
|
}): Promise<LocalPnpmProvision>;
|
|
75
|
-
export declare function provisionLocalPnpmSync(options: {
|
|
76
|
-
readonly root: string;
|
|
77
|
-
readonly run?: ((command: string) => void) | undefined;
|
|
78
|
-
readonly installed?: (() => boolean) | undefined;
|
|
79
|
-
readonly platform?: NodeJS.Platform | undefined;
|
|
80
|
-
readonly proc?: PnpmProcess | undefined;
|
|
81
|
-
readonly exists?: ((path: string) => boolean) | undefined;
|
|
82
|
-
}): LocalPnpmProvision;
|
|
83
71
|
export declare function desktopNodeBinary(proc?: ToolchainProcess, platform?: NodeJS.Platform, exists?: (path: string) => boolean): string | undefined;
|
|
84
72
|
export declare function desktopNodeShim(proc?: ToolchainProcess, platform?: NodeJS.Platform, exists?: (path: string) => boolean): string | undefined;
|
|
85
73
|
export declare function toolchainBinDir(root: string): string;
|
package/dist/toolchain.js
CHANGED
|
@@ -1,37 +1,11 @@
|
|
|
1
|
-
import { execaSync } from 'execa';
|
|
2
1
|
import lockfile from 'proper-lockfile';
|
|
3
|
-
import
|
|
4
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
|
|
5
3
|
import { join } from 'node:path';
|
|
6
|
-
import { quoteShellArg, quoteShellArgFor } from '@dsh-workbench/shared/host';
|
|
7
|
-
import { bootstrapEnv } from './bootstrap-run.js';
|
|
4
|
+
import { quoteShellArg, quoteShellArgFor, writeTextFile } from '@dsh-workbench/shared/host';
|
|
5
|
+
import { bootstrapEnv, runBootstrapCommand } from './bootstrap-run.js';
|
|
8
6
|
import { hostSurface } from './platform.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return undefined;
|
|
12
|
-
const resources = proc.resourcesPath;
|
|
13
|
-
if (resources === undefined || resources === '')
|
|
14
|
-
return undefined;
|
|
15
|
-
const path = join(resources, 'runtime', 'primary-runtime', 'dependencies', 'pnpm', 'bin', 'pnpm.cjs');
|
|
16
|
-
return exists(path) ? path : undefined;
|
|
17
|
-
}
|
|
18
|
-
export function desktopPnpmVersion(proc = process, exists = existsSync) {
|
|
19
|
-
if (hostSurface({ proc }).deployment !== 'desktop')
|
|
20
|
-
return undefined;
|
|
21
|
-
const resources = proc.resourcesPath;
|
|
22
|
-
if (resources === undefined || resources === '')
|
|
23
|
-
return undefined;
|
|
24
|
-
const manifest = join(resources, 'runtime', 'primary-runtime', 'dependencies', 'pnpm', 'package.json');
|
|
25
|
-
if (!exists(manifest))
|
|
26
|
-
return undefined;
|
|
27
|
-
try {
|
|
28
|
-
const parsed = JSON.parse(readFileSync(manifest, 'utf8'));
|
|
29
|
-
return typeof parsed.version === 'string' ? parsed.version : undefined;
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
7
|
+
import { desktopPnpmPath } from './desktop-runtime.js';
|
|
8
|
+
export { desktopBundledBins, desktopNodeExecutable, desktopPnpmPath, desktopPnpmVersion, desktopResourcesDir, desktopRuntimeEnv, desktopRuntimeEnvPath } from './desktop-runtime.js';
|
|
35
9
|
export const LOCAL_NPM_VERSION = [10, 9, 4].join('.');
|
|
36
10
|
export const LOCAL_PNPM_VERSION = [10, 32, 1].join('.');
|
|
37
11
|
export function localNpmRoot(root) {
|
|
@@ -92,6 +66,17 @@ export function localPnpmInstallCommand(root, proc = process, exists = existsSyn
|
|
|
92
66
|
return (`node ${quoteShellArgFor(pnpm, platform)} add --dir ${quoteShellArgFor(localPnpmRoot(root), platform)} ` +
|
|
93
67
|
`pnpm@${LOCAL_PNPM_VERSION} --store-dir ${quoteShellArgFor(join(root, 'pnpm-store'), platform)}`);
|
|
94
68
|
}
|
|
69
|
+
const LOCAL_PNPM_PROVISION_TIMEOUT_MS = 180_000;
|
|
70
|
+
function hostProvisionRun(root, seam) {
|
|
71
|
+
return async (command) => {
|
|
72
|
+
const result = await runBootstrapCommand(command, {
|
|
73
|
+
timeoutMs: LOCAL_PNPM_PROVISION_TIMEOUT_MS,
|
|
74
|
+
seam,
|
|
75
|
+
env: bootstrapEnv({ opencliRoot: join(root, 'opencli') }),
|
|
76
|
+
});
|
|
77
|
+
return { ok: result.ok, detail: result.detail };
|
|
78
|
+
};
|
|
79
|
+
}
|
|
95
80
|
export async function provisionLocalPnpm(options) {
|
|
96
81
|
const platform = options.platform ?? process.platform;
|
|
97
82
|
const bootstrap = options.pnpm?.trim();
|
|
@@ -112,8 +97,9 @@ export async function provisionLocalPnpm(options) {
|
|
|
112
97
|
return { ok: false, detail: `建不了 ${localPnpmRoot(options.root)}:${String(error)}` };
|
|
113
98
|
}
|
|
114
99
|
let detail = '';
|
|
100
|
+
const run = options.run ?? hostProvisionRun(options.root, options.seam);
|
|
115
101
|
for (const command of commands) {
|
|
116
|
-
const result = await
|
|
102
|
+
const result = await run(command);
|
|
117
103
|
if (result.ok) {
|
|
118
104
|
const installed = options.installed?.() ?? existsSync(localPnpmCommand(options.root, platform));
|
|
119
105
|
if (installed) {
|
|
@@ -131,41 +117,6 @@ export async function provisionLocalPnpm(options) {
|
|
|
131
117
|
}
|
|
132
118
|
return { ok: false, detail };
|
|
133
119
|
}
|
|
134
|
-
export function provisionLocalPnpmSync(options) {
|
|
135
|
-
const command = localPnpmInstallCommand(options.root, options.proc ?? process, options.exists ?? existsSync);
|
|
136
|
-
if (command === undefined)
|
|
137
|
-
return { ok: false, detail: '找不到 Desktop 自带 pnpm,装不了本地 pnpm 10' };
|
|
138
|
-
try {
|
|
139
|
-
mkdirSync(localPnpmRoot(options.root), { recursive: true });
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
return { ok: false, detail: `建不了 ${localPnpmRoot(options.root)}:${String(error)}` };
|
|
143
|
-
}
|
|
144
|
-
try {
|
|
145
|
-
const run = options.run ??
|
|
146
|
-
((line) => {
|
|
147
|
-
execaSync(line, {
|
|
148
|
-
stdio: 'ignore',
|
|
149
|
-
timeout: 180_000,
|
|
150
|
-
env: bootstrapEnv({ opencliRoot: join(options.root, 'opencli') }),
|
|
151
|
-
shell: true,
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
run(command);
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
return { ok: false, detail: String(error) };
|
|
158
|
-
}
|
|
159
|
-
const platform = options.platform ?? process.platform;
|
|
160
|
-
const installed = options.installed?.() ?? existsSync(localPnpmCommand(options.root, platform));
|
|
161
|
-
if (!installed)
|
|
162
|
-
return { ok: false, detail: 'pnpm 跑完但本地 pnpm 10 不在' };
|
|
163
|
-
return {
|
|
164
|
-
ok: true,
|
|
165
|
-
binDir: localPnpmBin(options.root),
|
|
166
|
-
detail: `pnpm@${LOCAL_PNPM_VERSION} 装到 ${localPnpmRoot(options.root)}`,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
120
|
function readText(file) {
|
|
170
121
|
try {
|
|
171
122
|
return readFileSync(file, 'utf8');
|
|
@@ -213,8 +164,7 @@ export function ensureToolchain(options) {
|
|
|
213
164
|
release = lockfile.lockSync(pathDir, { realpath: false });
|
|
214
165
|
if (readText(file) !== shim) {
|
|
215
166
|
rmSync(file, { force: true });
|
|
216
|
-
|
|
217
|
-
chmodSync(file, 0o755);
|
|
167
|
+
writeTextFile(file, shim, { mode: 0o755 });
|
|
218
168
|
files.push(file);
|
|
219
169
|
}
|
|
220
170
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/adapter-probe",
|
|
3
|
-
"version": "1.1.14
|
|
3
|
+
"version": "1.1.14",
|
|
4
4
|
"description": "Workbench adapter-probe adapter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -13,18 +13,15 @@
|
|
|
13
13
|
"dist"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"execa": "^10.2.0",
|
|
17
16
|
"proper-lockfile": "^4.1.2",
|
|
18
|
-
"
|
|
19
|
-
"@dsh-workbench/
|
|
20
|
-
"@dsh-workbench/
|
|
21
|
-
"@dsh-workbench/adapter-
|
|
22
|
-
"@dsh-workbench/adapter-supply": "1.1.14-beta.2"
|
|
17
|
+
"@dsh-workbench/adapter-profile": "1.1.14",
|
|
18
|
+
"@dsh-workbench/shared": "1.1.14",
|
|
19
|
+
"@dsh-workbench/adapter-runtime": "1.1.14",
|
|
20
|
+
"@dsh-workbench/adapter-supply": "1.1.14"
|
|
23
21
|
},
|
|
24
22
|
"devDependencies": {
|
|
25
23
|
"@types/node": "^24.19.0",
|
|
26
24
|
"@types/proper-lockfile": "^4.1.4",
|
|
27
|
-
"@types/write-file-atomic": "^4.0.3",
|
|
28
25
|
"vitest": "^5.0.2",
|
|
29
26
|
"dayjs": "^1.11.23",
|
|
30
27
|
"@vitest/coverage-v8": "^5.0.2"
|