@sanity/cli 8.26.0 → 8.27.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/actions/context/mcpEndpoint.js +165 -0
- package/dist/actions/context/mcpEndpoint.js.map +1 -0
- package/dist/actions/context/resolveOrganizationId.js +8 -1
- package/dist/actions/context/resolveOrganizationId.js.map +1 -1
- package/dist/commands/context/create.js +8 -22
- package/dist/commands/context/create.js.map +1 -1
- package/dist/commands/context/delete.js +2 -2
- package/dist/commands/context/delete.js.map +1 -1
- package/dist/commands/context/issues/list.js +0 -5
- package/dist/commands/context/issues/list.js.map +1 -1
- package/dist/commands/context/list.js +6 -14
- package/dist/commands/context/list.js.map +1 -1
- package/dist/commands/context/mcp/create.js +152 -0
- package/dist/commands/context/mcp/create.js.map +1 -0
- package/dist/commands/context/mcp/delete.js +82 -0
- package/dist/commands/context/mcp/delete.js.map +1 -0
- package/dist/commands/context/mcp/get.js +42 -0
- package/dist/commands/context/mcp/get.js.map +1 -0
- package/dist/commands/context/mcp/list.js +87 -0
- package/dist/commands/context/mcp/list.js.map +1 -0
- package/dist/commands/context/mcp/status.js +98 -0
- package/dist/commands/context/mcp/status.js.map +1 -0
- package/dist/commands/context/mcp/update.js +225 -0
- package/dist/commands/context/mcp/update.js.map +1 -0
- package/dist/commands/context/query.js +6 -14
- package/dist/commands/context/query.js.map +1 -1
- package/dist/commands/context/update.js +2 -2
- package/dist/commands/context/update.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +6 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/prompts/promptForText.js +12 -0
- package/dist/prompts/promptForText.js.map +1 -0
- package/dist/services/context.js +107 -6
- package/dist/services/context.js.map +1 -1
- package/dist/util/sharedFlags.js.map +1 -1
- package/dist/util/telemetry/cliCommandIdentity.js +6 -0
- package/dist/util/telemetry/cliCommandIdentity.js.map +1 -1
- package/oclif.config.js +1 -1
- package/oclif.manifest.json +2527 -1977
- package/package.json +2 -2
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { CLIError } from '@oclif/core/errors';
|
|
3
|
+
import { exitCodes } from '@sanity/cli-core';
|
|
4
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
5
|
+
import { getMcpEndpoint } from '../../services/context.js';
|
|
6
|
+
import { getOrganizationFlag } from '../../util/sharedFlags.js';
|
|
7
|
+
import { formatKeyValue } from '../debug/output.js';
|
|
8
|
+
/**
|
|
9
|
+
* The `<name>` argument of commands that act on an existing endpoint
|
|
10
|
+
*/ export const mcpEndpointNameArg = Args.string({
|
|
11
|
+
description: 'MCP endpoint name, as in its URL',
|
|
12
|
+
parse: parseEndpointName,
|
|
13
|
+
required: true
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* An argument `parse` that trims an endpoint name and rejects an empty one
|
|
17
|
+
*/ export async function parseEndpointName(input) {
|
|
18
|
+
const trimmed = input.trim();
|
|
19
|
+
if (trimmed === '') throw new Error('The MCP endpoint name cannot be empty');
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get an endpoint by name or ID, failing the command when the lookup fails or finds nothing
|
|
24
|
+
*/ export async function findMcpEndpoint(organizationId, nameOrId) {
|
|
25
|
+
let endpoint;
|
|
26
|
+
try {
|
|
27
|
+
endpoint = await getMcpEndpoint(organizationId, nameOrId);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
throw new CLIError(`Failed to get MCP endpoint: ${getErrorMessage(error)}`, {
|
|
30
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (!endpoint) {
|
|
34
|
+
throw new CLIError(`MCP endpoint "${nameOrId}" not found`, {
|
|
35
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return endpoint;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The `--organization` flag of commands that act on an existing endpoint
|
|
42
|
+
*/ export const mcpEndpointOrganizationFlag = getOrganizationFlag({
|
|
43
|
+
description: 'Organization the MCP endpoint belongs to',
|
|
44
|
+
semantics: 'override'
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* A flag `parse` that trims the value and rejects an empty one
|
|
48
|
+
*/ export function parseNonEmpty(flag) {
|
|
49
|
+
return async (input)=>{
|
|
50
|
+
const trimmed = input.trim();
|
|
51
|
+
if (trimmed === '') {
|
|
52
|
+
throw new Error(`\`--${flag}\` cannot be empty if provided`);
|
|
53
|
+
}
|
|
54
|
+
return trimmed;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The API names a dataset source `<projectId>.<datasetName>`; the project comes from
|
|
59
|
+
* `--project` or the CLI configuration.
|
|
60
|
+
*/ export function datasetSourceId(dataset, projectId) {
|
|
61
|
+
if (dataset === undefined) return undefined;
|
|
62
|
+
if (!projectId) {
|
|
63
|
+
throw new CLIError('Pass `--project` with `--dataset`, or run the command in a Sanity project directory.', {
|
|
64
|
+
exit: exitCodes.USAGE_ERROR
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return `${projectId}.${dataset}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Apply source changes to an endpoint's current sources, or to none when creating one. The dataset
|
|
71
|
+
* keeps its settings until it is switched for another one; `dataset: null`
|
|
72
|
+
* removes it. Sources are rebuilt from their known fields, since the stored
|
|
73
|
+
* configuration may carry more. `notes` names the changes that were already in
|
|
74
|
+
* place, which leave the sources as they were.
|
|
75
|
+
*/ export function editSources(current, changes) {
|
|
76
|
+
const notes = [];
|
|
77
|
+
const knowledgeBaseIds = current.filter((source)=>source.type === 'knowledge-base').map((source)=>source.id);
|
|
78
|
+
for (const id of new Set(changes.addKnowledgeBases)){
|
|
79
|
+
if (knowledgeBaseIds.includes(id)) {
|
|
80
|
+
notes.push(`Knowledge base "${id}" is already a source`);
|
|
81
|
+
} else {
|
|
82
|
+
knowledgeBaseIds.push(id);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const id of new Set(changes.removeKnowledgeBases)){
|
|
86
|
+
if (!knowledgeBaseIds.includes(id)) notes.push(`Knowledge base "${id}" is not a source`);
|
|
87
|
+
}
|
|
88
|
+
const sources = knowledgeBaseIds.filter((id)=>!changes.removeKnowledgeBases.includes(id)).map((id)=>({
|
|
89
|
+
id,
|
|
90
|
+
type: 'knowledge-base'
|
|
91
|
+
}));
|
|
92
|
+
const dataset = findDatasetSource(current);
|
|
93
|
+
if (changes.dataset === null && !dataset) notes.push('The endpoint has no dataset');
|
|
94
|
+
const datasetId = changes.dataset === undefined ? dataset?.id : changes.dataset;
|
|
95
|
+
if (datasetId) {
|
|
96
|
+
const kept = dataset?.id === datasetId ? {
|
|
97
|
+
perspective: dataset.perspective,
|
|
98
|
+
semanticSearch: dataset.semanticSearch,
|
|
99
|
+
workspace: dataset.workspace
|
|
100
|
+
} : {};
|
|
101
|
+
sources.push({
|
|
102
|
+
id: datasetId,
|
|
103
|
+
type: 'dataset',
|
|
104
|
+
...kept,
|
|
105
|
+
...changes.settings
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
notes,
|
|
110
|
+
sources
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function findDatasetSource(sources) {
|
|
114
|
+
return sources.find((source)=>source.type === 'dataset');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Key-value lines describing an endpoint, for `get`, `create` and `update` output
|
|
118
|
+
*/ export function formatMcpEndpoint(endpoint) {
|
|
119
|
+
const padTo = 15 // "Knowledge bases" and "Semantic search" are the longest keys
|
|
120
|
+
;
|
|
121
|
+
const knowledgeBaseIds = endpoint.sources.filter((source)=>source.type === 'knowledge-base').map((source)=>source.id);
|
|
122
|
+
const dataset = findDatasetSource(endpoint.sources);
|
|
123
|
+
const lines = [
|
|
124
|
+
formatKeyValue('ID', endpoint.id, {
|
|
125
|
+
padTo
|
|
126
|
+
}),
|
|
127
|
+
formatKeyValue('Name', endpoint.name, {
|
|
128
|
+
padTo
|
|
129
|
+
}),
|
|
130
|
+
formatKeyValue('Title', endpoint.title, {
|
|
131
|
+
padTo
|
|
132
|
+
}),
|
|
133
|
+
formatKeyValue('URL', endpoint.url, {
|
|
134
|
+
padTo
|
|
135
|
+
}),
|
|
136
|
+
formatKeyValue('Knowledge bases', knowledgeBaseIds.join(', ') || '-', {
|
|
137
|
+
padTo
|
|
138
|
+
}),
|
|
139
|
+
formatKeyValue('Dataset', dataset?.id ?? '-', {
|
|
140
|
+
padTo
|
|
141
|
+
})
|
|
142
|
+
];
|
|
143
|
+
if (dataset) {
|
|
144
|
+
lines.push(formatKeyValue('Workspace', dataset.workspace ?? '-', {
|
|
145
|
+
padTo
|
|
146
|
+
}), formatKeyValue('Perspective', dataset.perspective ?? '-', {
|
|
147
|
+
padTo
|
|
148
|
+
}), formatKeyValue('Semantic search', formatSemanticSearch(dataset.semanticSearch), {
|
|
149
|
+
padTo
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
lines.push(formatKeyValue('Instructions', endpoint.instructions ?? '-', {
|
|
153
|
+
padTo
|
|
154
|
+
}), formatKeyValue('GROQ filter', endpoint.groqFilter ?? '-', {
|
|
155
|
+
padTo
|
|
156
|
+
}));
|
|
157
|
+
return lines;
|
|
158
|
+
}
|
|
159
|
+
function formatSemanticSearch(semanticSearch) {
|
|
160
|
+
if (semanticSearch === true) return 'on';
|
|
161
|
+
if (semanticSearch === false) return 'off';
|
|
162
|
+
return '-';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=mcpEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/context/mcpEndpoint.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {type Context} from '@sanity/client'\n\nimport {getMcpEndpoint} from '../../services/context.js'\nimport {getOrganizationFlag} from '../../util/sharedFlags.js'\nimport {formatKeyValue} from '../debug/output.js'\n\ntype McpSource = Context.McpEndpoint['sources'][number]\ntype DatasetSource = Extract<McpSource, {type: 'dataset'}>\ntype McpSourceInput = Context.CreateMcpEndpointParams['sources'][number]\nexport type DatasetSettings = Partial<\n Pick<DatasetSource, 'perspective' | 'semanticSearch' | 'workspace'>\n>\n\n/**\n * The `<name>` argument of commands that act on an existing endpoint\n */\nexport const mcpEndpointNameArg = Args.string({\n description: 'MCP endpoint name, as in its URL',\n parse: parseEndpointName,\n required: true,\n})\n\n/**\n * An argument `parse` that trims an endpoint name and rejects an empty one\n */\nexport async function parseEndpointName(input: string): Promise<string> {\n const trimmed = input.trim()\n if (trimmed === '') throw new Error('The MCP endpoint name cannot be empty')\n return trimmed\n}\n\n/**\n * Get an endpoint by name or ID, failing the command when the lookup fails or finds nothing\n */\nexport async function findMcpEndpoint(\n organizationId: string,\n nameOrId: string,\n): Promise<Context.McpEndpoint> {\n let endpoint\n try {\n endpoint = await getMcpEndpoint(organizationId, nameOrId)\n } catch (error) {\n throw new CLIError(`Failed to get MCP endpoint: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n if (!endpoint) {\n throw new CLIError(`MCP endpoint \"${nameOrId}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n return endpoint\n}\n\n/**\n * The `--organization` flag of commands that act on an existing endpoint\n */\nexport const mcpEndpointOrganizationFlag = getOrganizationFlag({\n description: 'Organization the MCP endpoint belongs to',\n semantics: 'override',\n})\n\n/**\n * A flag `parse` that trims the value and rejects an empty one\n */\nexport function parseNonEmpty(flag: string): (input: string) => Promise<string> {\n return async (input) => {\n const trimmed = input.trim()\n if (trimmed === '') {\n throw new Error(`\\`--${flag}\\` cannot be empty if provided`)\n }\n return trimmed\n }\n}\n\n/**\n * The API names a dataset source `<projectId>.<datasetName>`; the project comes from\n * `--project` or the CLI configuration.\n */\nexport function datasetSourceId(\n dataset: string | undefined,\n projectId: string | undefined,\n): string | undefined {\n if (dataset === undefined) return undefined\n if (!projectId) {\n throw new CLIError(\n 'Pass `--project` with `--dataset`, or run the command in a Sanity project directory.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n return `${projectId}.${dataset}`\n}\n\n/**\n * Apply source changes to an endpoint's current sources, or to none when creating one. The dataset\n * keeps its settings until it is switched for another one; `dataset: null`\n * removes it. Sources are rebuilt from their known fields, since the stored\n * configuration may carry more. `notes` names the changes that were already in\n * place, which leave the sources as they were.\n */\nexport function editSources(\n current: McpSource[],\n changes: {\n addKnowledgeBases: string[]\n dataset: string | null | undefined\n removeKnowledgeBases: string[]\n settings: DatasetSettings\n },\n): {notes: string[]; sources: McpSourceInput[]} {\n const notes: string[] = []\n const knowledgeBaseIds = current\n .filter((source) => source.type === 'knowledge-base')\n .map((source) => source.id)\n\n for (const id of new Set(changes.addKnowledgeBases)) {\n if (knowledgeBaseIds.includes(id)) {\n notes.push(`Knowledge base \"${id}\" is already a source`)\n } else {\n knowledgeBaseIds.push(id)\n }\n }\n for (const id of new Set(changes.removeKnowledgeBases)) {\n if (!knowledgeBaseIds.includes(id)) notes.push(`Knowledge base \"${id}\" is not a source`)\n }\n const sources: McpSourceInput[] = knowledgeBaseIds\n .filter((id) => !changes.removeKnowledgeBases.includes(id))\n .map((id) => ({id, type: 'knowledge-base'}))\n\n const dataset = findDatasetSource(current)\n if (changes.dataset === null && !dataset) notes.push('The endpoint has no dataset')\n const datasetId = changes.dataset === undefined ? dataset?.id : changes.dataset\n if (datasetId) {\n const kept =\n dataset?.id === datasetId\n ? {\n perspective: dataset.perspective,\n semanticSearch: dataset.semanticSearch,\n workspace: dataset.workspace,\n }\n : {}\n sources.push({id: datasetId, type: 'dataset', ...kept, ...changes.settings})\n }\n\n return {notes, sources}\n}\n\nfunction findDatasetSource(sources: McpSource[]): DatasetSource | undefined {\n return sources.find((source): source is DatasetSource => source.type === 'dataset')\n}\n\n/**\n * Key-value lines describing an endpoint, for `get`, `create` and `update` output\n */\nexport function formatMcpEndpoint(endpoint: Context.McpEndpoint): string[] {\n const padTo = 15 // \"Knowledge bases\" and \"Semantic search\" are the longest keys\n const knowledgeBaseIds = endpoint.sources\n .filter((source) => source.type === 'knowledge-base')\n .map((source) => source.id)\n const dataset = findDatasetSource(endpoint.sources)\n\n const lines = [\n formatKeyValue('ID', endpoint.id, {padTo}),\n formatKeyValue('Name', endpoint.name, {padTo}),\n formatKeyValue('Title', endpoint.title, {padTo}),\n formatKeyValue('URL', endpoint.url, {padTo}),\n formatKeyValue('Knowledge bases', knowledgeBaseIds.join(', ') || '-', {padTo}),\n formatKeyValue('Dataset', dataset?.id ?? '-', {padTo}),\n ]\n if (dataset) {\n lines.push(\n formatKeyValue('Workspace', dataset.workspace ?? '-', {padTo}),\n formatKeyValue('Perspective', dataset.perspective ?? '-', {padTo}),\n formatKeyValue('Semantic search', formatSemanticSearch(dataset.semanticSearch), {padTo}),\n )\n }\n lines.push(\n formatKeyValue('Instructions', endpoint.instructions ?? '-', {padTo}),\n formatKeyValue('GROQ filter', endpoint.groqFilter ?? '-', {padTo}),\n )\n return lines\n}\n\nfunction formatSemanticSearch(semanticSearch: boolean | null | undefined): string {\n if (semanticSearch === true) return 'on'\n if (semanticSearch === false) return 'off'\n return '-'\n}\n"],"names":["Args","CLIError","exitCodes","getErrorMessage","getMcpEndpoint","getOrganizationFlag","formatKeyValue","mcpEndpointNameArg","string","description","parse","parseEndpointName","required","input","trimmed","trim","Error","findMcpEndpoint","organizationId","nameOrId","endpoint","error","exit","RUNTIME_ERROR","mcpEndpointOrganizationFlag","semantics","parseNonEmpty","flag","datasetSourceId","dataset","projectId","undefined","USAGE_ERROR","editSources","current","changes","notes","knowledgeBaseIds","filter","source","type","map","id","Set","addKnowledgeBases","includes","push","removeKnowledgeBases","sources","findDatasetSource","datasetId","kept","perspective","semanticSearch","workspace","settings","find","formatMcpEndpoint","padTo","lines","name","title","url","join","formatSemanticSearch","instructions","groqFilter"],"mappings":"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"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { CLIError } from '@oclif/core/errors';
|
|
2
|
+
import { exitCodes } from '@sanity/cli-core';
|
|
1
3
|
import { promptForOrganization } from '../../prompts/promptForOrganization.js';
|
|
2
|
-
/** The organization could not be determined and prompting is not possible. */ export class MissingOrganizationError extends
|
|
4
|
+
/** The organization could not be determined and prompting is not possible. */ export class MissingOrganizationError extends CLIError {
|
|
5
|
+
constructor(message){
|
|
6
|
+
super(message, {
|
|
7
|
+
exit: exitCodes.USAGE_ERROR
|
|
8
|
+
});
|
|
9
|
+
}
|
|
3
10
|
}
|
|
4
11
|
/**
|
|
5
12
|
* Resolve the organization to operate on: the `--organization` flag wins,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/context/resolveOrganizationId.ts"],"sourcesContent":["import {promptForOrganization} from '../../prompts/promptForOrganization.js'\n\n/** The organization could not be determined and prompting is not possible. */\nexport class MissingOrganizationError extends
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/context/resolveOrganizationId.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\n\nimport {promptForOrganization} from '../../prompts/promptForOrganization.js'\n\n/** The organization could not be determined and prompting is not possible. */\nexport class MissingOrganizationError extends CLIError {\n constructor(message: string) {\n super(message, {exit: exitCodes.USAGE_ERROR})\n }\n}\n\n/**\n * Resolve the organization to operate on: the `--organization` flag wins,\n * then the CLI config's `app.organizationId`, then an interactive prompt.\n */\nexport async function resolveOrganizationId(options: {\n configuredOrganizationId: string | undefined\n flagOrganizationId: string | undefined\n unattended: boolean\n}): Promise<string> {\n const {configuredOrganizationId, flagOrganizationId, unattended} = options\n\n if (flagOrganizationId) return flagOrganizationId\n if (configuredOrganizationId) return configuredOrganizationId\n\n if (unattended) {\n throw new MissingOrganizationError(\n 'Organization ID is required. Provide it with the --organization flag.',\n )\n }\n\n return promptForOrganization()\n}\n"],"names":["CLIError","exitCodes","promptForOrganization","MissingOrganizationError","message","exit","USAGE_ERROR","resolveOrganizationId","options","configuredOrganizationId","flagOrganizationId","unattended"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,QAAO,mBAAkB;AAE1C,SAAQC,qBAAqB,QAAO,yCAAwC;AAE5E,4EAA4E,GAC5E,OAAO,MAAMC,iCAAiCH;IAC5C,YAAYI,OAAe,CAAE;QAC3B,KAAK,CAACA,SAAS;YAACC,MAAMJ,UAAUK,WAAW;QAAA;IAC7C;AACF;AAEA;;;CAGC,GACD,OAAO,eAAeC,sBAAsBC,OAI3C;IACC,MAAM,EAACC,wBAAwB,EAAEC,kBAAkB,EAAEC,UAAU,EAAC,GAAGH;IAEnE,IAAIE,oBAAoB,OAAOA;IAC/B,IAAID,0BAA0B,OAAOA;IAErC,IAAIE,YAAY;QACd,MAAM,IAAIR,yBACR;IAEJ;IAEA,OAAOD;AACT"}
|
|
@@ -2,9 +2,10 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
3
3
|
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
4
4
|
import { requiredWhenUnattended } from '@sanity/cli-core/flags';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { spinner } from '@sanity/cli-core/ux';
|
|
6
|
+
import { resolveOrganizationId } from '../../actions/context/resolveOrganizationId.js';
|
|
7
7
|
import { formatKeyValue } from '../../actions/debug/output.js';
|
|
8
|
+
import { promptForText } from '../../prompts/promptForText.js';
|
|
8
9
|
import { createKnowledgeBase } from '../../services/context.js';
|
|
9
10
|
import { getOrganizationFlag } from '../../util/sharedFlags.js';
|
|
10
11
|
import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
|
|
@@ -52,19 +53,11 @@ export class CreateKnowledgeBaseCommand extends SanityCommand {
|
|
|
52
53
|
exit: exitCodes.USAGE_ERROR
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
unattended: this.isUnattended()
|
|
61
|
-
});
|
|
62
|
-
} catch (error) {
|
|
63
|
-
createContextDebug('Error resolving organization', error);
|
|
64
|
-
this.error(getErrorMessage(error), {
|
|
65
|
-
exit: error instanceof MissingOrganizationError ? exitCodes.USAGE_ERROR : exitCodes.RUNTIME_ERROR
|
|
66
|
-
});
|
|
67
|
-
}
|
|
56
|
+
const organizationId = await resolveOrganizationId({
|
|
57
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
58
|
+
flagOrganizationId: organization,
|
|
59
|
+
unattended: this.isUnattended()
|
|
60
|
+
});
|
|
68
61
|
const title = titleFlag?.trim() || await promptForText('Knowledge base title:');
|
|
69
62
|
const description = descriptionFlag?.trim() || await promptForText('Knowledge base description:');
|
|
70
63
|
const spin = spinner('Creating knowledge base').start();
|
|
@@ -95,12 +88,5 @@ export class CreateKnowledgeBaseCommand extends SanityCommand {
|
|
|
95
88
|
}
|
|
96
89
|
}
|
|
97
90
|
}
|
|
98
|
-
async function promptForText(message) {
|
|
99
|
-
const value = await input({
|
|
100
|
-
message,
|
|
101
|
-
validate: (input_)=>input_.trim().length > 0 || 'Value cannot be empty'
|
|
102
|
-
});
|
|
103
|
-
return value.trim();
|
|
104
|
-
}
|
|
105
91
|
|
|
106
92
|
//# sourceMappingURL=create.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/context/create.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/context/create.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {resolveOrganizationId} from '../../actions/context/resolveOrganizationId.js'\nimport {formatKeyValue} from '../../actions/debug/output.js'\nimport {promptForText} from '../../prompts/promptForText.js'\nimport {createKnowledgeBase} from '../../services/context.js'\nimport {getOrganizationFlag} from '../../util/sharedFlags.js'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.js'\n\nconst createContextDebug = subdebug('context:create')\n\nconst flags = {\n ...getOrganizationFlag({\n description: 'Organization to create the knowledge base in',\n semantics: 'override',\n }),\n description: requiredWhenUnattended(\n Flags.string({\n description: 'Knowledge base description',\n }),\n ),\n title: requiredWhenUnattended(\n Flags.string({\n description: 'Knowledge base title',\n }),\n ),\n} satisfies FlagInput\n\nexport class CreateKnowledgeBaseCommand extends SanityCommand<typeof CreateKnowledgeBaseCommand> {\n static override description = 'Create a knowledge base'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively create a knowledge base',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> --organization org-abc123 --title \"Support docs\" --description \"Product docs and troubleshooting guides\"',\n description: 'Create a knowledge base in a specific organization',\n },\n ]\n\n static override flags = flags\n\n static telemetry = defineCommandTelemetry(flags, {redact: ['title', 'description']})\n\n public async run(): Promise<void> {\n const {description: descriptionFlag, organization, title: titleFlag} = this.flags\n\n if (titleFlag !== undefined && titleFlag.trim() === '') {\n this.error('Title cannot be empty', {exit: exitCodes.USAGE_ERROR})\n }\n if (descriptionFlag !== undefined && descriptionFlag.trim() === '') {\n this.error('Description cannot be empty', {exit: exitCodes.USAGE_ERROR})\n }\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n const title = titleFlag?.trim() || (await promptForText('Knowledge base title:'))\n const description =\n descriptionFlag?.trim() || (await promptForText('Knowledge base description:'))\n\n const spin = spinner('Creating knowledge base').start()\n try {\n const knowledgeBase = await createKnowledgeBase({description, organizationId, title})\n spin.succeed('Knowledge base created')\n const padTo = 12 // \"Organization\" is the longest key\n this.log(formatKeyValue('ID', knowledgeBase.publicId, {padTo}))\n this.log(formatKeyValue('Title', knowledgeBase.title, {padTo}))\n this.log(formatKeyValue('Organization', knowledgeBase.organizationId, {padTo}))\n } catch (error) {\n spin.fail()\n createContextDebug('Error creating knowledge base', error)\n this.error(`Failed to create knowledge base: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","requiredWhenUnattended","spinner","resolveOrganizationId","formatKeyValue","promptForText","createKnowledgeBase","getOrganizationFlag","defineCommandTelemetry","createContextDebug","flags","description","semantics","string","title","CreateKnowledgeBaseCommand","examples","command","telemetry","redact","run","descriptionFlag","organization","titleFlag","undefined","trim","error","exit","USAGE_ERROR","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","isUnattended","spin","start","knowledgeBase","succeed","padTo","log","publicId","fail","RUNTIME_ERROR"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AAEjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,sBAAsB,QAAO,yBAAwB;AAC7D,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,qBAAqB,QAAO,iDAAgD;AACpF,SAAQC,cAAc,QAAO,gCAA+B;AAC5D,SAAQC,aAAa,QAAO,iCAAgC;AAC5D,SAAQC,mBAAmB,QAAO,4BAA2B;AAC7D,SAAQC,mBAAmB,QAAO,4BAA2B;AAC7D,SAAQC,sBAAsB,QAAO,2CAA0C;AAE/E,MAAMC,qBAAqBV,SAAS;AAEpC,MAAMW,QAAQ;IACZ,GAAGH,oBAAoB;QACrBI,aAAa;QACbC,WAAW;IACb,EAAE;IACFD,aAAaV,uBACXL,MAAMiB,MAAM,CAAC;QACXF,aAAa;IACf;IAEFG,OAAOb,uBACLL,MAAMiB,MAAM,CAAC;QACXF,aAAa;IACf;AAEJ;AAEA,OAAO,MAAMI,mCAAmCjB;IAC9C,OAAgBa,cAAc,0BAAyB;IAEvD,OAAgBK,WAAW;QACzB;YACEC,SAAS;YACTN,aAAa;QACf;QACA;YACEM,SACE;YACFN,aAAa;QACf;KACD,CAAA;IAED,OAAgBD,QAAQA,MAAK;IAE7B,OAAOQ,YAAYV,uBAAuBE,OAAO;QAACS,QAAQ;YAAC;YAAS;SAAc;IAAA,GAAE;IAEpF,MAAaC,MAAqB;QAChC,MAAM,EAACT,aAAaU,eAAe,EAAEC,YAAY,EAAER,OAAOS,SAAS,EAAC,GAAG,IAAI,CAACb,KAAK;QAEjF,IAAIa,cAAcC,aAAaD,UAAUE,IAAI,OAAO,IAAI;YACtD,IAAI,CAACC,KAAK,CAAC,yBAAyB;gBAACC,MAAM9B,UAAU+B,WAAW;YAAA;QAClE;QACA,IAAIP,oBAAoBG,aAAaH,gBAAgBI,IAAI,OAAO,IAAI;YAClE,IAAI,CAACC,KAAK,CAAC,+BAA+B;gBAACC,MAAM9B,UAAU+B,WAAW;YAAA;QACxE;QAEA,MAAMC,iBAAiB,MAAM1B,sBAAsB;YACjD2B,0BAA0B,AAAC,CAAA,MAAM,IAAI,CAACC,eAAe,EAAC,EAAGC,GAAG,EAAEH;YAC9DI,oBAAoBX;YACpBY,YAAY,IAAI,CAACC,YAAY;QAC/B;QAEA,MAAMrB,QAAQS,WAAWE,UAAW,MAAMpB,cAAc;QACxD,MAAMM,cACJU,iBAAiBI,UAAW,MAAMpB,cAAc;QAElD,MAAM+B,OAAOlC,QAAQ,2BAA2BmC,KAAK;QACrD,IAAI;YACF,MAAMC,gBAAgB,MAAMhC,oBAAoB;gBAACK;gBAAakB;gBAAgBf;YAAK;YACnFsB,KAAKG,OAAO,CAAC;YACb,MAAMC,QAAQ,GAAG,oCAAoC;;YACrD,IAAI,CAACC,GAAG,CAACrC,eAAe,MAAMkC,cAAcI,QAAQ,EAAE;gBAACF;YAAK;YAC5D,IAAI,CAACC,GAAG,CAACrC,eAAe,SAASkC,cAAcxB,KAAK,EAAE;gBAAC0B;YAAK;YAC5D,IAAI,CAACC,GAAG,CAACrC,eAAe,gBAAgBkC,cAAcT,cAAc,EAAE;gBAACW;YAAK;QAC9E,EAAE,OAAOd,OAAO;YACdU,KAAKO,IAAI;YACTlC,mBAAmB,iCAAiCiB;YACpD,IAAI,CAACA,KAAK,CAAC,CAAC,iCAAiC,EAAE1B,gBAAgB0B,QAAQ,EAAE;gBACvEC,MAAM9B,UAAU+C,aAAa;YAC/B;QACF;IACF;AACF"}
|
|
@@ -3,7 +3,7 @@ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
|
3
3
|
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
4
4
|
import { confirm } from '@sanity/cli-core/ux';
|
|
5
5
|
import { isHttpError } from '@sanity/client';
|
|
6
|
-
import { deleteKnowledgeBase, getKnowledgeBaseBlueprintOwnership } from '../../services/context.js';
|
|
6
|
+
import { deleteKnowledgeBase, describeBlueprintManager, getKnowledgeBaseBlueprintOwnership } from '../../services/context.js';
|
|
7
7
|
const deleteContextDebug = subdebug('context:delete');
|
|
8
8
|
export class DeleteKnowledgeBaseCommand extends SanityCommand {
|
|
9
9
|
static args = {
|
|
@@ -35,7 +35,7 @@ export class DeleteKnowledgeBaseCommand extends SanityCommand {
|
|
|
35
35
|
const { yes: skipConfirmation } = this.flags;
|
|
36
36
|
const ownership = await getKnowledgeBaseBlueprintOwnership(knowledgeBaseId);
|
|
37
37
|
if (ownership.managed) {
|
|
38
|
-
const manager = ownership.stackName
|
|
38
|
+
const manager = describeBlueprintManager(ownership.stackName);
|
|
39
39
|
this.error(`${manager} manages knowledge base "${knowledgeBaseId}". To delete it, deploy it with \`lifecycle: {deletionPolicy: 'allow'}\` in the blueprint, then remove it from the blueprint and deploy again.`, {
|
|
40
40
|
exit: exitCodes.USAGE_ERROR
|
|
41
41
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/context/delete.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {isHttpError} from '@sanity/client'\n\nimport {deleteKnowledgeBase
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/context/delete.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {isHttpError} from '@sanity/client'\n\nimport {\n deleteKnowledgeBase,\n describeBlueprintManager,\n getKnowledgeBaseBlueprintOwnership,\n} from '../../services/context.js'\n\nconst deleteContextDebug = subdebug('context:delete')\n\nexport class DeleteKnowledgeBaseCommand extends SanityCommand<typeof DeleteKnowledgeBaseCommand> {\n static override args = {\n knowledgeBaseId: Args.string({\n description: 'Knowledge base ID',\n required: true,\n }),\n }\n\n static override description = 'Delete a knowledge base and its generated content'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123',\n description: 'Delete a knowledge base after confirmation',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --yes',\n description: 'Delete a knowledge base without confirmation prompt',\n },\n ]\n\n static override flags = {\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skip confirmation prompt (unattended mode)',\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {knowledgeBaseId} = this.args\n const {yes: skipConfirmation} = this.flags\n\n const ownership = await getKnowledgeBaseBlueprintOwnership(knowledgeBaseId)\n if (ownership.managed) {\n const manager = describeBlueprintManager(ownership.stackName)\n this.error(\n `${manager} manages knowledge base \"${knowledgeBaseId}\". To delete it, deploy it with \\`lifecycle: {deletionPolicy: 'allow'}\\` in the blueprint, then remove it from the blueprint and deploy again.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (this.isUnattended() && !skipConfirmation) {\n this.error('Deletion requires confirmation. Pass `--yes` to delete the knowledge base.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n if (!skipConfirmation) {\n const confirmed = await confirm({\n default: false,\n message: `Delete knowledge base \"${knowledgeBaseId}\"? This permanently deletes its generated content.`,\n })\n\n if (!confirmed) {\n this.log('Knowledge base not deleted')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n await deleteKnowledgeBase(knowledgeBaseId)\n this.log('Knowledge base deleted')\n } catch (error) {\n deleteContextDebug('Error deleting knowledge base', error)\n if (isHttpError(error) && error.statusCode === 404) {\n this.error(`Knowledge base \"${knowledgeBaseId}\" not found`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n this.error(`Failed to delete knowledge base: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","confirm","isHttpError","deleteKnowledgeBase","describeBlueprintManager","getKnowledgeBaseBlueprintOwnership","deleteContextDebug","DeleteKnowledgeBaseCommand","args","knowledgeBaseId","string","description","required","examples","command","flags","yes","boolean","char","default","run","skipConfirmation","ownership","managed","manager","stackName","error","exit","USAGE_ERROR","isUnattended","confirmed","message","log","USER_ABORT","statusCode","RUNTIME_ERROR"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AAEvC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,WAAW,QAAO,iBAAgB;AAE1C,SACEC,mBAAmB,EACnBC,wBAAwB,EACxBC,kCAAkC,QAC7B,4BAA2B;AAElC,MAAMC,qBAAqBP,SAAS;AAEpC,OAAO,MAAMQ,mCAAmCT;IAC9C,OAAgBU,OAAO;QACrBC,iBAAiBd,KAAKe,MAAM,CAAC;YAC3BC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oDAAmD;IAEjF,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,KAAKpB,MAAMqB,OAAO,CAAC;YACjBC,MAAM;YACNC,SAAS;YACTR,aAAa;QACf;IACF,EAAqB;IAErB,MAAaS,MAAqB;QAChC,MAAM,EAACX,eAAe,EAAC,GAAG,IAAI,CAACD,IAAI;QACnC,MAAM,EAACQ,KAAKK,gBAAgB,EAAC,GAAG,IAAI,CAACN,KAAK;QAE1C,MAAMO,YAAY,MAAMjB,mCAAmCI;QAC3D,IAAIa,UAAUC,OAAO,EAAE;YACrB,MAAMC,UAAUpB,yBAAyBkB,UAAUG,SAAS;YAC5D,IAAI,CAACC,KAAK,CACR,GAAGF,QAAQ,yBAAyB,EAAEf,gBAAgB,8IAA8I,CAAC,EACrM;gBAACkB,MAAM9B,UAAU+B,WAAW;YAAA;QAEhC;QAEA,IAAI,IAAI,CAACC,YAAY,MAAM,CAACR,kBAAkB;YAC5C,IAAI,CAACK,KAAK,CAAC,8EAA8E;gBACvFC,MAAM9B,UAAU+B,WAAW;YAC7B;QACF;QAEA,IAAI,CAACP,kBAAkB;YACrB,MAAMS,YAAY,MAAM7B,QAAQ;gBAC9BkB,SAAS;gBACTY,SAAS,CAAC,uBAAuB,EAAEtB,gBAAgB,kDAAkD,CAAC;YACxG;YAEA,IAAI,CAACqB,WAAW;gBACd,IAAI,CAACE,GAAG,CAAC;gBACT,IAAI,CAACL,IAAI,CAAC9B,UAAUoC,UAAU;YAChC;QACF;QAEA,IAAI;YACF,MAAM9B,oBAAoBM;YAC1B,IAAI,CAACuB,GAAG,CAAC;QACX,EAAE,OAAON,OAAO;YACdpB,mBAAmB,iCAAiCoB;YACpD,IAAIxB,YAAYwB,UAAUA,MAAMQ,UAAU,KAAK,KAAK;gBAClD,IAAI,CAACR,KAAK,CAAC,CAAC,gBAAgB,EAAEjB,gBAAgB,WAAW,CAAC,EAAE;oBAC1DkB,MAAM9B,UAAUsC,aAAa;gBAC/B;YACF;YACA,IAAI,CAACT,KAAK,CAAC,CAAC,iCAAiC,EAAE1B,gBAAgB0B,QAAQ,EAAE;gBACvEC,MAAM9B,UAAUsC,aAAa;YAC/B;QACF;IACF;AACF"}
|
|
@@ -40,12 +40,7 @@ export class ListIssuesCommand extends SanityCommand {
|
|
|
40
40
|
description: 'Only list issues of this kind',
|
|
41
41
|
// A Record forces every kind the client knows to be listed, so the options can't drift
|
|
42
42
|
options: Object.keys({
|
|
43
|
-
add_entry: true,
|
|
44
43
|
conflict: true,
|
|
45
|
-
gap: true,
|
|
46
|
-
merge_entry: true,
|
|
47
|
-
remove_entry: true,
|
|
48
|
-
split_entry: true,
|
|
49
44
|
update_required: true
|
|
50
45
|
})
|
|
51
46
|
})(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/context/issues/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {type Context, isHttpError} from '@sanity/client'\n\nimport {listIssues} from '../../../services/context.js'\n\nconst listIssuesDebug = subdebug('context:issues:list')\n\nexport class ListIssuesCommand extends SanityCommand<typeof ListIssuesCommand> {\n static override args = {\n knowledgeBaseId: Args.string({\n description: 'Knowledge base ID',\n required: true,\n }),\n }\n\n static override description = 'List issues found by knowledge base builds'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123',\n description: 'List all issues for a knowledge base',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --status open',\n description: 'List issues awaiting triage',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --kind conflict --severity critical',\n description: 'List critical conflicts',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --scope billing',\n description: 'List issues about entries under billing/',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --json',\n description: 'Output issues as JSON',\n },\n ]\n\n static override flags = {\n kind: Flags.custom<IssueKind>({\n description: 'Only list issues of this kind',\n // A Record forces every kind the client knows to be listed, so the options can't drift\n options: Object.keys({\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/issues/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {type Context, isHttpError} from '@sanity/client'\n\nimport {listIssues} from '../../../services/context.js'\n\nconst listIssuesDebug = subdebug('context:issues:list')\n\nexport class ListIssuesCommand extends SanityCommand<typeof ListIssuesCommand> {\n static override args = {\n knowledgeBaseId: Args.string({\n description: 'Knowledge base ID',\n required: true,\n }),\n }\n\n static override description = 'List issues found by knowledge base builds'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123',\n description: 'List all issues for a knowledge base',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --status open',\n description: 'List issues awaiting triage',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --kind conflict --severity critical',\n description: 'List critical conflicts',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --scope billing',\n description: 'List issues about entries under billing/',\n },\n {\n command: '<%= config.bin %> <%= command.id %> kb-abc123 --json',\n description: 'Output issues as JSON',\n },\n ]\n\n static override flags = {\n kind: Flags.custom<IssueKind>({\n description: 'Only list issues of this kind',\n // A Record forces every kind the client knows to be listed, so the options can't drift\n options: Object.keys({\n conflict: true,\n update_required: true,\n } satisfies Record<IssueKind, true>),\n })(),\n scope: Flags.string({\n description:\n 'Only list issues about this entry path or anything under it (`*` for knowledge-base-wide issues)',\n helpValue: '<path>',\n parse: async (input: string) => {\n const trimmed = input.trim().replace(/\\/+$/, '')\n if (trimmed === '') {\n throw new Error('`--scope` cannot be empty if provided')\n }\n return trimmed\n },\n }),\n severity: Flags.custom<Context.IssueDoc['content']['severity']>({\n description: 'Only list issues of this severity',\n options: ['critical', 'suggestion'],\n })(),\n status: Flags.custom<Context.IssueDoc['status']>({\n description:\n 'Only list issues with this status (rejected = dismissed, accepted = resolved or applied)',\n options: ['open', 'accepted', 'rejected'],\n })(),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {knowledgeBaseId} = this.args\n const {json, kind, scope, severity, status} = this.flags\n\n let issues\n try {\n issues = await listIssues(knowledgeBaseId, status)\n } catch (error) {\n listIssuesDebug('Error listing issues', error)\n if (isHttpError(error) && error.statusCode === 404) {\n this.error(`Knowledge base \"${knowledgeBaseId}\" not found`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n this.error(`Failed to list issues: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n // The client only filters on status; the rest are applied here\n const matches = issues.filter(\n ({content}) =>\n (kind === undefined || content.kind === kind) &&\n (severity === undefined || content.severity === severity) &&\n (scope === undefined ||\n content.scopePath === scope ||\n content.scopePath.startsWith(`${scope}/`)),\n )\n\n if (json) {\n this.logJson(matches)\n return\n }\n\n if (matches.length === 0) {\n this.log('No issues found')\n return\n }\n\n // Two lines per issue so long IDs never wrap: ID and metadata, then the summary cut to fit\n const width = Math.max(process.stdout.columns ?? 100, 40)\n const blocks = matches.map(({_id, content, status: issueStatus}) => {\n const meta = [content.kind, content.severity, issueStatus, content.scopePath].join(' · ')\n return `${_id} ${meta}\\n ${truncate(content.issue, width - 2)}`\n })\n this.log(blocks.join('\\n\\n'))\n }\n}\n\ntype IssueKind = Context.IssueDoc['content']['kind']\n\nfunction truncate(text: string, maxLength: number): string {\n // Count characters, not UTF-16 units, so an emoji at the cut point isn't split\n const chars = [...text.replaceAll(/\\s+/g, ' ').trim()]\n return chars.length <= maxLength ? chars.join('') : `${chars.slice(0, maxLength - 1).join('')}…`\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","isHttpError","listIssues","listIssuesDebug","ListIssuesCommand","args","knowledgeBaseId","string","description","required","enableJsonFlag","examples","command","flags","kind","custom","options","Object","keys","conflict","update_required","scope","helpValue","parse","input","trimmed","trim","replace","Error","severity","status","run","json","issues","error","statusCode","exit","RUNTIME_ERROR","matches","filter","content","undefined","scopePath","startsWith","logJson","length","log","width","Math","max","process","stdout","columns","blocks","map","_id","issueStatus","meta","join","truncate","issue","text","maxLength","chars","replaceAll","slice"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
2
2
|
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
3
|
-
import {
|
|
3
|
+
import { resolveOrganizationId } from '../../actions/context/resolveOrganizationId.js';
|
|
4
4
|
import { listKnowledgeBases } from '../../services/context.js';
|
|
5
5
|
import { Table } from '../../util/responsiveTable.js';
|
|
6
6
|
import { getOrganizationFlag } from '../../util/sharedFlags.js';
|
|
@@ -30,19 +30,11 @@ export class ListKnowledgeBasesCommand extends SanityCommand {
|
|
|
30
30
|
};
|
|
31
31
|
async run() {
|
|
32
32
|
const { json, organization } = this.flags;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
unattended: this.isUnattended()
|
|
39
|
-
});
|
|
40
|
-
} catch (error) {
|
|
41
|
-
listContextDebug('Error resolving organization', error);
|
|
42
|
-
this.error(getErrorMessage(error), {
|
|
43
|
-
exit: error instanceof MissingOrganizationError ? exitCodes.USAGE_ERROR : exitCodes.RUNTIME_ERROR
|
|
44
|
-
});
|
|
45
|
-
}
|
|
33
|
+
const organizationId = await resolveOrganizationId({
|
|
34
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
35
|
+
flagOrganizationId: organization,
|
|
36
|
+
unattended: this.isUnattended()
|
|
37
|
+
});
|
|
46
38
|
let knowledgeBases;
|
|
47
39
|
try {
|
|
48
40
|
knowledgeBases = await listKnowledgeBases(organizationId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/context/list.ts"],"sourcesContent":["import {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/context/list.ts"],"sourcesContent":["import {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\n\nimport {resolveOrganizationId} from '../../actions/context/resolveOrganizationId.js'\nimport {listKnowledgeBases} from '../../services/context.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {getOrganizationFlag} from '../../util/sharedFlags.js'\n\nconst listContextDebug = subdebug('context:list')\n\nexport class ListKnowledgeBasesCommand extends SanityCommand<typeof ListKnowledgeBasesCommand> {\n static override description = 'List knowledge bases in an organization'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List knowledge bases, selecting the organization interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --organization org-abc123',\n description: 'List knowledge bases in a specific organization',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --organization org-abc123 --json',\n description: 'Output knowledge bases as JSON',\n },\n ]\n\n static override flags = {\n ...getOrganizationFlag({\n description: 'Organization to list knowledge bases for',\n semantics: 'override',\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {json, organization} = this.flags\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n let knowledgeBases\n try {\n knowledgeBases = await listKnowledgeBases(organizationId)\n } catch (error) {\n listContextDebug('Error listing knowledge bases', error)\n this.error(`Failed to list knowledge bases: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (json) {\n this.logJson(knowledgeBases)\n return\n }\n\n if (knowledgeBases.length === 0) {\n this.log('No knowledge bases found')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'ID'},\n {alignment: 'left', name: 'title', title: 'Title'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'right', name: 'openIssues', title: 'Open issues'},\n {alignment: 'left', name: 'updatedAt', title: 'Updated'},\n ],\n })\n\n for (const {openIssueCount, publicId, state, title, updatedAt} of knowledgeBases) {\n table.addRow({id: publicId, openIssues: openIssueCount, state, title, updatedAt})\n }\n\n this.log(table.render())\n }\n}\n"],"names":["exitCodes","SanityCommand","subdebug","getErrorMessage","resolveOrganizationId","listKnowledgeBases","Table","getOrganizationFlag","listContextDebug","ListKnowledgeBasesCommand","description","enableJsonFlag","examples","command","flags","semantics","run","json","organization","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","isUnattended","knowledgeBases","error","exit","RUNTIME_ERROR","logJson","length","log","table","columns","alignment","name","title","openIssueCount","publicId","state","updatedAt","addRow","id","openIssues","render"],"mappings":"AACA,SAAQA,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AAEvD,SAAQC,qBAAqB,QAAO,iDAAgD;AACpF,SAAQC,kBAAkB,QAAO,4BAA2B;AAC5D,SAAQC,KAAK,QAAO,gCAA+B;AACnD,SAAQC,mBAAmB,QAAO,4BAA2B;AAE7D,MAAMC,mBAAmBN,SAAS;AAElC,OAAO,MAAMO,kCAAkCR;IAC7C,OAAgBS,cAAc,0CAAyC;IAEvE,OAAgBC,iBAAiB,KAAI;IAErC,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGP,oBAAoB;YACrBG,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAqB;IAErB,MAAaC,MAAqB;QAChC,MAAM,EAACC,IAAI,EAAEC,YAAY,EAAC,GAAG,IAAI,CAACJ,KAAK;QAEvC,MAAMK,iBAAiB,MAAMf,sBAAsB;YACjDgB,0BAA0B,AAAC,CAAA,MAAM,IAAI,CAACC,eAAe,EAAC,EAAGC,GAAG,EAAEH;YAC9DI,oBAAoBL;YACpBM,YAAY,IAAI,CAACC,YAAY;QAC/B;QAEA,IAAIC;QACJ,IAAI;YACFA,iBAAiB,MAAMrB,mBAAmBc;QAC5C,EAAE,OAAOQ,OAAO;YACdnB,iBAAiB,iCAAiCmB;YAClD,IAAI,CAACA,KAAK,CAAC,CAAC,gCAAgC,EAAExB,gBAAgBwB,QAAQ,EAAE;gBACtEC,MAAM5B,UAAU6B,aAAa;YAC/B;QACF;QAEA,IAAIZ,MAAM;YACR,IAAI,CAACa,OAAO,CAACJ;YACb;QACF;QAEA,IAAIA,eAAeK,MAAM,KAAK,GAAG;YAC/B,IAAI,CAACC,GAAG,CAAC;YACT;QACF;QAEA,MAAMC,QAAQ,IAAI3B,MAAM;YACtB4B,SAAS;gBACP;oBAACC,WAAW;oBAAQC,MAAM;oBAAMC,OAAO;gBAAI;gBAC3C;oBAACF,WAAW;oBAAQC,MAAM;oBAASC,OAAO;gBAAO;gBACjD;oBAACF,WAAW;oBAAQC,MAAM;oBAASC,OAAO;gBAAO;gBACjD;oBAACF,WAAW;oBAASC,MAAM;oBAAcC,OAAO;gBAAa;gBAC7D;oBAACF,WAAW;oBAAQC,MAAM;oBAAaC,OAAO;gBAAS;aACxD;QACH;QAEA,KAAK,MAAM,EAACC,cAAc,EAAEC,QAAQ,EAAEC,KAAK,EAAEH,KAAK,EAAEI,SAAS,EAAC,IAAIf,eAAgB;YAChFO,MAAMS,MAAM,CAAC;gBAACC,IAAIJ;gBAAUK,YAAYN;gBAAgBE;gBAAOH;gBAAOI;YAAS;QACjF;QAEA,IAAI,CAACT,GAAG,CAACC,MAAMY,MAAM;IACvB;AACF"}
|