@kb-labs/marketplace-entry 2.30.0 → 2.32.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/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +59 -3
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/plugins/disable.d.ts +5 -0
- package/dist/commands/plugins/disable.js +63 -4
- package/dist/commands/plugins/disable.js.map +1 -1
- package/dist/commands/plugins/doctor.d.ts +1 -0
- package/dist/commands/plugins/doctor.js +61 -3
- package/dist/commands/plugins/doctor.js.map +1 -1
- package/dist/commands/plugins/enable.d.ts +5 -0
- package/dist/commands/plugins/enable.js +63 -4
- package/dist/commands/plugins/enable.js.map +1 -1
- package/dist/commands/plugins/link.d.ts +6 -0
- package/dist/commands/plugins/link.js +69 -8
- package/dist/commands/plugins/link.js.map +1 -1
- package/dist/commands/plugins/list.d.ts +2 -0
- package/dist/commands/plugins/list.js +66 -3
- package/dist/commands/plugins/list.js.map +1 -1
- package/dist/commands/plugins/unlink.d.ts +5 -0
- package/dist/commands/plugins/unlink.js +60 -4
- package/dist/commands/plugins/unlink.js.map +1 -1
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +69 -8
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/uninstall.d.ts +5 -0
- package/dist/commands/uninstall.js +63 -4
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts +6 -3
- package/dist/commands/update.js +73 -7
- package/dist/commands/update.js.map +1 -1
- package/package.json +4 -2
|
@@ -3,6 +3,7 @@ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
|
3
3
|
interface InstallFlags {
|
|
4
4
|
dev?: boolean;
|
|
5
5
|
json?: boolean;
|
|
6
|
+
scope?: string;
|
|
6
7
|
}
|
|
7
8
|
interface InstallInput {
|
|
8
9
|
argv?: string[];
|
|
@@ -16,6 +17,7 @@ interface InstalledEntry {
|
|
|
16
17
|
interface InstallResultData {
|
|
17
18
|
installed: InstalledEntry[];
|
|
18
19
|
warnings: string[];
|
|
20
|
+
scope: string;
|
|
19
21
|
}
|
|
20
22
|
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, InstallInput, InstallResultData>;
|
|
21
23
|
|
package/dist/commands/install.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineCommand, useEnv } from '@kb-labs/sdk';
|
|
2
|
+
import { findProjectConfigRoot } from '@kb-labs/core-workspace';
|
|
2
3
|
|
|
3
4
|
// src/commands/install.ts
|
|
4
5
|
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:4000";
|
|
@@ -37,6 +38,50 @@ async function post(path, body) {
|
|
|
37
38
|
clearTimeout(timer);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
41
|
+
var SCOPE_FLAG_CHOICES = ["platform", "project"];
|
|
42
|
+
async function resolveCliScope(cwd, flag) {
|
|
43
|
+
if (flag) {
|
|
44
|
+
assertMutatingScope(flag);
|
|
45
|
+
if (flag === "project") {
|
|
46
|
+
const projectRoot2 = await findProjectConfigRoot(cwd);
|
|
47
|
+
if (!projectRoot2) {
|
|
48
|
+
throw new CliScopeError(
|
|
49
|
+
"SCOPE_PROJECT_ROOT_NOT_FOUND",
|
|
50
|
+
`--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} \u2014 none found.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return { scope: "project", projectRoot: projectRoot2, reason: "flag" };
|
|
54
|
+
}
|
|
55
|
+
return { scope: "platform", reason: "flag" };
|
|
56
|
+
}
|
|
57
|
+
const projectRoot = await findProjectConfigRoot(cwd);
|
|
58
|
+
if (projectRoot) {
|
|
59
|
+
return { scope: "project", projectRoot, reason: "auto-detect" };
|
|
60
|
+
}
|
|
61
|
+
return { scope: "platform", reason: "fallback" };
|
|
62
|
+
}
|
|
63
|
+
function assertMutatingScope(value) {
|
|
64
|
+
if (!SCOPE_FLAG_CHOICES.includes(value)) {
|
|
65
|
+
throw new CliScopeError(
|
|
66
|
+
"SCOPE_INVALID",
|
|
67
|
+
`--scope must be one of: ${SCOPE_FLAG_CHOICES.join(", ")} (got ${JSON.stringify(value)})`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var CliScopeError = class extends Error {
|
|
72
|
+
code;
|
|
73
|
+
constructor(code, message) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.code = code;
|
|
76
|
+
this.name = "CliScopeError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
function scopeBody(ctx) {
|
|
80
|
+
return {
|
|
81
|
+
scope: ctx.scope,
|
|
82
|
+
...ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
40
85
|
|
|
41
86
|
// src/commands/install.ts
|
|
42
87
|
var install_default = defineCommand({
|
|
@@ -48,16 +93,27 @@ var install_default = defineCommand({
|
|
|
48
93
|
const flags = input.flags ?? input;
|
|
49
94
|
if (argv.length === 0) {
|
|
50
95
|
ctx.ui?.error?.("Please specify at least one package to install");
|
|
51
|
-
return { exitCode: 1, result: { installed: [], warnings: [] } };
|
|
96
|
+
return { exitCode: 1, result: { installed: [], warnings: [], scope: "" } };
|
|
97
|
+
}
|
|
98
|
+
let scopeCtx;
|
|
99
|
+
try {
|
|
100
|
+
scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err instanceof CliScopeError) {
|
|
103
|
+
ctx.ui?.error?.(err.message);
|
|
104
|
+
return { exitCode: 1, result: { installed: [], warnings: [], scope: "" } };
|
|
105
|
+
}
|
|
106
|
+
throw err;
|
|
52
107
|
}
|
|
53
108
|
const result = await post("/packages", {
|
|
54
109
|
specs: argv,
|
|
55
|
-
dev: Boolean(flags.dev)
|
|
110
|
+
dev: Boolean(flags.dev),
|
|
111
|
+
...scopeBody(scopeCtx)
|
|
56
112
|
});
|
|
57
113
|
if (flags.json) {
|
|
58
114
|
ctx.ui?.json?.(result);
|
|
59
115
|
} else {
|
|
60
|
-
ctx.ui?.success?.(
|
|
116
|
+
ctx.ui?.success?.(`Marketplace install completed (${result.scope ?? scopeCtx.scope})`, {
|
|
61
117
|
sections: [
|
|
62
118
|
{
|
|
63
119
|
header: "Installed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/http.ts","../../src/commands/install.ts"],"names":[],"mappings":"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","file":"install.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../http.js';\n\ninterface InstallFlags {\n dev?: boolean;\n json?: boolean;\n}\n\ninterface InstallInput {\n argv?: string[];\n flags?: InstallFlags;\n}\n\ninterface InstalledEntry {\n id: string;\n version: string;\n primaryKind: string;\n}\n\ninterface InstallResultData {\n installed: InstalledEntry[];\n warnings: string[];\n}\n\nexport default defineCommand<unknown, InstallInput, InstallResultData>({\n id: 'marketplace:install',\n description: 'Install package(s) from marketplace',\n\n handler: {\n async execute(ctx: PluginContextV3, input: InstallInput): Promise<CommandResult<InstallResultData>> {\n const argv = input.argv ?? [];\n const flags = (input.flags ?? input) as InstallFlags;\n\n if (argv.length === 0) {\n ctx.ui?.error?.('Please specify at least one package to install');\n return { exitCode: 1, result: { installed: [], warnings: [] } };\n }\n\n const result = await post<InstallResultData>('/packages', {\n specs: argv,\n dev: Boolean(flags.dev),\n });\n\n if (flags.json) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.('Marketplace install completed', {\n sections: [\n {\n header: 'Installed',\n items: result.installed.map(p => `${p.id}@${p.version} (${p.primaryKind})`),\n },\n ...(result.warnings.length > 0\n ? [{ header: 'Warnings', items: result.warnings }]\n : []),\n ],\n });\n }\n\n return { exitCode: 0, result };\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/http.ts","../../src/scope.ts","../../src/commands/install.ts"],"names":["projectRoot"],"mappings":"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","file":"install.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * @module @kb-labs/marketplace-entry/scope\n *\n * Client-side scope resolution for marketplace CLI commands. Uses the\n * canonical `findProjectConfigRoot` helper from `@kb-labs/core-workspace`\n * so the detection rules (which filenames count, how walk-up stops) match\n * what the config loader and the marketplace daemon enforce.\n *\n * Rules:\n * - `project` is the default if cwd (or any ancestor up to the filesystem\n * root) contains `.kb/kb.config.{json,jsonc}`.\n * - Otherwise the default is `platform`.\n * - `--scope` always overrides detection.\n * - For scope=\"project\" we return the absolute projectRoot so the daemon\n * doesn't need to re-discover it.\n */\n\nimport { findProjectConfigRoot } from '@kb-labs/core-workspace';\nimport type { MarketplaceScope, MarketplaceQueryScope } from '@kb-labs/marketplace-contracts';\n\nexport const SCOPE_FLAG_CHOICES: readonly MarketplaceScope[] = ['platform', 'project'];\nexport const QUERY_SCOPE_FLAG_CHOICES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport interface ResolvedCliScope {\n scope: MarketplaceScope;\n projectRoot?: string;\n /** How the scope was determined — surfaces in --verbose logs. */\n reason: 'flag' | 'auto-detect' | 'fallback';\n}\n\nexport interface ResolvedCliQueryScope extends Omit<ResolvedCliScope, 'scope'> {\n scope: MarketplaceQueryScope;\n}\n\n/**\n * Resolve the effective scope for a mutating command (`link`, `unlink`,\n * `install`, ...). `flag` is the value of `--scope` (if supplied). The\n * helper never returns `'all'` for mutating commands — callers restrict\n * choices via `SCOPE_FLAG_CHOICES`.\n */\nexport async function resolveCliScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliScope> {\n if (flag) {\n assertMutatingScope(flag);\n if (flag === 'project') {\n const projectRoot = await findProjectConfigRoot(cwd);\n if (!projectRoot) {\n throw new CliScopeError(\n 'SCOPE_PROJECT_ROOT_NOT_FOUND',\n `--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} — none found.`,\n );\n }\n return { scope: 'project', projectRoot, reason: 'flag' };\n }\n return { scope: 'platform', reason: 'flag' };\n }\n\n const projectRoot = await findProjectConfigRoot(cwd);\n if (projectRoot) {\n return { scope: 'project', projectRoot, reason: 'auto-detect' };\n }\n return { scope: 'platform', reason: 'fallback' };\n}\n\n/**\n * Resolve the effective scope for a read-only command (`list`). Accepts\n * `'all'` as an explicit flag value.\n */\nexport async function resolveCliQueryScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliQueryScope> {\n if (flag === 'all') {\n const projectRoot = await findProjectConfigRoot(cwd);\n return { scope: 'all', projectRoot, reason: 'flag' };\n }\n const base = await resolveCliScope(cwd, flag);\n return { scope: base.scope, projectRoot: base.projectRoot, reason: base.reason };\n}\n\nfunction assertMutatingScope(value: string): asserts value is MarketplaceScope {\n if (!SCOPE_FLAG_CHOICES.includes(value as MarketplaceScope)) {\n throw new CliScopeError(\n 'SCOPE_INVALID',\n `--scope must be one of: ${SCOPE_FLAG_CHOICES.join(', ')} (got ${JSON.stringify(value)})`,\n );\n }\n}\n\nexport class CliScopeError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n this.name = 'CliScopeError';\n }\n}\n\n/**\n * Build the body-payload fragment expected by `parseMutatingScope` on the\n * API side: `{ scope, projectRoot? }`. Kept as a helper so every command\n * sends the same shape and nothing drifts out-of-sync with the server.\n */\nexport function scopeBody(ctx: ResolvedCliScope | ResolvedCliQueryScope): {\n scope: MarketplaceScope | MarketplaceQueryScope;\n projectRoot?: string;\n} {\n return {\n scope: ctx.scope,\n ...(ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}),\n };\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../scope.js';\n\ninterface InstallFlags {\n dev?: boolean;\n json?: boolean;\n scope?: string;\n}\n\ninterface InstallInput {\n argv?: string[];\n flags?: InstallFlags;\n}\n\ninterface InstalledEntry {\n id: string;\n version: string;\n primaryKind: string;\n}\n\ninterface InstallResultData {\n installed: InstalledEntry[];\n warnings: string[];\n scope: string;\n}\n\nexport default defineCommand<unknown, InstallInput, InstallResultData>({\n id: 'marketplace:install',\n description: 'Install package(s) from marketplace',\n\n handler: {\n async execute(ctx: PluginContextV3, input: InstallInput): Promise<CommandResult<InstallResultData>> {\n const argv = input.argv ?? [];\n const flags = (input.flags ?? input) as InstallFlags;\n\n if (argv.length === 0) {\n ctx.ui?.error?.('Please specify at least one package to install');\n return { exitCode: 1, result: { installed: [], warnings: [], scope: '' } };\n }\n\n let scopeCtx;\n try {\n scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);\n } catch (err) {\n if (err instanceof CliScopeError) {\n ctx.ui?.error?.(err.message);\n return { exitCode: 1, result: { installed: [], warnings: [], scope: '' } };\n }\n throw err;\n }\n\n const result = await post<InstallResultData>('/packages', {\n specs: argv,\n dev: Boolean(flags.dev),\n ...scopeBody(scopeCtx),\n });\n\n if (flags.json) {\n ctx.ui?.json?.(result);\n } else {\n ctx.ui?.success?.(`Marketplace install completed (${result.scope ?? scopeCtx.scope})`, {\n sections: [\n {\n header: 'Installed',\n items: result.installed.map(p => `${p.id}@${p.version} (${p.primaryKind})`),\n },\n ...(result.warnings.length > 0\n ? [{ header: 'Warnings', items: result.warnings }]\n : []),\n ],\n });\n }\n\n return { exitCode: 0, result };\n },\n },\n});\n"]}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
2
|
|
|
3
|
+
interface DisableFlags {
|
|
4
|
+
scope?: string;
|
|
5
|
+
}
|
|
3
6
|
interface DisableInput {
|
|
4
7
|
argv?: string[];
|
|
8
|
+
flags?: DisableFlags;
|
|
5
9
|
}
|
|
6
10
|
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, DisableInput, {
|
|
7
11
|
packageId: string;
|
|
12
|
+
scope: string;
|
|
8
13
|
}>;
|
|
9
14
|
|
|
10
15
|
export { _default as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineCommand, useEnv } from '@kb-labs/sdk';
|
|
2
|
+
import { findProjectConfigRoot } from '@kb-labs/core-workspace';
|
|
2
3
|
|
|
3
4
|
// src/commands/plugins/disable.ts
|
|
4
5
|
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:4000";
|
|
@@ -37,6 +38,50 @@ async function patch(path, body) {
|
|
|
37
38
|
clearTimeout(timer);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
41
|
+
var SCOPE_FLAG_CHOICES = ["platform", "project"];
|
|
42
|
+
async function resolveCliScope(cwd, flag) {
|
|
43
|
+
if (flag) {
|
|
44
|
+
assertMutatingScope(flag);
|
|
45
|
+
if (flag === "project") {
|
|
46
|
+
const projectRoot2 = await findProjectConfigRoot(cwd);
|
|
47
|
+
if (!projectRoot2) {
|
|
48
|
+
throw new CliScopeError(
|
|
49
|
+
"SCOPE_PROJECT_ROOT_NOT_FOUND",
|
|
50
|
+
`--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} \u2014 none found.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return { scope: "project", projectRoot: projectRoot2, reason: "flag" };
|
|
54
|
+
}
|
|
55
|
+
return { scope: "platform", reason: "flag" };
|
|
56
|
+
}
|
|
57
|
+
const projectRoot = await findProjectConfigRoot(cwd);
|
|
58
|
+
if (projectRoot) {
|
|
59
|
+
return { scope: "project", projectRoot, reason: "auto-detect" };
|
|
60
|
+
}
|
|
61
|
+
return { scope: "platform", reason: "fallback" };
|
|
62
|
+
}
|
|
63
|
+
function assertMutatingScope(value) {
|
|
64
|
+
if (!SCOPE_FLAG_CHOICES.includes(value)) {
|
|
65
|
+
throw new CliScopeError(
|
|
66
|
+
"SCOPE_INVALID",
|
|
67
|
+
`--scope must be one of: ${SCOPE_FLAG_CHOICES.join(", ")} (got ${JSON.stringify(value)})`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var CliScopeError = class extends Error {
|
|
72
|
+
code;
|
|
73
|
+
constructor(code, message) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.code = code;
|
|
76
|
+
this.name = "CliScopeError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
function scopeBody(ctx) {
|
|
80
|
+
return {
|
|
81
|
+
scope: ctx.scope,
|
|
82
|
+
...ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
40
85
|
|
|
41
86
|
// src/commands/plugins/disable.ts
|
|
42
87
|
var disable_default = defineCommand({
|
|
@@ -47,11 +92,25 @@ var disable_default = defineCommand({
|
|
|
47
92
|
const packageId = input.argv?.[0];
|
|
48
93
|
if (!packageId) {
|
|
49
94
|
ctx.ui?.error?.("Specify a plugin to disable");
|
|
50
|
-
return { exitCode: 1, result: { packageId: "" } };
|
|
95
|
+
return { exitCode: 1, result: { packageId: "", scope: "" } };
|
|
96
|
+
}
|
|
97
|
+
const flags = input.flags ?? input;
|
|
98
|
+
let scopeCtx;
|
|
99
|
+
try {
|
|
100
|
+
scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err instanceof CliScopeError) {
|
|
103
|
+
ctx.ui?.error?.(err.message);
|
|
104
|
+
return { exitCode: 1, result: { packageId: "", scope: "" } };
|
|
105
|
+
}
|
|
106
|
+
throw err;
|
|
51
107
|
}
|
|
52
|
-
await patch(`/packages/${encodeURIComponent(packageId)}`, {
|
|
53
|
-
|
|
54
|
-
|
|
108
|
+
await patch(`/packages/${encodeURIComponent(packageId)}`, {
|
|
109
|
+
enabled: false,
|
|
110
|
+
...scopeBody(scopeCtx)
|
|
111
|
+
});
|
|
112
|
+
ctx.ui?.success?.(`Disabled ${packageId} (${scopeCtx.scope})`);
|
|
113
|
+
return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };
|
|
55
114
|
}
|
|
56
115
|
}
|
|
57
116
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/http.ts","../../../src/commands/plugins/disable.ts"],"names":[],"mappings":";;;AAMA,IAAM,mBAAA,GAAsB,uBAAA;AAC5B,IAAM,kBAAA,GAAqB,qBAAA;AAC3B,IAAM,gBAAA,GAAmB,GAAA;AAEzB,SAAS,UAAA,GAAqB;AAC5B,EAAA,MAAM,cAAA,GAAiB,OAAO,oBAAoB,CAAA;AAClD,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,OAAO,CAAA,EAAG,cAAc,CAAA,EAAG,kBAAkB,CAAA,CAAA;AAAA,EAC/C;AACA,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,gBAAgB,CAAA,IAAK,mBAAA;AAC5C,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,EAAG,kBAAkB,CAAA,CAAA;AACxC;AA4BA,eAAsB,KAAA,CAAmB,MAAc,IAAA,EAA2C;AAChG,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,UAAA,EAAY,GAAG,IAAI,CAAA,CAAA;AAClC,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,gBAAgB,CAAA;AACnE,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAC3B,MAAA,EAAQ,OAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,MACzB,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,MAAM,IAAI,MAAM,CAAA,YAAA,EAAe,IAAI,YAAY,GAAA,CAAI,MAAM,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,CAAA;AAAA,IACvE;AACA,IAAA,OAAO,MAAM,IAAI,IAAA,EAAK;AAAA,EACxB,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAAc,SAAS,YAAA,EAAc;AACxC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,YAAA,EAAe,IAAI,CAAA,gFAAA,CAA6E,CAAA;AAAA,IAClH;AACA,IAAA,MAAM,GAAA;AAAA,EACR,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;;;AChEA,IAAO,kBAAQ,aAAA,CAA4D;AAAA,EACzE,EAAA,EAAI,6BAAA;AAAA,EACJ,WAAA,EAAa,kBAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAoE;AACtG,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,GAAO,CAAC,CAAA;AAChC,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,6BAA6B,CAAA;AAC7C,QAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAQ,EAAE,SAAA,EAAW,IAAG,EAAE;AAAA,MAClD;AACA,MAAA,MAAM,KAAA,CAAM,aAAa,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA,EAAI,EAAE,OAAA,EAAS,KAAA,EAAO,CAAA;AAC5E,MAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,SAAA,EAAY,SAAS,CAAA,CAAE,CAAA;AACzC,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,EAAE,WAAU,EAAE;AAAA,IAC9C;AAAA;AAEJ,CAAC","file":"disable.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { patch } from '../../http.js';\n\ninterface DisableInput { argv?: string[] }\n\nexport default defineCommand<unknown, DisableInput, { packageId: string }>({\n id: 'marketplace:plugins:disable',\n description: 'Disable a plugin',\n\n handler: {\n async execute(ctx: PluginContextV3, input: DisableInput): Promise<CommandResult<{ packageId: string }>> {\n const packageId = input.argv?.[0];\n if (!packageId) {\n ctx.ui?.error?.('Specify a plugin to disable');\n return { exitCode: 1, result: { packageId: '' } };\n }\n await patch(`/packages/${encodeURIComponent(packageId)}`, { enabled: false });\n ctx.ui?.success?.(`Disabled ${packageId}`);\n return { exitCode: 0, result: { packageId } };\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/disable.ts"],"names":["projectRoot"],"mappings":"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","file":"disable.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * @module @kb-labs/marketplace-entry/scope\n *\n * Client-side scope resolution for marketplace CLI commands. Uses the\n * canonical `findProjectConfigRoot` helper from `@kb-labs/core-workspace`\n * so the detection rules (which filenames count, how walk-up stops) match\n * what the config loader and the marketplace daemon enforce.\n *\n * Rules:\n * - `project` is the default if cwd (or any ancestor up to the filesystem\n * root) contains `.kb/kb.config.{json,jsonc}`.\n * - Otherwise the default is `platform`.\n * - `--scope` always overrides detection.\n * - For scope=\"project\" we return the absolute projectRoot so the daemon\n * doesn't need to re-discover it.\n */\n\nimport { findProjectConfigRoot } from '@kb-labs/core-workspace';\nimport type { MarketplaceScope, MarketplaceQueryScope } from '@kb-labs/marketplace-contracts';\n\nexport const SCOPE_FLAG_CHOICES: readonly MarketplaceScope[] = ['platform', 'project'];\nexport const QUERY_SCOPE_FLAG_CHOICES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport interface ResolvedCliScope {\n scope: MarketplaceScope;\n projectRoot?: string;\n /** How the scope was determined — surfaces in --verbose logs. */\n reason: 'flag' | 'auto-detect' | 'fallback';\n}\n\nexport interface ResolvedCliQueryScope extends Omit<ResolvedCliScope, 'scope'> {\n scope: MarketplaceQueryScope;\n}\n\n/**\n * Resolve the effective scope for a mutating command (`link`, `unlink`,\n * `install`, ...). `flag` is the value of `--scope` (if supplied). The\n * helper never returns `'all'` for mutating commands — callers restrict\n * choices via `SCOPE_FLAG_CHOICES`.\n */\nexport async function resolveCliScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliScope> {\n if (flag) {\n assertMutatingScope(flag);\n if (flag === 'project') {\n const projectRoot = await findProjectConfigRoot(cwd);\n if (!projectRoot) {\n throw new CliScopeError(\n 'SCOPE_PROJECT_ROOT_NOT_FOUND',\n `--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} — none found.`,\n );\n }\n return { scope: 'project', projectRoot, reason: 'flag' };\n }\n return { scope: 'platform', reason: 'flag' };\n }\n\n const projectRoot = await findProjectConfigRoot(cwd);\n if (projectRoot) {\n return { scope: 'project', projectRoot, reason: 'auto-detect' };\n }\n return { scope: 'platform', reason: 'fallback' };\n}\n\n/**\n * Resolve the effective scope for a read-only command (`list`). Accepts\n * `'all'` as an explicit flag value.\n */\nexport async function resolveCliQueryScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliQueryScope> {\n if (flag === 'all') {\n const projectRoot = await findProjectConfigRoot(cwd);\n return { scope: 'all', projectRoot, reason: 'flag' };\n }\n const base = await resolveCliScope(cwd, flag);\n return { scope: base.scope, projectRoot: base.projectRoot, reason: base.reason };\n}\n\nfunction assertMutatingScope(value: string): asserts value is MarketplaceScope {\n if (!SCOPE_FLAG_CHOICES.includes(value as MarketplaceScope)) {\n throw new CliScopeError(\n 'SCOPE_INVALID',\n `--scope must be one of: ${SCOPE_FLAG_CHOICES.join(', ')} (got ${JSON.stringify(value)})`,\n );\n }\n}\n\nexport class CliScopeError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n this.name = 'CliScopeError';\n }\n}\n\n/**\n * Build the body-payload fragment expected by `parseMutatingScope` on the\n * API side: `{ scope, projectRoot? }`. Kept as a helper so every command\n * sends the same shape and nothing drifts out-of-sync with the server.\n */\nexport function scopeBody(ctx: ResolvedCliScope | ResolvedCliQueryScope): {\n scope: MarketplaceScope | MarketplaceQueryScope;\n projectRoot?: string;\n} {\n return {\n scope: ctx.scope,\n ...(ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}),\n };\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { patch } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface DisableFlags { scope?: string }\ninterface DisableInput { argv?: string[]; flags?: DisableFlags }\n\nexport default defineCommand<unknown, DisableInput, { packageId: string; scope: string }>({\n id: 'marketplace:plugins:disable',\n description: 'Disable a plugin',\n\n handler: {\n async execute(ctx: PluginContextV3, input: DisableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n if (!packageId) {\n ctx.ui?.error?.('Specify a plugin to disable');\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n const flags = (input.flags ?? input) as DisableFlags;\n\n let scopeCtx;\n try {\n scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);\n } catch (err) {\n if (err instanceof CliScopeError) {\n ctx.ui?.error?.(err.message);\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n throw err;\n }\n\n await patch(`/packages/${encodeURIComponent(packageId)}`, {\n enabled: false,\n ...scopeBody(scopeCtx),\n });\n ctx.ui?.success?.(`Disabled ${packageId} (${scopeCtx.scope})`);\n return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };\n },\n },\n});\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineCommand, useEnv } from '@kb-labs/sdk';
|
|
2
|
+
import { findProjectConfigRoot } from '@kb-labs/core-workspace';
|
|
2
3
|
|
|
3
4
|
// src/commands/plugins/doctor.ts
|
|
4
5
|
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:4000";
|
|
@@ -14,6 +15,11 @@ function getBaseUrl() {
|
|
|
14
15
|
}
|
|
15
16
|
async function get(path, params) {
|
|
16
17
|
const url = new URL(`${getBaseUrl()}${path}`);
|
|
18
|
+
if (params) {
|
|
19
|
+
for (const [k, v] of Object.entries(params)) {
|
|
20
|
+
url.searchParams.set(k, v);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
17
23
|
const controller = new AbortController();
|
|
18
24
|
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
19
25
|
try {
|
|
@@ -32,6 +38,44 @@ async function get(path, params) {
|
|
|
32
38
|
clearTimeout(timer);
|
|
33
39
|
}
|
|
34
40
|
}
|
|
41
|
+
var SCOPE_FLAG_CHOICES = ["platform", "project"];
|
|
42
|
+
async function resolveCliScope(cwd, flag) {
|
|
43
|
+
if (flag) {
|
|
44
|
+
assertMutatingScope(flag);
|
|
45
|
+
if (flag === "project") {
|
|
46
|
+
const projectRoot2 = await findProjectConfigRoot(cwd);
|
|
47
|
+
if (!projectRoot2) {
|
|
48
|
+
throw new CliScopeError(
|
|
49
|
+
"SCOPE_PROJECT_ROOT_NOT_FOUND",
|
|
50
|
+
`--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} \u2014 none found.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return { scope: "project", projectRoot: projectRoot2, reason: "flag" };
|
|
54
|
+
}
|
|
55
|
+
return { scope: "platform", reason: "flag" };
|
|
56
|
+
}
|
|
57
|
+
const projectRoot = await findProjectConfigRoot(cwd);
|
|
58
|
+
if (projectRoot) {
|
|
59
|
+
return { scope: "project", projectRoot, reason: "auto-detect" };
|
|
60
|
+
}
|
|
61
|
+
return { scope: "platform", reason: "fallback" };
|
|
62
|
+
}
|
|
63
|
+
function assertMutatingScope(value) {
|
|
64
|
+
if (!SCOPE_FLAG_CHOICES.includes(value)) {
|
|
65
|
+
throw new CliScopeError(
|
|
66
|
+
"SCOPE_INVALID",
|
|
67
|
+
`--scope must be one of: ${SCOPE_FLAG_CHOICES.join(", ")} (got ${JSON.stringify(value)})`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var CliScopeError = class extends Error {
|
|
72
|
+
code;
|
|
73
|
+
constructor(code, message) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.code = code;
|
|
76
|
+
this.name = "CliScopeError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
35
79
|
|
|
36
80
|
// src/commands/plugins/doctor.ts
|
|
37
81
|
var doctor_default = defineCommand({
|
|
@@ -40,14 +84,28 @@ var doctor_default = defineCommand({
|
|
|
40
84
|
handler: {
|
|
41
85
|
async execute(ctx, input) {
|
|
42
86
|
const flags = input.flags ?? input;
|
|
43
|
-
|
|
87
|
+
let scopeCtx;
|
|
88
|
+
try {
|
|
89
|
+
scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
if (err instanceof CliScopeError) {
|
|
92
|
+
ctx.ui?.error?.(err.message);
|
|
93
|
+
return { exitCode: 1, result: { ok: false, total: 0, issues: [] } };
|
|
94
|
+
}
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
const query = { scope: scopeCtx.scope };
|
|
98
|
+
if (scopeCtx.projectRoot) {
|
|
99
|
+
query.projectRoot = scopeCtx.projectRoot;
|
|
100
|
+
}
|
|
101
|
+
const report = await get("/diagnostics", query);
|
|
44
102
|
if (flags.json) {
|
|
45
103
|
ctx.ui?.json?.(report);
|
|
46
104
|
} else if (report.issues.length === 0) {
|
|
47
|
-
ctx.ui?.success?.(`All ${report.total} packages healthy`);
|
|
105
|
+
ctx.ui?.success?.(`All ${report.total} packages healthy (${scopeCtx.scope})`);
|
|
48
106
|
} else {
|
|
49
107
|
const errors = report.issues.filter((i) => i.severity === "error");
|
|
50
|
-
ctx.ui?.warn?.(
|
|
108
|
+
ctx.ui?.warn?.(`Marketplace Doctor (${scopeCtx.scope})`, {
|
|
51
109
|
sections: [
|
|
52
110
|
{ header: "Summary", items: [`Total: ${report.total}`, `Issues: ${report.issues.length}`, `Errors: ${errors.length}`] },
|
|
53
111
|
{ header: "Issues", items: report.issues.map((i) => `${i.severity === "error" ? "\u274C" : "\u26A0"} ${i.packageId}: ${i.message}`) }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/http.ts","../../../src/commands/plugins/doctor.ts"],"names":[],"mappings":"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","file":"doctor.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { get } from '../../http.js';\n\ninterface DoctorFlags { json?: boolean }\ninterface DoctorInput { flags?: DoctorFlags }\n\ninterface DoctorIssue {\n severity: string;\n packageId: string;\n message: string;\n remediation?: string;\n}\n\ninterface DoctorResultData {\n ok: boolean;\n total: number;\n issues: DoctorIssue[];\n}\n\nexport default defineCommand<unknown, DoctorInput, DoctorResultData>({\n id: 'marketplace:plugins:doctor',\n description: 'Diagnose marketplace health',\n\n handler: {\n async execute(ctx: PluginContextV3, input: DoctorInput): Promise<CommandResult<DoctorResultData>> {\n const flags = (input.flags ?? input) as DoctorFlags;\n const report = await get<DoctorResultData>('/diagnostics');\n\n if (flags.json) {\n ctx.ui?.json?.(report);\n } else if (report.issues.length === 0) {\n ctx.ui?.success?.(`All ${report.total} packages healthy`);\n } else {\n const errors = report.issues.filter(i => i.severity === 'error');\n ctx.ui?.warn?.('Marketplace Doctor', {\n sections: [\n { header: 'Summary', items: [`Total: ${report.total}`, `Issues: ${report.issues.length}`, `Errors: ${errors.length}`] },\n { header: 'Issues', items: report.issues.map(i => `${i.severity === 'error' ? '❌' : '⚠'} ${i.packageId}: ${i.message}`) },\n ],\n });\n }\n\n return { exitCode: report.ok ? 0 : 1, result: report };\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/doctor.ts"],"names":["projectRoot"],"mappings":"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","file":"doctor.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * @module @kb-labs/marketplace-entry/scope\n *\n * Client-side scope resolution for marketplace CLI commands. Uses the\n * canonical `findProjectConfigRoot` helper from `@kb-labs/core-workspace`\n * so the detection rules (which filenames count, how walk-up stops) match\n * what the config loader and the marketplace daemon enforce.\n *\n * Rules:\n * - `project` is the default if cwd (or any ancestor up to the filesystem\n * root) contains `.kb/kb.config.{json,jsonc}`.\n * - Otherwise the default is `platform`.\n * - `--scope` always overrides detection.\n * - For scope=\"project\" we return the absolute projectRoot so the daemon\n * doesn't need to re-discover it.\n */\n\nimport { findProjectConfigRoot } from '@kb-labs/core-workspace';\nimport type { MarketplaceScope, MarketplaceQueryScope } from '@kb-labs/marketplace-contracts';\n\nexport const SCOPE_FLAG_CHOICES: readonly MarketplaceScope[] = ['platform', 'project'];\nexport const QUERY_SCOPE_FLAG_CHOICES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport interface ResolvedCliScope {\n scope: MarketplaceScope;\n projectRoot?: string;\n /** How the scope was determined — surfaces in --verbose logs. */\n reason: 'flag' | 'auto-detect' | 'fallback';\n}\n\nexport interface ResolvedCliQueryScope extends Omit<ResolvedCliScope, 'scope'> {\n scope: MarketplaceQueryScope;\n}\n\n/**\n * Resolve the effective scope for a mutating command (`link`, `unlink`,\n * `install`, ...). `flag` is the value of `--scope` (if supplied). The\n * helper never returns `'all'` for mutating commands — callers restrict\n * choices via `SCOPE_FLAG_CHOICES`.\n */\nexport async function resolveCliScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliScope> {\n if (flag) {\n assertMutatingScope(flag);\n if (flag === 'project') {\n const projectRoot = await findProjectConfigRoot(cwd);\n if (!projectRoot) {\n throw new CliScopeError(\n 'SCOPE_PROJECT_ROOT_NOT_FOUND',\n `--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} — none found.`,\n );\n }\n return { scope: 'project', projectRoot, reason: 'flag' };\n }\n return { scope: 'platform', reason: 'flag' };\n }\n\n const projectRoot = await findProjectConfigRoot(cwd);\n if (projectRoot) {\n return { scope: 'project', projectRoot, reason: 'auto-detect' };\n }\n return { scope: 'platform', reason: 'fallback' };\n}\n\n/**\n * Resolve the effective scope for a read-only command (`list`). Accepts\n * `'all'` as an explicit flag value.\n */\nexport async function resolveCliQueryScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliQueryScope> {\n if (flag === 'all') {\n const projectRoot = await findProjectConfigRoot(cwd);\n return { scope: 'all', projectRoot, reason: 'flag' };\n }\n const base = await resolveCliScope(cwd, flag);\n return { scope: base.scope, projectRoot: base.projectRoot, reason: base.reason };\n}\n\nfunction assertMutatingScope(value: string): asserts value is MarketplaceScope {\n if (!SCOPE_FLAG_CHOICES.includes(value as MarketplaceScope)) {\n throw new CliScopeError(\n 'SCOPE_INVALID',\n `--scope must be one of: ${SCOPE_FLAG_CHOICES.join(', ')} (got ${JSON.stringify(value)})`,\n );\n }\n}\n\nexport class CliScopeError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n this.name = 'CliScopeError';\n }\n}\n\n/**\n * Build the body-payload fragment expected by `parseMutatingScope` on the\n * API side: `{ scope, projectRoot? }`. Kept as a helper so every command\n * sends the same shape and nothing drifts out-of-sync with the server.\n */\nexport function scopeBody(ctx: ResolvedCliScope | ResolvedCliQueryScope): {\n scope: MarketplaceScope | MarketplaceQueryScope;\n projectRoot?: string;\n} {\n return {\n scope: ctx.scope,\n ...(ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}),\n };\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { get } from '../../http.js';\nimport { resolveCliScope, CliScopeError } from '../../scope.js';\n\ninterface DoctorFlags { json?: boolean; scope?: string }\ninterface DoctorInput { flags?: DoctorFlags }\n\ninterface DoctorIssue {\n severity: string;\n packageId: string;\n message: string;\n remediation?: string;\n}\n\ninterface DoctorResultData {\n ok: boolean;\n total: number;\n issues: DoctorIssue[];\n}\n\nexport default defineCommand<unknown, DoctorInput, DoctorResultData>({\n id: 'marketplace:plugins:doctor',\n description: 'Diagnose marketplace health',\n\n handler: {\n async execute(ctx: PluginContextV3, input: DoctorInput): Promise<CommandResult<DoctorResultData>> {\n const flags = (input.flags ?? input) as DoctorFlags;\n\n let scopeCtx;\n try {\n scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);\n } catch (err) {\n if (err instanceof CliScopeError) {\n ctx.ui?.error?.(err.message);\n return { exitCode: 1, result: { ok: false, total: 0, issues: [] } };\n }\n throw err;\n }\n\n const query: Record<string, string> = { scope: scopeCtx.scope };\n if (scopeCtx.projectRoot) { query.projectRoot = scopeCtx.projectRoot; }\n const report = await get<DoctorResultData>('/diagnostics', query);\n\n if (flags.json) {\n ctx.ui?.json?.(report);\n } else if (report.issues.length === 0) {\n ctx.ui?.success?.(`All ${report.total} packages healthy (${scopeCtx.scope})`);\n } else {\n const errors = report.issues.filter(i => i.severity === 'error');\n ctx.ui?.warn?.(`Marketplace Doctor (${scopeCtx.scope})`, {\n sections: [\n { header: 'Summary', items: [`Total: ${report.total}`, `Issues: ${report.issues.length}`, `Errors: ${errors.length}`] },\n { header: 'Issues', items: report.issues.map(i => `${i.severity === 'error' ? '❌' : '⚠'} ${i.packageId}: ${i.message}`) },\n ],\n });\n }\n\n return { exitCode: report.ok ? 0 : 1, result: report };\n },\n },\n});\n"]}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
2
|
|
|
3
|
+
interface EnableFlags {
|
|
4
|
+
scope?: string;
|
|
5
|
+
}
|
|
3
6
|
interface EnableInput {
|
|
4
7
|
argv?: string[];
|
|
8
|
+
flags?: EnableFlags;
|
|
5
9
|
}
|
|
6
10
|
declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, EnableInput, {
|
|
7
11
|
packageId: string;
|
|
12
|
+
scope: string;
|
|
8
13
|
}>;
|
|
9
14
|
|
|
10
15
|
export { _default as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineCommand, useEnv } from '@kb-labs/sdk';
|
|
2
|
+
import { findProjectConfigRoot } from '@kb-labs/core-workspace';
|
|
2
3
|
|
|
3
4
|
// src/commands/plugins/enable.ts
|
|
4
5
|
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:4000";
|
|
@@ -37,6 +38,50 @@ async function patch(path, body) {
|
|
|
37
38
|
clearTimeout(timer);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
41
|
+
var SCOPE_FLAG_CHOICES = ["platform", "project"];
|
|
42
|
+
async function resolveCliScope(cwd, flag) {
|
|
43
|
+
if (flag) {
|
|
44
|
+
assertMutatingScope(flag);
|
|
45
|
+
if (flag === "project") {
|
|
46
|
+
const projectRoot2 = await findProjectConfigRoot(cwd);
|
|
47
|
+
if (!projectRoot2) {
|
|
48
|
+
throw new CliScopeError(
|
|
49
|
+
"SCOPE_PROJECT_ROOT_NOT_FOUND",
|
|
50
|
+
`--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} \u2014 none found.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return { scope: "project", projectRoot: projectRoot2, reason: "flag" };
|
|
54
|
+
}
|
|
55
|
+
return { scope: "platform", reason: "flag" };
|
|
56
|
+
}
|
|
57
|
+
const projectRoot = await findProjectConfigRoot(cwd);
|
|
58
|
+
if (projectRoot) {
|
|
59
|
+
return { scope: "project", projectRoot, reason: "auto-detect" };
|
|
60
|
+
}
|
|
61
|
+
return { scope: "platform", reason: "fallback" };
|
|
62
|
+
}
|
|
63
|
+
function assertMutatingScope(value) {
|
|
64
|
+
if (!SCOPE_FLAG_CHOICES.includes(value)) {
|
|
65
|
+
throw new CliScopeError(
|
|
66
|
+
"SCOPE_INVALID",
|
|
67
|
+
`--scope must be one of: ${SCOPE_FLAG_CHOICES.join(", ")} (got ${JSON.stringify(value)})`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var CliScopeError = class extends Error {
|
|
72
|
+
code;
|
|
73
|
+
constructor(code, message) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.code = code;
|
|
76
|
+
this.name = "CliScopeError";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
function scopeBody(ctx) {
|
|
80
|
+
return {
|
|
81
|
+
scope: ctx.scope,
|
|
82
|
+
...ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
40
85
|
|
|
41
86
|
// src/commands/plugins/enable.ts
|
|
42
87
|
var enable_default = defineCommand({
|
|
@@ -47,11 +92,25 @@ var enable_default = defineCommand({
|
|
|
47
92
|
const packageId = input.argv?.[0];
|
|
48
93
|
if (!packageId) {
|
|
49
94
|
ctx.ui?.error?.("Specify a plugin to enable");
|
|
50
|
-
return { exitCode: 1, result: { packageId: "" } };
|
|
95
|
+
return { exitCode: 1, result: { packageId: "", scope: "" } };
|
|
96
|
+
}
|
|
97
|
+
const flags = input.flags ?? input;
|
|
98
|
+
let scopeCtx;
|
|
99
|
+
try {
|
|
100
|
+
scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
if (err instanceof CliScopeError) {
|
|
103
|
+
ctx.ui?.error?.(err.message);
|
|
104
|
+
return { exitCode: 1, result: { packageId: "", scope: "" } };
|
|
105
|
+
}
|
|
106
|
+
throw err;
|
|
51
107
|
}
|
|
52
|
-
await patch(`/packages/${encodeURIComponent(packageId)}`, {
|
|
53
|
-
|
|
54
|
-
|
|
108
|
+
await patch(`/packages/${encodeURIComponent(packageId)}`, {
|
|
109
|
+
enabled: true,
|
|
110
|
+
...scopeBody(scopeCtx)
|
|
111
|
+
});
|
|
112
|
+
ctx.ui?.success?.(`Enabled ${packageId} (${scopeCtx.scope})`);
|
|
113
|
+
return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };
|
|
55
114
|
}
|
|
56
115
|
}
|
|
57
116
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/http.ts","../../../src/commands/plugins/enable.ts"],"names":[],"mappings":";;;AAMA,IAAM,mBAAA,GAAsB,uBAAA;AAC5B,IAAM,kBAAA,GAAqB,qBAAA;AAC3B,IAAM,gBAAA,GAAmB,GAAA;AAEzB,SAAS,UAAA,GAAqB;AAC5B,EAAA,MAAM,cAAA,GAAiB,OAAO,oBAAoB,CAAA;AAClD,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,OAAO,CAAA,EAAG,cAAc,CAAA,EAAG,kBAAkB,CAAA,CAAA;AAAA,EAC/C;AACA,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,gBAAgB,CAAA,IAAK,mBAAA;AAC5C,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,EAAG,kBAAkB,CAAA,CAAA;AACxC;AA4BA,eAAsB,KAAA,CAAmB,MAAc,IAAA,EAA2C;AAChG,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,UAAA,EAAY,GAAG,IAAI,CAAA,CAAA;AAClC,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,gBAAgB,CAAA;AACnE,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAC3B,MAAA,EAAQ,OAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,MACzB,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,MAAM,IAAI,MAAM,CAAA,YAAA,EAAe,IAAI,YAAY,GAAA,CAAI,MAAM,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,CAAA;AAAA,IACvE;AACA,IAAA,OAAO,MAAM,IAAI,IAAA,EAAK;AAAA,EACxB,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAAc,SAAS,YAAA,EAAc;AACxC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,YAAA,EAAe,IAAI,CAAA,gFAAA,CAA6E,CAAA;AAAA,IAClH;AACA,IAAA,MAAM,GAAA;AAAA,EACR,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;;;AChEA,IAAO,iBAAQ,aAAA,CAA2D;AAAA,EACxE,EAAA,EAAI,4BAAA;AAAA,EACJ,WAAA,EAAa,iBAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAmE;AACrG,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,GAAO,CAAC,CAAA;AAChC,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,4BAA4B,CAAA;AAC5C,QAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAQ,EAAE,SAAA,EAAW,IAAG,EAAE;AAAA,MAClD;AACA,MAAA,MAAM,KAAA,CAAM,aAAa,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA,EAAI,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AAC3E,MAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,QAAA,EAAW,SAAS,CAAA,CAAE,CAAA;AACxC,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,EAAE,WAAU,EAAE;AAAA,IAC9C;AAAA;AAEJ,CAAC","file":"enable.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { patch } from '../../http.js';\n\ninterface EnableInput { argv?: string[] }\n\nexport default defineCommand<unknown, EnableInput, { packageId: string }>({\n id: 'marketplace:plugins:enable',\n description: 'Enable a plugin',\n\n handler: {\n async execute(ctx: PluginContextV3, input: EnableInput): Promise<CommandResult<{ packageId: string }>> {\n const packageId = input.argv?.[0];\n if (!packageId) {\n ctx.ui?.error?.('Specify a plugin to enable');\n return { exitCode: 1, result: { packageId: '' } };\n }\n await patch(`/packages/${encodeURIComponent(packageId)}`, { enabled: true });\n ctx.ui?.success?.(`Enabled ${packageId}`);\n return { exitCode: 0, result: { packageId } };\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/enable.ts"],"names":["projectRoot"],"mappings":"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","file":"enable.js","sourcesContent":["/**\n * HTTP client for marketplace service via Gateway.\n */\n\nimport { useEnv } from '@kb-labs/sdk';\n\nconst DEFAULT_GATEWAY_URL = 'http://127.0.0.1:4000';\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\nconst FETCH_TIMEOUT_MS = 30_000;\n\nfunction getBaseUrl(): string {\n const marketplaceUrl = useEnv('KB_MARKETPLACE_URL');\n if (marketplaceUrl) {\n return `${marketplaceUrl}${MARKETPLACE_PREFIX}`;\n }\n const gateway = useEnv('KB_GATEWAY_URL') ?? DEFAULT_GATEWAY_URL;\n return `${gateway}${MARKETPLACE_PREFIX}`;\n}\n\nexport async function post<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function patch<T = unknown>(path: string, body: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function del<T = unknown>(path: string, body?: Record<string, unknown>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: body ? { 'Content-Type': 'application/json' } : {},\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n if (res.status === 204) { return undefined as T; }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function get<T = unknown>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${getBaseUrl()}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {url.searchParams.set(k, v);}\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(url.toString(), { signal: controller.signal });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Marketplace ${path} failed (${res.status}): ${text}`);\n }\n return await res.json() as T;\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n throw new Error(`Marketplace ${path} timed out — is the marketplace service running? (kb-dev start marketplace)`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * @module @kb-labs/marketplace-entry/scope\n *\n * Client-side scope resolution for marketplace CLI commands. Uses the\n * canonical `findProjectConfigRoot` helper from `@kb-labs/core-workspace`\n * so the detection rules (which filenames count, how walk-up stops) match\n * what the config loader and the marketplace daemon enforce.\n *\n * Rules:\n * - `project` is the default if cwd (or any ancestor up to the filesystem\n * root) contains `.kb/kb.config.{json,jsonc}`.\n * - Otherwise the default is `platform`.\n * - `--scope` always overrides detection.\n * - For scope=\"project\" we return the absolute projectRoot so the daemon\n * doesn't need to re-discover it.\n */\n\nimport { findProjectConfigRoot } from '@kb-labs/core-workspace';\nimport type { MarketplaceScope, MarketplaceQueryScope } from '@kb-labs/marketplace-contracts';\n\nexport const SCOPE_FLAG_CHOICES: readonly MarketplaceScope[] = ['platform', 'project'];\nexport const QUERY_SCOPE_FLAG_CHOICES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport interface ResolvedCliScope {\n scope: MarketplaceScope;\n projectRoot?: string;\n /** How the scope was determined — surfaces in --verbose logs. */\n reason: 'flag' | 'auto-detect' | 'fallback';\n}\n\nexport interface ResolvedCliQueryScope extends Omit<ResolvedCliScope, 'scope'> {\n scope: MarketplaceQueryScope;\n}\n\n/**\n * Resolve the effective scope for a mutating command (`link`, `unlink`,\n * `install`, ...). `flag` is the value of `--scope` (if supplied). The\n * helper never returns `'all'` for mutating commands — callers restrict\n * choices via `SCOPE_FLAG_CHOICES`.\n */\nexport async function resolveCliScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliScope> {\n if (flag) {\n assertMutatingScope(flag);\n if (flag === 'project') {\n const projectRoot = await findProjectConfigRoot(cwd);\n if (!projectRoot) {\n throw new CliScopeError(\n 'SCOPE_PROJECT_ROOT_NOT_FOUND',\n `--scope=project requires a .kb/kb.config.{json,jsonc} ancestor of ${cwd} — none found.`,\n );\n }\n return { scope: 'project', projectRoot, reason: 'flag' };\n }\n return { scope: 'platform', reason: 'flag' };\n }\n\n const projectRoot = await findProjectConfigRoot(cwd);\n if (projectRoot) {\n return { scope: 'project', projectRoot, reason: 'auto-detect' };\n }\n return { scope: 'platform', reason: 'fallback' };\n}\n\n/**\n * Resolve the effective scope for a read-only command (`list`). Accepts\n * `'all'` as an explicit flag value.\n */\nexport async function resolveCliQueryScope(\n cwd: string,\n flag: string | undefined,\n): Promise<ResolvedCliQueryScope> {\n if (flag === 'all') {\n const projectRoot = await findProjectConfigRoot(cwd);\n return { scope: 'all', projectRoot, reason: 'flag' };\n }\n const base = await resolveCliScope(cwd, flag);\n return { scope: base.scope, projectRoot: base.projectRoot, reason: base.reason };\n}\n\nfunction assertMutatingScope(value: string): asserts value is MarketplaceScope {\n if (!SCOPE_FLAG_CHOICES.includes(value as MarketplaceScope)) {\n throw new CliScopeError(\n 'SCOPE_INVALID',\n `--scope must be one of: ${SCOPE_FLAG_CHOICES.join(', ')} (got ${JSON.stringify(value)})`,\n );\n }\n}\n\nexport class CliScopeError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n this.name = 'CliScopeError';\n }\n}\n\n/**\n * Build the body-payload fragment expected by `parseMutatingScope` on the\n * API side: `{ scope, projectRoot? }`. Kept as a helper so every command\n * sends the same shape and nothing drifts out-of-sync with the server.\n */\nexport function scopeBody(ctx: ResolvedCliScope | ResolvedCliQueryScope): {\n scope: MarketplaceScope | MarketplaceQueryScope;\n projectRoot?: string;\n} {\n return {\n scope: ctx.scope,\n ...(ctx.projectRoot ? { projectRoot: ctx.projectRoot } : {}),\n };\n}\n","import { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { patch } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface EnableFlags { scope?: string }\ninterface EnableInput { argv?: string[]; flags?: EnableFlags }\n\nexport default defineCommand<unknown, EnableInput, { packageId: string; scope: string }>({\n id: 'marketplace:plugins:enable',\n description: 'Enable a plugin',\n\n handler: {\n async execute(ctx: PluginContextV3, input: EnableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n if (!packageId) {\n ctx.ui?.error?.('Specify a plugin to enable');\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n const flags = (input.flags ?? input) as EnableFlags;\n\n let scopeCtx;\n try {\n scopeCtx = await resolveCliScope(ctx.cwd, flags.scope);\n } catch (err) {\n if (err instanceof CliScopeError) {\n ctx.ui?.error?.(err.message);\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n throw err;\n }\n\n await patch(`/packages/${encodeURIComponent(packageId)}`, {\n enabled: true,\n ...scopeBody(scopeCtx),\n });\n ctx.ui?.success?.(`Enabled ${packageId} (${scopeCtx.scope})`);\n return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };\n },\n },\n});\n"]}
|