@sanity/cli 6.0.0-alpha.13 β 6.0.0-alpha.15
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/README.md +113 -102
- package/dist/actions/build/buildApp.js +4 -3
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStaticFiles.js +3 -2
- package/dist/actions/build/buildStaticFiles.js.map +1 -1
- package/dist/actions/build/buildStudio.js +1 -0
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/buildVendorDependencies.js +15 -36
- package/dist/actions/build/buildVendorDependencies.js.map +1 -1
- package/dist/actions/build/checkRequiredDependencies.js +7 -5
- package/dist/actions/build/checkRequiredDependencies.js.map +1 -1
- package/dist/actions/build/checkStudioDependencyVersions.js +6 -6
- package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +2 -2
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +2 -2
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/dev/startStudioDevServer.js +2 -2
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/manifest/extractManifest.js +2 -2
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/mcp/detectAvailableEditors.js +16 -4
- package/dist/actions/mcp/detectAvailableEditors.js.map +1 -1
- package/dist/actions/mcp/editorConfigs.js +64 -6
- package/dist/actions/mcp/editorConfigs.js.map +1 -1
- package/dist/actions/mcp/writeMCPConfig.js +27 -15
- package/dist/actions/mcp/writeMCPConfig.js.map +1 -1
- package/dist/actions/schema/extractSchema.js +7 -32
- package/dist/actions/schema/extractSchema.js.map +1 -1
- package/dist/actions/schema/extractSchemaWatcher.js +126 -0
- package/dist/actions/schema/extractSchemaWatcher.js.map +1 -0
- package/dist/actions/schema/formatSchemaValidation.js +5 -1
- package/dist/actions/schema/formatSchemaValidation.js.map +1 -1
- package/dist/actions/schema/getExtractOptions.js +16 -0
- package/dist/actions/schema/getExtractOptions.js.map +1 -0
- package/dist/actions/schema/runSchemaExtraction.js +39 -0
- package/dist/actions/schema/runSchemaExtraction.js.map +1 -0
- package/dist/actions/schema/watchExtractSchema.js +71 -0
- package/dist/actions/schema/watchExtractSchema.js.map +1 -0
- package/dist/actions/versions/tryFindLatestVersion.js +1 -1
- package/dist/actions/versions/tryFindLatestVersion.js.map +1 -1
- package/dist/commands/mcp/configure.js +1 -1
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/commands/schema/extract.js +32 -4
- package/dist/commands/schema/extract.js.map +1 -1
- package/dist/server/previewServer.js +2 -2
- package/dist/server/previewServer.js.map +1 -1
- package/dist/telemetry/extractSchema.telemetry.js +5 -0
- package/dist/telemetry/extractSchema.telemetry.js.map +1 -1
- package/dist/util/compareDependencyVersions.js +3 -5
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/dist/util/getLocalPackageVersion.js +30 -22
- package/dist/util/getLocalPackageVersion.js.map +1 -1
- package/dist/util/getWorkspace.js +1 -1
- package/dist/util/getWorkspace.js.map +1 -1
- package/dist/util/resolveLatestVersions.js +2 -2
- package/dist/util/resolveLatestVersions.js.map +1 -1
- package/dist/util/update/fetchLatestVersion.js +1 -1
- package/dist/util/update/fetchLatestVersion.js.map +1 -1
- package/oclif.manifest.json +168 -146
- package/package.json +5 -5
- package/dist/util/readModuleVersion.js +0 -21
- package/dist/util/readModuleVersion.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {getLocalPackageVersion} from '../../util/getLocalPackageVersion.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {shouldAutoUpdate} from '../build/shouldAutoUpdate.js'\nimport {extractAppManifest} from '../manifest/extractAppManifest.js'\nimport {type AppManifest} from '../manifest/types.js'\nimport {checkDir} from './checkDir.js'\nimport {createUserApplicationForApp} from './createUserApplicationForApp.js'\nimport {deployDebug} from './deployDebug.js'\nimport {findUserApplicationForApp} from './findUserApplicationForApp.js'\nimport {type DeployAppOptions} from './types.js'\n\n/**\n * Deploy a Sanity application.\n *\n * @internal\n */\nexport async function deployApp(options: DeployAppOptions) {\n const {cliConfig, flags, output, sourceDir, workDir} = options\n\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const isAutoUpdating = shouldAutoUpdate({cliConfig, flags, output})\n const installedSdkVersion = await getLocalPackageVersion('@sanity/sdk-react', workDir)\n\n if (!installedSdkVersion) {\n output.error(`Failed to find installed @sanity/sdk-react version`, {exit: 1})\n return\n }\n\n if (!organizationId) {\n output.error(NO_ORGANIZATION_ID, {exit: 1})\n return\n }\n\n let spin = spinner('Verifying local content...')\n\n try {\n let userApplication = await findUserApplicationForApp({\n cliConfig,\n organizationId,\n output,\n })\n\n deployDebug(`User application found`, userApplication)\n\n if (!userApplication) {\n deployDebug(`No user application found. Creating a new one`)\n\n userApplication = await createUserApplicationForApp(organizationId)\n deployDebug(`User application created`, userApplication)\n }\n\n // Warn about missing app ID if auto updates are enabled\n if (isAutoUpdating && !appId) {\n warnAboutMissingAppId({appType: 'app', output})\n }\n\n // Always build the project, unless --no-build is passed\n const shouldBuild = flags.build\n if (shouldBuild) {\n deployDebug(`Building app`)\n await buildApp({\n autoUpdatesEnabled: isAutoUpdating,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n })\n }\n\n // Ensure that the directory exists, is a directory and seems to have valid content\n spin = spin.start()\n try {\n await checkDir(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n output.error('Error checking directory', {exit: 1})\n return\n }\n\n // Create a tarball of the given directory\n const parentDir = dirname(sourceDir)\n const base = basename(sourceDir)\n const tarball = pack(parentDir, {entries: [base]}).pipe(createGzip())\n let manifest: AppManifest | undefined\n try {\n manifest = await extractAppManifest({flags, workDir})\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n deployDebug('Error extracting app manifest', err)\n output.warn(`Error extracting app manifest: ${message}`)\n }\n\n spin = spinner('Deploying...').start()\n await createDeployment({\n applicationId: userApplication.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version: installedSdkVersion,\n })\n\n spin.succeed()\n\n // And let the user know we're done\n output.log(`\\nπ ${styleText('bold', 'Success!')} Application deployed`)\n\n if (!appId) {\n output.log(`\\nββββ ${styleText('bold', 'Next step:')} ββββ`)\n output.log(\n styleText(\n 'bold',\n '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:',\n ),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config hereβ¦\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${userApplication.id}',\n}\\n`,\n)}`)\n }\n } catch (error) {\n spin.clear()\n // Don't throw generic error if user cancels\n if (error.name === 'ExitPromptError') {\n output.error('Deployment cancelled by user', {exit: 1})\n return\n }\n // If the error is a CLIError, we can just output the message & error options (if any), while ensuring we exit\n if (error instanceof CLIError) {\n const {message, ...errorOptions} = error\n output.error(message, {...errorOptions, exit: 1})\n return\n }\n\n deployDebug('Error deploying application', error)\n output.error(`Error deploying application: ${error}`, {exit: 1})\n }\n}\n"],"names":["basename","dirname","styleText","createGzip","CLIError","spinner","pack","createDeployment","getAppId","NO_ORGANIZATION_ID","getLocalPackageVersion","warnAboutMissingAppId","buildApp","shouldAutoUpdate","extractAppManifest","checkDir","createUserApplicationForApp","deployDebug","findUserApplicationForApp","deployApp","options","cliConfig","flags","output","sourceDir","workDir","organizationId","app","appId","isAutoUpdating","installedSdkVersion","error","exit","spin","userApplication","appType","shouldBuild","build","autoUpdatesEnabled","outDir","start","succeed","err","fail","parentDir","base","tarball","entries","pipe","manifest","message","Error","String","warn","applicationId","id","isApp","version","log","clear","name","errorOptions"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { pack } from 'tar-fs';
|
|
|
7
7
|
import { createDeployment } from '../../services/userApplications.js';
|
|
8
8
|
import { getAppId } from '../../util/appId.js';
|
|
9
9
|
import { NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getLocalPackageVersion } from '../../util/getLocalPackageVersion.js';
|
|
11
11
|
import { buildStudio } from '../build/buildStudio.js';
|
|
12
12
|
import { shouldAutoUpdate } from '../build/shouldAutoUpdate.js';
|
|
13
13
|
import { checkDir } from './checkDir.js';
|
|
@@ -19,7 +19,7 @@ export async function deployStudio(options) {
|
|
|
19
19
|
const appHost = cliConfig.studioHost;
|
|
20
20
|
const appId = getAppId(cliConfig);
|
|
21
21
|
const projectId = cliConfig.api?.projectId;
|
|
22
|
-
const installedSanityVersion = await
|
|
22
|
+
const installedSanityVersion = await getLocalPackageVersion('sanity', workDir);
|
|
23
23
|
const isAutoUpdating = shouldAutoUpdate({
|
|
24
24
|
cliConfig,
|
|
25
25
|
flags,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {getLocalPackageVersion} from '../../util/getLocalPackageVersion.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {shouldAutoUpdate} from '../build/shouldAutoUpdate.js'\nimport {checkDir} from './checkDir.js'\nimport {createStudioUserApplication} from './createStudioUserApplication.js'\nimport {deployDebug} from './deployDebug.js'\nimport {findUserApplicationForStudio} from './findUserApplicationForStudio.js'\nimport {type DeployAppOptions} from './types.js'\n\nexport async function deployStudio(options: DeployAppOptions) {\n const {cliConfig, flags, output, sourceDir, workDir} = options\n\n const appHost = cliConfig.studioHost\n const appId = getAppId(cliConfig)\n const projectId = cliConfig.api?.projectId\n const installedSanityVersion = await getLocalPackageVersion('sanity', workDir)\n const isAutoUpdating = shouldAutoUpdate({cliConfig, flags, output})\n\n if (!installedSanityVersion) {\n output.error(`Failed to find installed sanity version`, {exit: 1})\n return\n }\n\n if (!projectId) {\n output.error(NO_PROJECT_ID, {exit: 1})\n return\n }\n\n let spin = spinner('Verifying local content')\n\n try {\n let userApplication = await findUserApplicationForStudio({\n appHost,\n appId,\n output,\n projectId,\n })\n\n if (!userApplication) {\n // otherwise, prompt the user for a hostname\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the part you want to use.')\n\n userApplication = await createStudioUserApplication(projectId)\n\n deployDebug('Created user application', userApplication)\n }\n\n deployDebug('Found user application', userApplication)\n\n // Always build the project, unless --no-build is passed\n const shouldBuild = flags.build\n if (shouldBuild) {\n deployDebug(`Building studio`)\n await buildStudio({\n autoUpdatesEnabled: isAutoUpdating,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n })\n }\n\n // TODO: Implement schema deployment\n // await deploySchemasAction(\n // {\n // 'extract-manifest': shouldBuild,\n // 'manifest-dir': `${sourceDir}/static`,\n // 'schema-required': flags['schema-required'],\n // 'verbose': flags.verbose,\n // },\n // {...context, manifestExtractor: createManifestExtractor(context)},\n // )\n\n // Ensure that the directory exists, is a directory and seems to have valid content\n spin = spin.start()\n try {\n await checkDir(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n output.error('Error checking directory', {exit: 1})\n }\n\n // Create a tarball of the given directory\n const parentDir = dirname(sourceDir)\n const base = basename(sourceDir)\n const tarball = pack(parentDir, {entries: [base]}).pipe(createGzip())\n\n spin = spinner('Deploying to sanity.studio').start()\n\n const {location} = await createDeployment({\n applicationId: userApplication.id,\n isApp: false,\n isAutoUpdating,\n projectId,\n tarball,\n version: installedSanityVersion,\n })\n\n spin.succeed()\n\n // And let the user know we're done\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', location || 'unknown URL')}`)\n\n if (!appId) {\n output.log(`\\nAdd ${styleText('cyan', `deployment: { appId: '${userApplication.id}' }`)}`)\n output.log(`to sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting on next deploy.`)\n }\n } catch (error) {\n // if the error is a CLIError, we can just output the message and exit\n if (error instanceof CLIError) {\n output.error(error.message, {exit: 1})\n return\n }\n\n spin.fail()\n deployDebug('Error deploying studio', error)\n output.error(`Error deploying studio: ${error}`, {exit: 1})\n }\n}\n"],"names":["basename","dirname","styleText","createGzip","CLIError","spinner","pack","createDeployment","getAppId","NO_PROJECT_ID","getLocalPackageVersion","buildStudio","shouldAutoUpdate","checkDir","createStudioUserApplication","deployDebug","findUserApplicationForStudio","deployStudio","options","cliConfig","flags","output","sourceDir","workDir","appHost","studioHost","appId","projectId","api","installedSanityVersion","isAutoUpdating","error","exit","spin","userApplication","log","shouldBuild","build","autoUpdatesEnabled","outDir","start","succeed","err","fail","parentDir","base","tarball","entries","pipe","location","applicationId","id","isApp","version","message"],"mappings":"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"}
|
|
@@ -7,9 +7,9 @@ import { gracefulServerDeath } from '../../server/gracefulServerDeath.js';
|
|
|
7
7
|
import { getProjectById } from '../../services/projects.js';
|
|
8
8
|
import { getAppId } from '../../util/appId.js';
|
|
9
9
|
import { compareDependencyVersions } from '../../util/compareDependencyVersions.js';
|
|
10
|
+
import { getLocalPackageVersion } from '../../util/getLocalPackageVersion.js';
|
|
10
11
|
import { getPackageManagerChoice } from '../../util/packageManager/packageManagerChoice.js';
|
|
11
12
|
import { upgradePackages } from '../../util/packageManager/upgradePackages.js';
|
|
12
|
-
import { readModuleVersion } from '../../util/readModuleVersion.js';
|
|
13
13
|
import { warnAboutMissingAppId } from '../../util/warnAboutMissingAppId.js';
|
|
14
14
|
import { checkRequiredDependencies } from '../build/checkRequiredDependencies.js';
|
|
15
15
|
import { checkStudioDependencyVersions } from '../build/checkStudioDependencyVersions.js';
|
|
@@ -138,7 +138,7 @@ export async function startStudioDevServer(options) {
|
|
|
138
138
|
const startupDuration = Date.now() - startTime;
|
|
139
139
|
const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`;
|
|
140
140
|
const appType = 'Sanity Studio';
|
|
141
|
-
const viteVersion = await
|
|
141
|
+
const viteVersion = await getLocalPackageVersion('vite', import.meta.url);
|
|
142
142
|
spin.succeed();
|
|
143
143
|
loggerInfo(`${appType} ` + `using ${styleText('cyan', `vite@${viteVersion}`)} ` + `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)} ` + `and running at ${styleText('cyan', url)}`);
|
|
144
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/dev/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport semver from 'semver'\n\nimport {startDevServer} from '../../server/devServer.js'\nimport {gracefulServerDeath} from '../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {getAppId} from '../../util/appId.js'\nimport {compareDependencyVersions} from '../../util/compareDependencyVersions.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {readModuleVersion} from '../../util/readModuleVersion.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {checkRequiredDependencies} from '../build/checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from '../build/checkStudioDependencyVersions.js'\nimport {shouldAutoUpdate} from '../build/shouldAutoUpdate.js'\nimport {devDebug} from './devDebug.js'\nimport {getCoreAppURL} from './getCoreAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\nimport {type DevActionOptions} from './types.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<{close?: () => Promise<void>}> {\n const {cliConfig, flags, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n const loadInDashboard = flags['load-in-dashboard']\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies(options)\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semver.parse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (!appId) {\n warnAboutMissingAppId({\n appType: 'studio',\n output,\n projectId,\n })\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n const config = getDevServerConfig({cliConfig, flags, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n getCoreAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await readModuleVersion(import.meta.url, 'vite')\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)} ` +\n `and running at ${styleText('cyan', url)}`,\n )\n }\n\n return {close}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","isInteractive","confirm","logSymbols","spinner","semver","startDevServer","gracefulServerDeath","getProjectById","getAppId","compareDependencyVersions","getPackageManagerChoice","upgradePackages","readModuleVersion","warnAboutMissingAppId","checkRequiredDependencies","checkStudioDependencyVersions","shouldAutoUpdate","devDebug","getCoreAppURL","getDevServerConfig","startStudioDevServer","options","cliConfig","flags","output","workDir","projectId","api","organizationId","loadInDashboard","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","parse","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","appType","length","message","map","mod","pkg","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","httpPort","startupDuration","url","basePath","viteVersion","Math","ceil"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/dev/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport semver from 'semver'\n\nimport {startDevServer} from '../../server/devServer.js'\nimport {gracefulServerDeath} from '../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {getAppId} from '../../util/appId.js'\nimport {compareDependencyVersions} from '../../util/compareDependencyVersions.js'\nimport {getLocalPackageVersion} from '../../util/getLocalPackageVersion.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {checkRequiredDependencies} from '../build/checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from '../build/checkStudioDependencyVersions.js'\nimport {shouldAutoUpdate} from '../build/shouldAutoUpdate.js'\nimport {devDebug} from './devDebug.js'\nimport {getCoreAppURL} from './getCoreAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\nimport {type DevActionOptions} from './types.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<{close?: () => Promise<void>}> {\n const {cliConfig, flags, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n const loadInDashboard = flags['load-in-dashboard']\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies(options)\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semver.parse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (!appId) {\n warnAboutMissingAppId({\n appType: 'studio',\n output,\n projectId,\n })\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n const config = getDevServerConfig({cliConfig, flags, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n getCoreAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)} ` +\n `and running at ${styleText('cyan', url)}`,\n )\n }\n\n return {close}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","isInteractive","confirm","logSymbols","spinner","semver","startDevServer","gracefulServerDeath","getProjectById","getAppId","compareDependencyVersions","getLocalPackageVersion","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","checkRequiredDependencies","checkStudioDependencyVersions","shouldAutoUpdate","devDebug","getCoreAppURL","getDevServerConfig","startStudioDevServer","options","cliConfig","flags","output","workDir","projectId","api","organizationId","loadInDashboard","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","parse","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","appType","length","message","map","mod","pkg","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","httpPort","startupDuration","url","basePath","viteVersion","Math","ceil"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
3
|
import { findProjectRoot, getTimer, studioWorkerTask } from '@sanity/cli-core';
|
|
4
4
|
import { spinner } from '@sanity/cli-core/ux';
|
|
5
|
-
import {
|
|
5
|
+
import { getLocalPackageVersion } from '../../util/getLocalPackageVersion.js';
|
|
6
6
|
import { SchemaExtractionError } from '../schema/utils/SchemaExtractionError.js';
|
|
7
7
|
import { manifestDebug } from './debug.js';
|
|
8
8
|
import { writeWorkspaceFiles } from './writeWorkspaceFiles.js';
|
|
@@ -61,7 +61,7 @@ export async function extractManifest(outPath) {
|
|
|
61
61
|
* 2: Added tools file.
|
|
62
62
|
* 3. Added studioVersion field.
|
|
63
63
|
*/ createdAt: new Date().toISOString(),
|
|
64
|
-
studioVersion: await
|
|
64
|
+
studioVersion: await getLocalPackageVersion('sanity', workDir),
|
|
65
65
|
version: 3,
|
|
66
66
|
workspaces: workspaceFiles
|
|
67
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/manifest/extractManifest.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport {join, resolve} from 'node:path'\n\nimport {findProjectRoot, getTimer, Output, studioWorkerTask} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/manifest/extractManifest.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport {join, resolve} from 'node:path'\n\nimport {findProjectRoot, getTimer, Output, studioWorkerTask} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {getLocalPackageVersion} from '../../util/getLocalPackageVersion.js'\nimport {type ExtractSchemaWorkerError} from '../schema/types.js'\nimport {SchemaExtractionError} from '../schema/utils/SchemaExtractionError.js'\nimport {manifestDebug} from './debug.js'\nimport {\n type CreateManifest,\n type CreateWorkspaceManifest,\n type ExtractManifestWorkerData,\n} from './types'\nimport {writeWorkspaceFiles} from './writeWorkspaceFiles.js'\n\nexport const MANIFEST_FILENAME = 'create-manifest.json'\n\n/** Escape-hatch env flags to change action behavior */\nconst FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_EXTRACT_MANIFEST_ENABLED'\nconst EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== 'false'\nconst EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === 'true'\n\nconst CREATE_TIMER = 'create-manifest'\n\ninterface ExtractManifestOptions {\n outPath: string\n output: Output\n}\n\n/**\n * This function will never throw.\n * @returns `undefined` if extract succeeded - caught error if it failed\n */\nexport async function extractManifestSafe(\n options: ExtractManifestOptions,\n): Promise<Error | undefined> {\n const {outPath, output} = options\n if (!EXTRACT_MANIFEST_ENABLED) {\n return undefined\n }\n\n try {\n await extractManifest(outPath)\n return undefined\n } catch (err) {\n if (EXTRACT_MANIFEST_LOG_ERRORS) {\n output.error(err)\n }\n return err\n }\n}\n\ninterface ExtractManifestWorkerResult {\n type: 'success'\n workspaceManifests: CreateWorkspaceManifest[]\n}\n\ntype ExtractManifestWorkerMessage = ExtractManifestWorkerResult | ExtractSchemaWorkerError\n\nexport async function extractManifest(outPath: string): Promise<void> {\n const projectRoot = await findProjectRoot(process.cwd())\n\n const workDir = projectRoot.directory\n const configPath = projectRoot.path\n const staticPath = resolve(join(workDir, outPath))\n const path = join(staticPath, MANIFEST_FILENAME)\n\n const timer = getTimer()\n timer.start(CREATE_TIMER)\n const spin = spinner('Extracting manifest').start()\n\n try {\n const result = await studioWorkerTask<ExtractManifestWorkerMessage>(\n new URL('extractManifest.worker.js', import.meta.url),\n {\n name: 'extractManifest',\n studioRootPath: workDir,\n workerData: {configPath, workDir} satisfies ExtractManifestWorkerData,\n },\n )\n\n if (result.type === 'error') {\n throw new SchemaExtractionError(result.error, result.validation)\n }\n\n await mkdir(staticPath, {recursive: true})\n\n const workspaceFiles = await writeWorkspaceFiles(result.workspaceManifests, staticPath)\n\n const manifest: CreateManifest = {\n /**\n * Version history:\n * 1: Initial release.\n * 2: Added tools file.\n * 3. Added studioVersion field.\n */\n createdAt: new Date().toISOString(),\n studioVersion: await getLocalPackageVersion('sanity', workDir),\n version: 3,\n workspaces: workspaceFiles,\n }\n\n await writeFile(path, JSON.stringify(manifest, null, 2))\n const manifestDuration = timer.end(CREATE_TIMER)\n\n spin.succeed(`Extracted manifest (${manifestDuration.toFixed(0)}ms)`)\n } catch (err) {\n manifestDebug('Error extracting manifest', err)\n spin.fail()\n\n throw err\n }\n}\n"],"names":["mkdir","writeFile","join","resolve","findProjectRoot","getTimer","studioWorkerTask","spinner","getLocalPackageVersion","SchemaExtractionError","manifestDebug","writeWorkspaceFiles","MANIFEST_FILENAME","FEATURE_ENABLED_ENV_NAME","EXTRACT_MANIFEST_ENABLED","process","env","EXTRACT_MANIFEST_LOG_ERRORS","SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS","CREATE_TIMER","extractManifestSafe","options","outPath","output","undefined","extractManifest","err","error","projectRoot","cwd","workDir","directory","configPath","path","staticPath","timer","start","spin","result","URL","url","name","studioRootPath","workerData","type","validation","recursive","workspaceFiles","workspaceManifests","manifest","createdAt","Date","toISOString","studioVersion","version","workspaces","JSON","stringify","manifestDuration","end","succeed","toFixed","fail"],"mappings":"AAAA,SAAQA,KAAK,EAAEC,SAAS,QAAO,mBAAkB;AACjD,SAAQC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAEvC,SAAQC,eAAe,EAAEC,QAAQ,EAAUC,gBAAgB,QAAO,mBAAkB;AACpF,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,sBAAsB,QAAO,uCAAsC;AAE3E,SAAQC,qBAAqB,QAAO,2CAA0C;AAC9E,SAAQC,aAAa,QAAO,aAAY;AAMxC,SAAQC,mBAAmB,QAAO,2BAA0B;AAE5D,OAAO,MAAMC,oBAAoB,uBAAsB;AAEvD,qDAAqD,GACrD,MAAMC,2BAA2B;AACjC,MAAMC,2BAA2BC,QAAQC,GAAG,CAACH,yBAAyB,KAAK;AAC3E,MAAMI,8BAA8BF,QAAQC,GAAG,CAACE,sCAAsC,KAAK;AAE3F,MAAMC,eAAe;AAOrB;;;CAGC,GACD,OAAO,eAAeC,oBACpBC,OAA+B;IAE/B,MAAM,EAACC,OAAO,EAAEC,MAAM,EAAC,GAAGF;IAC1B,IAAI,CAACP,0BAA0B;QAC7B,OAAOU;IACT;IAEA,IAAI;QACF,MAAMC,gBAAgBH;QACtB,OAAOE;IACT,EAAE,OAAOE,KAAK;QACZ,IAAIT,6BAA6B;YAC/BM,OAAOI,KAAK,CAACD;QACf;QACA,OAAOA;IACT;AACF;AASA,OAAO,eAAeD,gBAAgBH,OAAe;IACnD,MAAMM,cAAc,MAAMxB,gBAAgBW,QAAQc,GAAG;IAErD,MAAMC,UAAUF,YAAYG,SAAS;IACrC,MAAMC,aAAaJ,YAAYK,IAAI;IACnC,MAAMC,aAAa/B,QAAQD,KAAK4B,SAASR;IACzC,MAAMW,OAAO/B,KAAKgC,YAAYtB;IAE9B,MAAMuB,QAAQ9B;IACd8B,MAAMC,KAAK,CAACjB;IACZ,MAAMkB,OAAO9B,QAAQ,uBAAuB6B,KAAK;IAEjD,IAAI;QACF,MAAME,SAAS,MAAMhC,iBACnB,IAAIiC,IAAI,6BAA6B,YAAYC,GAAG,GACpD;YACEC,MAAM;YACNC,gBAAgBZ;YAChBa,YAAY;gBAACX;gBAAYF;YAAO;QAClC;QAGF,IAAIQ,OAAOM,IAAI,KAAK,SAAS;YAC3B,MAAM,IAAInC,sBAAsB6B,OAAOX,KAAK,EAAEW,OAAOO,UAAU;QACjE;QAEA,MAAM7C,MAAMkC,YAAY;YAACY,WAAW;QAAI;QAExC,MAAMC,iBAAiB,MAAMpC,oBAAoB2B,OAAOU,kBAAkB,EAAEd;QAE5E,MAAMe,WAA2B;YAC/B;;;;;OAKC,GACDC,WAAW,IAAIC,OAAOC,WAAW;YACjCC,eAAe,MAAM7C,uBAAuB,UAAUsB;YACtDwB,SAAS;YACTC,YAAYR;QACd;QAEA,MAAM9C,UAAUgC,MAAMuB,KAAKC,SAAS,CAACR,UAAU,MAAM;QACrD,MAAMS,mBAAmBvB,MAAMwB,GAAG,CAACxC;QAEnCkB,KAAKuB,OAAO,CAAC,CAAC,oBAAoB,EAAEF,iBAAiBG,OAAO,CAAC,GAAG,GAAG,CAAC;IACtE,EAAE,OAAOnC,KAAK;QACZhB,cAAc,6BAA6BgB;QAC3CW,KAAKyB,IAAI;QAET,MAAMpC;IACR;AACF"}
|
|
@@ -2,17 +2,29 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import { subdebug } from '@sanity/cli-core';
|
|
4
4
|
import { parse as parseJsonc } from 'jsonc-parser';
|
|
5
|
+
import { parse as parseToml } from 'smol-toml';
|
|
5
6
|
import { EDITOR_CONFIGS } from './editorConfigs.js';
|
|
6
7
|
const debug = subdebug('mcp:detectAvailableEditors');
|
|
7
8
|
/**
|
|
8
|
-
* Safely parse
|
|
9
|
+
* Safely parse config file content
|
|
9
10
|
* Returns parsed config or null if unparseable
|
|
10
|
-
*/ function parseConfig(content) {
|
|
11
|
+
*/ function parseConfig(content, format) {
|
|
11
12
|
const trimmed = content.trim();
|
|
12
13
|
if (trimmed === '') {
|
|
13
14
|
return {} // Empty file - safe to write, treat as empty config
|
|
14
15
|
;
|
|
15
16
|
}
|
|
17
|
+
if (format === 'toml') {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = parseToml(content);
|
|
20
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
const errors = [];
|
|
17
29
|
const parsed = parseJsonc(content, errors, {
|
|
18
30
|
allowTrailingComma: true
|
|
@@ -27,7 +39,7 @@ const debug = subdebug('mcp:detectAvailableEditors');
|
|
|
27
39
|
* Check if an editor's config is usable and whether Sanity MCP is already configured.
|
|
28
40
|
* Returns null only if config exists but can't be parsed (to avoid data loss).
|
|
29
41
|
*/ async function checkEditorConfig(name, configPath) {
|
|
30
|
-
const { configKey } = EDITOR_CONFIGS[name];
|
|
42
|
+
const { configKey, format } = EDITOR_CONFIGS[name];
|
|
31
43
|
// Config file doesn't exist - can create it
|
|
32
44
|
if (!existsSync(configPath)) {
|
|
33
45
|
return {
|
|
@@ -39,7 +51,7 @@ const debug = subdebug('mcp:detectAvailableEditors');
|
|
|
39
51
|
// Config exists - try to parse it
|
|
40
52
|
try {
|
|
41
53
|
const content = await fs.readFile(configPath, 'utf8');
|
|
42
|
-
const config = parseConfig(content);
|
|
54
|
+
const config = parseConfig(content, format);
|
|
43
55
|
if (config === null) {
|
|
44
56
|
debug('Skipping %s: could not parse %s', name, configPath);
|
|
45
57
|
return null // Can't parse - skip this editor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/detectAvailableEditors.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\n\nimport {subdebug} from '@sanity/cli-core'\nimport {type ParseError, parse as parseJsonc} from 'jsonc-parser'\n\nimport {EDITOR_CONFIGS, type EditorName} from './editorConfigs.js'\n\nconst debug = subdebug('mcp:detectAvailableEditors')\n\nexport interface Editor {\n configPath: string\n /** Whether Sanity MCP is already configured for this editor */\n configured: boolean\n name: EditorName\n}\n\ninterface MCPConfig {\n [key: string]: Record<string, unknown> | undefined\n}\n\n/**\n * Safely parse
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/detectAvailableEditors.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\n\nimport {subdebug} from '@sanity/cli-core'\nimport {type ParseError, parse as parseJsonc} from 'jsonc-parser'\nimport {parse as parseToml} from 'smol-toml'\n\nimport {EDITOR_CONFIGS, type EditorName} from './editorConfigs.js'\n\nconst debug = subdebug('mcp:detectAvailableEditors')\n\nexport interface Editor {\n configPath: string\n /** Whether Sanity MCP is already configured for this editor */\n configured: boolean\n name: EditorName\n}\n\ninterface MCPConfig {\n [key: string]: Record<string, unknown> | undefined\n}\n\n/**\n * Safely parse config file content\n * Returns parsed config or null if unparseable\n */\nfunction parseConfig(content: string, format: 'jsonc' | 'toml'): MCPConfig | null {\n const trimmed = content.trim()\n if (trimmed === '') {\n return {} // Empty file - safe to write, treat as empty config\n }\n\n if (format === 'toml') {\n try {\n const parsed = parseToml(content)\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return null\n }\n\n return parsed as MCPConfig\n } catch {\n return null\n }\n }\n\n const errors: ParseError[] = []\n const parsed = parseJsonc(content, errors, {allowTrailingComma: true})\n\n if (errors.length > 0 || typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return null // Parse failed\n }\n\n return parsed as MCPConfig\n}\n\n/**\n * Check if an editor's config is usable and whether Sanity MCP is already configured.\n * Returns null only if config exists but can't be parsed (to avoid data loss).\n */\nasync function checkEditorConfig(name: EditorName, configPath: string): Promise<Editor | null> {\n const {configKey, format} = EDITOR_CONFIGS[name]\n\n // Config file doesn't exist - can create it\n if (!existsSync(configPath)) {\n return {configPath, configured: false, name}\n }\n\n // Config exists - try to parse it\n try {\n const content = await fs.readFile(configPath, 'utf8')\n const config = parseConfig(content, format)\n\n if (config === null) {\n debug('Skipping %s: could not parse %s', name, configPath)\n return null // Can't parse - skip this editor\n }\n\n // Check if Sanity MCP is already configured\n const configured = Boolean(config[configKey]?.Sanity)\n\n return {configPath, configured, name}\n } catch (err) {\n debug('Skipping %s: could not read %s: %s', name, configPath, err)\n return null\n }\n}\n\n/**\n * Detect which editors are installed and have parseable configs.\n * Editors with unparseable configs are skipped to avoid data loss.\n */\nexport async function detectAvailableEditors(): Promise<Editor[]> {\n const editors: Editor[] = []\n\n for (const [name, config] of Object.entries(EDITOR_CONFIGS)) {\n const configPath = await config.detect()\n if (configPath) {\n const editor = await checkEditorConfig(name as EditorName, configPath)\n if (editor) editors.push(editor)\n }\n }\n\n return editors\n}\n"],"names":["existsSync","fs","subdebug","parse","parseJsonc","parseToml","EDITOR_CONFIGS","debug","parseConfig","content","format","trimmed","trim","parsed","Array","isArray","errors","allowTrailingComma","length","checkEditorConfig","name","configPath","configKey","configured","readFile","config","Boolean","Sanity","err","detectAvailableEditors","editors","Object","entries","detect","editor","push"],"mappings":"AAAA,SAAQA,UAAU,QAAO,UAAS;AAClC,OAAOC,QAAQ,mBAAkB;AAEjC,SAAQC,QAAQ,QAAO,mBAAkB;AACzC,SAAyBC,SAASC,UAAU,QAAO,eAAc;AACjE,SAAQD,SAASE,SAAS,QAAO,YAAW;AAE5C,SAAQC,cAAc,QAAwB,qBAAoB;AAElE,MAAMC,QAAQL,SAAS;AAavB;;;CAGC,GACD,SAASM,YAAYC,OAAe,EAAEC,MAAwB;IAC5D,MAAMC,UAAUF,QAAQG,IAAI;IAC5B,IAAID,YAAY,IAAI;QAClB,OAAO,CAAC,EAAE,oDAAoD;;IAChE;IAEA,IAAID,WAAW,QAAQ;QACrB,IAAI;YACF,MAAMG,SAASR,UAAUI;YACzB,IAAI,OAAOI,WAAW,YAAYA,WAAW,QAAQC,MAAMC,OAAO,CAACF,SAAS;gBAC1E,OAAO;YACT;YAEA,OAAOA;QACT,EAAE,OAAM;YACN,OAAO;QACT;IACF;IAEA,MAAMG,SAAuB,EAAE;IAC/B,MAAMH,SAAST,WAAWK,SAASO,QAAQ;QAACC,oBAAoB;IAAI;IAEpE,IAAID,OAAOE,MAAM,GAAG,KAAK,OAAOL,WAAW,YAAYA,WAAW,QAAQC,MAAMC,OAAO,CAACF,SAAS;QAC/F,OAAO,KAAK,eAAe;;IAC7B;IAEA,OAAOA;AACT;AAEA;;;CAGC,GACD,eAAeM,kBAAkBC,IAAgB,EAAEC,UAAkB;IACnE,MAAM,EAACC,SAAS,EAAEZ,MAAM,EAAC,GAAGJ,cAAc,CAACc,KAAK;IAEhD,4CAA4C;IAC5C,IAAI,CAACpB,WAAWqB,aAAa;QAC3B,OAAO;YAACA;YAAYE,YAAY;YAAOH;QAAI;IAC7C;IAEA,kCAAkC;IAClC,IAAI;QACF,MAAMX,UAAU,MAAMR,GAAGuB,QAAQ,CAACH,YAAY;QAC9C,MAAMI,SAASjB,YAAYC,SAASC;QAEpC,IAAIe,WAAW,MAAM;YACnBlB,MAAM,mCAAmCa,MAAMC;YAC/C,OAAO,KAAK,iCAAiC;;QAC/C;QAEA,4CAA4C;QAC5C,MAAME,aAAaG,QAAQD,MAAM,CAACH,UAAU,EAAEK;QAE9C,OAAO;YAACN;YAAYE;YAAYH;QAAI;IACtC,EAAE,OAAOQ,KAAK;QACZrB,MAAM,sCAAsCa,MAAMC,YAAYO;QAC9D,OAAO;IACT;AACF;AAEA;;;CAGC,GACD,OAAO,eAAeC;IACpB,MAAMC,UAAoB,EAAE;IAE5B,KAAK,MAAM,CAACV,MAAMK,OAAO,IAAIM,OAAOC,OAAO,CAAC1B,gBAAiB;QAC3D,MAAMe,aAAa,MAAMI,OAAOQ,MAAM;QACtC,IAAIZ,YAAY;YACd,MAAMa,SAAS,MAAMf,kBAAkBC,MAAoBC;YAC3D,IAAIa,QAAQJ,QAAQK,IAAI,CAACD;QAC3B;IACF;IAEA,OAAOJ;AACT"}
|
|
@@ -30,7 +30,33 @@ const homeDir = os.homedir();
|
|
|
30
30
|
} catch {
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
},
|
|
34
|
+
format: 'jsonc'
|
|
35
|
+
},
|
|
36
|
+
'Codex CLI': {
|
|
37
|
+
buildServerConfig: (token)=>({
|
|
38
|
+
http_headers: {
|
|
39
|
+
Authorization: `Bearer ${token}`
|
|
40
|
+
},
|
|
41
|
+
type: 'http',
|
|
42
|
+
url: MCP_SERVER_URL
|
|
43
|
+
}),
|
|
44
|
+
configKey: 'mcp_servers',
|
|
45
|
+
detect: async ()=>{
|
|
46
|
+
try {
|
|
47
|
+
await execa('codex', [
|
|
48
|
+
'--version'
|
|
49
|
+
], {
|
|
50
|
+
stdio: 'pipe',
|
|
51
|
+
timeout: 5000
|
|
52
|
+
});
|
|
53
|
+
const codexHome = process.env.CODEX_HOME || path.join(homeDir, '.codex');
|
|
54
|
+
return path.join(codexHome, 'config.toml');
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
format: 'toml'
|
|
34
60
|
},
|
|
35
61
|
Cursor: {
|
|
36
62
|
buildServerConfig: defaultHttpConfig,
|
|
@@ -38,7 +64,35 @@ const homeDir = os.homedir();
|
|
|
38
64
|
detect: async ()=>{
|
|
39
65
|
const cursorDir = path.join(homeDir, '.cursor');
|
|
40
66
|
return existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null;
|
|
41
|
-
}
|
|
67
|
+
},
|
|
68
|
+
format: 'jsonc'
|
|
69
|
+
},
|
|
70
|
+
'Gemini CLI': {
|
|
71
|
+
buildServerConfig: defaultHttpConfig,
|
|
72
|
+
configKey: 'mcpServers',
|
|
73
|
+
detect: async ()=>{
|
|
74
|
+
const geminiDir = path.join(homeDir, '.gemini');
|
|
75
|
+
return existsSync(geminiDir) ? path.join(geminiDir, 'settings.json') : null;
|
|
76
|
+
},
|
|
77
|
+
format: 'jsonc'
|
|
78
|
+
},
|
|
79
|
+
'GitHub Copilot CLI': {
|
|
80
|
+
buildServerConfig: (token)=>({
|
|
81
|
+
headers: {
|
|
82
|
+
Authorization: `Bearer ${token}`
|
|
83
|
+
},
|
|
84
|
+
tools: [
|
|
85
|
+
'*'
|
|
86
|
+
],
|
|
87
|
+
type: 'http',
|
|
88
|
+
url: MCP_SERVER_URL
|
|
89
|
+
}),
|
|
90
|
+
configKey: 'mcpServers',
|
|
91
|
+
detect: async ()=>{
|
|
92
|
+
const copilotDir = process.platform === 'linux' && process.env.XDG_CONFIG_HOME ? path.join(process.env.XDG_CONFIG_HOME, 'copilot') : path.join(homeDir, '.copilot');
|
|
93
|
+
return existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null;
|
|
94
|
+
},
|
|
95
|
+
format: 'jsonc'
|
|
42
96
|
},
|
|
43
97
|
OpenCode: {
|
|
44
98
|
buildServerConfig: (token)=>({
|
|
@@ -61,7 +115,8 @@ const homeDir = os.homedir();
|
|
|
61
115
|
} catch {
|
|
62
116
|
return null;
|
|
63
117
|
}
|
|
64
|
-
}
|
|
118
|
+
},
|
|
119
|
+
format: 'jsonc'
|
|
65
120
|
},
|
|
66
121
|
'VS Code': {
|
|
67
122
|
buildServerConfig: defaultHttpConfig,
|
|
@@ -87,7 +142,8 @@ const homeDir = os.homedir();
|
|
|
87
142
|
}
|
|
88
143
|
}
|
|
89
144
|
return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
90
|
-
}
|
|
145
|
+
},
|
|
146
|
+
format: 'jsonc'
|
|
91
147
|
},
|
|
92
148
|
'VS Code Insiders': {
|
|
93
149
|
buildServerConfig: defaultHttpConfig,
|
|
@@ -113,7 +169,8 @@ const homeDir = os.homedir();
|
|
|
113
169
|
}
|
|
114
170
|
}
|
|
115
171
|
return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
116
|
-
}
|
|
172
|
+
},
|
|
173
|
+
format: 'jsonc'
|
|
117
174
|
},
|
|
118
175
|
Zed: {
|
|
119
176
|
buildServerConfig: (token)=>({
|
|
@@ -140,7 +197,8 @@ const homeDir = os.homedir();
|
|
|
140
197
|
}
|
|
141
198
|
}
|
|
142
199
|
return configDir && existsSync(configDir) ? path.join(configDir, 'settings.json') : null;
|
|
143
|
-
}
|
|
200
|
+
},
|
|
201
|
+
format: 'jsonc'
|
|
144
202
|
}
|
|
145
203
|
};
|
|
146
204
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/editorConfigs.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {execa} from 'execa'\n\nimport {MCP_SERVER_URL} from '../../services/mcp.js'\n\ninterface EditorConfig {\n buildServerConfig: (token: string) => Record<string, unknown>\n configKey: string\n /** Returns the config file path if editor is detected, null otherwise */\n detect: () => Promise<string | null>\n}\n\nconst defaultHttpConfig = (token: string) => ({\n headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n})\n\nconst homeDir = os.homedir()\n\n/**\n * Centralized editor configuration including detection logic.\n * To add a new editor: add an entry here - EditorName type is derived automatically.\n */\nexport const EDITOR_CONFIGS = {\n 'Claude Code': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n detect: async () => {\n try {\n await execa('claude', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.claude.json')\n } catch {\n return null\n }\n },\n },\n Cursor: {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n detect: async () => {\n const cursorDir = path.join(homeDir, '.cursor')\n return existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null\n },\n },\n OpenCode: {\n buildServerConfig: (token) => ({\n headers: {Authorization: `Bearer ${token}`},\n type: 'remote',\n url: MCP_SERVER_URL,\n }),\n configKey: 'mcp',\n detect: async () => {\n try {\n await execa('opencode', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.config/opencode/opencode.json')\n } catch {\n return null\n }\n },\n },\n 'VS Code': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n },\n },\n 'VS Code Insiders': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code - Insiders/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code - Insiders/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code - Insiders/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n },\n },\n Zed: {\n buildServerConfig: (token) => ({\n headers: {Authorization: `Bearer ${token}`},\n settings: {},\n url: MCP_SERVER_URL,\n }),\n configKey: 'context_servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Zed')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/zed')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'settings.json') : null\n },\n },\n} satisfies Record<string, EditorConfig>\n\n/** Derived from EDITOR_CONFIGS keys - add a new editor there and this updates automatically */\nexport type EditorName = keyof typeof EDITOR_CONFIGS\n"],"names":["existsSync","os","path","execa","MCP_SERVER_URL","defaultHttpConfig","token","headers","Authorization","type","url","homeDir","homedir","EDITOR_CONFIGS","buildServerConfig","configKey","detect","stdio","timeout","join","Cursor","cursorDir","
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/editorConfigs.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {execa} from 'execa'\n\nimport {MCP_SERVER_URL} from '../../services/mcp.js'\n\ninterface EditorConfig {\n buildServerConfig: (token: string) => Record<string, unknown>\n configKey: string\n /** Returns the config file path if editor is detected, null otherwise */\n detect: () => Promise<string | null>\n format: 'jsonc' | 'toml'\n}\n\nconst defaultHttpConfig = (token: string) => ({\n headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n})\n\nconst homeDir = os.homedir()\n\n/**\n * Centralized editor configuration including detection logic.\n * To add a new editor: add an entry here - EditorName type is derived automatically.\n */\nexport const EDITOR_CONFIGS = {\n 'Claude Code': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n detect: async () => {\n try {\n await execa('claude', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.claude.json')\n } catch {\n return null\n }\n },\n format: 'jsonc',\n },\n 'Codex CLI': {\n buildServerConfig: (token) => ({\n http_headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n }),\n configKey: 'mcp_servers',\n detect: async () => {\n try {\n await execa('codex', ['--version'], {stdio: 'pipe', timeout: 5000})\n const codexHome = process.env.CODEX_HOME || path.join(homeDir, '.codex')\n return path.join(codexHome, 'config.toml')\n } catch {\n return null\n }\n },\n format: 'toml',\n },\n Cursor: {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n detect: async () => {\n const cursorDir = path.join(homeDir, '.cursor')\n return existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null\n },\n format: 'jsonc',\n },\n 'Gemini CLI': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n detect: async () => {\n const geminiDir = path.join(homeDir, '.gemini')\n return existsSync(geminiDir) ? path.join(geminiDir, 'settings.json') : null\n },\n format: 'jsonc',\n },\n 'GitHub Copilot CLI': {\n buildServerConfig: (token: string) => ({\n headers: {Authorization: `Bearer ${token}`},\n tools: ['*'],\n type: 'http',\n url: MCP_SERVER_URL,\n }),\n configKey: 'mcpServers',\n detect: async () => {\n const copilotDir =\n process.platform === 'linux' && process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, 'copilot')\n : path.join(homeDir, '.copilot')\n return existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null\n },\n format: 'jsonc',\n },\n OpenCode: {\n buildServerConfig: (token) => ({\n headers: {Authorization: `Bearer ${token}`},\n type: 'remote',\n url: MCP_SERVER_URL,\n }),\n configKey: 'mcp',\n detect: async () => {\n try {\n await execa('opencode', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.config/opencode/opencode.json')\n } catch {\n return null\n }\n },\n format: 'jsonc',\n },\n 'VS Code': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n },\n format: 'jsonc',\n },\n 'VS Code Insiders': {\n buildServerConfig: defaultHttpConfig,\n configKey: 'servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code - Insiders/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code - Insiders/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code - Insiders/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n },\n format: 'jsonc',\n },\n Zed: {\n buildServerConfig: (token) => ({\n headers: {Authorization: `Bearer ${token}`},\n settings: {},\n url: MCP_SERVER_URL,\n }),\n configKey: 'context_servers',\n detect: async () => {\n let configDir: string | null = null\n switch (process.platform) {\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Zed')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/zed')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'settings.json') : null\n },\n format: 'jsonc',\n },\n} satisfies Record<string, EditorConfig>\n\n/** Derived from EDITOR_CONFIGS keys - add a new editor there and this updates automatically */\nexport type EditorName = keyof typeof EDITOR_CONFIGS\n"],"names":["existsSync","os","path","execa","MCP_SERVER_URL","defaultHttpConfig","token","headers","Authorization","type","url","homeDir","homedir","EDITOR_CONFIGS","buildServerConfig","configKey","detect","stdio","timeout","join","format","http_headers","codexHome","process","env","CODEX_HOME","Cursor","cursorDir","geminiDir","tools","copilotDir","platform","XDG_CONFIG_HOME","OpenCode","configDir","APPDATA","Zed","settings"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { applyEdits, modify } from 'jsonc-parser';
|
|
5
|
+
import { parse as parseToml, stringify as stringifyToml } from 'smol-toml';
|
|
5
6
|
import { EDITOR_CONFIGS } from './editorConfigs.js';
|
|
6
7
|
/**
|
|
7
8
|
* Write MCP configuration to editor config file
|
|
@@ -10,27 +11,38 @@ import { EDITOR_CONFIGS } from './editorConfigs.js';
|
|
|
10
11
|
* Note: Config parseability is already validated in detectAvailableEditors()
|
|
11
12
|
*/ export async function writeMCPConfig(editor, token) {
|
|
12
13
|
const configPath = editor.configPath;
|
|
13
|
-
const { buildServerConfig, configKey } = EDITOR_CONFIGS[editor.name];
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const { buildServerConfig, configKey, format } = EDITOR_CONFIGS[editor.name];
|
|
15
|
+
const serverConfig = buildServerConfig(token);
|
|
16
|
+
// Read existing content or start with empty object/document
|
|
17
|
+
let content = format === 'toml' ? '' : '{}';
|
|
16
18
|
if (existsSync(configPath)) {
|
|
17
19
|
const fileContent = await fs.readFile(configPath, 'utf8');
|
|
18
20
|
if (fileContent.trim()) {
|
|
19
21
|
content = fileContent;
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
configKey
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
if (format === 'toml') {
|
|
25
|
+
const tomlConfig = content.trim() ? parseToml(content) : {};
|
|
26
|
+
const existingServers = tomlConfig[configKey];
|
|
27
|
+
tomlConfig[configKey] = {
|
|
28
|
+
...existingServers && typeof existingServers === 'object' ? existingServers : {},
|
|
29
|
+
Sanity: serverConfig
|
|
30
|
+
};
|
|
31
|
+
content = stringifyToml(tomlConfig);
|
|
32
|
+
} else {
|
|
33
|
+
// Modify using jsonc-parser - preserves comments
|
|
34
|
+
// Setting a nested path automatically creates intermediate objects
|
|
35
|
+
const edits = modify(content, [
|
|
36
|
+
configKey,
|
|
37
|
+
'Sanity'
|
|
38
|
+
], serverConfig, {
|
|
39
|
+
formattingOptions: {
|
|
40
|
+
insertSpaces: true,
|
|
41
|
+
tabSize: 2
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
content = applyEdits(content, edits);
|
|
45
|
+
}
|
|
34
46
|
// Ensure parent directory exists and write
|
|
35
47
|
await fs.mkdir(path.dirname(configPath), {
|
|
36
48
|
recursive: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/writeMCPConfig.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {applyEdits, modify} from 'jsonc-parser'\n\nimport {EDITOR_CONFIGS} from './editorConfigs.js'\nimport {Editor} from './types.js'\n\n/**\n * Write MCP configuration to editor config file\n * Uses jsonc-parser's modify/applyEdits to preserve comments\n *\n * Note: Config parseability is already validated in detectAvailableEditors()\n */\nexport async function writeMCPConfig(editor: Editor, token: string): Promise<void> {\n const configPath = editor.configPath\n const {buildServerConfig, configKey} = EDITOR_CONFIGS[editor.name]\n\n // Read existing content or start with empty object\n let content = '{}'\n if (existsSync(configPath)) {\n const fileContent = await fs.readFile(configPath, 'utf8')\n if (fileContent.trim()) {\n content = fileContent\n }\n }\n\n // Modify using jsonc-parser - preserves comments\n
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/writeMCPConfig.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {applyEdits, modify} from 'jsonc-parser'\nimport {parse as parseToml, stringify as stringifyToml} from 'smol-toml'\n\nimport {EDITOR_CONFIGS} from './editorConfigs.js'\nimport {Editor} from './types.js'\n\ninterface TomlConfig {\n [key: string]: Record<string, unknown> | undefined\n}\n\n/**\n * Write MCP configuration to editor config file\n * Uses jsonc-parser's modify/applyEdits to preserve comments\n *\n * Note: Config parseability is already validated in detectAvailableEditors()\n */\nexport async function writeMCPConfig(editor: Editor, token: string): Promise<void> {\n const configPath = editor.configPath\n const {buildServerConfig, configKey, format} = EDITOR_CONFIGS[editor.name]\n const serverConfig = buildServerConfig(token)\n\n // Read existing content or start with empty object/document\n let content = format === 'toml' ? '' : '{}'\n if (existsSync(configPath)) {\n const fileContent = await fs.readFile(configPath, 'utf8')\n if (fileContent.trim()) {\n content = fileContent\n }\n }\n\n if (format === 'toml') {\n const tomlConfig = content.trim() ? (parseToml(content) as TomlConfig) : {}\n const existingServers = tomlConfig[configKey]\n\n tomlConfig[configKey] = {\n ...(existingServers && typeof existingServers === 'object' ? existingServers : {}),\n Sanity: serverConfig,\n }\n\n content = stringifyToml(tomlConfig)\n } else {\n // Modify using jsonc-parser - preserves comments\n // Setting a nested path automatically creates intermediate objects\n const edits = modify(content, [configKey, 'Sanity'], serverConfig, {\n formattingOptions: {insertSpaces: true, tabSize: 2},\n })\n content = applyEdits(content, edits)\n }\n\n // Ensure parent directory exists and write\n await fs.mkdir(path.dirname(configPath), {recursive: true})\n await fs.writeFile(configPath, content, 'utf8')\n}\n"],"names":["existsSync","fs","path","applyEdits","modify","parse","parseToml","stringify","stringifyToml","EDITOR_CONFIGS","writeMCPConfig","editor","token","configPath","buildServerConfig","configKey","format","name","serverConfig","content","fileContent","readFile","trim","tomlConfig","existingServers","Sanity","edits","formattingOptions","insertSpaces","tabSize","mkdir","dirname","recursive","writeFile"],"mappings":"AAAA,SAAQA,UAAU,QAAO,UAAS;AAClC,OAAOC,QAAQ,mBAAkB;AACjC,OAAOC,UAAU,YAAW;AAE5B,SAAQC,UAAU,EAAEC,MAAM,QAAO,eAAc;AAC/C,SAAQC,SAASC,SAAS,EAAEC,aAAaC,aAAa,QAAO,YAAW;AAExE,SAAQC,cAAc,QAAO,qBAAoB;AAOjD;;;;;CAKC,GACD,OAAO,eAAeC,eAAeC,MAAc,EAAEC,KAAa;IAChE,MAAMC,aAAaF,OAAOE,UAAU;IACpC,MAAM,EAACC,iBAAiB,EAAEC,SAAS,EAAEC,MAAM,EAAC,GAAGP,cAAc,CAACE,OAAOM,IAAI,CAAC;IAC1E,MAAMC,eAAeJ,kBAAkBF;IAEvC,4DAA4D;IAC5D,IAAIO,UAAUH,WAAW,SAAS,KAAK;IACvC,IAAIhB,WAAWa,aAAa;QAC1B,MAAMO,cAAc,MAAMnB,GAAGoB,QAAQ,CAACR,YAAY;QAClD,IAAIO,YAAYE,IAAI,IAAI;YACtBH,UAAUC;QACZ;IACF;IAEA,IAAIJ,WAAW,QAAQ;QACrB,MAAMO,aAAaJ,QAAQG,IAAI,KAAMhB,UAAUa,WAA0B,CAAC;QAC1E,MAAMK,kBAAkBD,UAAU,CAACR,UAAU;QAE7CQ,UAAU,CAACR,UAAU,GAAG;YACtB,GAAIS,mBAAmB,OAAOA,oBAAoB,WAAWA,kBAAkB,CAAC,CAAC;YACjFC,QAAQP;QACV;QAEAC,UAAUX,cAAce;IAC1B,OAAO;QACL,iDAAiD;QACjD,mEAAmE;QACnE,MAAMG,QAAQtB,OAAOe,SAAS;YAACJ;YAAW;SAAS,EAAEG,cAAc;YACjES,mBAAmB;gBAACC,cAAc;gBAAMC,SAAS;YAAC;QACpD;QACAV,UAAUhB,WAAWgB,SAASO;IAChC;IAEA,2CAA2C;IAC3C,MAAMzB,GAAG6B,KAAK,CAAC5B,KAAK6B,OAAO,CAAClB,aAAa;QAACmB,WAAW;IAAI;IACzD,MAAM/B,GAAGgC,SAAS,CAACpB,YAAYM,SAAS;AAC1C"}
|