@kb-labs/marketplace-entry 2.109.0 → 2.111.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.js +4 -4
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/plugins/disable.js +4 -4
- package/dist/commands/plugins/disable.js.map +1 -1
- package/dist/commands/plugins/doctor.js +3 -3
- package/dist/commands/plugins/doctor.js.map +1 -1
- package/dist/commands/plugins/enable.js +4 -4
- package/dist/commands/plugins/enable.js.map +1 -1
- package/dist/commands/plugins/link.js +4 -4
- package/dist/commands/plugins/link.js.map +1 -1
- package/dist/commands/plugins/list.js +3 -3
- package/dist/commands/plugins/list.js.map +1 -1
- package/dist/commands/plugins/refresh.d.ts +1 -3
- package/dist/commands/plugins/refresh.js +2 -2
- package/dist/commands/plugins/refresh.js.map +1 -1
- package/dist/commands/plugins/unlink.js +4 -4
- package/dist/commands/plugins/unlink.js.map +1 -1
- package/dist/commands/sync.js +4 -4
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/uninstall.js +4 -4
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +3 -3
- package/dist/commands/update.js.map +1 -1
- package/package.json +3 -3
package/dist/commands/install.js
CHANGED
|
@@ -108,7 +108,7 @@ var install_default = defineCommand({
|
|
|
108
108
|
const flags = input.flags ?? input;
|
|
109
109
|
if (argv.length === 0) {
|
|
110
110
|
validationError(ctx, "Please specify at least one package to install", "Usage: kb marketplace install <package>", flags.json);
|
|
111
|
-
return {
|
|
111
|
+
return { ok: false, error: "Please specify at least one package to install", result: { installed: [], warnings: [], scope: "" } };
|
|
112
112
|
}
|
|
113
113
|
let scopeCtx;
|
|
114
114
|
try {
|
|
@@ -119,7 +119,7 @@ var install_default = defineCommand({
|
|
|
119
119
|
} else {
|
|
120
120
|
handleError(ctx, err, flags.json);
|
|
121
121
|
}
|
|
122
|
-
return {
|
|
122
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { installed: [], warnings: [], scope: "" } };
|
|
123
123
|
}
|
|
124
124
|
try {
|
|
125
125
|
const result = await post("/packages/install", {
|
|
@@ -141,10 +141,10 @@ var install_default = defineCommand({
|
|
|
141
141
|
]
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
|
-
return {
|
|
144
|
+
return { ok: true, result };
|
|
145
145
|
} catch (err) {
|
|
146
146
|
handleError(ctx, err, flags.json);
|
|
147
|
-
return {
|
|
147
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { installed: [], warnings: [], scope: "" } };
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
}
|
|
@@ -1 +1 @@
|
|
|
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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, 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 token?: string;\n 'dry-run'?: 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 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 intent(_ctx: PluginContextV3, input: InstallInput) {\n const argv = input.argv ?? [];\n const packages = argv.length > 0 ? argv : ['(no packages specified)'];\n return {\n summary: `Install ${packages.join(', ')} from marketplace`,\n operations: packages.map(pkg => ({\n type: 'create' as const,\n resource: 'marketplace-package',\n details: { package: pkg },\n })),\n };\n },\n\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 validationError(ctx, 'Please specify at least one package to install', 'Usage: kb marketplace install <package>', flags.json);\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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { exitCode: 1, result: { installed: [], warnings: [], scope: '' } };\n }\n\n try {\n const result = await post<InstallResultData>('/packages/install', {\n specs: argv,\n dev: Boolean(flags.dev),\n ...(flags.token ? { token: flags.token } : {}),\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 } catch (err) {\n handleError(ctx, err, flags.json);\n return { exitCode: 1, result: { installed: [], warnings: [], scope: '' } };\n }\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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, 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 token?: string;\n 'dry-run'?: 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 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 intent(_ctx: PluginContextV3, input: InstallInput) {\n const argv = input.argv ?? [];\n const packages = argv.length > 0 ? argv : ['(no packages specified)'];\n return {\n summary: `Install ${packages.join(', ')} from marketplace`,\n operations: packages.map(pkg => ({\n type: 'create' as const,\n resource: 'marketplace-package',\n details: { package: pkg },\n })),\n };\n },\n\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 validationError(ctx, 'Please specify at least one package to install', 'Usage: kb marketplace install <package>', flags.json);\n return { ok: false, error: 'Please specify at least one package to install', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { installed: [], warnings: [], scope: '' } };\n }\n\n try {\n const result = await post<InstallResultData>('/packages/install', {\n specs: argv,\n dev: Boolean(flags.dev),\n ...(flags.token ? { token: flags.token } : {}),\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 { ok: true, result };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { installed: [], warnings: [], scope: '' } };\n }\n },\n },\n});\n"]}
|
|
@@ -103,7 +103,7 @@ var disable_default = defineCommand({
|
|
|
103
103
|
const flags = input.flags ?? input;
|
|
104
104
|
if (!packageId) {
|
|
105
105
|
validationError(ctx, "Specify a plugin to disable", "Usage: kb marketplace plugins disable <plugin-id>", flags.json);
|
|
106
|
-
return {
|
|
106
|
+
return { ok: false, error: "A package id is required", result: { packageId: "", scope: "" } };
|
|
107
107
|
}
|
|
108
108
|
let scopeCtx;
|
|
109
109
|
try {
|
|
@@ -114,7 +114,7 @@ var disable_default = defineCommand({
|
|
|
114
114
|
} else {
|
|
115
115
|
handleError(ctx, err, flags.json);
|
|
116
116
|
}
|
|
117
|
-
return {
|
|
117
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: "", scope: "" } };
|
|
118
118
|
}
|
|
119
119
|
try {
|
|
120
120
|
await post(`/packages/disable`, { packageId, ...scopeBody(scopeCtx) });
|
|
@@ -123,10 +123,10 @@ var disable_default = defineCommand({
|
|
|
123
123
|
} else {
|
|
124
124
|
ctx.ui?.success?.(`Disabled ${packageId} (${scopeCtx.scope})`);
|
|
125
125
|
}
|
|
126
|
-
return {
|
|
126
|
+
return { ok: true, result: { packageId, scope: scopeCtx.scope } };
|
|
127
127
|
} catch (err) {
|
|
128
128
|
handleError(ctx, err, flags.json);
|
|
129
|
-
return {
|
|
129
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: "", scope: "" } };
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -1 +1 @@
|
|
|
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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface DisableFlags { json?: boolean; scope?: string; 'dry-run'?: boolean }\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 intent(_ctx: PluginContextV3, input: DisableInput) {\n const packageId = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Disable plugin \"${packageId}\"`,\n operations: [{ type: 'update' as const, resource: 'plugin', details: { packageId, enabled: false } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: DisableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n const flags = (input.flags ?? input) as DisableFlags;\n\n if (!packageId) {\n validationError(ctx, 'Specify a plugin to disable', 'Usage: kb marketplace plugins disable <plugin-id>', flags.json);\n return { exitCode: 1, result: { packageId: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n\n try {\n await post(`/packages/disable`, { packageId, ...scopeBody(scopeCtx) });\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, packageId, scope: scopeCtx.scope });\n } else {\n ctx.ui?.success?.(`Disabled ${packageId} (${scopeCtx.scope})`);\n }\n return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface DisableFlags { json?: boolean; scope?: string; 'dry-run'?: boolean }\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 intent(_ctx: PluginContextV3, input: DisableInput) {\n const packageId = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Disable plugin \"${packageId}\"`,\n operations: [{ type: 'update' as const, resource: 'plugin', details: { packageId, enabled: false } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: DisableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n const flags = (input.flags ?? input) as DisableFlags;\n\n if (!packageId) {\n validationError(ctx, 'Specify a plugin to disable', 'Usage: kb marketplace plugins disable <plugin-id>', flags.json);\n return { ok: false, error: 'A package id is required', result: { packageId: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: '', scope: '' } };\n }\n\n try {\n await post(`/packages/disable`, { packageId, ...scopeBody(scopeCtx) });\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, packageId, scope: scopeCtx.scope });\n } else {\n ctx.ui?.success?.(`Disabled ${packageId} (${scopeCtx.scope})`);\n }\n return { ok: true, result: { packageId, scope: scopeCtx.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: '', scope: '' } };\n }\n },\n },\n});\n"]}
|
|
@@ -93,7 +93,7 @@ var doctor_default = defineCommand({
|
|
|
93
93
|
} else {
|
|
94
94
|
handleError(ctx, err, flags.json);
|
|
95
95
|
}
|
|
96
|
-
return {
|
|
96
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { ok: false, total: 0, issues: [] } };
|
|
97
97
|
}
|
|
98
98
|
try {
|
|
99
99
|
const query = { scope: scopeCtx.scope };
|
|
@@ -114,10 +114,10 @@ var doctor_default = defineCommand({
|
|
|
114
114
|
]
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
|
-
return {
|
|
117
|
+
return report.ok ? { ok: true, result: report } : { ok: false, error: "Marketplace doctor found issues", result: report };
|
|
118
118
|
} catch (err) {
|
|
119
119
|
handleError(ctx, err, flags.json);
|
|
120
|
-
return {
|
|
120
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { ok: false, total: 0, issues: [] } };
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -1 +1 @@
|
|
|
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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, handleError, validationError, 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { exitCode: 1, result: { ok: false, total: 0, issues: [] } };\n }\n\n try {\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 } catch (err) {\n handleError(ctx, err, flags.json);\n return { exitCode: 1, result: { ok: false, total: 0, issues: [] } };\n }\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/doctor.ts"],"names":["projectRoot"],"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;AAoFA,eAAsB,GAAA,CAAiB,MAAc,MAAA,EAA6C;AAChG,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,CAAA,EAAG,YAAY,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AAC5C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAAC,MAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AAAA,IAAE;AAAA,EAC3E;AACA,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,CAAI,QAAA,IAAY,EAAE,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AACrE,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;ACvGO,IAAM,kBAAA,GAAkD,CAAC,UAAA,EAAY,SAAS,CAAA;AAoBrF,eAAsB,eAAA,CACpB,KACA,IAAA,EAC2B;AAC3B,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,mBAAA,CAAoB,IAAI,CAAA;AACxB,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,MAAMA,YAAAA,GAAc,MAAM,qBAAA,CAAsB,GAAG,CAAA;AACnD,MAAA,IAAI,CAACA,YAAAA,EAAa;AAChB,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,8BAAA;AAAA,UACA,qEAAqE,GAAG,CAAA,mBAAA;AAAA,SAC1E;AAAA,MACF;AACA,MAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,WAAA,EAAAA,YAAAA,EAAa,QAAQ,MAAA,EAAO;AAAA,IACzD;AACA,IAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,MAAA,EAAQ,MAAA,EAAO;AAAA,EAC7C;AAEA,EAAA,MAAM,WAAA,GAAc,MAAM,qBAAA,CAAsB,GAAG,CAAA;AACnD,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,WAAA,EAAa,QAAQ,aAAA,EAAc;AAAA,EAChE;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,MAAA,EAAQ,UAAA,EAAW;AACjD;AAkBA,SAAS,oBAAoB,KAAA,EAAkD;AAC7E,EAAA,IAAI,CAAC,kBAAA,CAAmB,QAAA,CAAS,KAAyB,CAAA,EAAG;AAC3D,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,eAAA;AAAA,MACA,CAAA,wBAAA,EAA2B,mBAAmB,IAAA,CAAK,IAAI,CAAC,CAAA,MAAA,EAAS,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA;AAAA,KACxF;AAAA,EACF;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAC9B,IAAA;AAAA,EACT,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF,CAAA;;;AC9EA,IAAO,iBAAQ,aAAA,CAAsD;AAAA,EACnE,EAAA,EAAI,4BAAA;AAAA,EACJ,WAAA,EAAa,6BAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA8D;AAChG,MAAA,MAAM,KAAA,GAAS,MAAM,KAAA,IAAS,KAAA;AAE9B,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,GAAA,CAAI,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,MACvD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,eAAe,aAAA,EAAe;AAChC,UAAA,eAAA,CAAgB,GAAA,EAAK,GAAA,CAAI,OAAA,EAAS,MAAA,EAAW,MAAM,IAAI,CAAA;AAAA,QACzD,CAAA,MAAO;AACL,UAAA,WAAA,CAAY,GAAA,EAAK,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA;AAAA,QAClC;AACA,QAAA,OAAO,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,GAAG,MAAA,EAAQ,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,GAAG,MAAA,EAAQ,IAAG,EAAE;AAAA,MAC3H;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAgC,EAAE,KAAA,EAAO,QAAA,CAAS,KAAA,EAAM;AAC9D,QAAA,IAAI,SAAS,WAAA,EAAa;AAAE,UAAA,KAAA,CAAM,cAAc,QAAA,CAAS,WAAA;AAAA,QAAa;AACtE,QAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAsB,cAAA,EAAgB,KAAK,CAAA;AAEhE,QAAA,IAAI,MAAM,IAAA,EAAM;AACd,UAAA,GAAA,CAAI,EAAA,EAAI,OAAO,MAAM,CAAA;AAAA,QACvB,CAAA,MAAA,IAAW,MAAA,CAAO,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AACrC,UAAA,GAAA,CAAI,EAAA,EAAI,UAAU,CAAA,IAAA,EAAO,MAAA,CAAO,KAAK,CAAA,mBAAA,EAAsB,QAAA,CAAS,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,QAC9E,CAAA,MAAO;AACL,UAAA,MAAM,SAAS,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,aAAa,OAAO,CAAA;AAC/D,UAAA,GAAA,CAAI,EAAA,EAAI,IAAA,GAAO,CAAA,oBAAA,EAAuB,QAAA,CAAS,KAAK,CAAA,CAAA,CAAA,EAAK;AAAA,YACvD,QAAA,EAAU;AAAA,cACR,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAC,CAAA,OAAA,EAAU,OAAO,KAAK,CAAA,CAAA,EAAI,CAAA,QAAA,EAAW,MAAA,CAAO,OAAO,MAAM,CAAA,CAAA,EAAI,WAAW,MAAA,CAAO,MAAM,EAAE,CAAA,EAAE;AAAA,cACtH,EAAE,QAAQ,QAAA,EAAU,KAAA,EAAO,OAAO,MAAA,CAAO,GAAA,CAAI,OAAK,CAAA,EAAG,CAAA,CAAE,aAAa,OAAA,GAAU,QAAA,GAAM,QAAG,CAAA,CAAA,EAAI,CAAA,CAAE,SAAS,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA;AAAE;AAC1H,WACD,CAAA;AAAA,QACH;AAEA,QAAA,OAAO,MAAA,CAAO,EAAA,GAAK,EAAE,EAAA,EAAI,MAAM,MAAA,EAAQ,MAAA,EAAO,GAAI,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,iCAAA,EAAmC,QAAQ,MAAA,EAAO;AAAA,MAC1H,SAAS,GAAA,EAAK;AACZ,QAAA,WAAA,CAAY,GAAA,EAAK,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA;AAChC,QAAA,OAAO,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,GAAG,MAAA,EAAQ,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,GAAG,MAAA,EAAQ,IAAG,EAAE;AAAA,MAC3H;AAAA,IACF;AAAA;AAEJ,CAAC","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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, handleError, validationError, 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { ok: false, total: 0, issues: [] } };\n }\n\n try {\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 report.ok ? { ok: true, result: report } : { ok: false, error: 'Marketplace doctor found issues', result: report };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { ok: false, total: 0, issues: [] } };\n }\n },\n },\n});\n"]}
|
|
@@ -103,7 +103,7 @@ var enable_default = defineCommand({
|
|
|
103
103
|
const flags = input.flags ?? input;
|
|
104
104
|
if (!packageId) {
|
|
105
105
|
validationError(ctx, "Specify a plugin to enable", "Usage: kb marketplace plugins enable <plugin-id>", flags.json);
|
|
106
|
-
return {
|
|
106
|
+
return { ok: false, error: "A package id is required", result: { packageId: "", scope: "" } };
|
|
107
107
|
}
|
|
108
108
|
let scopeCtx;
|
|
109
109
|
try {
|
|
@@ -114,7 +114,7 @@ var enable_default = defineCommand({
|
|
|
114
114
|
} else {
|
|
115
115
|
handleError(ctx, err, flags.json);
|
|
116
116
|
}
|
|
117
|
-
return {
|
|
117
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: "", scope: "" } };
|
|
118
118
|
}
|
|
119
119
|
try {
|
|
120
120
|
await post(`/packages/enable`, { packageId, ...scopeBody(scopeCtx) });
|
|
@@ -123,10 +123,10 @@ var enable_default = defineCommand({
|
|
|
123
123
|
} else {
|
|
124
124
|
ctx.ui?.success?.(`Enabled ${packageId} (${scopeCtx.scope})`);
|
|
125
125
|
}
|
|
126
|
-
return {
|
|
126
|
+
return { ok: true, result: { packageId, scope: scopeCtx.scope } };
|
|
127
127
|
} catch (err) {
|
|
128
128
|
handleError(ctx, err, flags.json);
|
|
129
|
-
return {
|
|
129
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: "", scope: "" } };
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -1 +1 @@
|
|
|
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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface EnableFlags { json?: boolean; scope?: string; 'dry-run'?: boolean }\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 intent(_ctx: PluginContextV3, input: EnableInput) {\n const packageId = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Enable plugin \"${packageId}\"`,\n operations: [{ type: 'update' as const, resource: 'plugin', details: { packageId, enabled: true } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: EnableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n const flags = (input.flags ?? input) as EnableFlags;\n\n if (!packageId) {\n validationError(ctx, 'Specify a plugin to enable', 'Usage: kb marketplace plugins enable <plugin-id>', flags.json);\n return { exitCode: 1, result: { packageId: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\n\n try {\n await post(`/packages/enable`, { packageId, ...scopeBody(scopeCtx) });\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, packageId, scope: scopeCtx.scope });\n } else {\n ctx.ui?.success?.(`Enabled ${packageId} (${scopeCtx.scope})`);\n }\n return { exitCode: 0, result: { packageId, scope: scopeCtx.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { exitCode: 1, result: { packageId: '', scope: '' } };\n }\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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface EnableFlags { json?: boolean; scope?: string; 'dry-run'?: boolean }\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 intent(_ctx: PluginContextV3, input: EnableInput) {\n const packageId = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Enable plugin \"${packageId}\"`,\n operations: [{ type: 'update' as const, resource: 'plugin', details: { packageId, enabled: true } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: EnableInput): Promise<CommandResult<{ packageId: string; scope: string }>> {\n const packageId = input.argv?.[0];\n const flags = (input.flags ?? input) as EnableFlags;\n\n if (!packageId) {\n validationError(ctx, 'Specify a plugin to enable', 'Usage: kb marketplace plugins enable <plugin-id>', flags.json);\n return { ok: false, error: 'A package id is required', result: { packageId: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: '', scope: '' } };\n }\n\n try {\n await post(`/packages/enable`, { packageId, ...scopeBody(scopeCtx) });\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, packageId, scope: scopeCtx.scope });\n } else {\n ctx.ui?.success?.(`Enabled ${packageId} (${scopeCtx.scope})`);\n }\n return { ok: true, result: { packageId, scope: scopeCtx.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { packageId: '', scope: '' } };\n }\n },\n },\n});\n"]}
|
|
@@ -104,7 +104,7 @@ var link_default = defineCommand({
|
|
|
104
104
|
const flags = input.flags ?? input;
|
|
105
105
|
if (!pluginPath) {
|
|
106
106
|
validationError(ctx, "Specify a plugin path to link", "Usage: kb marketplace plugins link <path>", flags.json);
|
|
107
|
-
return {
|
|
107
|
+
return { ok: false, error: "A plugin path is required", result: { id: "", scope: "" } };
|
|
108
108
|
}
|
|
109
109
|
let scopeCtx;
|
|
110
110
|
try {
|
|
@@ -115,7 +115,7 @@ var link_default = defineCommand({
|
|
|
115
115
|
} else {
|
|
116
116
|
handleError(ctx, err, flags.json);
|
|
117
117
|
}
|
|
118
|
-
return {
|
|
118
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { id: "", scope: "" } };
|
|
119
119
|
}
|
|
120
120
|
try {
|
|
121
121
|
const absPath = path.resolve(ctx.cwd, pluginPath);
|
|
@@ -125,10 +125,10 @@ var link_default = defineCommand({
|
|
|
125
125
|
} else {
|
|
126
126
|
ctx.ui?.success?.(`Linked ${result.id} (${result.scope})`);
|
|
127
127
|
}
|
|
128
|
-
return {
|
|
128
|
+
return { ok: true, result: { id: result.id, scope: result.scope } };
|
|
129
129
|
} catch (err) {
|
|
130
130
|
handleError(ctx, err, flags.json);
|
|
131
|
-
return {
|
|
131
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { id: "", scope: "" } };
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/link.ts"],"names":["path","projectRoot"],"mappings":"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","file":"link.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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport * as path from 'node:path';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface LinkFlags {\n scope?: string;\n json?: boolean;\n 'dry-run'?: boolean;\n}\n\ninterface LinkInput {\n argv?: string[];\n flags?: LinkFlags;\n}\n\ninterface LinkResponse {\n id: string;\n version: string;\n primaryKind: string;\n provides: string[];\n packageRoot: string;\n scope: string;\n}\n\nexport default defineCommand<unknown, LinkInput, { id: string; scope: string }>({\n id: 'marketplace:plugins:link',\n description: 'Link a local plugin for development',\n\n handler: {\n async intent(_ctx: PluginContextV3, input: LinkInput) {\n const pluginPath = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Link local plugin at \"${pluginPath}\"`,\n operations: [{ type: 'create' as const, resource: 'plugin-link', details: { path: pluginPath } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: LinkInput): Promise<CommandResult<{ id: string; scope: string }>> {\n const pluginPath = input.argv?.[0];\n const flags = (input.flags ?? input) as LinkFlags;\n\n if (!pluginPath) {\n validationError(ctx, 'Specify a plugin path to link', 'Usage: kb marketplace plugins link <path>', flags.json);\n return { exitCode: 1, result: { id: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { exitCode: 1, result: { id: '', scope: '' } };\n }\n\n try {\n // Resolve path against cwd so the daemon always receives an absolute\n // location. Keeps the server side from inheriting any ambient cwd.\n const absPath = path.resolve(ctx.cwd, pluginPath);\n const result = await post<LinkResponse>(`/packages/link`, { path: absPath, ...scopeBody(scopeCtx) });\n\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, id: result.id, scope: result.scope });\n } else {\n ctx.ui?.success?.(`Linked ${result.id} (${result.scope})`);\n }\n return { exitCode: 0, result: { id: result.id, scope: result.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { exitCode: 1, result: { id: '', scope: '' } };\n }\n },\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/http.ts","../../../src/scope.ts","../../../src/commands/plugins/link.ts"],"names":["path","projectRoot"],"mappings":"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","file":"link.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 // 204 No Content (e.g. unlink, uninstall) has no body — don't call\n // res.json() or it throws \"Unexpected end of JSON input\".\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 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, validationError, handleError, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport * as path from 'node:path';\nimport { post } from '../../http.js';\nimport { resolveCliScope, scopeBody, CliScopeError } from '../../scope.js';\n\ninterface LinkFlags {\n scope?: string;\n json?: boolean;\n 'dry-run'?: boolean;\n}\n\ninterface LinkInput {\n argv?: string[];\n flags?: LinkFlags;\n}\n\ninterface LinkResponse {\n id: string;\n version: string;\n primaryKind: string;\n provides: string[];\n packageRoot: string;\n scope: string;\n}\n\nexport default defineCommand<unknown, LinkInput, { id: string; scope: string }>({\n id: 'marketplace:plugins:link',\n description: 'Link a local plugin for development',\n\n handler: {\n async intent(_ctx: PluginContextV3, input: LinkInput) {\n const pluginPath = input.argv?.[0] ?? '(unknown)';\n return {\n summary: `Link local plugin at \"${pluginPath}\"`,\n operations: [{ type: 'create' as const, resource: 'plugin-link', details: { path: pluginPath } }],\n };\n },\n\n async execute(ctx: PluginContextV3, input: LinkInput): Promise<CommandResult<{ id: string; scope: string }>> {\n const pluginPath = input.argv?.[0];\n const flags = (input.flags ?? input) as LinkFlags;\n\n if (!pluginPath) {\n validationError(ctx, 'Specify a plugin path to link', 'Usage: kb marketplace plugins link <path>', flags.json);\n return { ok: false, error: 'A plugin path is required', result: { id: '', 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 validationError(ctx, err.message, undefined, flags.json);\n } else {\n handleError(ctx, err, flags.json);\n }\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { id: '', scope: '' } };\n }\n\n try {\n // Resolve path against cwd so the daemon always receives an absolute\n // location. Keeps the server side from inheriting any ambient cwd.\n const absPath = path.resolve(ctx.cwd, pluginPath);\n const result = await post<LinkResponse>(`/packages/link`, { path: absPath, ...scopeBody(scopeCtx) });\n\n if (flags.json) {\n ctx.ui?.json?.({ ok: true, id: result.id, scope: result.scope });\n } else {\n ctx.ui?.success?.(`Linked ${result.id} (${result.scope})`);\n }\n return { ok: true, result: { id: result.id, scope: result.scope } };\n } catch (err) {\n handleError(ctx, err, flags.json);\n return { ok: false, error: err instanceof Error ? err.message : String(err), result: { id: '', scope: '' } };\n }\n },\n },\n});\n"]}
|
|
@@ -101,7 +101,7 @@ var list_default = defineCommand({
|
|
|
101
101
|
} else {
|
|
102
102
|
handleError(ctx, err, flags.json);
|
|
103
103
|
}
|
|
104
|
-
return {
|
|
104
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { entries: [], total: 0 } };
|
|
105
105
|
}
|
|
106
106
|
try {
|
|
107
107
|
const query = { kind: "plugin", scope: scopeCtx.scope };
|
|
@@ -126,10 +126,10 @@ var list_default = defineCommand({
|
|
|
126
126
|
}]
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
|
-
return {
|
|
129
|
+
return { ok: true, result: data };
|
|
130
130
|
} catch (err) {
|
|
131
131
|
handleError(ctx, err, flags.json);
|
|
132
|
-
return {
|
|
132
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err), result: { entries: [], total: 0 } };
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
}
|