@sanity/cli 5.3.0-next.8 → 5.3.0-next.81
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/lib/_chunks-cjs/cli.js +277 -181
- package/lib/_chunks-cjs/cli.js.map +1 -1
- package/lib/_chunks-cjs/loadEnv.js.map +1 -1
- package/lib/index.d.ts +13 -7
- package/lib/index.js +5 -3
- package/lib/index.js.map +1 -1
- package/package.json +11 -13
package/lib/_chunks-cjs/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
18
18
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
|
|
19
19
|
mod
|
|
20
20
|
));
|
|
21
|
-
var os = require("node:os"), chalk = require("chalk"), loadEnv = require("./loadEnv.js"), require$$0$5 = require("path"), require$$1$2 = require("module"), require$$0$4 = require("fs"), semver = require("semver"), telemetry = require("@sanity/telemetry"), childProcess = require("node:child_process"), fs$1 = require("node:fs"), path$3 = require("node:path"), fs = require("node:fs/promises"), util$3 = require("node:util"), require$$0$6 = require("os"), getLatestVersion = require("get-latest-version"), pkgDir = require("pkg-dir"), client$1 = require("@sanity/client"), require$$0$7 = require("constants"), require$$0$8 = require("stream"), require$$0$9 = require("util"), require$$0$a = require("assert"), require$$0$b = require("events"), require$$3$1 = require("crypto"), require$$1$3 = require("child_process"), getCliConfig = require("./getCliConfig.js"), require$$0$c = require("fs/promises"), require$$0$d = require("buffer"), journeyConfig = require("./journeyConfig.js"), Stream = require("node:stream"), promises$1 = require("node:stream/promises"), templateValidator = require("@sanity/template-validator"), require$$2$1 = require("string_decoder"), require$$0$e = require("zlib"), require$$7$1 = require("process"), http = require("node:http"), traverse = require("@babel/traverse"), node_url = require("node:url"), node_events = require("node:events"), node_string_decoder = require("node:string_decoder"), process$2 = require("node:process"), require$$2$2 = require("readline"), require$$0$f = require("tty");
|
|
21
|
+
var os = require("node:os"), chalk = require("chalk"), loadEnv = require("./loadEnv.js"), require$$0$5 = require("path"), require$$1$2 = require("module"), require$$0$4 = require("fs"), semver = require("semver"), telemetry = require("@sanity/telemetry"), childProcess = require("node:child_process"), fs$1 = require("node:fs"), path$3 = require("node:path"), fs = require("node:fs/promises"), util$3 = require("node:util"), require$$0$6 = require("os"), getLatestVersion = require("get-latest-version"), pkgDir = require("pkg-dir"), client$1 = require("@sanity/client"), require$$0$7 = require("constants"), require$$0$8 = require("stream"), require$$0$9 = require("util"), require$$0$a = require("assert"), require$$0$b = require("events"), require$$3$1 = require("crypto"), require$$1$3 = require("child_process"), getCliConfig = require("./getCliConfig.js"), require$$0$c = require("fs/promises"), require$$0$d = require("buffer"), journeyConfig = require("./journeyConfig.js"), Stream = require("node:stream"), promises$1 = require("node:stream/promises"), templateValidator = require("@sanity/template-validator"), require$$2$1 = require("string_decoder"), require$$0$e = require("zlib"), require$$7$1 = require("process"), http = require("node:http"), jsoncParser = require("jsonc-parser"), traverse = require("@babel/traverse"), node_url = require("node:url"), node_events = require("node:events"), node_string_decoder = require("node:string_decoder"), process$2 = require("node:process"), require$$2$2 = require("readline"), require$$0$f = require("tty");
|
|
22
22
|
function _interopDefaultCompat(e) {
|
|
23
23
|
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
24
24
|
}
|
|
@@ -2411,7 +2411,7 @@ function trimHash(version2) {
|
|
|
2411
2411
|
}
|
|
2412
2412
|
const BASE_URL = "https://www.sanity.io/docs/help/";
|
|
2413
2413
|
function generateHelpUrl(slug) {
|
|
2414
|
-
return BASE_URL
|
|
2414
|
+
return `${BASE_URL}${slug}`;
|
|
2415
2415
|
}
|
|
2416
2416
|
var polyfills, hasRequiredPolyfills;
|
|
2417
2417
|
function requirePolyfills() {
|
|
@@ -15818,7 +15818,7 @@ var cleanStack$2, hasRequiredCleanStack$1;
|
|
|
15818
15818
|
function requireCleanStack$1() {
|
|
15819
15819
|
if (hasRequiredCleanStack$1) return cleanStack$2;
|
|
15820
15820
|
hasRequiredCleanStack$1 = 1;
|
|
15821
|
-
const os2 = require$$0__default$2.default, extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/, pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/,
|
|
15821
|
+
const os2 = require$$0__default$2.default, extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/, pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/, homeDir2 = typeof os2.homedir > "u" ? "" : os2.homedir();
|
|
15822
15822
|
return cleanStack$2 = (stack2, options2) => (options2 = Object.assign({ pretty: !1 }, options2), stack2.replace(/\\/g, "/").split(`
|
|
15823
15823
|
`).filter((line3) => {
|
|
15824
15824
|
const pathMatches = line3.match(extractPathRegex);
|
|
@@ -15826,7 +15826,7 @@ function requireCleanStack$1() {
|
|
|
15826
15826
|
return !0;
|
|
15827
15827
|
const match2 = pathMatches[1];
|
|
15828
15828
|
return match2.includes(".app/Contents/Resources/electron.asar") || match2.includes(".app/Contents/Resources/default_app.asar") ? !1 : !pathRegex.test(match2);
|
|
15829
|
-
}).filter((line3) => line3.trim() !== "").map((line3) => options2.pretty ? line3.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(
|
|
15829
|
+
}).filter((line3) => line3.trim() !== "").map((line3) => options2.pretty ? line3.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir2, "~"))) : line3).join(`
|
|
15830
15830
|
`)), cleanStack$2;
|
|
15831
15831
|
}
|
|
15832
15832
|
var aggregateError, hasRequiredAggregateError;
|
|
@@ -19588,7 +19588,30 @@ const cliPackageManager = {
|
|
|
19588
19588
|
getInstallCommand,
|
|
19589
19589
|
getPackageManagerChoice,
|
|
19590
19590
|
installNewPackages
|
|
19591
|
-
};
|
|
19591
|
+
}, DEFAULT_MESSAGE = 'To set up your project with the MCP server, restart {{editorNames}} and type **"Get started with Sanity"** in the chat.';
|
|
19592
|
+
function applyCyanFormatting(text, chalk2) {
|
|
19593
|
+
return text.replace(/\*\*([^*]+)\*\*/g, (_, content) => chalk2.cyan(content));
|
|
19594
|
+
}
|
|
19595
|
+
function interpolateTemplate(template, editorNames) {
|
|
19596
|
+
return template.replace(/\{\{editorNames\}\}/g, editorNames);
|
|
19597
|
+
}
|
|
19598
|
+
async function fetchPostInitPrompt({
|
|
19599
|
+
client: client2,
|
|
19600
|
+
editorNames,
|
|
19601
|
+
chalk: chalk2
|
|
19602
|
+
}) {
|
|
19603
|
+
try {
|
|
19604
|
+
const template = (await client2.request({
|
|
19605
|
+
method: "GET",
|
|
19606
|
+
uri: "/journey/mcp/post-init-prompt",
|
|
19607
|
+
timeout: 1e3
|
|
19608
|
+
}))?.message || DEFAULT_MESSAGE, interpolated = interpolateTemplate(template, editorNames);
|
|
19609
|
+
return applyCyanFormatting(interpolated, chalk2);
|
|
19610
|
+
} catch {
|
|
19611
|
+
const interpolated = interpolateTemplate(DEFAULT_MESSAGE, editorNames);
|
|
19612
|
+
return applyCyanFormatting(interpolated, chalk2);
|
|
19613
|
+
}
|
|
19614
|
+
}
|
|
19592
19615
|
var ini = {}, hasRequiredIni;
|
|
19593
19616
|
function requireIni() {
|
|
19594
19617
|
if (hasRequiredIni) return ini;
|
|
@@ -23447,7 +23470,7 @@ function isGithubRepoShorthand(value) {
|
|
|
23447
23470
|
return URL.canParse(value) ? !1 : /^[\w-]+\/[\w-.]+(\/[@\w-.]+)*$/.test(value);
|
|
23448
23471
|
}
|
|
23449
23472
|
function isGithubRepoUrl(value) {
|
|
23450
|
-
if (URL.canParse(value)
|
|
23473
|
+
if (!URL.canParse(value))
|
|
23451
23474
|
return !1;
|
|
23452
23475
|
const url = new URL(value), pathSegments = url.pathname.slice(1).split("/");
|
|
23453
23476
|
return url.protocol === "https:" && url.hostname === "github.com" && // The pathname must have at least 2 segments. If it has more than 2, the
|
|
@@ -23903,6 +23926,223 @@ function samlProviderToLoginProvider(saml) {
|
|
|
23903
23926
|
url: saml.loginUrl
|
|
23904
23927
|
};
|
|
23905
23928
|
}
|
|
23929
|
+
const MCP_SERVER_URL = "https://mcp.sanity.io", NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`, defaultHttpConfig = (token2) => ({
|
|
23930
|
+
type: "http",
|
|
23931
|
+
url: MCP_SERVER_URL,
|
|
23932
|
+
headers: { Authorization: `Bearer ${token2}` }
|
|
23933
|
+
}), homeDir = os__default.default.homedir(), EDITOR_CONFIGS = {
|
|
23934
|
+
Cursor: {
|
|
23935
|
+
configKey: "mcpServers",
|
|
23936
|
+
detect: async () => {
|
|
23937
|
+
const cursorDir = path__default.default.join(homeDir, ".cursor");
|
|
23938
|
+
return fs$1.existsSync(cursorDir) ? path__default.default.join(cursorDir, "mcp.json") : null;
|
|
23939
|
+
},
|
|
23940
|
+
buildServerConfig: defaultHttpConfig
|
|
23941
|
+
},
|
|
23942
|
+
"VS Code": {
|
|
23943
|
+
configKey: "servers",
|
|
23944
|
+
detect: async () => {
|
|
23945
|
+
let configDir = null;
|
|
23946
|
+
switch (process.platform) {
|
|
23947
|
+
case "darwin":
|
|
23948
|
+
configDir = path__default.default.join(homeDir, "Library/Application Support/Code/User");
|
|
23949
|
+
break;
|
|
23950
|
+
case "win32":
|
|
23951
|
+
process.env.APPDATA && (configDir = path__default.default.join(process.env.APPDATA, "Code/User"));
|
|
23952
|
+
break;
|
|
23953
|
+
default:
|
|
23954
|
+
configDir = path__default.default.join(homeDir, ".config/Code/User");
|
|
23955
|
+
}
|
|
23956
|
+
return configDir && fs$1.existsSync(configDir) ? path__default.default.join(configDir, "mcp.json") : null;
|
|
23957
|
+
},
|
|
23958
|
+
buildServerConfig: defaultHttpConfig
|
|
23959
|
+
},
|
|
23960
|
+
"VS Code Insiders": {
|
|
23961
|
+
configKey: "servers",
|
|
23962
|
+
detect: async () => {
|
|
23963
|
+
let configDir = null;
|
|
23964
|
+
switch (process.platform) {
|
|
23965
|
+
case "darwin":
|
|
23966
|
+
configDir = path__default.default.join(homeDir, "Library/Application Support/Code - Insiders/User");
|
|
23967
|
+
break;
|
|
23968
|
+
case "win32":
|
|
23969
|
+
process.env.APPDATA && (configDir = path__default.default.join(process.env.APPDATA, "Code - Insiders/User"));
|
|
23970
|
+
break;
|
|
23971
|
+
default:
|
|
23972
|
+
configDir = path__default.default.join(homeDir, ".config/Code - Insiders/User");
|
|
23973
|
+
}
|
|
23974
|
+
return configDir && fs$1.existsSync(configDir) ? path__default.default.join(configDir, "mcp.json") : null;
|
|
23975
|
+
},
|
|
23976
|
+
buildServerConfig: defaultHttpConfig
|
|
23977
|
+
},
|
|
23978
|
+
"Claude Code": {
|
|
23979
|
+
configKey: "mcpServers",
|
|
23980
|
+
detect: async () => {
|
|
23981
|
+
try {
|
|
23982
|
+
return await execa("claude", ["--version"], { stdio: "pipe", timeout: 5e3 }), path__default.default.join(homeDir, ".claude.json");
|
|
23983
|
+
} catch {
|
|
23984
|
+
return null;
|
|
23985
|
+
}
|
|
23986
|
+
},
|
|
23987
|
+
buildServerConfig: defaultHttpConfig
|
|
23988
|
+
},
|
|
23989
|
+
Zed: {
|
|
23990
|
+
configKey: "context_servers",
|
|
23991
|
+
detect: async () => {
|
|
23992
|
+
let configDir = null;
|
|
23993
|
+
return process.platform === "win32" ? process.env.APPDATA && (configDir = path__default.default.join(process.env.APPDATA, "Zed")) : configDir = path__default.default.join(homeDir, ".config/zed"), configDir && fs$1.existsSync(configDir) ? path__default.default.join(configDir, "settings.json") : null;
|
|
23994
|
+
},
|
|
23995
|
+
buildServerConfig: (token2) => ({
|
|
23996
|
+
url: MCP_SERVER_URL,
|
|
23997
|
+
headers: { Authorization: `Bearer ${token2}` },
|
|
23998
|
+
settings: {}
|
|
23999
|
+
})
|
|
24000
|
+
},
|
|
24001
|
+
OpenCode: {
|
|
24002
|
+
configKey: "mcp",
|
|
24003
|
+
detect: async () => {
|
|
24004
|
+
try {
|
|
24005
|
+
return await execa("opencode", ["--version"], { stdio: "pipe", timeout: 5e3 }), path__default.default.join(homeDir, ".config/opencode/opencode.json");
|
|
24006
|
+
} catch {
|
|
24007
|
+
return null;
|
|
24008
|
+
}
|
|
24009
|
+
},
|
|
24010
|
+
buildServerConfig: (token2) => ({
|
|
24011
|
+
type: "remote",
|
|
24012
|
+
url: MCP_SERVER_URL,
|
|
24013
|
+
headers: { Authorization: `Bearer ${token2}` }
|
|
24014
|
+
})
|
|
24015
|
+
}
|
|
24016
|
+
};
|
|
24017
|
+
function parseConfig(content) {
|
|
24018
|
+
if (content.trim() === "")
|
|
24019
|
+
return {};
|
|
24020
|
+
const errors = [], parsed = jsoncParser.parse(content, errors, { allowTrailingComma: !0 });
|
|
24021
|
+
return errors.length > 0 || typeof parsed != "object" || parsed === null || Array.isArray(parsed) ? null : parsed;
|
|
24022
|
+
}
|
|
24023
|
+
async function checkEditorConfig(name, configPath) {
|
|
24024
|
+
const { configKey } = EDITOR_CONFIGS[name];
|
|
24025
|
+
if (!fs$1.existsSync(configPath))
|
|
24026
|
+
return { name, configPath, configured: !1 };
|
|
24027
|
+
try {
|
|
24028
|
+
const content = await fs__default.default.readFile(configPath, "utf-8"), config2 = parseConfig(content);
|
|
24029
|
+
if (config2 === null)
|
|
24030
|
+
return getCliConfig.debug("Skipping %s: could not parse %s", name, configPath), null;
|
|
24031
|
+
const configured = !!config2[configKey]?.Sanity;
|
|
24032
|
+
return { name, configPath, configured };
|
|
24033
|
+
} catch (err) {
|
|
24034
|
+
return getCliConfig.debug("Skipping %s: could not read %s: %s", name, configPath, err), null;
|
|
24035
|
+
}
|
|
24036
|
+
}
|
|
24037
|
+
async function detectAvailableEditors() {
|
|
24038
|
+
const editors = [];
|
|
24039
|
+
for (const [name, config2] of Object.entries(EDITOR_CONFIGS)) {
|
|
24040
|
+
const configPath = await config2.detect();
|
|
24041
|
+
if (configPath) {
|
|
24042
|
+
const editor2 = await checkEditorConfig(name, configPath);
|
|
24043
|
+
editor2 && editors.push(editor2);
|
|
24044
|
+
}
|
|
24045
|
+
}
|
|
24046
|
+
return editors;
|
|
24047
|
+
}
|
|
24048
|
+
async function promptForMCPSetup(prompt2, editors) {
|
|
24049
|
+
const editorChoices = editors.map((e) => ({
|
|
24050
|
+
name: e.configured ? `${e.name} (already installed)` : e.name,
|
|
24051
|
+
value: e.name,
|
|
24052
|
+
checked: !e.configured
|
|
24053
|
+
// Only pre-select if NOT already configured
|
|
24054
|
+
})), selectedNames = (await prompt2([
|
|
24055
|
+
{
|
|
24056
|
+
type: "checkbox",
|
|
24057
|
+
name: "selectedEditors",
|
|
24058
|
+
message: "Configure Sanity MCP server?",
|
|
24059
|
+
choices: editorChoices
|
|
24060
|
+
}
|
|
24061
|
+
])).selectedEditors;
|
|
24062
|
+
return !selectedNames || selectedNames.length === 0 ? null : editors.filter((e) => selectedNames.includes(e.name));
|
|
24063
|
+
}
|
|
24064
|
+
async function createMCPToken(apiClient) {
|
|
24065
|
+
if (!getCliToken())
|
|
24066
|
+
throw new Error("Not authenticated. Please run `sanity login` first.");
|
|
24067
|
+
const client2 = apiClient({ requireUser: !0, requireProject: !1 }).clone().config({ apiVersion: "2025-12-09" }), sessionResponse = await client2.request({
|
|
24068
|
+
method: "POST",
|
|
24069
|
+
uri: "/auth/session/create",
|
|
24070
|
+
body: {
|
|
24071
|
+
sourceId: "sanity-mcp",
|
|
24072
|
+
withStamp: !1
|
|
24073
|
+
}
|
|
24074
|
+
});
|
|
24075
|
+
return (await client2.request({
|
|
24076
|
+
method: "GET",
|
|
24077
|
+
uri: "/auth/fetch",
|
|
24078
|
+
query: { sid: sessionResponse.sid }
|
|
24079
|
+
})).token;
|
|
24080
|
+
}
|
|
24081
|
+
async function writeMCPConfig(editor2, token2) {
|
|
24082
|
+
const configPath = editor2.configPath, { configKey, buildServerConfig } = EDITOR_CONFIGS[editor2.name];
|
|
24083
|
+
let content = "{}";
|
|
24084
|
+
if (fs$1.existsSync(configPath)) {
|
|
24085
|
+
const fileContent = await fs__default.default.readFile(configPath, "utf-8");
|
|
24086
|
+
fileContent.trim() && (content = fileContent);
|
|
24087
|
+
}
|
|
24088
|
+
const edits = jsoncParser.modify(content, [configKey, "Sanity"], buildServerConfig(token2), {
|
|
24089
|
+
formattingOptions: { tabSize: 2, insertSpaces: !0 }
|
|
24090
|
+
});
|
|
24091
|
+
content = jsoncParser.applyEdits(content, edits), await fs__default.default.mkdir(path__default.default.dirname(configPath), { recursive: !0 }), await fs__default.default.writeFile(configPath, content, "utf-8");
|
|
24092
|
+
}
|
|
24093
|
+
async function setupMCP(context, options2) {
|
|
24094
|
+
const { output, prompt: prompt2 } = context;
|
|
24095
|
+
if (options2.mcp === !1)
|
|
24096
|
+
return output.warn("Skipping MCP configuration due to --no-mcp flag"), {
|
|
24097
|
+
detectedEditors: [],
|
|
24098
|
+
configuredEditors: [],
|
|
24099
|
+
skipped: !0
|
|
24100
|
+
};
|
|
24101
|
+
const editors = await detectAvailableEditors(), detectedEditors = editors.map((e) => e.name);
|
|
24102
|
+
if (editors.length === 0)
|
|
24103
|
+
return output.warn(NO_EDITORS_DETECTED_MESSAGE), {
|
|
24104
|
+
detectedEditors,
|
|
24105
|
+
configuredEditors: [],
|
|
24106
|
+
skipped: !0
|
|
24107
|
+
};
|
|
24108
|
+
const selected = await promptForMCPSetup(prompt2, editors);
|
|
24109
|
+
if (!selected || selected.length === 0)
|
|
24110
|
+
return {
|
|
24111
|
+
detectedEditors,
|
|
24112
|
+
configuredEditors: [],
|
|
24113
|
+
skipped: !0
|
|
24114
|
+
};
|
|
24115
|
+
let token2;
|
|
24116
|
+
try {
|
|
24117
|
+
token2 = await createMCPToken(context.apiClient);
|
|
24118
|
+
} catch (error2) {
|
|
24119
|
+
const err = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
24120
|
+
return output.warn(`Could not configure MCP: ${err.message}`), output.warn("You can set up MCP manually later using https://mcp.sanity.io"), {
|
|
24121
|
+
detectedEditors,
|
|
24122
|
+
configuredEditors: [],
|
|
24123
|
+
skipped: !1,
|
|
24124
|
+
error: err
|
|
24125
|
+
};
|
|
24126
|
+
}
|
|
24127
|
+
try {
|
|
24128
|
+
for (const editor2 of selected)
|
|
24129
|
+
await writeMCPConfig(editor2, token2);
|
|
24130
|
+
} catch (error2) {
|
|
24131
|
+
const err = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
24132
|
+
return output.warn(`Could not configure MCP: ${err.message}`), output.warn("You can set up MCP manually later using https://mcp.sanity.io"), {
|
|
24133
|
+
detectedEditors,
|
|
24134
|
+
configuredEditors: [],
|
|
24135
|
+
skipped: !1,
|
|
24136
|
+
error: err
|
|
24137
|
+
};
|
|
24138
|
+
}
|
|
24139
|
+
const configuredEditors = selected.map((e) => e.name);
|
|
24140
|
+
return output.success(`MCP configured for ${configuredEditors.join(", ")}`), {
|
|
24141
|
+
detectedEditors,
|
|
24142
|
+
configuredEditors,
|
|
24143
|
+
skipped: !1
|
|
24144
|
+
};
|
|
24145
|
+
}
|
|
23906
24146
|
function createProject(apiClient, options2) {
|
|
23907
24147
|
return apiClient({
|
|
23908
24148
|
requireUser: !0,
|
|
@@ -34206,7 +34446,7 @@ export default defineCliConfig({
|
|
|
34206
34446
|
deployment: {
|
|
34207
34447
|
/**
|
|
34208
34448
|
* Enable auto-updates for studios.
|
|
34209
|
-
* Learn more at https://www.sanity.io/docs/
|
|
34449
|
+
* Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56
|
|
34210
34450
|
*/
|
|
34211
34451
|
autoUpdates: __BOOL__autoUpdates__,
|
|
34212
34452
|
}
|
|
@@ -39625,7 +39865,7 @@ async function bootstrapRemoteTemplate(opts, context) {
|
|
|
39625
39865
|
fs: new distExports.LocalFileSystemDetector(packagePath),
|
|
39626
39866
|
frameworkList: frameworksExports.frameworks
|
|
39627
39867
|
}), port = getDefaultPortForFramework(packageFramework?.slug);
|
|
39628
|
-
corsAdded.includes(port)
|
|
39868
|
+
corsAdded.includes(port) && (getCliConfig.debug("Setting CORS origin to http://localhost:%d", port), await setCorsOrigin(`http://localhost:${port}`, variables.projectId, apiClient), corsAdded.push(port)), getCliConfig.debug("Applying environment variables to %s", pkg);
|
|
39629
39869
|
const envName = packageFramework?.slug === "nextjs" ? ".env.local" : ".env";
|
|
39630
39870
|
await applyEnvVariables(packagePath, { ...variables, readToken, writeToken }, envName);
|
|
39631
39871
|
}
|
|
@@ -39774,160 +40014,6 @@ function readPackageJson(filePath) {
|
|
|
39774
40014
|
return;
|
|
39775
40015
|
}
|
|
39776
40016
|
}
|
|
39777
|
-
const MCP_SERVER_URL = "https://mcp.sanity.io", NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`;
|
|
39778
|
-
async function detectAvailableEditors() {
|
|
39779
|
-
const editors = [], homeDir = os__default.default.homedir(), cursorDir = path__default.default.join(homeDir, ".cursor");
|
|
39780
|
-
fs$1.existsSync(cursorDir) && editors.push({
|
|
39781
|
-
name: "Cursor",
|
|
39782
|
-
configPath: path__default.default.join(cursorDir, "mcp.json"),
|
|
39783
|
-
configKey: "mcpServers"
|
|
39784
|
-
});
|
|
39785
|
-
let vscodeConfigDir = null;
|
|
39786
|
-
switch (process.platform) {
|
|
39787
|
-
case "darwin":
|
|
39788
|
-
vscodeConfigDir = path__default.default.join(homeDir, "Library/Application Support/Code/User");
|
|
39789
|
-
break;
|
|
39790
|
-
case "win32":
|
|
39791
|
-
process.env.APPDATA && (vscodeConfigDir = path__default.default.join(process.env.APPDATA, "Code/User"));
|
|
39792
|
-
break;
|
|
39793
|
-
default:
|
|
39794
|
-
vscodeConfigDir = path__default.default.join(homeDir, ".config/Code/User");
|
|
39795
|
-
}
|
|
39796
|
-
vscodeConfigDir && fs$1.existsSync(vscodeConfigDir) && editors.push({
|
|
39797
|
-
name: "VS Code",
|
|
39798
|
-
configPath: path__default.default.join(vscodeConfigDir, "mcp.json"),
|
|
39799
|
-
configKey: "servers"
|
|
39800
|
-
});
|
|
39801
|
-
try {
|
|
39802
|
-
await execa("claude", ["--version"], { stdio: "pipe", timeout: 5e3 }), editors.push({
|
|
39803
|
-
name: "Claude Code",
|
|
39804
|
-
configPath: path__default.default.join(homeDir, ".claude.json"),
|
|
39805
|
-
configKey: "mcpServers"
|
|
39806
|
-
});
|
|
39807
|
-
} catch {
|
|
39808
|
-
}
|
|
39809
|
-
return editors;
|
|
39810
|
-
}
|
|
39811
|
-
async function promptForMCPSetup(prompt2, detectedEditors, editorsWithExisting) {
|
|
39812
|
-
const editorChoices = detectedEditors.map((e) => {
|
|
39813
|
-
const isConfigured = editorsWithExisting.some((existing) => existing.name === e.name);
|
|
39814
|
-
return {
|
|
39815
|
-
name: isConfigured ? `${e.name} (already installed)` : e.name,
|
|
39816
|
-
value: e.name,
|
|
39817
|
-
checked: !isConfigured
|
|
39818
|
-
// Only pre-select if NOT already configured
|
|
39819
|
-
};
|
|
39820
|
-
}), selectedNames = (await prompt2([
|
|
39821
|
-
{
|
|
39822
|
-
type: "checkbox",
|
|
39823
|
-
name: "selectedEditors",
|
|
39824
|
-
message: "Configure Sanity MCP server?",
|
|
39825
|
-
choices: editorChoices
|
|
39826
|
-
}
|
|
39827
|
-
])).selectedEditors;
|
|
39828
|
-
return !selectedNames || selectedNames.length === 0 ? null : detectedEditors.filter((e) => selectedNames.includes(e.name));
|
|
39829
|
-
}
|
|
39830
|
-
async function createMCPToken(apiClient) {
|
|
39831
|
-
if (!getCliToken())
|
|
39832
|
-
throw new Error("Not authenticated. Please run `sanity login` first.");
|
|
39833
|
-
const client2 = apiClient({ requireUser: !0, requireProject: !1 }).clone().config({ apiVersion: "2025-12-09" }), sessionResponse = await client2.request({
|
|
39834
|
-
method: "POST",
|
|
39835
|
-
uri: "/auth/session/create",
|
|
39836
|
-
body: {
|
|
39837
|
-
sourceId: "sanity-mcp",
|
|
39838
|
-
withStamp: !1
|
|
39839
|
-
}
|
|
39840
|
-
});
|
|
39841
|
-
return (await client2.request({
|
|
39842
|
-
method: "GET",
|
|
39843
|
-
uri: "/auth/fetch",
|
|
39844
|
-
query: { sid: sessionResponse.sid }
|
|
39845
|
-
})).token;
|
|
39846
|
-
}
|
|
39847
|
-
async function getEditorsWithExistingConfig(editors) {
|
|
39848
|
-
const configured = [];
|
|
39849
|
-
for (const editor2 of editors)
|
|
39850
|
-
if (fs$1.existsSync(editor2.configPath))
|
|
39851
|
-
try {
|
|
39852
|
-
const content = await fs__default.default.readFile(editor2.configPath, "utf-8");
|
|
39853
|
-
JSON.parse(content)[editor2.configKey]?.Sanity && configured.push(editor2);
|
|
39854
|
-
} catch (err) {
|
|
39855
|
-
getCliConfig.debug("Could not read MCP config for %s: %s", editor2.name, err);
|
|
39856
|
-
}
|
|
39857
|
-
return configured;
|
|
39858
|
-
}
|
|
39859
|
-
async function writeMCPConfig(editor2, token2) {
|
|
39860
|
-
const configPath = editor2.configPath;
|
|
39861
|
-
let existingConfig = {};
|
|
39862
|
-
if (fs$1.existsSync(configPath))
|
|
39863
|
-
try {
|
|
39864
|
-
const content = await fs__default.default.readFile(configPath, "utf-8");
|
|
39865
|
-
existingConfig = JSON.parse(content);
|
|
39866
|
-
} catch {
|
|
39867
|
-
getCliConfig.debug(`Warning: Could not parse ${configPath}. Creating new config.`);
|
|
39868
|
-
}
|
|
39869
|
-
const serverKey = editor2.configKey;
|
|
39870
|
-
existingConfig[serverKey] || (existingConfig[serverKey] = {}), existingConfig[serverKey].Sanity = {
|
|
39871
|
-
type: "http",
|
|
39872
|
-
url: MCP_SERVER_URL,
|
|
39873
|
-
headers: {
|
|
39874
|
-
Authorization: `Bearer ${token2}`
|
|
39875
|
-
}
|
|
39876
|
-
}, await fs__default.default.mkdir(path__default.default.dirname(configPath), { recursive: !0 }), await fs__default.default.writeFile(configPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
39877
|
-
}
|
|
39878
|
-
async function setupMCP(context, options2) {
|
|
39879
|
-
const { output, prompt: prompt2 } = context;
|
|
39880
|
-
if (options2.mcp === !1)
|
|
39881
|
-
return output.warn("Skipping MCP configuration due to --no-mcp flag"), {
|
|
39882
|
-
detectedEditors: [],
|
|
39883
|
-
configuredEditors: [],
|
|
39884
|
-
skipped: !0
|
|
39885
|
-
};
|
|
39886
|
-
const detected = await detectAvailableEditors(), detectedEditors = detected.map((e) => e.name);
|
|
39887
|
-
if (detected.length === 0)
|
|
39888
|
-
return output.warn(NO_EDITORS_DETECTED_MESSAGE), {
|
|
39889
|
-
detectedEditors,
|
|
39890
|
-
configuredEditors: [],
|
|
39891
|
-
skipped: !0
|
|
39892
|
-
};
|
|
39893
|
-
const editorsWithExisting = await getEditorsWithExistingConfig(detected), selected = await promptForMCPSetup(prompt2, detected, editorsWithExisting);
|
|
39894
|
-
if (!selected || selected.length === 0)
|
|
39895
|
-
return {
|
|
39896
|
-
detectedEditors,
|
|
39897
|
-
configuredEditors: [],
|
|
39898
|
-
skipped: !0
|
|
39899
|
-
};
|
|
39900
|
-
let token2;
|
|
39901
|
-
try {
|
|
39902
|
-
token2 = await createMCPToken(context.apiClient);
|
|
39903
|
-
} catch (error2) {
|
|
39904
|
-
const err = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
39905
|
-
return output.warn(`Could not configure MCP: ${err.message}`), output.warn("You can set up MCP manually later using https://mcp.sanity.io"), {
|
|
39906
|
-
detectedEditors,
|
|
39907
|
-
configuredEditors: [],
|
|
39908
|
-
skipped: !1,
|
|
39909
|
-
error: err
|
|
39910
|
-
};
|
|
39911
|
-
}
|
|
39912
|
-
try {
|
|
39913
|
-
for (const editor2 of selected)
|
|
39914
|
-
await writeMCPConfig(editor2, token2);
|
|
39915
|
-
} catch (error2) {
|
|
39916
|
-
const err = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
39917
|
-
return output.warn(`Could not configure MCP: ${err.message}`), output.warn("You can set up MCP manually later using https://mcp.sanity.io"), {
|
|
39918
|
-
detectedEditors,
|
|
39919
|
-
configuredEditors: [],
|
|
39920
|
-
skipped: !1,
|
|
39921
|
-
error: err
|
|
39922
|
-
};
|
|
39923
|
-
}
|
|
39924
|
-
const configuredEditors = selected.map((e) => e.name);
|
|
39925
|
-
return output.success(`MCP configured for ${configuredEditors.join(", ")}`), {
|
|
39926
|
-
detectedEditors,
|
|
39927
|
-
configuredEditors,
|
|
39928
|
-
skipped: !1
|
|
39929
|
-
};
|
|
39930
|
-
}
|
|
39931
40017
|
const authorType = `import {UserIcon} from '@sanity/icons'
|
|
39932
40018
|
import {defineArrayMember, defineField, defineType} from 'sanity'
|
|
39933
40019
|
|
|
@@ -40597,12 +40683,14 @@ You can find your project on Sanity Manage \u2014 https://www.sanity.io/manage/p
|
|
|
40597
40683
|
if (chosen === "npm" ? await execa("npm", ["install", "--legacy-peer-deps", "next-sanity@11"], execOptions) : chosen === "yarn" ? await execa("npx", ["install-peerdeps", "--yarn", "next-sanity@11"], execOptions) : chosen === "pnpm" && await execa("pnpm", ["install", "next-sanity@11"], execOptions), print(
|
|
40598
40684
|
`
|
|
40599
40685
|
${chalk2.green("Success!")} Your Sanity configuration files has been added to this project`
|
|
40600
|
-
), mcpConfigured.length > 0) {
|
|
40601
|
-
const
|
|
40602
|
-
print(
|
|
40686
|
+
), mcpConfigured && mcpConfigured.length > 0) {
|
|
40687
|
+
const message = await getPostInitMCPPrompt(mcpConfigured);
|
|
40688
|
+
print(`
|
|
40689
|
+
${message}`), print(`
|
|
40690
|
+
Learn more: ${chalk2.cyan("https://mcp.sanity.io")}`), print(
|
|
40603
40691
|
`
|
|
40604
|
-
|
|
40605
|
-
)
|
|
40692
|
+
Have feedback? Tell us in the community: ${chalk2.cyan("https://www.sanity.io/community/join")}`
|
|
40693
|
+
);
|
|
40606
40694
|
}
|
|
40607
40695
|
return;
|
|
40608
40696
|
}
|
|
@@ -40679,12 +40767,14 @@ Sanity MCP server has been configured for ${editorNames}. You might need to rest
|
|
|
40679
40767
|
if (print(`\u2705 ${chalk2.green.bold("Success!")} Your custom app has been scaffolded.`), isCurrentDir || print(goToProjectDir), print(
|
|
40680
40768
|
`
|
|
40681
40769
|
${chalk2.bold("Next")}, configure the project(s) and dataset(s) your app should work with.`
|
|
40682
|
-
), print("\nGet started in `src/App.tsx`, or refer to our documentation for a walkthrough:"), print(chalk2.blue.underline("https://www.sanity.io/docs/app-sdk/sdk-configuration")), mcpConfigured.length > 0) {
|
|
40683
|
-
const
|
|
40684
|
-
print(
|
|
40770
|
+
), print("\nGet started in `src/App.tsx`, or refer to our documentation for a walkthrough:"), print(chalk2.blue.underline("https://www.sanity.io/docs/app-sdk/sdk-configuration")), mcpConfigured && mcpConfigured.length > 0) {
|
|
40771
|
+
const message = await getPostInitMCPPrompt(mcpConfigured);
|
|
40772
|
+
print(`
|
|
40773
|
+
${message}`), print(`
|
|
40774
|
+
Learn more: ${chalk2.cyan("https://mcp.sanity.io")}`), print(
|
|
40685
40775
|
`
|
|
40686
|
-
|
|
40687
|
-
)
|
|
40776
|
+
Have feedback? Tell us in the community: ${chalk2.cyan("https://www.sanity.io/community/join")}`
|
|
40777
|
+
);
|
|
40688
40778
|
}
|
|
40689
40779
|
print(`
|
|
40690
40780
|
`), print("Other helpful commands:"), print("npx sanity docs browse to open the documentation in a browser"), print("npx sanity dev to start the development server for your app"), print("npx sanity deploy to deploy your app");
|
|
@@ -40692,12 +40782,10 @@ Sanity MCP server has been configured for ${editorNames}. You might need to rest
|
|
|
40692
40782
|
if (print(`\u2705 ${chalk2.green.bold("Success!")} Your Studio has been created.`), isCurrentDir || print(goToProjectDir), print(
|
|
40693
40783
|
`
|
|
40694
40784
|
Get started by running ${chalk2.cyan(devCommand)} to launch your Studio's development server`
|
|
40695
|
-
), mcpConfigured.length > 0) {
|
|
40696
|
-
const
|
|
40697
|
-
print(
|
|
40698
|
-
|
|
40699
|
-
To set up your project with the MCP server, restart ${editorNames} and type ${chalk2.cyan('"Get started with Sanity"')} in the chat`
|
|
40700
|
-
), print(`
|
|
40785
|
+
), mcpConfigured && mcpConfigured.length > 0) {
|
|
40786
|
+
const message = await getPostInitMCPPrompt(mcpConfigured);
|
|
40787
|
+
print(`
|
|
40788
|
+
${message}`), print(`
|
|
40701
40789
|
Learn more: ${chalk2.cyan("https://mcp.sanity.io")}`), print(
|
|
40702
40790
|
`
|
|
40703
40791
|
Have feedback? Tell us in the community: ${chalk2.cyan("https://www.sanity.io/community/join")}`
|
|
@@ -40760,6 +40848,14 @@ Join the Sanity community: ${chalk2.cyan("https://www.sanity.io/community/join")
|
|
|
40760
40848
|
datasetName: dataset.datasetName
|
|
40761
40849
|
};
|
|
40762
40850
|
}
|
|
40851
|
+
async function getPostInitMCPPrompt(editorsNames) {
|
|
40852
|
+
const promptClient = apiClient({ requireUser: !1, requireProject: !1 });
|
|
40853
|
+
return fetchPostInitPrompt({
|
|
40854
|
+
client: promptClient,
|
|
40855
|
+
editorNames: new Intl.ListFormat("en").format(editorsNames),
|
|
40856
|
+
chalk: chalk2
|
|
40857
|
+
});
|
|
40858
|
+
}
|
|
40763
40859
|
async function getOrCreateProject() {
|
|
40764
40860
|
const client2 = apiClient({ requireUser: !0, requireProject: !1 });
|
|
40765
40861
|
let projects, organizations;
|
|
@@ -41433,7 +41529,7 @@ Examples
|
|
|
41433
41529
|
group: "mcp",
|
|
41434
41530
|
helpText: helpText$8,
|
|
41435
41531
|
signature: "",
|
|
41436
|
-
description: "Configure Sanity MCP server for AI editors
|
|
41532
|
+
description: "Configure Sanity MCP server for AI editors",
|
|
41437
41533
|
async action(args, context) {
|
|
41438
41534
|
const { output, telemetry: telemetry2 } = context, trace = telemetry2.trace(MCPConfigureTrace);
|
|
41439
41535
|
if ((await detectAvailableEditors()).length === 0) {
|
|
@@ -70123,7 +70219,7 @@ var cleanStack$1, hasRequiredCleanStack;
|
|
|
70123
70219
|
function requireCleanStack() {
|
|
70124
70220
|
if (hasRequiredCleanStack) return cleanStack$1;
|
|
70125
70221
|
hasRequiredCleanStack = 1;
|
|
70126
|
-
const os2 = require$$0__default$2.default, escapeStringRegexp2 = requireEscapeStringRegexp(), extractPathRegex = /\s+at.*[(\s](.*)\)?/, pathRegex = /^(?:(?:(?:node|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/,
|
|
70222
|
+
const os2 = require$$0__default$2.default, escapeStringRegexp2 = requireEscapeStringRegexp(), extractPathRegex = /\s+at.*[(\s](.*)\)?/, pathRegex = /^(?:(?:(?:node|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/, homeDir2 = typeof os2.homedir > "u" ? "" : os2.homedir();
|
|
70127
70223
|
return cleanStack$1 = (stack2, { pretty = !1, basePath } = {}) => {
|
|
70128
70224
|
const basePathRegex = basePath && new RegExp(`(at | \\()${escapeStringRegexp2(basePath)}`, "g");
|
|
70129
70225
|
return stack2.replace(/\\/g, "/").split(`
|
|
@@ -70133,7 +70229,7 @@ function requireCleanStack() {
|
|
|
70133
70229
|
return !0;
|
|
70134
70230
|
const match2 = pathMatches[1];
|
|
70135
70231
|
return match2.includes(".app/Contents/Resources/electron.asar") || match2.includes(".app/Contents/Resources/default_app.asar") ? !1 : !pathRegex.test(match2);
|
|
70136
|
-
}).filter((line3) => line3.trim() !== "").map((line3) => (basePathRegex && (line3 = line3.replace(basePathRegex, "$1")), pretty && (line3 = line3.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(
|
|
70232
|
+
}).filter((line3) => line3.trim() !== "").map((line3) => (basePathRegex && (line3 = line3.replace(basePathRegex, "$1")), pretty && (line3 = line3.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir2, "~")))), line3)).join(`
|
|
70137
70233
|
`);
|
|
70138
70234
|
}, cleanStack$1;
|
|
70139
70235
|
}
|