@dsh-workbench/shared 1.1.7 → 1.1.9
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/api/blocker-table.d.ts +1 -0
- package/dist/api/blocker-table.js +1 -1
- package/dist/components/SelectField.css +0 -6
- package/dist/components/SelectField.d.ts +2 -3
- package/dist/components/SelectField.js +9 -30
- package/dist/components/SelectFieldNodes.d.ts +3 -1
- package/dist/components/SelectFieldNodes.js +2 -1
- package/dist/components/SelectFieldWheel.d.ts +9 -0
- package/dist/components/SelectFieldWheel.js +35 -0
- package/dist/config/constants.d.ts +4 -4
- package/dist/config/constants.js +4 -4
- package/dist/contract/capabilities.d.ts +29 -0
- package/dist/contract/capabilities.js +1 -0
- package/dist/contract/needs.d.ts +3 -3
- package/dist/contract/needs.js +1 -1
- package/dist/contract/plugin-source.d.ts +19 -0
- package/dist/contract/protocol/bundle-install.d.ts +3 -1
- package/dist/contract/protocol/bundle-install.js +3 -0
- package/dist/contract/protocol/market-index.d.ts +1 -0
- package/dist/contract/protocol/platform.d.ts +1 -1
- package/dist/contract/runner.d.ts +6 -0
- package/dist/contract/runner.js +1 -0
- package/dist/contract/unit.d.ts +4 -4
- package/dist/host/adapter-contract.d.ts +3 -0
- package/dist/host/adapter-contract.js +93 -0
- package/dist/host/adapter-set.js +6 -4
- package/dist/host/adapter-types.d.ts +1 -1
- package/dist/host/bundle-manager.d.ts +3 -0
- package/dist/host/bundle-manager.js +181 -0
- package/dist/host/cli.js +3 -1
- package/dist/host/config-sync.d.ts +48 -0
- package/dist/host/config-sync.js +342 -0
- package/dist/host/dsh-plugins.d.ts +5 -0
- package/dist/host/dsh-plugins.js +51 -0
- package/dist/host/extension.js +1 -1
- package/dist/host/flow/check.d.ts +9 -0
- package/dist/host/flow/check.js +179 -0
- package/dist/host/flow/expr.d.ts +30 -0
- package/dist/host/flow/expr.js +99 -0
- package/dist/host/flow/kit.d.ts +14 -0
- package/dist/host/flow/kit.js +13 -0
- package/dist/host/flow/run.d.ts +13 -0
- package/dist/host/flow/run.js +287 -0
- package/dist/host/flow/types.d.ts +188 -0
- package/dist/host/flow/types.js +1 -0
- package/dist/host/host-actions.d.ts +2 -0
- package/dist/host/host-actions.js +5 -0
- package/dist/host/host-kit.d.ts +19 -0
- package/dist/host/host-kit.js +14 -0
- package/dist/host/http.d.ts +2 -6
- package/dist/host/http.js +2 -2
- package/dist/host/installed-module.d.ts +23 -0
- package/dist/host/installed-module.js +264 -0
- package/dist/host/lib-install.d.ts +7 -9
- package/dist/host/lib-install.js +9 -12
- package/dist/host/lib-runners.d.ts +3 -5
- package/dist/host/lib-runners.js +2 -2
- package/dist/host/local-declaration.d.ts +7 -0
- package/dist/host/local-declaration.js +33 -0
- package/dist/host/market-index-claim.d.ts +0 -1
- package/dist/host/market-index-claim.js +0 -3
- package/dist/host/market-index-doc.d.ts +1 -45
- package/dist/host/market-index-parse.d.ts +9 -4
- package/dist/host/market-index-parse.js +17 -92
- package/dist/host/market-index.d.ts +5 -6
- package/dist/host/market-index.js +29 -87
- package/dist/host/module-root.d.ts +1 -0
- package/dist/host/module-root.js +5 -0
- package/dist/host/npm-registry.d.ts +10 -0
- package/dist/host/npm-registry.js +16 -0
- package/dist/host/opencli-runner.d.ts +2 -1
- package/dist/host/package-content.d.ts +7 -0
- package/dist/host/package-content.js +69 -0
- package/dist/host/package-kind.d.ts +13 -0
- package/dist/host/package-kind.js +51 -0
- package/dist/host/package-route.d.ts +31 -0
- package/dist/host/package-route.js +57 -0
- package/dist/host/paths.d.ts +11 -19
- package/dist/host/paths.js +16 -43
- package/dist/host/platform.js +1 -1
- package/dist/host/plugin-ledger.d.ts +8 -8
- package/dist/host/plugin-ledger.js +23 -16
- package/dist/host/plugin.d.ts +1 -2
- package/dist/host/plugin.js +4 -5
- package/dist/host/port-types.d.ts +42 -9
- package/dist/host/preflight.d.ts +3 -2
- package/dist/host/profile-create.d.ts +18 -0
- package/dist/host/profile-create.js +118 -0
- package/dist/host/profile-registries.d.ts +10 -0
- package/dist/host/profile-registries.js +150 -0
- package/dist/host/registry-declaration.d.ts +21 -0
- package/dist/host/registry-declaration.js +33 -0
- package/dist/host/release-probe.d.ts +34 -0
- package/dist/host/release-probe.js +88 -0
- package/dist/host/runner.d.ts +26 -0
- package/dist/host/runner.js +50 -0
- package/dist/host/shell.d.ts +0 -2
- package/dist/host/shell.js +0 -7
- package/dist/host/spec.js +1 -1
- package/dist/host/supply-index.d.ts +1 -0
- package/dist/host/supply-index.js +8 -7
- package/dist/host/supply-port.js +13 -3
- package/dist/host/unit-face.d.ts +2 -1
- package/dist/host/version.js +11 -6
- package/dist/host.d.ts +24 -6
- package/dist/host.js +23 -6
- package/dist/i18n/en.js +19 -20
- package/dist/i18n/index.d.ts +20 -21
- package/dist/i18n/runtime-terms.d.ts +15 -0
- package/dist/i18n/runtime-terms.js +22 -0
- package/dist/i18n/zh.d.ts +19 -20
- package/dist/i18n/zh.js +19 -20
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/testing/fake-adapter-set.d.ts +5 -0
- package/dist/testing/fake-adapter-set.js +150 -0
- package/dist/testing/needs.js +1 -1
- package/dist/testing.d.ts +1 -0
- package/dist/testing.js +1 -0
- package/package.json +1 -1
- package/src/api/__tests__/blocker-table.test.ts +25 -0
- package/src/api/{workbench-client.test.ts → __tests__/workbench-client.test.ts} +2 -2
- package/src/api/blocker-table.ts +6 -2
- package/src/components/SelectField.css +0 -6
- package/src/components/SelectField.tsx +7 -36
- package/src/components/SelectFieldNodes.tsx +4 -1
- package/src/components/{Card.test.tsx → __tests__/Card.test.tsx} +2 -2
- package/src/components/{CardAnchor.test.tsx → __tests__/CardAnchor.test.tsx} +3 -3
- package/src/components/{CardHead.test.tsx → __tests__/CardHead.test.tsx} +1 -1
- package/src/components/{ChoiceGroup.test.tsx → __tests__/ChoiceGroup.test.tsx} +2 -2
- package/src/components/{ConfirmBar.test.tsx → __tests__/ConfirmBar.test.tsx} +5 -5
- package/src/components/{Field.test.tsx → __tests__/Field.test.tsx} +1 -1
- package/src/components/{Form.test.tsx → __tests__/Form.test.tsx} +5 -5
- package/src/components/{FormActions.test.tsx → __tests__/FormActions.test.tsx} +3 -3
- package/src/components/{FormRows.test.tsx → __tests__/FormRows.test.tsx} +2 -2
- package/src/components/{FormTypes.test.ts → __tests__/FormTypes.test.ts} +1 -1
- package/src/components/{FormWiring.test.tsx → __tests__/FormWiring.test.tsx} +4 -4
- package/src/components/{Link.test.tsx → __tests__/Link.test.tsx} +1 -1
- package/src/components/{Rows.test.tsx → __tests__/Rows.test.tsx} +2 -2
- package/src/components/{SelectField.test.tsx → __tests__/SelectField.test.tsx} +7 -37
- package/src/components/{Spinner.test.tsx → __tests__/Spinner.test.tsx} +4 -4
- package/src/config/{constants.test.ts → __tests__/constants.test.ts} +1 -1
- package/src/config/{storage.test.ts → __tests__/storage.test.ts} +1 -1
- package/src/config/constants.ts +4 -4
- package/src/contract/capabilities.ts +30 -0
- package/src/contract/needs.ts +4 -4
- package/src/contract/plugin-source.ts +24 -0
- package/src/contract/protocol/bundle-install.ts +7 -1
- package/src/contract/protocol/market-index.ts +1 -0
- package/src/contract/protocol/platform.ts +1 -1
- package/src/contract/runner.ts +6 -0
- package/src/contract/unit.ts +4 -4
- package/src/host/{extension.test.ts → __tests__/extension.test.ts} +4 -4
- package/src/host/{install-failure.test.ts → __tests__/install-failure.test.ts} +1 -1
- package/src/host/{installed-sources.test.ts → __tests__/installed-sources.test.ts} +1 -1
- package/src/host/__tests__/lib-runners.test.ts +11 -2
- package/src/host/__tests__/market-index-assemble.test.ts +26 -0
- package/src/host/__tests__/market-index.test.ts +41 -51
- package/src/host/__tests__/plugin-ledger.test.ts +19 -6
- package/src/host/{recipe.test.ts → __tests__/recipe.test.ts} +3 -3
- package/src/host/__tests__/runtime-layout.test.ts +14 -0
- package/src/host/__tests__/supply-index.test.ts +2 -2
- package/src/host/__tests__/supply-port.test.ts +32 -0
- package/src/host/adapter-contract.ts +93 -0
- package/src/host/adapter-set.ts +6 -4
- package/src/host/adapter-types.ts +1 -1
- package/src/host/bundle-manager.ts +195 -0
- package/src/host/cli.ts +3 -1
- package/src/host/config-sync.ts +386 -0
- package/src/host/dsh-plugins.ts +60 -0
- package/src/host/extension.ts +1 -1
- package/src/host/flow/__tests__/advanced.test.ts +302 -0
- package/src/host/flow/__tests__/check.test.ts +169 -0
- package/src/host/flow/__tests__/run.test.ts +301 -0
- package/src/host/flow/check.ts +216 -0
- package/src/host/flow/expr.ts +94 -0
- package/src/host/flow/kit.ts +30 -0
- package/src/host/flow/run.ts +325 -0
- package/src/host/flow/types.ts +199 -0
- package/src/host/host-actions.ts +7 -0
- package/src/host/host-kit.ts +26 -0
- package/src/host/http.ts +6 -8
- package/src/host/installed-module.ts +272 -0
- package/src/host/lib-install.ts +14 -12
- package/src/host/lib-runners.ts +6 -8
- package/src/host/local-declaration.ts +37 -0
- package/src/host/market-index-claim.ts +0 -4
- package/src/host/market-index-doc.ts +1 -53
- package/src/host/market-index-parse.ts +21 -85
- package/src/host/market-index.ts +33 -127
- package/src/host/module-root.ts +6 -0
- package/src/host/npm-registry.ts +21 -0
- package/src/host/package-content.ts +76 -0
- package/src/host/package-kind.ts +63 -0
- package/src/host/package-route.ts +93 -0
- package/src/host/paths.ts +27 -52
- package/src/host/platform.ts +1 -1
- package/src/host/plugin-ledger.ts +25 -18
- package/src/host/plugin.ts +4 -5
- package/src/host/port-types.ts +43 -9
- package/src/host/preflight.ts +3 -2
- package/src/host/profile-create.ts +133 -0
- package/src/host/profile-registries.ts +145 -0
- package/src/host/registry-declaration.ts +70 -0
- package/src/host/release-probe.ts +202 -0
- package/src/host/shell.ts +0 -9
- package/src/host/spec.ts +1 -1
- package/src/host/supply-index.ts +9 -7
- package/src/host/supply-port.ts +13 -3
- package/src/host/unit-face.ts +2 -1
- package/src/host/version.ts +12 -7
- package/src/host.ts +34 -6
- package/src/i18n/{index.test.ts → __tests__/index.test.ts} +3 -3
- package/src/i18n/{merge.test.ts → __tests__/merge.test.ts} +1 -1
- package/src/i18n/{zh.test.ts → __tests__/zh.test.ts} +2 -2
- package/src/i18n/en.ts +19 -21
- package/src/i18n/runtime-terms.ts +26 -0
- package/src/i18n/zh.ts +19 -21
- package/src/index.ts +4 -0
- package/src/lib/{board-fact.test.ts → __tests__/board-fact.test.ts} +1 -1
- package/src/lib/{busy.test.ts → __tests__/busy.test.ts} +1 -1
- package/src/lib/{form-problem.test.ts → __tests__/form-problem.test.ts} +1 -1
- package/src/lib/{git-address.test.ts → __tests__/git-address.test.ts} +1 -1
- package/src/lib/{react.test.ts → __tests__/react.test.ts} +1 -1
- package/src/lib/{text.test.ts → __tests__/text.test.ts} +1 -1
- package/src/lib/{ui.test.ts → __tests__/ui.test.ts} +1 -1
- package/src/testing/__tests__/fake-adapter-set.test.ts +28 -0
- package/src/testing/fake-adapter-set.ts +173 -0
- package/src/testing/needs.ts +1 -1
- package/src/testing.ts +1 -0
- package/src/host/__tests__/command-name.test.ts +0 -16
- package/src/host/__tests__/opencli-runner.test.ts +0 -120
- package/src/host/channel-plugin.ts +0 -55
- package/src/host/command-name.ts +0 -15
- package/src/host/opencli-runner.ts +0 -76
- package/src/host/paths.test.ts +0 -26
- package/src/host/plugin-source.ts +0 -137
- package/src/host/runtime-links.test.ts +0 -31
- package/src/host/runtime-links.ts +0 -23
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DshShell } from '../api/dsh.js';
|
|
2
|
+
export type PackageRouteKind = 'runtime-plugin' | 'dsh-bundle' | 'neither';
|
|
3
|
+
export interface PackageRoute {
|
|
4
|
+
readonly kind: PackageRouteKind;
|
|
5
|
+
readonly pkg?: string;
|
|
6
|
+
readonly pluginName?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PackageRouter {
|
|
9
|
+
packageRouteOf(options: RouteOptions): Promise<PackageRoute | undefined>;
|
|
10
|
+
reset(): void;
|
|
11
|
+
}
|
|
12
|
+
interface RouteOptions {
|
|
13
|
+
readonly spec: string;
|
|
14
|
+
readonly shell?: DshShell | undefined;
|
|
15
|
+
readonly registry?: string | undefined;
|
|
16
|
+
readonly force?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface PackageRouterOptions {
|
|
19
|
+
readonly manifestFile: string;
|
|
20
|
+
readonly cacheDir?: string | undefined;
|
|
21
|
+
readonly dshLookup?: ((options: {
|
|
22
|
+
shell: DshShell;
|
|
23
|
+
name: string;
|
|
24
|
+
registry: string;
|
|
25
|
+
}) => Promise<{
|
|
26
|
+
readable: boolean;
|
|
27
|
+
raw: unknown;
|
|
28
|
+
}>) | undefined;
|
|
29
|
+
}
|
|
30
|
+
export declare function createPackageRouter(options: PackageRouterOptions): PackageRouter;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { VERSION_CHECK_TTL_MS } from '../config/constants.js';
|
|
2
|
+
import { dshMarkersOf, splitNpmSpec, verdictOf } from './package-kind.js';
|
|
3
|
+
import { withPackageDir } from './package-content.js';
|
|
4
|
+
import { localDirOf } from './local-declaration.js';
|
|
5
|
+
function routeOfVerdict(verdict, fallback) {
|
|
6
|
+
const pkg = verdict.pkg ?? fallback;
|
|
7
|
+
if (verdict.kind === 'neither')
|
|
8
|
+
return { kind: 'neither', ...(pkg === undefined ? {} : { pkg }) };
|
|
9
|
+
if (verdict.kind === 'dsh-bundle' || verdict.kind === 'both')
|
|
10
|
+
return { kind: 'dsh-bundle' };
|
|
11
|
+
return {
|
|
12
|
+
kind: 'runtime-plugin',
|
|
13
|
+
...(pkg === undefined ? {} : { pkg }),
|
|
14
|
+
...(verdict.pluginName === undefined ? {} : { pluginName: verdict.pluginName }),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function createPackageRouter(options) {
|
|
18
|
+
const cache = new Map();
|
|
19
|
+
return {
|
|
20
|
+
packageRouteOf: (routeOptions) => routeOf(cache, options, routeOptions),
|
|
21
|
+
reset: () => {
|
|
22
|
+
cache.clear();
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function routeOf(cache, options, routeOptions) {
|
|
27
|
+
const local = localDirOf(routeOptions.spec);
|
|
28
|
+
if (local !== undefined) {
|
|
29
|
+
const verdict = verdictOf(local, options.manifestFile);
|
|
30
|
+
return verdict === undefined ? undefined : routeOfVerdict(verdict, splitNpmSpec(routeOptions.spec)?.name);
|
|
31
|
+
}
|
|
32
|
+
const ref = splitNpmSpec(routeOptions.spec);
|
|
33
|
+
if (ref === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
const shell = routeOptions.shell;
|
|
36
|
+
const registry = routeOptions.registry;
|
|
37
|
+
if (shell === undefined || registry === undefined)
|
|
38
|
+
return undefined;
|
|
39
|
+
const key = `${registry}|${routeOptions.spec}`;
|
|
40
|
+
const hit = cache.get(key);
|
|
41
|
+
if (routeOptions.force !== true && hit !== undefined && Date.now() - hit.at < VERSION_CHECK_TTL_MS) {
|
|
42
|
+
return hit.route ?? undefined;
|
|
43
|
+
}
|
|
44
|
+
const found = options.dshLookup === undefined
|
|
45
|
+
? { readable: false, raw: undefined }
|
|
46
|
+
: await options.dshLookup({ shell, name: routeOptions.spec, registry });
|
|
47
|
+
let route;
|
|
48
|
+
if (found.readable && dshMarkersOf(found.raw)) {
|
|
49
|
+
route = { kind: 'dsh-bundle' };
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const verdict = await withPackageDir({ shell, spec: routeOptions.spec, registry, ...(options.cacheDir === undefined ? {} : { cacheDir: options.cacheDir }) }, (dir) => verdictOf(dir, options.manifestFile));
|
|
53
|
+
route = verdict === undefined ? undefined : routeOfVerdict(verdict, ref.name);
|
|
54
|
+
}
|
|
55
|
+
cache.set(key, { at: Date.now(), route: route ?? null });
|
|
56
|
+
return route;
|
|
57
|
+
}
|
package/dist/host/paths.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export declare function npmCacheDir(): string;
|
|
13
|
-
export declare function libsBinDir(): string;
|
|
14
|
-
/**
|
|
15
|
-
* 把隔离运行时的共用依赖 bin 目录放到 PATH 最前面(可执行文件都从这儿找)。
|
|
16
|
-
* @param env 改哪份环境(默认当前进程)。
|
|
17
|
-
* @returns 真的插进去了就 `true`;已经在里面就 `false`。
|
|
18
|
-
*/
|
|
19
|
-
export declare function ensureLibsBinOnPath(env?: NodeJS.ProcessEnv): boolean;
|
|
1
|
+
export interface RuntimeLayout {
|
|
2
|
+
readonly root: string;
|
|
3
|
+
readonly home: string;
|
|
4
|
+
readonly vendorPrefix: string;
|
|
5
|
+
readonly vendorPluginsDir: string;
|
|
6
|
+
readonly libsPrefix: string;
|
|
7
|
+
readonly libsBinDir: string;
|
|
8
|
+
readonly npmCacheDir: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function runtimeRootOf(id: string): string;
|
|
11
|
+
export declare function runtimeLayoutOf(id: string): RuntimeLayout;
|
package/dist/host/paths.js
CHANGED
|
@@ -1,45 +1,18 @@
|
|
|
1
|
-
import { delimiter } from 'node:path';
|
|
2
1
|
import { workbenchRoot } from './data-root.js';
|
|
3
|
-
export function
|
|
4
|
-
return `${workbenchRoot()}
|
|
5
|
-
}
|
|
6
|
-
export function
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function toolchainOpencliDir() {
|
|
20
|
-
return `${isolatedRoot()}/toolchain/node_modules/${OPENCLI_NPM_PACKAGE}`;
|
|
21
|
-
}
|
|
22
|
-
export function vendorPeerLink() {
|
|
23
|
-
const base = `${vendorPrefix()}/node_modules`;
|
|
24
|
-
const [scope] = OPENCLI_NPM_PACKAGE.split('/');
|
|
25
|
-
return { dir: `${base}/${OPENCLI_NPM_PACKAGE}`, parent: `${base}/${scope}` };
|
|
26
|
-
}
|
|
27
|
-
export function npmCacheDir() {
|
|
28
|
-
return `${isolatedRoot()}/npm-cache`;
|
|
29
|
-
}
|
|
30
|
-
export function libsBinDir() {
|
|
31
|
-
return `${libsPrefix()}/node_modules/.bin`;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 把隔离运行时的共用依赖 bin 目录放到 PATH 最前面(可执行文件都从这儿找)。
|
|
35
|
-
* @param env 改哪份环境(默认当前进程)。
|
|
36
|
-
* @returns 真的插进去了就 `true`;已经在里面就 `false`。
|
|
37
|
-
*/
|
|
38
|
-
export function ensureLibsBinOnPath(env = process.env) {
|
|
39
|
-
const dir = libsBinDir();
|
|
40
|
-
const parts = (env.PATH ?? '').split(delimiter).filter((one) => one !== '');
|
|
41
|
-
if (parts.includes(dir))
|
|
42
|
-
return false;
|
|
43
|
-
env.PATH = [dir, ...parts].join(delimiter);
|
|
44
|
-
return true;
|
|
2
|
+
export function runtimeRootOf(id) {
|
|
3
|
+
return `${workbenchRoot()}/${id}`;
|
|
4
|
+
}
|
|
5
|
+
export function runtimeLayoutOf(id) {
|
|
6
|
+
const root = runtimeRootOf(id);
|
|
7
|
+
const vendorPrefix = `${root}/plugins-npm`;
|
|
8
|
+
const libsPrefix = `${root}/libs`;
|
|
9
|
+
return {
|
|
10
|
+
root,
|
|
11
|
+
home: `${root}/home`,
|
|
12
|
+
vendorPrefix,
|
|
13
|
+
vendorPluginsDir: `${vendorPrefix}/node_modules`,
|
|
14
|
+
libsPrefix,
|
|
15
|
+
libsBinDir: `${libsPrefix}/node_modules/.bin`,
|
|
16
|
+
npmCacheDir: `${root}/npm-cache`,
|
|
17
|
+
};
|
|
45
18
|
}
|
package/dist/host/platform.js
CHANGED
|
@@ -33,7 +33,7 @@ export function hostSurface(input = {}) {
|
|
|
33
33
|
restartHint: deployment === 'desktop' ? '退出并重开 Desktop' : '重启一次 dsh',
|
|
34
34
|
toolchain: {
|
|
35
35
|
node: { source: deployment === 'desktop' ? 'desktop-shim' : 'path' },
|
|
36
|
-
npm: { neededFor: '
|
|
36
|
+
npm: { neededFor: 'runtime-install' },
|
|
37
37
|
pnpm: { neededFor: 'workshop', expectedMajor: 10 },
|
|
38
38
|
},
|
|
39
39
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ModuleStore } from './workspace-store.js';
|
|
2
2
|
export declare const PLUGIN_LEDGER_FILE = "plugins.json";
|
|
3
3
|
export interface PluginLedgerEntry {
|
|
4
|
-
readonly
|
|
4
|
+
readonly home: string;
|
|
5
5
|
readonly package: string;
|
|
6
6
|
readonly name?: string;
|
|
7
7
|
readonly registry?: string;
|
|
@@ -10,23 +10,23 @@ export interface PluginLedgerEntry {
|
|
|
10
10
|
readonly releasedAt?: string;
|
|
11
11
|
}
|
|
12
12
|
export declare function ledgerKeyOf(entry: {
|
|
13
|
-
readonly
|
|
13
|
+
readonly home: string;
|
|
14
14
|
readonly package: string;
|
|
15
15
|
}): string;
|
|
16
16
|
export declare function parsePluginLedger(raw: unknown): PluginLedgerEntry[];
|
|
17
17
|
export declare function readPluginLedger(store: ModuleStore): PluginLedgerEntry[];
|
|
18
18
|
export declare function writePluginLedger(store: ModuleStore, entries: readonly PluginLedgerEntry[]): void;
|
|
19
|
-
export declare function pluginEntriesOfHome(entries: readonly PluginLedgerEntry[],
|
|
19
|
+
export declare function pluginEntriesOfHome(entries: readonly PluginLedgerEntry[], home: string): PluginLedgerEntry[];
|
|
20
20
|
export declare function isHeldEntry(entry: PluginLedgerEntry): boolean;
|
|
21
|
-
export declare function heldEntriesOfHome(entries: readonly PluginLedgerEntry[],
|
|
22
|
-
export declare function heldEntryOfPlugin(entries: readonly PluginLedgerEntry[],
|
|
23
|
-
export declare function withReleasedEntry(entries: readonly PluginLedgerEntry[],
|
|
21
|
+
export declare function heldEntriesOfHome(entries: readonly PluginLedgerEntry[], home: string): PluginLedgerEntry[];
|
|
22
|
+
export declare function heldEntryOfPlugin(entries: readonly PluginLedgerEntry[], home: string, plugin: string): PluginLedgerEntry | undefined;
|
|
23
|
+
export declare function withReleasedEntry(entries: readonly PluginLedgerEntry[], home: string, pkg: string, releasedAt: string): PluginLedgerEntry[];
|
|
24
24
|
export type PluginRetention = 'remove' | 'keep-held' | 'keep-claimed' | 'keep-unsure';
|
|
25
25
|
export declare function pluginRetentionOf(options: {
|
|
26
26
|
readonly held: boolean;
|
|
27
27
|
readonly claimedBy: readonly string[];
|
|
28
28
|
readonly trustworthy: boolean;
|
|
29
29
|
}): PluginRetention;
|
|
30
|
-
export declare function pluginEntryOf(entries: readonly PluginLedgerEntry[],
|
|
30
|
+
export declare function pluginEntryOf(entries: readonly PluginLedgerEntry[], home: string, pkg: string): PluginLedgerEntry | undefined;
|
|
31
31
|
export declare function withPluginEntry(entries: readonly PluginLedgerEntry[], entry: PluginLedgerEntry): PluginLedgerEntry[];
|
|
32
|
-
export declare function withoutPluginEntry(entries: readonly PluginLedgerEntry[],
|
|
32
|
+
export declare function withoutPluginEntry(entries: readonly PluginLedgerEntry[], home: string, pkg: string): PluginLedgerEntry[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const PLUGIN_LEDGER_FILE = 'plugins.json';
|
|
2
2
|
export function ledgerKeyOf(entry) {
|
|
3
|
-
return `${entry.
|
|
3
|
+
return `${entry.home}\u0000${entry.package}`;
|
|
4
4
|
}
|
|
5
5
|
function textOf(value) {
|
|
6
6
|
if (typeof value !== 'string')
|
|
@@ -8,20 +8,27 @@ function textOf(value) {
|
|
|
8
8
|
const trimmed = value.trim();
|
|
9
9
|
return trimmed === '' ? undefined : trimmed;
|
|
10
10
|
}
|
|
11
|
+
function legacyHomeOf(box) {
|
|
12
|
+
for (const [key, value] of Object.entries(box)) {
|
|
13
|
+
if (key !== 'home' && key.toLowerCase().endsWith('home'))
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
11
18
|
function entryOf(value) {
|
|
12
19
|
if (typeof value !== 'object' || value === null)
|
|
13
20
|
return undefined;
|
|
14
21
|
const box = value;
|
|
15
|
-
const
|
|
22
|
+
const home = textOf(box['home']) ?? textOf(legacyHomeOf(box));
|
|
16
23
|
const pkg = textOf(box['package']);
|
|
17
24
|
const installedAt = textOf(box['installedAt']);
|
|
18
|
-
if (
|
|
25
|
+
if (home === undefined || pkg === undefined || installedAt === undefined)
|
|
19
26
|
return undefined;
|
|
20
27
|
const name = textOf(box['name']);
|
|
21
28
|
const registry = textOf(box['registry']);
|
|
22
29
|
const releasedAt = textOf(box['releasedAt']);
|
|
23
30
|
return {
|
|
24
|
-
|
|
31
|
+
home,
|
|
25
32
|
package: pkg,
|
|
26
33
|
installedAt,
|
|
27
34
|
...(name === undefined ? {} : { name }),
|
|
@@ -57,23 +64,23 @@ export function writePluginLedger(store, entries) {
|
|
|
57
64
|
}
|
|
58
65
|
store.write(PLUGIN_LEDGER_FILE, { entries });
|
|
59
66
|
}
|
|
60
|
-
export function pluginEntriesOfHome(entries,
|
|
61
|
-
return entries.filter((entry) => entry.
|
|
67
|
+
export function pluginEntriesOfHome(entries, home) {
|
|
68
|
+
return entries.filter((entry) => entry.home === home);
|
|
62
69
|
}
|
|
63
70
|
export function isHeldEntry(entry) {
|
|
64
71
|
return entry.releasedAt === undefined;
|
|
65
72
|
}
|
|
66
|
-
export function heldEntriesOfHome(entries,
|
|
67
|
-
return pluginEntriesOfHome(entries,
|
|
73
|
+
export function heldEntriesOfHome(entries, home) {
|
|
74
|
+
return pluginEntriesOfHome(entries, home).filter(isHeldEntry);
|
|
68
75
|
}
|
|
69
|
-
export function heldEntryOfPlugin(entries,
|
|
76
|
+
export function heldEntryOfPlugin(entries, home, plugin) {
|
|
70
77
|
const key = plugin.trim();
|
|
71
78
|
if (key === '')
|
|
72
79
|
return undefined;
|
|
73
|
-
return heldEntriesOfHome(entries,
|
|
80
|
+
return heldEntriesOfHome(entries, home).find((entry) => entry.name === key || entry.package === key);
|
|
74
81
|
}
|
|
75
|
-
export function withReleasedEntry(entries,
|
|
76
|
-
const entry = pluginEntryOf(entries,
|
|
82
|
+
export function withReleasedEntry(entries, home, pkg, releasedAt) {
|
|
83
|
+
const entry = pluginEntryOf(entries, home, pkg);
|
|
77
84
|
if (entry === undefined || entry.releasedAt !== undefined)
|
|
78
85
|
return [...entries];
|
|
79
86
|
return withPluginEntry(entries, { ...entry, releasedAt });
|
|
@@ -85,15 +92,15 @@ export function pluginRetentionOf(options) {
|
|
|
85
92
|
return 'keep-unsure';
|
|
86
93
|
return options.claimedBy.length > 0 ? 'keep-claimed' : 'remove';
|
|
87
94
|
}
|
|
88
|
-
export function pluginEntryOf(entries,
|
|
89
|
-
const key = ledgerKeyOf({
|
|
95
|
+
export function pluginEntryOf(entries, home, pkg) {
|
|
96
|
+
const key = ledgerKeyOf({ home, package: pkg });
|
|
90
97
|
return entries.find((entry) => ledgerKeyOf(entry) === key);
|
|
91
98
|
}
|
|
92
99
|
export function withPluginEntry(entries, entry) {
|
|
93
100
|
const key = ledgerKeyOf(entry);
|
|
94
101
|
return [...entries.filter((item) => ledgerKeyOf(item) !== key), entry];
|
|
95
102
|
}
|
|
96
|
-
export function withoutPluginEntry(entries,
|
|
97
|
-
const key = ledgerKeyOf({
|
|
103
|
+
export function withoutPluginEntry(entries, home, pkg) {
|
|
104
|
+
const key = ledgerKeyOf({ home, package: pkg });
|
|
98
105
|
return entries.filter((entry) => ledgerKeyOf(entry) !== key);
|
|
99
106
|
}
|
package/dist/host/plugin.d.ts
CHANGED
package/dist/host/plugin.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { readFileSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
export const OPENCLI_MANIFEST_FILE = 'opencli-plugin.json';
|
|
4
3
|
function asRecord(value) {
|
|
5
4
|
return typeof value === 'object' && value !== null ? value : undefined;
|
|
6
5
|
}
|
|
@@ -11,9 +10,9 @@ function isCommandFile(name) {
|
|
|
11
10
|
return false;
|
|
12
11
|
return name.endsWith('.ts') || name.endsWith('.js');
|
|
13
12
|
}
|
|
14
|
-
function pluginManifestOf(dir) {
|
|
13
|
+
function pluginManifestOf(dir, manifestFile) {
|
|
15
14
|
try {
|
|
16
|
-
const parsed = JSON.parse(readFileSync(join(dir,
|
|
15
|
+
const parsed = JSON.parse(readFileSync(join(dir, manifestFile), 'utf8'));
|
|
17
16
|
if (Array.isArray(parsed))
|
|
18
17
|
return undefined;
|
|
19
18
|
return asRecord(parsed);
|
|
@@ -30,8 +29,8 @@ function hasCommandFile(dir) {
|
|
|
30
29
|
return false;
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
|
-
export function pluginAt(dir) {
|
|
34
|
-
const manifest = pluginManifestOf(dir);
|
|
32
|
+
export function pluginAt(dir, manifestFile) {
|
|
33
|
+
const manifest = pluginManifestOf(dir, manifestFile);
|
|
35
34
|
if (manifest === undefined || !hasCommandFile(dir))
|
|
36
35
|
return undefined;
|
|
37
36
|
const name = manifest.name;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { DshHostContext, DshShell } from '../api/dsh.js';
|
|
2
|
+
import type { RuntimeCapabilities, RuntimeProfile } from '../contract/capabilities.js';
|
|
3
|
+
import type { PluginPackageKind } from '../contract/protocol/bundle-install.js';
|
|
2
4
|
import type { LibNeed, SupplySource } from '../contract/needs.js';
|
|
3
5
|
import type { NeedProbeInput, UnitCapability } from '../contract/unit-capability.js';
|
|
6
|
+
import type { DataReader } from '../contract/data.js';
|
|
7
|
+
import type { LibRunner } from '../contract/runner.js';
|
|
4
8
|
import type { WorkbenchSelfUpdate } from '../contract/protocol/bundle-install.js';
|
|
5
|
-
import type { BundleManager, InstalledModule,
|
|
9
|
+
import type { BundleManager, InstalledModule, ProfileModule, ProfilePackage, RegistryNotebook, RuntimeStatus, SelfUpdateRequest, SelfUpdateStart } from './adapter-types.js';
|
|
6
10
|
import type { PostResource, RouteHandler, RouteTable } from './http.js';
|
|
7
|
-
import type { PluginSourceOptions, ResolvedPluginSource } from '
|
|
11
|
+
import type { PluginSourceOptions, ResolvedPluginSource } from '../contract/plugin-source.js';
|
|
8
12
|
export interface LoggerLike {
|
|
9
13
|
info?(message: string): void;
|
|
10
14
|
warn?(message: string): void;
|
|
@@ -16,7 +20,7 @@ export interface ProfilePort {
|
|
|
16
20
|
}
|
|
17
21
|
export type SupplyPluginSource = ResolvedPluginSource;
|
|
18
22
|
export interface SupplyPackageRoute {
|
|
19
|
-
readonly kind:
|
|
23
|
+
readonly kind: PluginPackageKind | 'dsh-bundle' | 'neither';
|
|
20
24
|
readonly pkg?: string;
|
|
21
25
|
readonly pluginName?: string;
|
|
22
26
|
}
|
|
@@ -63,6 +67,9 @@ export interface EnvSupplyPort {
|
|
|
63
67
|
}>;
|
|
64
68
|
readonly version?: string | undefined;
|
|
65
69
|
}): string;
|
|
70
|
+
libUninstallCommand(options: {
|
|
71
|
+
readonly need: LibNeed;
|
|
72
|
+
}): string;
|
|
66
73
|
pluginInstallPlan(options: SupplyPluginInstallOptions): ResolvedPluginSource;
|
|
67
74
|
latestVersion(options: SupplyLatestOptions): Promise<string | undefined>;
|
|
68
75
|
missingReleaseParts(options: SupplyMissingPartsOptions): Promise<readonly string[]>;
|
|
@@ -70,10 +77,14 @@ export interface EnvSupplyPort {
|
|
|
70
77
|
splitNpmSpec(spec: string): SupplyNpmRef | undefined;
|
|
71
78
|
}
|
|
72
79
|
export interface ModulePort {
|
|
80
|
+
isolatedRoot(): string;
|
|
73
81
|
isolatedHome(): string;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
pluginPackagePrefix?(): string;
|
|
83
|
+
pluginManifestFile?(): string;
|
|
84
|
+
cliCatalogPath?(): string;
|
|
85
|
+
vendorPluginsDir?(): string;
|
|
86
|
+
runtimeInstallCommand?(): string;
|
|
87
|
+
afterLibInstall(): void;
|
|
77
88
|
profileDirOf(ctx: DshHostContext): string | null;
|
|
78
89
|
profileModules(dir: string | null): readonly ProfileModule[];
|
|
79
90
|
readInstalledModule(dir: string | null, pkg: string): InstalledModule;
|
|
@@ -116,8 +127,10 @@ export interface ProbePreflightInput {
|
|
|
116
127
|
readonly routes: RouteTable;
|
|
117
128
|
readonly ctx: DshHostContext;
|
|
118
129
|
readonly shell: DshShell;
|
|
119
|
-
readonly
|
|
120
|
-
readonly
|
|
130
|
+
readonly runtimeCommands: Readonly<Record<string, string>>;
|
|
131
|
+
readonly runtimeCapabilities: RuntimeCapabilities;
|
|
132
|
+
readonly runtimeCheck?: (() => Promise<RuntimeCheck>) | undefined;
|
|
133
|
+
readonly runtimeLabel?: string | undefined;
|
|
121
134
|
readonly warmReads: () => readonly (readonly string[])[];
|
|
122
135
|
}
|
|
123
136
|
export interface ProbePort {
|
|
@@ -129,9 +142,29 @@ export interface RuntimeSeedOptions {
|
|
|
129
142
|
readonly corePackageUrl: string;
|
|
130
143
|
readonly log: (message: string) => void;
|
|
131
144
|
}
|
|
145
|
+
export type { RuntimeCapabilities, RuntimeProfile, RuntimeTerms } from '../contract/capabilities.js';
|
|
146
|
+
export interface RuntimeCheck {
|
|
147
|
+
readonly ok: boolean;
|
|
148
|
+
readonly detail: string;
|
|
149
|
+
}
|
|
150
|
+
export interface RuntimeCommandSurface {
|
|
151
|
+
readonly name: string;
|
|
152
|
+
readonly pluginPrefix: string;
|
|
153
|
+
invoke(site: string, command?: string): string;
|
|
154
|
+
help(site: string): string;
|
|
155
|
+
browser?(verb: readonly string[]): string;
|
|
156
|
+
background?(command: string, argv: readonly string[]): string;
|
|
157
|
+
readonly authorHint?: string;
|
|
158
|
+
}
|
|
132
159
|
export interface RuntimePort {
|
|
133
160
|
packageRoot(moduleUrl: string): string;
|
|
134
|
-
|
|
161
|
+
capabilities(ctx: DshHostContext): RuntimeCapabilities;
|
|
162
|
+
profile?(ctx: DshHostContext): RuntimeProfile;
|
|
163
|
+
commandSurface?(ctx: DshHostContext): RuntimeCommandSurface | undefined;
|
|
164
|
+
check?(ctx: DshHostContext): Promise<RuntimeCheck>;
|
|
165
|
+
commands(ctx: DshHostContext): Readonly<Record<string, string>>;
|
|
166
|
+
runners(ctx: DshHostContext, data: DataReader): Readonly<Record<string, LibRunner>>;
|
|
167
|
+
health(ctx: DshHostContext): Readonly<Record<string, RuntimeStatus>>;
|
|
135
168
|
seed(ctx: DshHostContext, options: RuntimeSeedOptions): void;
|
|
136
169
|
warnUnwritableRoot(ctx: DshHostContext): void;
|
|
137
170
|
}
|
package/dist/host/preflight.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export type PreflightStepId = 'toolchain' | '
|
|
1
|
+
export type PreflightStepId = 'toolchain' | 'cli' | 'bridge' | 'runtime' | 'diy' | 'warm';
|
|
2
2
|
export type PreflightStepStatus = 'pending' | 'running' | 'ok' | 'warn' | 'failed';
|
|
3
3
|
export type PreflightFailure = 'permission' | 'network' | 'missing' | 'unknown';
|
|
4
4
|
export type PreflightGuidance = 'install' | 'path' | 'shell';
|
|
5
|
-
export type PreflightBridgeIssue =
|
|
5
|
+
export type PreflightBridgeIssue = string;
|
|
6
6
|
export interface PreflightStep {
|
|
7
7
|
readonly id: PreflightStepId;
|
|
8
|
+
readonly label?: string;
|
|
8
9
|
readonly status: PreflightStepStatus;
|
|
9
10
|
readonly detail?: string;
|
|
10
11
|
readonly action?: string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PostResource, RouteHandler } from './http.js';
|
|
2
|
+
import type { ProfileCreateApplied, ProfileCreateSnapshot } from '../contract/protocol/profile-create.js';
|
|
3
|
+
export interface ProfileCreateDeps {
|
|
4
|
+
readonly home: string;
|
|
5
|
+
readonly self: string;
|
|
6
|
+
readonly packageRoot: string;
|
|
7
|
+
readonly runSetup?: ((env: Readonly<Record<string, string>>) => Promise<{
|
|
8
|
+
ok: boolean;
|
|
9
|
+
log: string;
|
|
10
|
+
}>) | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare function profileCreateSnapshot(deps: ProfileCreateDeps): ProfileCreateSnapshot;
|
|
13
|
+
export declare function profileCreateHandler(deps: ProfileCreateDeps): RouteHandler;
|
|
14
|
+
export declare function profileCreateApply(deps: ProfileCreateDeps, payload: unknown): Promise<ProfileCreateApplied | {
|
|
15
|
+
ok: false;
|
|
16
|
+
text: string;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function profileCreateAction(deps: ProfileCreateDeps): PostResource;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, rmSync } from 'node:fs';
|
|
2
|
+
import { join, resolve, sep } from 'node:path';
|
|
3
|
+
import { quoteShellArg } from './shell-text.js';
|
|
4
|
+
import { PROFILE_CREATE_RESOURCE } from '../contract/protocol/profile-create.js';
|
|
5
|
+
const PROFILE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
6
|
+
const BUNDLE = '@dsh-workbench/core';
|
|
7
|
+
function textOf(value) {
|
|
8
|
+
return typeof value === 'string' ? value : '';
|
|
9
|
+
}
|
|
10
|
+
function profileNames(profilesDir) {
|
|
11
|
+
try {
|
|
12
|
+
return readdirSync(profilesDir, { withFileTypes: true })
|
|
13
|
+
.filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
|
|
14
|
+
.map((entry) => entry.name)
|
|
15
|
+
.filter((name) => existsSync(join(profilesDir, name, 'package.json')))
|
|
16
|
+
.sort((a, b) => a.localeCompare(b));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function profileCreateSnapshot(deps) {
|
|
23
|
+
const profiles = profileNames(join(deps.home, 'profiles')).map((name) => ({
|
|
24
|
+
name,
|
|
25
|
+
current: name === deps.self,
|
|
26
|
+
readable: true,
|
|
27
|
+
}));
|
|
28
|
+
return { current: deps.self, profiles };
|
|
29
|
+
}
|
|
30
|
+
export function profileCreateHandler(deps) {
|
|
31
|
+
return () => ({ ok: true, ...profileCreateSnapshot(deps) });
|
|
32
|
+
}
|
|
33
|
+
function inside(base, path) {
|
|
34
|
+
const root = resolve(base);
|
|
35
|
+
const target = resolve(path);
|
|
36
|
+
return target === root ? false : target.startsWith(`${root}${sep}`);
|
|
37
|
+
}
|
|
38
|
+
export async function profileCreateApply(deps, payload) {
|
|
39
|
+
const body = typeof payload === 'object' && payload !== null ? payload : {};
|
|
40
|
+
const profile = textOf(body['profile']).trim();
|
|
41
|
+
const source = textOf(body['source']).trim();
|
|
42
|
+
const copy = typeof body['copy'] === 'object' && body['copy'] !== null ? body['copy'] : {};
|
|
43
|
+
const flags = {
|
|
44
|
+
settings: copy['settings'] === true,
|
|
45
|
+
};
|
|
46
|
+
if (!PROFILE_NAME.test(profile))
|
|
47
|
+
return { ok: false, text: '新工作台的名字不合法:只用字母、数字、点、下划线或短横线' };
|
|
48
|
+
if (source === '')
|
|
49
|
+
return { ok: false, text: '先选一个来源 profile' };
|
|
50
|
+
if (source === profile)
|
|
51
|
+
return { ok: false, text: '来源不能是新工作台自己' };
|
|
52
|
+
const profilesDir = join(deps.home, 'profiles');
|
|
53
|
+
if (!profileNames(profilesDir).includes(source))
|
|
54
|
+
return { ok: false, text: `没有这个 profile:${source}` };
|
|
55
|
+
if (existsSync(join(profilesDir, profile)))
|
|
56
|
+
return { ok: false, text: `已经有一个叫 ${profile} 的 profile` };
|
|
57
|
+
const targetHome = join(deps.home, profile);
|
|
58
|
+
if (existsSync(targetHome))
|
|
59
|
+
return { ok: false, text: `运行时目录已经存在:${targetHome}` };
|
|
60
|
+
const env = {
|
|
61
|
+
DSH_HOME: deps.home,
|
|
62
|
+
DSH_WORKBENCH_HOME: targetHome,
|
|
63
|
+
WORKBENCH_PROFILE: profile,
|
|
64
|
+
WORKBENCH_SOURCE_PROFILE: source,
|
|
65
|
+
WB_CLONE: '1',
|
|
66
|
+
WB_COPY_SETTINGS: flags.settings ? '1' : '0',
|
|
67
|
+
};
|
|
68
|
+
const setup = deps.runSetup;
|
|
69
|
+
if (setup === undefined) {
|
|
70
|
+
return { ok: false, text: '这台机器上没有装工作台的脚本入口,建不了新的工作台。' };
|
|
71
|
+
}
|
|
72
|
+
const cleanup = () => {
|
|
73
|
+
try {
|
|
74
|
+
if (inside(profilesDir, join(profilesDir, profile)))
|
|
75
|
+
rmSync(join(profilesDir, profile), { recursive: true, force: true });
|
|
76
|
+
if (inside(deps.home, targetHome))
|
|
77
|
+
rmSync(targetHome, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const result = await setup(env);
|
|
84
|
+
if (!result.ok) {
|
|
85
|
+
cleanup();
|
|
86
|
+
return { ok: false, text: `创建失败:${result.log.trim().slice(-1200) || 'setup 没给出原因'}` };
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const manifest = JSON.parse(readFileSync(join(profilesDir, profile, 'package.json'), 'utf8'));
|
|
90
|
+
const bundles = manifest.dsh?.profile?.bundles;
|
|
91
|
+
if (!Array.isArray(bundles) || !bundles.includes(BUNDLE)) {
|
|
92
|
+
cleanup();
|
|
93
|
+
return { ok: false, text: 'profile 建好了,但工作台 bundle 没被选中;先跑一次 setup 修好它' };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
cleanup();
|
|
98
|
+
return { ok: false, text: `profile 建好了,但读不了清单:${error instanceof Error ? error.message : String(error)}` };
|
|
99
|
+
}
|
|
100
|
+
const copied = Object.entries(flags)
|
|
101
|
+
.filter(([, on]) => on)
|
|
102
|
+
.map(([name]) => name);
|
|
103
|
+
const bin = join(deps.packageRoot, 'bin', 'dsh-workbench');
|
|
104
|
+
return {
|
|
105
|
+
ok: true,
|
|
106
|
+
profile,
|
|
107
|
+
source,
|
|
108
|
+
home: targetHome,
|
|
109
|
+
command: `WORKBENCH_PROFILE=${quoteShellArg(profile)} ${quoteShellArg(bin)}`,
|
|
110
|
+
copied,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export function profileCreateAction(deps) {
|
|
114
|
+
return {
|
|
115
|
+
resource: PROFILE_CREATE_RESOURCE,
|
|
116
|
+
handle: (payload) => profileCreateApply(deps, payload),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RegistryEntry, RegistryNotebook } from './adapter-types.js';
|
|
2
|
+
export declare const REGISTRY_MARKER = "# dsh-workbench \u5199\u7684\uFF1A\u8FD9\u4E00\u884C\u7684\u5305\u53EA\u5728\u8FD9\u4E2A\u6E90\u4E0A\uFF08dsh \u5378\u8F7D\u6CA1\u6709\u6E90\u53C2\u6570\uFF0Cpnpm \u5F97\u95EE\u5F97\u5230\uFF09";
|
|
3
|
+
export declare function sourcesFromLockfile(text: string): readonly RegistryEntry[];
|
|
4
|
+
export interface RegistryConfigMerge {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly added: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function mergeRegistryConfig(text: string, entries: readonly RegistryEntry[]): RegistryConfigMerge;
|
|
9
|
+
export declare function replaceScopeRegistry(text: string, scope: string, registry: string): string;
|
|
10
|
+
export declare function createRegistryNotebook(dir: string | null): RegistryNotebook;
|