@rrlab/cli 1.1.0 → 1.1.1-git-4903a88.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/bin +3 -5
- package/dist/cli.usage.kdl +26 -25
- package/dist/config.d.mts +1 -1
- package/dist/magic-string.es-BgIV5Mu3.mjs +1011 -0
- package/dist/plugin/__tests__/bin-probe.test.d.mts +1 -0
- package/dist/plugin/__tests__/bin-probe.test.mjs +64 -0
- package/dist/plugin/__tests__/decide-scaffold.test.d.mts +1 -0
- package/dist/plugin/__tests__/decide-scaffold.test.mjs +103 -0
- package/dist/plugin/__tests__/define-plugin.test.d.mts +1 -0
- package/dist/plugin/__tests__/define-plugin.test.mjs +130 -0
- package/dist/plugin/__tests__/pick-preset.test.d.mts +1 -0
- package/dist/plugin/__tests__/pick-preset.test.mjs +72 -0
- package/dist/plugin/__tests__/registry.test.d.mts +1 -0
- package/dist/plugin/__tests__/registry.test.mjs +104 -0
- package/dist/plugin/bin-probe.d.mts +4 -0
- package/dist/plugin/bin-probe.mjs +22 -0
- package/dist/plugin/decide-scaffold.d.mts +18 -0
- package/dist/plugin/decide-scaffold.mjs +36 -0
- package/dist/plugin/define-plugin.d.mts +17 -0
- package/dist/plugin/define-plugin.mjs +25 -0
- package/dist/plugin/directory.d.mts +47 -0
- package/dist/plugin/directory.mjs +45 -0
- package/dist/plugin/errors.d.mts +11 -0
- package/dist/plugin/errors.mjs +15 -0
- package/dist/plugin/index.d.mts +7 -0
- package/dist/plugin/index.mjs +50 -0
- package/dist/plugin/pick-preset.d.mts +13 -0
- package/dist/plugin/pick-preset.mjs +17 -0
- package/dist/plugin/registry.d.mts +19 -0
- package/dist/plugin/registry.mjs +2 -0
- package/dist/plugin/tool-service.d.mts +45 -0
- package/dist/plugin/tool-service.mjs +64 -0
- package/dist/plugin/types.d.mts +3 -0
- package/dist/plugin/types.mjs +1 -0
- package/dist/registry-BgqfKK5L.mjs +55 -0
- package/dist/run.mjs +969 -585
- package/dist/test.DNmyFkvJ-09ScyH13.mjs +13617 -0
- package/dist/tool-DKL6TauZ.d.mts +43 -0
- package/dist/{types-snfbujDH.d.mts → types-Iu4IyWof.d.mts} +11 -75
- package/package.json +6 -5
- package/src/actions/clean.ts +36 -0
- package/src/actions/config.ts +46 -0
- package/src/actions/doctor.ts +47 -0
- package/src/actions/format.ts +13 -0
- package/src/actions/jsc.ts +13 -0
- package/src/actions/lint.ts +13 -0
- package/src/actions/pack.ts +12 -0
- package/src/actions/plugins/add.ts +143 -0
- package/src/actions/plugins/list.ts +27 -0
- package/src/actions/plugins/remove.ts +110 -0
- package/src/actions/plugins/shared.ts +58 -0
- package/src/actions/run-tool.ts +23 -0
- package/src/actions/tsc.ts +65 -0
- package/src/errors/invalid-plugin-module.ts +6 -0
- package/src/errors/missing-plugin.ts +17 -0
- package/src/errors/plugin-api-version.ts +6 -0
- package/src/errors/unknown-plugin.ts +7 -0
- package/src/lib/plugin/define-plugin.ts +56 -0
- package/src/lib/plugin/directory.ts +30 -0
- package/src/lib/plugin/errors.ts +15 -0
- package/src/lib/{plugin.ts → plugin/index.ts} +8 -9
- package/src/lib/plugin/registry.ts +82 -0
- package/src/{plugin → lib/plugin}/tool-service.ts +10 -14
- package/src/{plugin → lib/plugin}/types.ts +10 -33
- package/src/program/base.ts +75 -0
- package/src/program/commands/check.ts +31 -62
- package/src/program/commands/clean.ts +12 -43
- package/src/program/commands/completion.ts +6 -4
- package/src/program/commands/config.ts +6 -11
- package/src/program/commands/doctor.ts +5 -54
- package/src/program/commands/format.ts +18 -25
- package/src/program/commands/jscheck.ts +18 -31
- package/src/program/commands/lint.ts +18 -26
- package/src/program/commands/pack.ts +18 -22
- package/src/program/commands/plugins.ts +17 -364
- package/src/program/commands/tscheck.ts +19 -77
- package/src/program/index.ts +20 -27
- package/src/program/root.ts +62 -0
- package/src/render/banner.ts +25 -0
- package/src/render/board.ts +41 -0
- package/src/render/footer.ts +31 -0
- package/src/render/labels.ts +28 -0
- package/src/render/lines.ts +100 -0
- package/src/render/plugin-view.ts +68 -0
- package/src/render/steps.ts +20 -0
- package/src/run.ts +2 -8
- package/src/services/config.ts +4 -0
- package/src/services/context.ts +84 -0
- package/src/services/file-ops.ts +79 -0
- package/src/services/json-edit.ts +1 -1
- package/src/services/plugin-meta.ts +63 -0
- package/src/services/plugin-services.ts +41 -0
- package/src/services/prompts.ts +1 -1
- package/src/services/static-checker.ts +46 -0
- package/src/types/config.ts +2 -1
- package/src/types/tool.ts +13 -26
- package/src/ui/theme.ts +5 -0
- package/dist/plugin.d.mts +0 -87
- package/dist/plugin.mjs +0 -214
- package/src/plugin/define-plugin.ts +0 -54
- package/src/plugin/registry.ts +0 -48
- package/src/program/board.ts +0 -86
- package/src/program/composed-jsc.ts +0 -43
- package/src/program/missing-plugin.ts +0 -18
- package/src/program/ui.ts +0 -59
- package/src/services/ctx.ts +0 -71
- package/src/services/plugins-registry.ts +0 -22
- /package/src/{plugin → lib/plugin}/bin-probe.ts +0 -0
- /package/src/{plugin → lib/plugin}/decide-scaffold.ts +0 -0
- /package/src/{plugin → lib/plugin}/pick-preset.ts +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/lib/plugin/directory.ts
|
|
2
|
+
const PLUGINS_DIRECTORY = {
|
|
3
|
+
ts: {
|
|
4
|
+
pkg: "@rrlab/ts-plugin",
|
|
5
|
+
name: "ts",
|
|
6
|
+
capabilities: ["typecheck"]
|
|
7
|
+
},
|
|
8
|
+
biome: {
|
|
9
|
+
pkg: "@rrlab/biome-plugin",
|
|
10
|
+
name: "biome",
|
|
11
|
+
capabilities: [
|
|
12
|
+
"format",
|
|
13
|
+
"jscheck",
|
|
14
|
+
"lint"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
oxc: {
|
|
18
|
+
pkg: "@rrlab/oxc-plugin",
|
|
19
|
+
name: "oxc",
|
|
20
|
+
capabilities: [
|
|
21
|
+
"format",
|
|
22
|
+
"lint",
|
|
23
|
+
"jscheck",
|
|
24
|
+
"typecheck"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
tsdown: {
|
|
28
|
+
pkg: "@rrlab/tsdown-plugin",
|
|
29
|
+
name: "tsdown",
|
|
30
|
+
capabilities: ["pack"]
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
function allPluginNames() {
|
|
34
|
+
return Object.keys(PLUGINS_DIRECTORY);
|
|
35
|
+
}
|
|
36
|
+
function isPluginName(name) {
|
|
37
|
+
return Object.hasOwn(PLUGINS_DIRECTORY, name);
|
|
38
|
+
}
|
|
39
|
+
function providersOf(capability) {
|
|
40
|
+
return Object.values(PLUGINS_DIRECTORY).filter((info) => {
|
|
41
|
+
return info.capabilities.includes(capability);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { PLUGINS_DIRECTORY, allPluginNames, isPluginName, providersOf };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/lib/plugin/errors.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `PluginRegistry.get` when more than one plugin provides the same
|
|
4
|
+
* capability. The message is load-bearing for the "ambiguity → user narrows
|
|
5
|
+
* config" UX (decision 003) — `registry.test.ts` asserts the plugin names appear.
|
|
6
|
+
*/
|
|
7
|
+
declare class MultipleProvidersError extends Error {
|
|
8
|
+
constructor(kind: string, pluginNames: readonly string[]);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { MultipleProvidersError };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/lib/plugin/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `PluginRegistry.get` when more than one plugin provides the same
|
|
4
|
+
* capability. The message is load-bearing for the "ambiguity → user narrows
|
|
5
|
+
* config" UX (decision 003) — `registry.test.ts` asserts the plugin names appear.
|
|
6
|
+
*/
|
|
7
|
+
var MultipleProvidersError = class extends Error {
|
|
8
|
+
constructor(kind, pluginNames) {
|
|
9
|
+
const names = pluginNames.join(", ");
|
|
10
|
+
const example = pluginNames.map((name) => `${name}({ only: ['${kind}'] })`).join(" or ");
|
|
11
|
+
super(`Multiple plugins provide capability '${kind}': ${names}. Narrow each plugin's capabilities in run-run.config.ts using the 'only' option — e.g. ${example}.`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { MultipleProvidersError };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { a as InstallFlags, c as Plugin, d as PluginServices, f as UninstallContext, g as ReleaseServiceOptions, h as ReleaseService, i as InstallContext, l as PluginCapability, m as UninstallResult, n as ClackPromptsSelectOption, o as InstallResult, p as UninstallFlags, r as FileOp, s as JsonEdit, t as ClackPrompts, u as PluginContext } from "../types-Iu4IyWof.mjs";
|
|
2
|
+
import { a as Linter, c as StaticChecker, d as TypeChecker, i as LintOptions, l as StaticCheckerOptions, n as FormatOptions, o as Packer, r as Formatter, s as RunReport, t as Doctor, u as TypeCheckOptions } from "../tool-DKL6TauZ.mjs";
|
|
3
|
+
import { DecideScaffoldOptions, ScaffoldDecision, decideScaffold } from "./decide-scaffold.mjs";
|
|
4
|
+
import { PluginDefinition, definePlugin } from "./define-plugin.mjs";
|
|
5
|
+
import { PickPresetOptions, pickPreset } from "./pick-preset.mjs";
|
|
6
|
+
import { ToolService, ToolServiceOptions } from "./tool-service.mjs";
|
|
7
|
+
export { type ClackPrompts, type ClackPromptsSelectOption, type DecideScaffoldOptions, type Doctor, type FileOp, type FormatOptions, type Formatter, type InstallContext, type InstallFlags, type InstallResult, type JsonEdit, type LintOptions, type Linter, type Packer, type PickPresetOptions, type Plugin, type PluginCapability, type PluginContext, type PluginDefinition, type PluginServices, ReleaseService, type ReleaseServiceOptions, type RunReport, type ScaffoldDecision, type StaticChecker, type StaticCheckerOptions, ToolService, type ToolServiceOptions, type TypeCheckOptions, type TypeChecker, type UninstallContext, type UninstallFlags, type UninstallResult, decideScaffold, definePlugin, pickPreset };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ToolService } from "./tool-service.mjs";
|
|
2
|
+
import { decideScaffold } from "./decide-scaffold.mjs";
|
|
3
|
+
import { definePlugin } from "./define-plugin.mjs";
|
|
4
|
+
import { pickPreset } from "./pick-preset.mjs";
|
|
5
|
+
//#region src/services/release.ts
|
|
6
|
+
const REGISTRY = "https://registry.npmjs.org";
|
|
7
|
+
const PROBE_TIMEOUT_MS = 5e3;
|
|
8
|
+
/**
|
|
9
|
+
* Represents the "release" the current `rr plugins add` runs against — the
|
|
10
|
+
* dist-tag the user picked (default: latest), plus the logic to resolve install
|
|
11
|
+
* specs for related packages under that release.
|
|
12
|
+
*
|
|
13
|
+
* - With no `tag`, `resolve()` always returns `"latest"` and never hits the
|
|
14
|
+
* registry.
|
|
15
|
+
* - With a `tag` (e.g. `"pr-226"`), probes `<pkg>@<tag>`: returns the tag when
|
|
16
|
+
* it exists, falls back to `"latest"` otherwise so a partial preview release
|
|
17
|
+
* (where only a subset of packages got published) still installs cleanly.
|
|
18
|
+
* - Per-package result is cached within the service instance.
|
|
19
|
+
*/
|
|
20
|
+
var ReleaseService = class {
|
|
21
|
+
tag;
|
|
22
|
+
#fetcher;
|
|
23
|
+
#cache = /* @__PURE__ */ new Map();
|
|
24
|
+
constructor(tag, { fetcher = fetch } = {}) {
|
|
25
|
+
this.tag = tag;
|
|
26
|
+
this.#fetcher = fetcher;
|
|
27
|
+
}
|
|
28
|
+
resolve(pkg) {
|
|
29
|
+
if (!this.tag || this.tag === "latest") return Promise.resolve("latest");
|
|
30
|
+
const cached = this.#cache.get(pkg);
|
|
31
|
+
if (cached) return cached;
|
|
32
|
+
const promise = this.#probe(pkg);
|
|
33
|
+
this.#cache.set(pkg, promise);
|
|
34
|
+
return promise;
|
|
35
|
+
}
|
|
36
|
+
async #probe(pkg) {
|
|
37
|
+
const tag = this.tag;
|
|
38
|
+
const controller = new AbortController();
|
|
39
|
+
const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
|
40
|
+
try {
|
|
41
|
+
return (await this.#fetcher(`${REGISTRY}/${pkg}/${encodeURIComponent(tag)}`, { signal: controller.signal })).ok ? tag : "latest";
|
|
42
|
+
} catch {
|
|
43
|
+
return "latest";
|
|
44
|
+
} finally {
|
|
45
|
+
clearTimeout(timeout);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { ReleaseService, ToolService, decideScaffold, definePlugin, pickPreset };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { i as InstallContext } from "../types-Iu4IyWof.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/plugin/pick-preset.d.ts
|
|
4
|
+
type PickPresetOptions<K extends string> = {
|
|
5
|
+
message: string;
|
|
6
|
+
presets: Record<K, {
|
|
7
|
+
label: string;
|
|
8
|
+
}>;
|
|
9
|
+
defaultPreset: K;
|
|
10
|
+
};
|
|
11
|
+
declare function pickPreset<K extends string>(ctx: InstallContext, opts: PickPresetOptions<K>): Promise<K>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { PickPresetOptions, pickPreset };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/lib/plugin/pick-preset.ts
|
|
2
|
+
async function pickPreset(ctx, opts) {
|
|
3
|
+
const { message, presets, defaultPreset } = opts;
|
|
4
|
+
if (ctx.flags.yes || ctx.flags.nonInteractive) return defaultPreset;
|
|
5
|
+
const choice = await ctx.prompts.select({
|
|
6
|
+
message,
|
|
7
|
+
options: Object.entries(presets).map(([value, meta]) => ({
|
|
8
|
+
value,
|
|
9
|
+
label: meta.label
|
|
10
|
+
})),
|
|
11
|
+
initialValue: defaultPreset
|
|
12
|
+
});
|
|
13
|
+
if (ctx.prompts.isCancel(choice)) throw new Error("Cancelled by user.");
|
|
14
|
+
return choice;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { pickPreset };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { c as Plugin, d as PluginServices, l as PluginCapability } from "../types-Iu4IyWof.mjs";
|
|
2
|
+
import { a as Linter, c as StaticChecker, d as TypeChecker, o as Packer, r as Formatter, t as Doctor } from "../tool-DKL6TauZ.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/plugin/registry.d.ts
|
|
5
|
+
type Provider<K extends PluginCapability> = {
|
|
6
|
+
plugin: Plugin;
|
|
7
|
+
service: NonNullable<PluginServices[K]>;
|
|
8
|
+
};
|
|
9
|
+
declare class PluginRegistry {
|
|
10
|
+
#private;
|
|
11
|
+
register(plugin: Plugin, services: PluginServices): void;
|
|
12
|
+
getServiceOrThrow<K extends PluginCapability>(capability: K): NonNullable<PluginServices[K]>;
|
|
13
|
+
getService<K extends PluginCapability>(capability: K): NonNullable<PluginServices[K]> | undefined;
|
|
14
|
+
getAllServices(): NonNullable<(Linter & Doctor) | (Formatter & Doctor) | (StaticChecker & Doctor) | (TypeChecker & Doctor) | (Packer & Doctor) | undefined>[];
|
|
15
|
+
providersOf<K extends PluginCapability>(capability: K): Provider<K>[];
|
|
16
|
+
providerOf<K extends PluginCapability>(capability: K): Provider<K> | undefined;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { PluginRegistry };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { s as RunReport } from "../tool-DKL6TauZ.mjs";
|
|
2
|
+
import { ShellService } from "@vlandoss/clibuddy";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/plugin/tool-service.d.ts
|
|
5
|
+
type ToolServiceOptions = {
|
|
6
|
+
pkg?: string;
|
|
7
|
+
bin: string;
|
|
8
|
+
color: (str: string) => string;
|
|
9
|
+
shellService: ShellService;
|
|
10
|
+
/**
|
|
11
|
+
* Module URL the resolver walks up from when looking for `pkg` in
|
|
12
|
+
* `node_modules`. Plugins MUST pass their own `import.meta.url` so the
|
|
13
|
+
* binary is resolved from the plugin's own dependency graph (peer-installed
|
|
14
|
+
* by the host project), not the kernel's. Kernel-internal services pass
|
|
15
|
+
* `import.meta.url` of their own module file.
|
|
16
|
+
*/
|
|
17
|
+
from: string;
|
|
18
|
+
};
|
|
19
|
+
type RunReportOptions = {
|
|
20
|
+
cwd?: string;
|
|
21
|
+
};
|
|
22
|
+
declare class ToolService {
|
|
23
|
+
#private;
|
|
24
|
+
get pkg(): string;
|
|
25
|
+
get ui(): string;
|
|
26
|
+
constructor({
|
|
27
|
+
pkg,
|
|
28
|
+
bin,
|
|
29
|
+
color,
|
|
30
|
+
shellService,
|
|
31
|
+
from
|
|
32
|
+
}: ToolServiceOptions);
|
|
33
|
+
getBinDir(): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Runs the tool capturing its output instead of streaming it, and reports the
|
|
36
|
+
* verdict straight from the exit code — never a guess parsed from the output.
|
|
37
|
+
* The board needs the capture to attribute each parallel run's output to its
|
|
38
|
+
* package; the non-zero exit is returned (not thrown) so every task settles
|
|
39
|
+
* and the caller can aggregate. See `decisions/013-check-stream-to-capture-contract.md`.
|
|
40
|
+
*/
|
|
41
|
+
runReport(args?: string[], options?: RunReportOptions): Promise<RunReport>;
|
|
42
|
+
doctor(): Promise<RunReport>;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { RunReportOptions, ToolService, ToolServiceOptions };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { palette, resolvePackageBin } from "@vlandoss/clibuddy";
|
|
2
|
+
//#region src/lib/plugin/tool-service.ts
|
|
3
|
+
var ToolService = class {
|
|
4
|
+
#shellService;
|
|
5
|
+
#pkg;
|
|
6
|
+
#bin;
|
|
7
|
+
#from;
|
|
8
|
+
#ui;
|
|
9
|
+
get pkg() {
|
|
10
|
+
return this.#pkg;
|
|
11
|
+
}
|
|
12
|
+
get ui() {
|
|
13
|
+
return this.#ui;
|
|
14
|
+
}
|
|
15
|
+
constructor({ pkg, bin, color, shellService, from }) {
|
|
16
|
+
this.#bin = bin;
|
|
17
|
+
this.#pkg = pkg ?? bin;
|
|
18
|
+
this.#ui = color(bin);
|
|
19
|
+
this.#shellService = shellService;
|
|
20
|
+
this.#from = from;
|
|
21
|
+
}
|
|
22
|
+
async getBinDir() {
|
|
23
|
+
return resolvePackageBin(this.#pkg, {
|
|
24
|
+
from: this.#from,
|
|
25
|
+
binName: this.#bin
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Runs the tool capturing its output instead of streaming it, and reports the
|
|
30
|
+
* verdict straight from the exit code — never a guess parsed from the output.
|
|
31
|
+
* The board needs the capture to attribute each parallel run's output to its
|
|
32
|
+
* package; the non-zero exit is returned (not thrown) so every task settles
|
|
33
|
+
* and the caller can aggregate. See `decisions/013-check-stream-to-capture-contract.md`.
|
|
34
|
+
*/
|
|
35
|
+
async runReport(args = [], options = {}) {
|
|
36
|
+
const output = await (options.cwd ? this.#shellService.at(options.cwd) : this.#shellService).runCaptured(await this.getBinDir(), args, { throwOnError: false });
|
|
37
|
+
const header = palette.dim(`$ ${[this.#bin, ...args].join(" ")}`);
|
|
38
|
+
const body = combine(output.stdout, output.stderr);
|
|
39
|
+
return {
|
|
40
|
+
ok: output.exitCode === 0,
|
|
41
|
+
output: body ? `${header}\n${body}` : header
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async doctor() {
|
|
45
|
+
const output = await this.#shellService.runCaptured(await this.getBinDir(), ["--help"], { throwOnError: false });
|
|
46
|
+
const ok = output.exitCode === 0;
|
|
47
|
+
const command = palette.dim(`$ ${this.#bin} --help`);
|
|
48
|
+
if (ok) return {
|
|
49
|
+
ok,
|
|
50
|
+
output: command
|
|
51
|
+
};
|
|
52
|
+
const detail = combine(output.stdout, output.stderr);
|
|
53
|
+
return {
|
|
54
|
+
ok,
|
|
55
|
+
output: detail ? `${command}\n${detail}` : command
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/** Joins the non-empty, trimmed streams of a captured run. */
|
|
60
|
+
function combine(stdout, stderr) {
|
|
61
|
+
return [stdout, stderr].map((stream) => stream?.trim()).filter(Boolean).join("\n");
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { ToolService };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as InstallFlags, c as Plugin, d as PluginServices, f as UninstallContext, i as InstallContext, l as PluginCapability, m as UninstallResult, n as ClackPromptsSelectOption, o as InstallResult, p as UninstallFlags, r as FileOp, s as JsonEdit, t as ClackPrompts, u as PluginContext } from "../types-Iu4IyWof.mjs";
|
|
2
|
+
import { a as Linter, c as StaticChecker, d as TypeChecker, i as LintOptions, l as StaticCheckerOptions, n as FormatOptions, o as Packer, r as Formatter, s as RunReport, t as Doctor, u as TypeCheckOptions } from "../tool-DKL6TauZ.mjs";
|
|
3
|
+
export { ClackPrompts, ClackPromptsSelectOption, type Doctor, FileOp, type FormatOptions, type Formatter, InstallContext, InstallFlags, InstallResult, JsonEdit, type LintOptions, type Linter, type Packer, Plugin, PluginCapability, PluginContext, PluginServices, type RunReport, type StaticChecker, type StaticCheckerOptions, type TypeCheckOptions, type TypeChecker, UninstallContext, UninstallFlags, UninstallResult };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { providersOf } from "./plugin/directory.mjs";
|
|
2
|
+
import { MultipleProvidersError } from "./plugin/errors.mjs";
|
|
3
|
+
//#region src/errors/missing-plugin.ts
|
|
4
|
+
var MissingPluginError = class extends Error {
|
|
5
|
+
constructor(capability) {
|
|
6
|
+
const plugins = providersOf(capability);
|
|
7
|
+
const pkgList = plugins.map((it) => it.pkg).join(", ");
|
|
8
|
+
const addList = plugins.map((it) => `rr plugins add ${it.name}`).join(" | ");
|
|
9
|
+
super(`No plugin provides the '${capability}' capability.` + (pkgList ? `\n Install one of: ${pkgList}.` : "") + (addList ? `\n Try: ${addList}.` : ""));
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/lib/plugin/registry.ts
|
|
14
|
+
var PluginRegistry = class {
|
|
15
|
+
#entries = [];
|
|
16
|
+
register(plugin, services) {
|
|
17
|
+
this.#entries.push({
|
|
18
|
+
plugin,
|
|
19
|
+
services
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
getServiceOrThrow(capability) {
|
|
23
|
+
const provider = this.providerOf(capability);
|
|
24
|
+
if (!provider) throw new MissingPluginError(capability);
|
|
25
|
+
return provider.service;
|
|
26
|
+
}
|
|
27
|
+
getService(capability) {
|
|
28
|
+
return this.providerOf(capability)?.service;
|
|
29
|
+
}
|
|
30
|
+
getAllServices() {
|
|
31
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const { services } of this.#entries) for (const service of Object.values(services)) if (service) seen.add(service);
|
|
33
|
+
return [...seen];
|
|
34
|
+
}
|
|
35
|
+
providersOf(capability) {
|
|
36
|
+
const providers = [];
|
|
37
|
+
for (const { plugin, services } of this.#entries) {
|
|
38
|
+
const service = services[capability];
|
|
39
|
+
if (service) providers.push({
|
|
40
|
+
plugin,
|
|
41
|
+
service
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return providers;
|
|
45
|
+
}
|
|
46
|
+
providerOf(capability) {
|
|
47
|
+
const providers = this.providersOf(capability);
|
|
48
|
+
const [first, ...rest] = providers;
|
|
49
|
+
if (!first) return;
|
|
50
|
+
if (rest.length > 0) throw new MultipleProvidersError(capability, providers.map(({ plugin }) => plugin.name));
|
|
51
|
+
return first;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { PluginRegistry as t };
|