@sanity/cli 6.1.8 → 6.2.1

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.
Files changed (147) hide show
  1. package/README.md +301 -294
  2. package/dist/actions/debug/gatherDebugInfo.js +130 -81
  3. package/dist/actions/debug/gatherDebugInfo.js.map +1 -1
  4. package/dist/actions/debug/output.js +25 -0
  5. package/dist/actions/debug/output.js.map +1 -0
  6. package/dist/actions/debug/types.js.map +1 -1
  7. package/dist/actions/manifest/__tests__/testHelpers.js +21 -0
  8. package/dist/actions/manifest/__tests__/testHelpers.js.map +1 -0
  9. package/dist/actions/manifest/schemaTypeTransformer.js +2 -1
  10. package/dist/actions/manifest/schemaTypeTransformer.js.map +1 -1
  11. package/dist/actions/mcp/setupMCP.js +5 -5
  12. package/dist/actions/mcp/setupMCP.js.map +1 -1
  13. package/dist/actions/schema/getExtractOptions.js.map +1 -1
  14. package/dist/commands/{backup → backups}/disable.js +3 -0
  15. package/dist/commands/backups/disable.js.map +1 -0
  16. package/dist/commands/{backup → backups}/download.js +3 -0
  17. package/dist/commands/backups/download.js.map +1 -0
  18. package/dist/commands/{backup → backups}/enable.js +3 -0
  19. package/dist/commands/backups/enable.js.map +1 -0
  20. package/dist/commands/{backup → backups}/list.js +3 -0
  21. package/dist/commands/backups/list.js.map +1 -0
  22. package/dist/commands/{dataset → datasets}/alias/create.js +3 -0
  23. package/dist/commands/datasets/alias/create.js.map +1 -0
  24. package/dist/commands/{dataset → datasets}/alias/delete.js +3 -0
  25. package/dist/commands/datasets/alias/delete.js.map +1 -0
  26. package/dist/commands/{dataset → datasets}/alias/link.js +3 -0
  27. package/dist/commands/datasets/alias/link.js.map +1 -0
  28. package/dist/commands/{dataset → datasets}/alias/unlink.js +3 -0
  29. package/dist/commands/datasets/alias/unlink.js.map +1 -0
  30. package/dist/commands/{dataset → datasets}/copy.js +3 -0
  31. package/dist/commands/datasets/copy.js.map +1 -0
  32. package/dist/commands/{dataset → datasets}/create.js +3 -0
  33. package/dist/commands/datasets/create.js.map +1 -0
  34. package/dist/commands/{dataset → datasets}/delete.js +3 -0
  35. package/dist/commands/datasets/delete.js.map +1 -0
  36. package/dist/commands/{dataset → datasets}/embeddings/disable.js +3 -0
  37. package/dist/commands/datasets/embeddings/disable.js.map +1 -0
  38. package/dist/commands/{dataset → datasets}/embeddings/enable.js +3 -0
  39. package/dist/commands/datasets/embeddings/enable.js.map +1 -0
  40. package/dist/commands/{dataset → datasets}/embeddings/status.js +3 -0
  41. package/dist/commands/datasets/embeddings/status.js.map +1 -0
  42. package/dist/commands/{dataset → datasets}/export.js +3 -0
  43. package/dist/commands/datasets/export.js.map +1 -0
  44. package/dist/commands/{dataset → datasets}/import.js +14 -10
  45. package/dist/commands/datasets/import.js.map +1 -0
  46. package/dist/commands/{dataset → datasets}/list.js +3 -0
  47. package/dist/commands/datasets/list.js.map +1 -0
  48. package/dist/commands/{dataset → datasets}/visibility/get.js +3 -0
  49. package/dist/commands/datasets/visibility/get.js.map +1 -0
  50. package/dist/commands/{dataset → datasets}/visibility/set.js +3 -0
  51. package/dist/commands/datasets/visibility/set.js.map +1 -0
  52. package/dist/commands/debug.js +189 -74
  53. package/dist/commands/debug.js.map +1 -1
  54. package/dist/commands/documents/create.js +3 -0
  55. package/dist/commands/documents/create.js.map +1 -1
  56. package/dist/commands/documents/delete.js +3 -0
  57. package/dist/commands/documents/delete.js.map +1 -1
  58. package/dist/commands/documents/get.js +3 -0
  59. package/dist/commands/documents/get.js.map +1 -1
  60. package/dist/commands/documents/query.js +3 -0
  61. package/dist/commands/documents/query.js.map +1 -1
  62. package/dist/commands/documents/validate.js +3 -0
  63. package/dist/commands/documents/validate.js.map +1 -1
  64. package/dist/commands/{hook → hooks}/attempt.js +3 -0
  65. package/dist/commands/hooks/attempt.js.map +1 -0
  66. package/dist/commands/{hook → hooks}/create.js +3 -0
  67. package/dist/commands/hooks/create.js.map +1 -0
  68. package/dist/commands/{hook → hooks}/delete.js +3 -0
  69. package/dist/commands/hooks/delete.js.map +1 -0
  70. package/dist/commands/{hook → hooks}/list.js +3 -0
  71. package/dist/commands/hooks/list.js.map +1 -0
  72. package/dist/commands/{hook → hooks}/logs.js +3 -0
  73. package/dist/commands/hooks/logs.js.map +1 -0
  74. package/dist/commands/init.js +65 -13
  75. package/dist/commands/init.js.map +1 -1
  76. package/dist/commands/mcp/configure.js +3 -2
  77. package/dist/commands/mcp/configure.js.map +1 -1
  78. package/dist/commands/preview.js +1 -0
  79. package/dist/commands/preview.js.map +1 -1
  80. package/dist/commands/projects/create.js +3 -0
  81. package/dist/commands/projects/create.js.map +1 -1
  82. package/dist/commands/projects/list.js +3 -0
  83. package/dist/commands/projects/list.js.map +1 -1
  84. package/dist/commands/{schema → schemas}/delete.js +3 -0
  85. package/dist/commands/schemas/delete.js.map +1 -0
  86. package/dist/commands/{schema → schemas}/deploy.js +3 -0
  87. package/dist/commands/schemas/deploy.js.map +1 -0
  88. package/dist/commands/{schema → schemas}/extract.js +3 -0
  89. package/dist/commands/schemas/extract.js.map +1 -0
  90. package/dist/commands/{schema → schemas}/list.js +3 -0
  91. package/dist/commands/schemas/list.js.map +1 -0
  92. package/dist/commands/{schema → schemas}/validate.js +3 -0
  93. package/dist/commands/schemas/validate.js.map +1 -0
  94. package/dist/commands/tokens/add.js +3 -0
  95. package/dist/commands/tokens/add.js.map +1 -1
  96. package/dist/commands/tokens/delete.js +3 -0
  97. package/dist/commands/tokens/delete.js.map +1 -1
  98. package/dist/commands/tokens/list.js +3 -0
  99. package/dist/commands/tokens/list.js.map +1 -1
  100. package/dist/commands/users/invite.js +3 -0
  101. package/dist/commands/users/invite.js.map +1 -1
  102. package/dist/commands/users/list.js +3 -0
  103. package/dist/commands/users/list.js.map +1 -1
  104. package/dist/hooks/commandNotFound/topicAliases.js +71 -0
  105. package/dist/hooks/commandNotFound/topicAliases.js.map +1 -0
  106. package/dist/services/telemetry.js +23 -2
  107. package/dist/services/telemetry.js.map +1 -1
  108. package/dist/topicAliases.js +51 -0
  109. package/dist/topicAliases.js.map +1 -0
  110. package/dist/util/packageManager/packageManagerChoice.js +1 -2
  111. package/dist/util/packageManager/packageManagerChoice.js.map +1 -1
  112. package/oclif.config.js +20 -7
  113. package/oclif.manifest.json +478 -362
  114. package/package.json +17 -16
  115. package/dist/actions/debug/formatters.js +0 -22
  116. package/dist/actions/debug/formatters.js.map +0 -1
  117. package/dist/actions/debug/getGlobalConfigLocation.js +0 -7
  118. package/dist/actions/debug/getGlobalConfigLocation.js.map +0 -1
  119. package/dist/commands/backup/disable.js.map +0 -1
  120. package/dist/commands/backup/download.js.map +0 -1
  121. package/dist/commands/backup/enable.js.map +0 -1
  122. package/dist/commands/backup/list.js.map +0 -1
  123. package/dist/commands/dataset/alias/create.js.map +0 -1
  124. package/dist/commands/dataset/alias/delete.js.map +0 -1
  125. package/dist/commands/dataset/alias/link.js.map +0 -1
  126. package/dist/commands/dataset/alias/unlink.js.map +0 -1
  127. package/dist/commands/dataset/copy.js.map +0 -1
  128. package/dist/commands/dataset/create.js.map +0 -1
  129. package/dist/commands/dataset/delete.js.map +0 -1
  130. package/dist/commands/dataset/embeddings/disable.js.map +0 -1
  131. package/dist/commands/dataset/embeddings/enable.js.map +0 -1
  132. package/dist/commands/dataset/embeddings/status.js.map +0 -1
  133. package/dist/commands/dataset/export.js.map +0 -1
  134. package/dist/commands/dataset/import.js.map +0 -1
  135. package/dist/commands/dataset/list.js.map +0 -1
  136. package/dist/commands/dataset/visibility/get.js.map +0 -1
  137. package/dist/commands/dataset/visibility/set.js.map +0 -1
  138. package/dist/commands/hook/attempt.js.map +0 -1
  139. package/dist/commands/hook/create.js.map +0 -1
  140. package/dist/commands/hook/delete.js.map +0 -1
  141. package/dist/commands/hook/list.js.map +0 -1
  142. package/dist/commands/hook/logs.js.map +0 -1
  143. package/dist/commands/schema/delete.js.map +0 -1
  144. package/dist/commands/schema/deploy.js.map +0 -1
  145. package/dist/commands/schema/extract.js.map +0 -1
  146. package/dist/commands/schema/list.js.map +0 -1
  147. package/dist/commands/schema/validate.js.map +0 -1
@@ -1,102 +1,151 @@
1
- import { getCliToken, getUserConfig } from '@sanity/cli-core';
1
+ import { access } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getCliToken, getStudioConfig, getUserConfig, tryFindStudioConfigPath } from '@sanity/cli-core';
2
4
  import { getProjectById } from '../../services/projects.js';
3
5
  import { getCliUser, getProjectUser } from '../../services/user.js';
4
- import { findSanityModulesVersions } from '../versions/findSanityModulesVersions.js';
5
- export async function gatherDebugInfo(options) {
6
- const { cliConfig, includeSecrets, projectRoot } = options;
7
- // Gather all info in parallel where possible
8
- const [auth, globalConfig, projectConfigResult, versions] = await Promise.all([
9
- gatherAuthInfo(includeSecrets),
10
- gatherGlobalConfig(),
11
- cliConfig ? gatherProjectConfig(cliConfig) : undefined,
12
- gatherVersionsInfo(projectRoot)
13
- ]);
14
- // Gather user and project info that depend on auth
15
- const user = await gatherUserInfo(projectConfigResult, auth.hasToken);
16
- const project = await gatherProjectInfo(projectConfigResult, auth.hasToken, user);
17
- return {
18
- auth,
19
- globalConfig,
20
- project,
21
- projectConfig: projectConfigResult,
22
- user,
23
- versions
24
- };
25
- }
26
- async function gatherAuthInfo(includeSecrets) {
6
+ import { getCliVersion } from '../../util/getCliVersion.js';
7
+ import { detectCliInstallation } from '../../util/packageManager/installationInfo/index.js';
8
+ export async function gatherUserInfo(projectId) {
27
9
  const token = await getCliToken();
28
- const hasToken = Boolean(token);
29
- return {
30
- authToken: includeSecrets && token ? token : '<redacted>',
31
- hasToken,
32
- userType: 'normal'
33
- };
34
- }
35
- function gatherGlobalConfig() {
36
- return getUserConfig().all;
37
- }
38
- function gatherProjectConfig(cliConfig) {
39
- if (!cliConfig.api?.projectId) {
40
- return new Error('Missing required "api.projectId" key');
41
- }
42
- return cliConfig;
43
- }
44
- async function gatherVersionsInfo(projectRoot) {
45
- if (!projectRoot) {
46
- return undefined;
47
- }
48
- try {
49
- return await findSanityModulesVersions({
50
- cwd: projectRoot.directory
51
- });
52
- } catch {
53
- return [];
54
- }
55
- }
56
- async function gatherUserInfo(projectConfig, hasToken) {
57
- if (!hasToken) {
10
+ if (!token) {
58
11
  return new Error('Not logged in');
59
12
  }
60
13
  try {
61
- /**
62
- * If the project config has a project ID, get the user for the project
63
- * Otherwise, get the user for the global client
64
- */ const userInfo = !projectConfig || projectConfig instanceof Error || !projectConfig.api?.projectId ? await getCliUser() : await getProjectUser(projectConfig.api.projectId);
14
+ const userInfo = projectId ? await getProjectUser(projectId) : await getCliUser();
65
15
  return {
66
16
  email: userInfo.email,
67
17
  id: userInfo.id,
68
- name: userInfo.name
18
+ name: userInfo.name,
19
+ provider: userInfo.provider
69
20
  };
70
21
  } catch (error) {
71
22
  return error instanceof Error ? error : new Error('Failed to fetch user info');
72
23
  }
73
24
  }
74
- async function gatherProjectInfo(projectConfig, hasToken, user) {
75
- if (!hasToken || !projectConfig || projectConfig instanceof Error) {
76
- return null;
25
+ export async function gatherAuthInfo(includeSecrets) {
26
+ const token = await getCliToken();
27
+ const hasToken = Boolean(token);
28
+ const config = getUserConfig();
29
+ const authType = config.get('authType');
30
+ return {
31
+ authToken: token ? includeSecrets ? token : '<redacted>' : undefined,
32
+ hasToken,
33
+ userType: typeof authType === 'string' ? authType : 'normal'
34
+ };
35
+ }
36
+ export async function gatherCliInfo() {
37
+ const [version, installation] = await Promise.all([
38
+ getCliVersion(),
39
+ detectCliInstallation()
40
+ ]);
41
+ const { packageManager, resolvedFrom } = installation.currentExecution;
42
+ let installContext;
43
+ switch(resolvedFrom){
44
+ case 'global':
45
+ {
46
+ installContext = packageManager ? `globally (${packageManager})` : 'globally';
47
+ break;
48
+ }
49
+ case 'local':
50
+ {
51
+ installContext = 'locally';
52
+ break;
53
+ }
54
+ case 'npx':
55
+ {
56
+ installContext = 'via npx';
57
+ break;
58
+ }
59
+ default:
60
+ {
61
+ installContext = 'unknown';
62
+ }
63
+ }
64
+ return {
65
+ installContext,
66
+ version
67
+ };
68
+ }
69
+ export async function gatherProjectInfo(projectDirectory) {
70
+ if (!projectDirectory) {
71
+ return undefined;
77
72
  }
78
- const projectId = projectConfig.api?.projectId;
79
- if (!projectId) {
80
- return null;
73
+ const [cliConfigName, studioConfigFullPath] = await Promise.all([
74
+ findCliConfigFile(projectDirectory),
75
+ tryFindStudioConfigPath(projectDirectory)
76
+ ]);
77
+ return {
78
+ cliConfigPath: cliConfigName,
79
+ rootPath: projectDirectory,
80
+ studioConfigPath: studioConfigFullPath ? path.basename(studioConfigFullPath) : undefined
81
+ };
82
+ }
83
+ export async function gatherStudioWorkspaces(projectDirectory) {
84
+ const rawConfig = await getStudioConfig(projectDirectory, {
85
+ resolvePlugins: false
86
+ });
87
+ if (Array.isArray(rawConfig)) {
88
+ return rawConfig.map((ws)=>({
89
+ dataset: ws.dataset,
90
+ name: ws.name,
91
+ projectId: ws.projectId
92
+ }));
81
93
  }
82
- try {
83
- const projectInfo = await getProjectById(projectId);
84
- if (!projectInfo) {
85
- return new Error(`Project specified in configuration (${projectId}) does not exist in API`);
94
+ return [
95
+ {
96
+ dataset: rawConfig.dataset,
97
+ name: rawConfig.name,
98
+ projectId: rawConfig.projectId
99
+ }
100
+ ];
101
+ }
102
+ export async function gatherResolvedWorkspaces(projectDirectory, userId) {
103
+ // resolvePlugins: true goes through getStudioWorkspaces() which calls resolveConfig()
104
+ // from the sanity package. resolveConfig() always returns an array of workspaces,
105
+ // so resolvedConfigSchema (z.array(...)) is guaranteed to match.
106
+ const resolvedConfig = await getStudioConfig(projectDirectory, {
107
+ resolvePlugins: true
108
+ });
109
+ const projectMap = await fetchRolesByProject(resolvedConfig, userId);
110
+ return resolvedConfig.map((ws)=>({
111
+ name: ws.name,
112
+ roles: projectMap.get(ws.projectId) ?? [],
113
+ title: ws.title
114
+ }));
115
+ }
116
+ async function findCliConfigFile(directory) {
117
+ for (const name of [
118
+ 'sanity.cli.ts',
119
+ 'sanity.cli.js'
120
+ ]){
121
+ try {
122
+ await access(path.join(directory, name));
123
+ return name;
124
+ } catch {
125
+ // File doesn't exist, try next
86
126
  }
87
- const userId = user instanceof Error || !user ? null : user.id;
88
- const member = (projectInfo.members || []).find((member)=>member.id === userId);
89
- return {
90
- displayName: projectInfo.displayName,
91
- id: projectId,
92
- // @ts-expect-error - Incorrect type definition in @sanity/client
93
- userRoles: member && member.roles ? member.roles.map((role)=>role.name) : [
94
- '<none>'
95
- ]
96
- };
97
- } catch (error) {
98
- return error instanceof Error ? error : new Error('Failed to fetch project info');
99
127
  }
128
+ return undefined;
129
+ }
130
+ async function fetchRolesByProject(workspaces, userId) {
131
+ const projectMap = new Map();
132
+ if (!userId) return projectMap;
133
+ const projectIds = [
134
+ ...new Set(workspaces.map((ws)=>ws.projectId))
135
+ ];
136
+ await Promise.all(projectIds.map(async (projectId)=>{
137
+ try {
138
+ const project = await getProjectById(projectId);
139
+ if (!project) return;
140
+ const member = (project.members || []).find((m)=>m.id === userId);
141
+ // @ts-expect-error - Incorrect type definition in @sanity/client
142
+ const roles = member?.roles?.map((r)=>r.name) ?? [];
143
+ projectMap.set(projectId, roles);
144
+ } catch {
145
+ // Project not accessible, skip roles
146
+ }
147
+ }));
148
+ return projectMap;
100
149
  }
101
150
 
102
151
  //# sourceMappingURL=gatherDebugInfo.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/debug/gatherDebugInfo.ts"],"sourcesContent":["import {type CliConfig, getCliToken, getUserConfig, type ProjectRootResult} from '@sanity/cli-core'\n\nimport {getProjectById} from '../../services/projects.js'\nimport {getCliUser, getProjectUser} from '../../services/user.js'\nimport {findSanityModulesVersions} from '../versions/findSanityModulesVersions.js'\nimport {type ModuleVersionResult} from '../versions/types.js'\nimport {\n type AuthInfo,\n type DebugInfo,\n type DebugInfoOptions,\n type ProjectInfo,\n type UserInfo,\n} from './types.js'\n\nexport async function gatherDebugInfo(options: DebugInfoOptions): Promise<DebugInfo> {\n const {cliConfig, includeSecrets, projectRoot} = options\n\n // Gather all info in parallel where possible\n const [auth, globalConfig, projectConfigResult, versions] = await Promise.all([\n gatherAuthInfo(includeSecrets),\n gatherGlobalConfig(),\n cliConfig ? gatherProjectConfig(cliConfig) : undefined,\n gatherVersionsInfo(projectRoot),\n ])\n\n // Gather user and project info that depend on auth\n const user = await gatherUserInfo(projectConfigResult, auth.hasToken)\n const project = await gatherProjectInfo(projectConfigResult, auth.hasToken, user)\n\n return {\n auth,\n globalConfig,\n project,\n projectConfig: projectConfigResult,\n user,\n versions,\n }\n}\n\nasync function gatherAuthInfo(includeSecrets: boolean): Promise<AuthInfo> {\n const token = await getCliToken()\n const hasToken = Boolean(token)\n\n return {\n authToken: includeSecrets && token ? token : '<redacted>',\n hasToken,\n userType: 'normal',\n }\n}\n\nfunction gatherGlobalConfig(): Record<string, unknown> {\n return getUserConfig().all\n}\n\nfunction gatherProjectConfig(cliConfig: CliConfig): CliConfig | Error {\n if (!cliConfig.api?.projectId) {\n return new Error('Missing required \"api.projectId\" key')\n }\n\n return cliConfig\n}\n\nasync function gatherVersionsInfo(\n projectRoot: ProjectRootResult | undefined,\n): Promise<ModuleVersionResult[] | undefined> {\n if (!projectRoot) {\n return undefined\n }\n\n try {\n return await findSanityModulesVersions({cwd: projectRoot.directory})\n } catch {\n return []\n }\n}\n\nasync function gatherUserInfo(\n projectConfig: CliConfig | Error | undefined,\n hasToken: boolean,\n): Promise<Error | UserInfo | null> {\n if (!hasToken) {\n return new Error('Not logged in')\n }\n\n try {\n /**\n * If the project config has a project ID, get the user for the project\n * Otherwise, get the user for the global client\n */\n const userInfo =\n !projectConfig || projectConfig instanceof Error || !projectConfig.api?.projectId\n ? await getCliUser()\n : await getProjectUser(projectConfig.api.projectId)\n\n return {\n email: userInfo.email,\n id: userInfo.id,\n name: userInfo.name,\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch user info')\n }\n}\n\nasync function gatherProjectInfo(\n projectConfig: CliConfig | Error | undefined,\n hasToken: boolean,\n user: Error | UserInfo | null,\n): Promise<Error | ProjectInfo | null> {\n if (!hasToken || !projectConfig || projectConfig instanceof Error) {\n return null\n }\n\n const projectId = projectConfig.api?.projectId\n if (!projectId) {\n return null\n }\n\n try {\n const projectInfo = await getProjectById(projectId)\n\n if (!projectInfo) {\n return new Error(`Project specified in configuration (${projectId}) does not exist in API`)\n }\n\n const userId = user instanceof Error || !user ? null : user.id\n const member = (projectInfo.members || []).find((member) => member.id === userId)\n\n return {\n displayName: projectInfo.displayName,\n id: projectId,\n // @ts-expect-error - Incorrect type definition in @sanity/client\n userRoles: member && member.roles ? member.roles.map((role) => role.name) : ['<none>'],\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch project info')\n }\n}\n"],"names":["getCliToken","getUserConfig","getProjectById","getCliUser","getProjectUser","findSanityModulesVersions","gatherDebugInfo","options","cliConfig","includeSecrets","projectRoot","auth","globalConfig","projectConfigResult","versions","Promise","all","gatherAuthInfo","gatherGlobalConfig","gatherProjectConfig","undefined","gatherVersionsInfo","user","gatherUserInfo","hasToken","project","gatherProjectInfo","projectConfig","token","Boolean","authToken","userType","api","projectId","Error","cwd","directory","userInfo","email","id","name","error","projectInfo","userId","member","members","find","displayName","userRoles","roles","map","role"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/debug/gatherDebugInfo.ts"],"sourcesContent":["import {access} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {\n getCliToken,\n getStudioConfig,\n getUserConfig,\n tryFindStudioConfigPath,\n} from '@sanity/cli-core'\n\nimport {getProjectById} from '../../services/projects.js'\nimport {getCliUser, getProjectUser} from '../../services/user.js'\nimport {getCliVersion} from '../../util/getCliVersion.js'\nimport {detectCliInstallation} from '../../util/packageManager/installationInfo/index.js'\nimport {\n type AuthInfo,\n type CliInfo,\n type ProjectInfo,\n type ResolvedWorkspace,\n type StudioWorkspace,\n type UserInfo,\n} from './types.js'\n\nexport async function gatherUserInfo(projectId: string | undefined): Promise<Error | UserInfo> {\n const token = await getCliToken()\n if (!token) {\n return new Error('Not logged in')\n }\n\n try {\n const userInfo = projectId ? await getProjectUser(projectId) : await getCliUser()\n\n return {\n email: userInfo.email,\n id: userInfo.id,\n name: userInfo.name,\n provider: userInfo.provider,\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch user info')\n }\n}\n\nexport async function gatherAuthInfo(includeSecrets: boolean): Promise<AuthInfo> {\n const token = await getCliToken()\n const hasToken = Boolean(token)\n const config = getUserConfig()\n const authType = config.get('authType')\n\n return {\n authToken: token ? (includeSecrets ? token : '<redacted>') : undefined,\n hasToken,\n userType: typeof authType === 'string' ? authType : 'normal',\n }\n}\n\nexport async function gatherCliInfo(): Promise<CliInfo> {\n const [version, installation] = await Promise.all([getCliVersion(), detectCliInstallation()])\n\n const {packageManager, resolvedFrom} = installation.currentExecution\n\n let installContext: string\n switch (resolvedFrom) {\n case 'global': {\n installContext = packageManager ? `globally (${packageManager})` : 'globally'\n break\n }\n case 'local': {\n installContext = 'locally'\n break\n }\n case 'npx': {\n installContext = 'via npx'\n break\n }\n default: {\n installContext = 'unknown'\n }\n }\n\n return {installContext, version}\n}\n\nexport async function gatherProjectInfo(\n projectDirectory: string | undefined,\n): Promise<ProjectInfo | undefined> {\n if (!projectDirectory) {\n return undefined\n }\n\n const [cliConfigName, studioConfigFullPath] = await Promise.all([\n findCliConfigFile(projectDirectory),\n tryFindStudioConfigPath(projectDirectory),\n ])\n\n return {\n cliConfigPath: cliConfigName,\n rootPath: projectDirectory,\n studioConfigPath: studioConfigFullPath ? path.basename(studioConfigFullPath) : undefined,\n }\n}\n\nexport async function gatherStudioWorkspaces(projectDirectory: string): Promise<StudioWorkspace[]> {\n const rawConfig = await getStudioConfig(projectDirectory, {resolvePlugins: false})\n\n if (Array.isArray(rawConfig)) {\n return rawConfig.map((ws) => ({\n dataset: ws.dataset,\n name: ws.name,\n projectId: ws.projectId,\n }))\n }\n\n return [\n {\n dataset: rawConfig.dataset,\n name: rawConfig.name,\n projectId: rawConfig.projectId,\n },\n ]\n}\n\nexport async function gatherResolvedWorkspaces(\n projectDirectory: string,\n userId: string | undefined,\n): Promise<ResolvedWorkspace[]> {\n // resolvePlugins: true goes through getStudioWorkspaces() which calls resolveConfig()\n // from the sanity package. resolveConfig() always returns an array of workspaces,\n // so resolvedConfigSchema (z.array(...)) is guaranteed to match.\n const resolvedConfig = await getStudioConfig(projectDirectory, {resolvePlugins: true})\n\n const projectMap = await fetchRolesByProject(resolvedConfig, userId)\n\n return resolvedConfig.map((ws) => ({\n name: ws.name,\n roles: projectMap.get(ws.projectId) ?? [],\n title: ws.title,\n }))\n}\n\nasync function findCliConfigFile(directory: string): Promise<string | undefined> {\n for (const name of ['sanity.cli.ts', 'sanity.cli.js']) {\n try {\n await access(path.join(directory, name))\n return name\n } catch {\n // File doesn't exist, try next\n }\n }\n return undefined\n}\n\nasync function fetchRolesByProject(\n workspaces: {projectId: string}[],\n userId: string | undefined,\n): Promise<Map<string, string[]>> {\n const projectMap = new Map<string, string[]>()\n if (!userId) return projectMap\n\n const projectIds = [...new Set(workspaces.map((ws) => ws.projectId))]\n await Promise.all(\n projectIds.map(async (projectId) => {\n try {\n const project = await getProjectById(projectId)\n if (!project) return\n const member = (project.members || []).find((m) => m.id === userId)\n // @ts-expect-error - Incorrect type definition in @sanity/client\n const roles: string[] = member?.roles?.map((r) => r.name) ?? []\n projectMap.set(projectId, roles)\n } catch {\n // Project not accessible, skip roles\n }\n }),\n )\n return projectMap\n}\n"],"names":["access","path","getCliToken","getStudioConfig","getUserConfig","tryFindStudioConfigPath","getProjectById","getCliUser","getProjectUser","getCliVersion","detectCliInstallation","gatherUserInfo","projectId","token","Error","userInfo","email","id","name","provider","error","gatherAuthInfo","includeSecrets","hasToken","Boolean","config","authType","get","authToken","undefined","userType","gatherCliInfo","version","installation","Promise","all","packageManager","resolvedFrom","currentExecution","installContext","gatherProjectInfo","projectDirectory","cliConfigName","studioConfigFullPath","findCliConfigFile","cliConfigPath","rootPath","studioConfigPath","basename","gatherStudioWorkspaces","rawConfig","resolvePlugins","Array","isArray","map","ws","dataset","gatherResolvedWorkspaces","userId","resolvedConfig","projectMap","fetchRolesByProject","roles","title","directory","join","workspaces","Map","projectIds","Set","project","member","members","find","m","r","set"],"mappings":"AAAA,SAAQA,MAAM,QAAO,mBAAkB;AACvC,OAAOC,UAAU,YAAW;AAE5B,SACEC,WAAW,EACXC,eAAe,EACfC,aAAa,EACbC,uBAAuB,QAClB,mBAAkB;AAEzB,SAAQC,cAAc,QAAO,6BAA4B;AACzD,SAAQC,UAAU,EAAEC,cAAc,QAAO,yBAAwB;AACjE,SAAQC,aAAa,QAAO,8BAA6B;AACzD,SAAQC,qBAAqB,QAAO,sDAAqD;AAUzF,OAAO,eAAeC,eAAeC,SAA6B;IAChE,MAAMC,QAAQ,MAAMX;IACpB,IAAI,CAACW,OAAO;QACV,OAAO,IAAIC,MAAM;IACnB;IAEA,IAAI;QACF,MAAMC,WAAWH,YAAY,MAAMJ,eAAeI,aAAa,MAAML;QAErE,OAAO;YACLS,OAAOD,SAASC,KAAK;YACrBC,IAAIF,SAASE,EAAE;YACfC,MAAMH,SAASG,IAAI;YACnBC,UAAUJ,SAASI,QAAQ;QAC7B;IACF,EAAE,OAAOC,OAAO;QACd,OAAOA,iBAAiBN,QAAQM,QAAQ,IAAIN,MAAM;IACpD;AACF;AAEA,OAAO,eAAeO,eAAeC,cAAuB;IAC1D,MAAMT,QAAQ,MAAMX;IACpB,MAAMqB,WAAWC,QAAQX;IACzB,MAAMY,SAASrB;IACf,MAAMsB,WAAWD,OAAOE,GAAG,CAAC;IAE5B,OAAO;QACLC,WAAWf,QAASS,iBAAiBT,QAAQ,eAAgBgB;QAC7DN;QACAO,UAAU,OAAOJ,aAAa,WAAWA,WAAW;IACtD;AACF;AAEA,OAAO,eAAeK;IACpB,MAAM,CAACC,SAASC,aAAa,GAAG,MAAMC,QAAQC,GAAG,CAAC;QAAC1B;QAAiBC;KAAwB;IAE5F,MAAM,EAAC0B,cAAc,EAAEC,YAAY,EAAC,GAAGJ,aAAaK,gBAAgB;IAEpE,IAAIC;IACJ,OAAQF;QACN,KAAK;YAAU;gBACbE,iBAAiBH,iBAAiB,CAAC,UAAU,EAAEA,eAAe,CAAC,CAAC,GAAG;gBACnE;YACF;QACA,KAAK;YAAS;gBACZG,iBAAiB;gBACjB;YACF;QACA,KAAK;YAAO;gBACVA,iBAAiB;gBACjB;YACF;QACA;YAAS;gBACPA,iBAAiB;YACnB;IACF;IAEA,OAAO;QAACA;QAAgBP;IAAO;AACjC;AAEA,OAAO,eAAeQ,kBACpBC,gBAAoC;IAEpC,IAAI,CAACA,kBAAkB;QACrB,OAAOZ;IACT;IAEA,MAAM,CAACa,eAAeC,qBAAqB,GAAG,MAAMT,QAAQC,GAAG,CAAC;QAC9DS,kBAAkBH;QAClBpC,wBAAwBoC;KACzB;IAED,OAAO;QACLI,eAAeH;QACfI,UAAUL;QACVM,kBAAkBJ,uBAAuB1C,KAAK+C,QAAQ,CAACL,wBAAwBd;IACjF;AACF;AAEA,OAAO,eAAeoB,uBAAuBR,gBAAwB;IACnE,MAAMS,YAAY,MAAM/C,gBAAgBsC,kBAAkB;QAACU,gBAAgB;IAAK;IAEhF,IAAIC,MAAMC,OAAO,CAACH,YAAY;QAC5B,OAAOA,UAAUI,GAAG,CAAC,CAACC,KAAQ,CAAA;gBAC5BC,SAASD,GAAGC,OAAO;gBACnBtC,MAAMqC,GAAGrC,IAAI;gBACbN,WAAW2C,GAAG3C,SAAS;YACzB,CAAA;IACF;IAEA,OAAO;QACL;YACE4C,SAASN,UAAUM,OAAO;YAC1BtC,MAAMgC,UAAUhC,IAAI;YACpBN,WAAWsC,UAAUtC,SAAS;QAChC;KACD;AACH;AAEA,OAAO,eAAe6C,yBACpBhB,gBAAwB,EACxBiB,MAA0B;IAE1B,sFAAsF;IACtF,kFAAkF;IAClF,iEAAiE;IACjE,MAAMC,iBAAiB,MAAMxD,gBAAgBsC,kBAAkB;QAACU,gBAAgB;IAAI;IAEpF,MAAMS,aAAa,MAAMC,oBAAoBF,gBAAgBD;IAE7D,OAAOC,eAAeL,GAAG,CAAC,CAACC,KAAQ,CAAA;YACjCrC,MAAMqC,GAAGrC,IAAI;YACb4C,OAAOF,WAAWjC,GAAG,CAAC4B,GAAG3C,SAAS,KAAK,EAAE;YACzCmD,OAAOR,GAAGQ,KAAK;QACjB,CAAA;AACF;AAEA,eAAenB,kBAAkBoB,SAAiB;IAChD,KAAK,MAAM9C,QAAQ;QAAC;QAAiB;KAAgB,CAAE;QACrD,IAAI;YACF,MAAMlB,OAAOC,KAAKgE,IAAI,CAACD,WAAW9C;YAClC,OAAOA;QACT,EAAE,OAAM;QACN,+BAA+B;QACjC;IACF;IACA,OAAOW;AACT;AAEA,eAAegC,oBACbK,UAAiC,EACjCR,MAA0B;IAE1B,MAAME,aAAa,IAAIO;IACvB,IAAI,CAACT,QAAQ,OAAOE;IAEpB,MAAMQ,aAAa;WAAI,IAAIC,IAAIH,WAAWZ,GAAG,CAAC,CAACC,KAAOA,GAAG3C,SAAS;KAAG;IACrE,MAAMsB,QAAQC,GAAG,CACfiC,WAAWd,GAAG,CAAC,OAAO1C;QACpB,IAAI;YACF,MAAM0D,UAAU,MAAMhE,eAAeM;YACrC,IAAI,CAAC0D,SAAS;YACd,MAAMC,SAAS,AAACD,CAAAA,QAAQE,OAAO,IAAI,EAAE,AAAD,EAAGC,IAAI,CAAC,CAACC,IAAMA,EAAEzD,EAAE,KAAKyC;YAC5D,iEAAiE;YACjE,MAAMI,QAAkBS,QAAQT,OAAOR,IAAI,CAACqB,IAAMA,EAAEzD,IAAI,KAAK,EAAE;YAC/D0C,WAAWgB,GAAG,CAAChE,WAAWkD;QAC5B,EAAE,OAAM;QACN,qCAAqC;QACvC;IACF;IAEF,OAAOF;AACT"}
@@ -0,0 +1,25 @@
1
+ import { inspect, styleText } from 'node:util';
2
+ export function sectionHeader(title) {
3
+ return styleText('bold', `${title}:`);
4
+ }
5
+ export function formatKeyValue(key, value, options) {
6
+ const indent = options?.indent ?? 2;
7
+ const padTo = options?.padTo ?? 0;
8
+ const paddedKey = `${key}:`.padEnd(padTo > 0 ? padTo + 1 : key.length + 1);
9
+ const formattedValue = formatValue(value);
10
+ return `${' '.repeat(indent)}${styleText('dim', paddedKey)} ${formattedValue}`;
11
+ }
12
+ function formatValue(value) {
13
+ if (Array.isArray(value)) {
14
+ return `[ ${value.map((v)=>JSON.stringify(v)).join(', ')} ]`;
15
+ }
16
+ if (typeof value === 'string') {
17
+ return value;
18
+ }
19
+ return inspect(value, {
20
+ colors: true,
21
+ depth: Infinity
22
+ });
23
+ }
24
+
25
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/debug/output.ts"],"sourcesContent":["import {inspect, styleText} from 'node:util'\n\nexport function sectionHeader(title: string): string {\n return styleText('bold', `${title}:`)\n}\n\nexport function formatKeyValue(\n key: string,\n value: unknown,\n options?: {indent?: number; padTo?: number},\n): string {\n const indent = options?.indent ?? 2\n const padTo = options?.padTo ?? 0\n const paddedKey = `${key}:`.padEnd(padTo > 0 ? padTo + 1 : key.length + 1)\n const formattedValue = formatValue(value)\n return `${' '.repeat(indent)}${styleText('dim', paddedKey)} ${formattedValue}`\n}\n\nfunction formatValue(value: unknown): string {\n if (Array.isArray(value)) {\n return `[ ${value.map((v) => JSON.stringify(v)).join(', ')} ]`\n }\n if (typeof value === 'string') {\n return value\n }\n return inspect(value, {colors: true, depth: Infinity})\n}\n"],"names":["inspect","styleText","sectionHeader","title","formatKeyValue","key","value","options","indent","padTo","paddedKey","padEnd","length","formattedValue","formatValue","repeat","Array","isArray","map","v","JSON","stringify","join","colors","depth","Infinity"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,SAAS,QAAO,YAAW;AAE5C,OAAO,SAASC,cAAcC,KAAa;IACzC,OAAOF,UAAU,QAAQ,GAAGE,MAAM,CAAC,CAAC;AACtC;AAEA,OAAO,SAASC,eACdC,GAAW,EACXC,KAAc,EACdC,OAA2C;IAE3C,MAAMC,SAASD,SAASC,UAAU;IAClC,MAAMC,QAAQF,SAASE,SAAS;IAChC,MAAMC,YAAY,GAAGL,IAAI,CAAC,CAAC,CAACM,MAAM,CAACF,QAAQ,IAAIA,QAAQ,IAAIJ,IAAIO,MAAM,GAAG;IACxE,MAAMC,iBAAiBC,YAAYR;IACnC,OAAO,GAAG,IAAIS,MAAM,CAACP,UAAUP,UAAU,OAAOS,WAAW,CAAC,EAAEG,gBAAgB;AAChF;AAEA,SAASC,YAAYR,KAAc;IACjC,IAAIU,MAAMC,OAAO,CAACX,QAAQ;QACxB,OAAO,CAAC,EAAE,EAAEA,MAAMY,GAAG,CAAC,CAACC,IAAMC,KAAKC,SAAS,CAACF,IAAIG,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE;IACA,IAAI,OAAOhB,UAAU,UAAU;QAC7B,OAAOA;IACT;IACA,OAAON,QAAQM,OAAO;QAACiB,QAAQ;QAAMC,OAAOC;IAAQ;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/debug/types.ts"],"sourcesContent":["import {type CliConfig, type ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ModuleVersionResult} from '../versions/types.js'\n\nexport interface DebugInfoOptions {\n cliConfig: CliConfig | undefined\n includeSecrets: boolean\n projectRoot: ProjectRootResult | undefined\n}\n\nexport interface UserInfo {\n email: string\n id: string\n name: string\n}\n\nexport interface ProjectInfo {\n displayName: string\n id: string\n userRoles: string[]\n}\n\nexport interface AuthInfo {\n authToken: string\n hasToken: boolean\n userType: string\n}\n\nexport interface DebugInfo {\n auth: AuthInfo\n globalConfig: Record<string, unknown>\n project: Error | ProjectInfo | null\n projectConfig: CliConfig | Error | undefined\n user: Error | UserInfo | null\n versions: ModuleVersionResult[] | undefined\n}\n"],"names":[],"mappings":"AA4BA,WAOC"}
1
+ {"version":3,"sources":["../../../src/actions/debug/types.ts"],"sourcesContent":["export interface UserInfo {\n email: string\n id: string\n name: string\n provider: string\n}\n\nexport interface AuthInfo {\n authToken: string | undefined\n hasToken: boolean\n userType: string\n}\n\nexport interface CliInfo {\n installContext: string\n version: string\n}\n\nexport interface ProjectInfo {\n cliConfigPath: string | undefined\n rootPath: string\n studioConfigPath: string | undefined\n}\n\nexport interface StudioWorkspace {\n dataset: string\n name: string | undefined\n projectId: string\n}\n\nexport interface ResolvedWorkspace {\n name: string\n roles: string[]\n title: string\n}\n"],"names":[],"mappings":"AA8BA,WAIC"}
@@ -0,0 +1,21 @@
1
+ import { Schema } from '@sanity/schema';
2
+ import { transformType } from '../schemaTypeTransformer.js';
3
+ const defaultTypeNames = new Set(Schema.compile({
4
+ name: 'default',
5
+ types: []
6
+ }).getTypeNames());
7
+ /**
8
+ * Compiles a schema from user-defined types and extracts only the user-defined types
9
+ * as ManifestSchemaType[], filtering out Sanity's built-in types.
10
+ */ export function extractTypes(types) {
11
+ const schema = Schema.compile({
12
+ name: 'test',
13
+ types
14
+ });
15
+ const context = {
16
+ schema
17
+ };
18
+ return schema.getTypeNames().filter((name)=>!defaultTypeNames.has(name)).map((name)=>transformType(schema.get(name), context));
19
+ }
20
+
21
+ //# sourceMappingURL=testHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/manifest/__tests__/testHelpers.ts"],"sourcesContent":["import {Schema} from '@sanity/schema'\n\nimport {transformType} from '../schemaTypeTransformer.js'\nimport {type ManifestSchemaType} from '../types.js'\n\nconst defaultTypeNames = new Set(\n Schema.compile({name: 'default', types: []}).getTypeNames() as string[],\n)\n\n/**\n * Compiles a schema from user-defined types and extracts only the user-defined types\n * as ManifestSchemaType[], filtering out Sanity's built-in types.\n */\nexport function extractTypes(types: unknown[]): ManifestSchemaType[] {\n const schema = Schema.compile({name: 'test', types})\n const context = {schema}\n return (schema.getTypeNames() as string[])\n .filter((name: string) => !defaultTypeNames.has(name))\n .map((name: string) => transformType(schema.get(name), context))\n}\n"],"names":["Schema","transformType","defaultTypeNames","Set","compile","name","types","getTypeNames","extractTypes","schema","context","filter","has","map","get"],"mappings":"AAAA,SAAQA,MAAM,QAAO,iBAAgB;AAErC,SAAQC,aAAa,QAAO,8BAA6B;AAGzD,MAAMC,mBAAmB,IAAIC,IAC3BH,OAAOI,OAAO,CAAC;IAACC,MAAM;IAAWC,OAAO,EAAE;AAAA,GAAGC,YAAY;AAG3D;;;CAGC,GACD,OAAO,SAASC,aAAaF,KAAgB;IAC3C,MAAMG,SAAST,OAAOI,OAAO,CAAC;QAACC,MAAM;QAAQC;IAAK;IAClD,MAAMI,UAAU;QAACD;IAAM;IACvB,OAAO,AAACA,OAAOF,YAAY,GACxBI,MAAM,CAAC,CAACN,OAAiB,CAACH,iBAAiBU,GAAG,CAACP,OAC/CQ,GAAG,CAAC,CAACR,OAAiBJ,cAAcQ,OAAOK,GAAG,CAACT,OAAOK;AAC3D"}
@@ -100,7 +100,8 @@ const MAX_CUSTOM_PROPERTY_DEPTH = 5;
100
100
  }
101
101
  /**
102
102
  * Retains serializable properties from an unknown value, recursively processing objects and arrays
103
- */ function retainSerializableProps(maybeSerializable, depth = 0) {
103
+ * @internal Exported for testing purposes only
104
+ */ export function retainSerializableProps(maybeSerializable, depth = 0) {
104
105
  if (depth > MAX_CUSTOM_PROPERTY_DEPTH) {
105
106
  return undefined;
106
107
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/manifest/schemaTypeTransformer.ts"],"sourcesContent":["import {\n type ArraySchemaType,\n type BlockDefinition,\n type BooleanSchemaType,\n type FileSchemaType,\n type MultiFieldSet,\n type NumberSchemaType,\n type ObjectField,\n type ObjectSchemaType,\n type ReferenceSchemaType,\n type SchemaType,\n type StringSchemaType,\n} from '@sanity/types'\n\nimport {transformBlockType} from './blockTypeTransformer.js'\nimport {\n transformCrossDatasetReference,\n transformGlobalDocumentReference,\n transformReference,\n} from './referenceTransformer.js'\nimport {\n getCustomFields,\n getDefinedTypeName,\n isCrossDatasetReference,\n isCustomized,\n isDefined,\n isGlobalDocumentReference,\n isPrimitive,\n isRecord,\n isReference,\n} from './schemaTypeHelpers.js'\nimport {\n type Context,\n ensureConditional,\n ensureCustomTitle,\n ensureString,\n type SerializableProp,\n} from './transformerUtils.js'\nimport {\n type ManifestField,\n type ManifestFieldset,\n type ManifestSchemaType,\n type ManifestSerializable,\n} from './types.js'\nimport {transformValidation} from './validationTransformer.js'\n\ntype SchemaTypeKey =\n | 'group' // we strip this from fields\n | keyof ArraySchemaType\n | keyof BlockDefinition\n | keyof BooleanSchemaType\n | keyof FileSchemaType\n | keyof NumberSchemaType\n | keyof ObjectSchemaType\n | keyof ReferenceSchemaType\n | keyof StringSchemaType\n\ntype ObjectFields = Record<string, never> | {fields: ManifestField[]}\n\nconst MAX_CUSTOM_PROPERTY_DEPTH = 5\n\n/**\n * Transforms a SchemaType to its manifest representation\n */\nexport function transformType(type: SchemaType, context: Context): ManifestSchemaType {\n const typeName = type.type ? type.type.name : type.jsonType\n\n return {\n ...transformCommonTypeFields(type, typeName, context),\n name: type.name,\n type: typeName,\n ...ensureCustomTitle(type.name, type.title),\n }\n}\n\n/**\n * Transforms common fields shared across all schema types\n */\nfunction transformCommonTypeFields(\n type: SchemaType & {fieldset?: string},\n typeName: string,\n context: Context,\n): Omit<ManifestSchemaType, 'name' | 'title' | 'type'> {\n const arrayProps =\n typeName === 'array' && type.jsonType === 'array' ? transformArrayMember(type, context) : {}\n\n const referenceProps = isReference(type) ? transformReference(type, retainCustomTypeProps) : {}\n const crossDatasetRefProps = isCrossDatasetReference(type)\n ? transformCrossDatasetReference(type)\n : {}\n const globalRefProps = isGlobalDocumentReference(type)\n ? transformGlobalDocumentReference(type)\n : {}\n\n const objectFields: ObjectFields =\n type.jsonType === 'object' && type.type && isCustomized(type)\n ? {\n fields: getCustomFields(type).map((objectField) => transformField(objectField, context)),\n }\n : {}\n\n return {\n ...retainCustomTypeProps(type),\n ...transformValidation(type.validation, retainSerializableProps),\n ...ensureString('description', type.description),\n ...objectFields,\n ...arrayProps,\n ...referenceProps,\n ...crossDatasetRefProps,\n ...globalRefProps,\n ...ensureConditional('readOnly', type.readOnly),\n ...ensureConditional('hidden', type.hidden),\n ...transformFieldsets(type),\n // fieldset prop gets instrumented via getCustomFields\n ...ensureString('fieldset', type.fieldset),\n ...transformBlockType(type, context, transformType),\n }\n}\n\n/**\n * Transforms fieldsets from a schema type\n */\nfunction transformFieldsets(\n type: SchemaType,\n): Record<string, never> | {fieldsets: ManifestFieldset[]} {\n if (type.jsonType !== 'object') {\n return {}\n }\n const fieldsets = type.fieldsets\n ?.filter((fs): fs is MultiFieldSet => !fs.single)\n .map((fs) => {\n const options = isRecord(fs.options) ? {options: retainSerializableProps(fs.options)} : {}\n return {\n name: fs.name,\n ...ensureCustomTitle(fs.name, fs.title),\n ...ensureString('description', fs.description),\n ...ensureConditional('readOnly', fs.readOnly),\n ...ensureConditional('hidden', fs.hidden),\n ...options,\n }\n })\n\n return fieldsets?.length ? {fieldsets} : {}\n}\n\n/**\n * Retains custom type properties that should be included in the manifest\n */\nfunction retainCustomTypeProps(type: SchemaType): Record<string, SerializableProp> {\n const manuallySerializedFields = new Set<SchemaTypeKey>([\n '__experimental_actions',\n '__experimental_formPreviewTitle',\n '__experimental_omnisearch_visibility',\n '__experimental_search',\n 'components',\n 'description',\n 'fields',\n 'fieldsets',\n //only exists on fields\n 'group',\n 'groups',\n 'hidden',\n 'icon',\n 'jsonType',\n //explicitly added\n 'name',\n 'of',\n 'orderings',\n 'preview',\n 'readOnly',\n 'title',\n 'to',\n // not serialized\n 'type',\n 'validation',\n // we know about these, but let them be generically handled\n // deprecated\n // rows (from text)\n // initialValue\n // options\n // crossDatasetReference props\n ])\n const typeWithoutManuallyHandledFields = Object.fromEntries(\n Object.entries(type).filter(\n ([key]) => !manuallySerializedFields.has(key as unknown as SchemaTypeKey),\n ),\n )\n return retainSerializableProps(typeWithoutManuallyHandledFields) as Record<\n string,\n SerializableProp\n >\n}\n\n/**\n * Retains serializable properties from an unknown value, recursively processing objects and arrays\n */\nfunction retainSerializableProps(maybeSerializable: unknown, depth = 0): SerializableProp {\n if (depth > MAX_CUSTOM_PROPERTY_DEPTH) {\n return undefined\n }\n\n if (!isDefined(maybeSerializable)) {\n return undefined\n }\n\n if (isPrimitive(maybeSerializable)) {\n // cull empty strings\n if (maybeSerializable === '') {\n return undefined\n }\n return maybeSerializable\n }\n\n // url-schemes ect..\n if (maybeSerializable instanceof RegExp) {\n return maybeSerializable.toString()\n }\n\n if (Array.isArray(maybeSerializable)) {\n const arrayItems = maybeSerializable\n .map((item) => retainSerializableProps(item, depth + 1))\n .filter((item): item is ManifestSerializable => isDefined(item))\n return arrayItems.length > 0 ? arrayItems : undefined\n }\n\n if (isRecord(maybeSerializable)) {\n const serializableEntries = Object.entries(maybeSerializable)\n .map(([key, value]) => {\n return [key, retainSerializableProps(value, depth + 1)]\n })\n .filter(([, value]) => isDefined(value))\n return serializableEntries.length > 0 ? Object.fromEntries(serializableEntries) : undefined\n }\n\n return undefined\n}\n\n/**\n * Transforms an ObjectField to its manifest representation\n */\nfunction transformField(field: ObjectField & {fieldset?: string}, context: Context): ManifestField {\n const fieldType = field.type\n const typeName = getDefinedTypeName(fieldType) ?? fieldType.name\n return {\n ...transformCommonTypeFields(fieldType, typeName, context),\n name: field.name,\n type: typeName,\n ...ensureCustomTitle(field.name, fieldType.title),\n // this prop gets added synthetically via getCustomFields\n ...ensureString('fieldset', field.fieldset),\n }\n}\n\n/**\n * Transforms array member types to their manifest representation\n */\nfunction transformArrayMember(\n arrayMember: ArraySchemaType,\n context: Context,\n): Pick<ManifestField, 'of'> {\n return {\n of: arrayMember.of.map((type) => {\n const typeName = getDefinedTypeName(type) ?? type.name\n return {\n ...transformCommonTypeFields(type, typeName, context),\n type: typeName,\n ...(typeName === type.name ? {} : {name: type.name}),\n ...ensureCustomTitle(type.name, type.title),\n }\n }),\n }\n}\n"],"names":["transformBlockType","transformCrossDatasetReference","transformGlobalDocumentReference","transformReference","getCustomFields","getDefinedTypeName","isCrossDatasetReference","isCustomized","isDefined","isGlobalDocumentReference","isPrimitive","isRecord","isReference","ensureConditional","ensureCustomTitle","ensureString","transformValidation","MAX_CUSTOM_PROPERTY_DEPTH","transformType","type","context","typeName","name","jsonType","transformCommonTypeFields","title","arrayProps","transformArrayMember","referenceProps","retainCustomTypeProps","crossDatasetRefProps","globalRefProps","objectFields","fields","map","objectField","transformField","validation","retainSerializableProps","description","readOnly","hidden","transformFieldsets","fieldset","fieldsets","filter","fs","single","options","length","manuallySerializedFields","Set","typeWithoutManuallyHandledFields","Object","fromEntries","entries","key","has","maybeSerializable","depth","undefined","RegExp","toString","Array","isArray","arrayItems","item","serializableEntries","value","field","fieldType","arrayMember","of"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/manifest/schemaTypeTransformer.ts"],"sourcesContent":["import {\n type ArraySchemaType,\n type BlockDefinition,\n type BooleanSchemaType,\n type FileSchemaType,\n type MultiFieldSet,\n type NumberSchemaType,\n type ObjectField,\n type ObjectSchemaType,\n type ReferenceSchemaType,\n type SchemaType,\n type StringSchemaType,\n} from '@sanity/types'\n\nimport {transformBlockType} from './blockTypeTransformer.js'\nimport {\n transformCrossDatasetReference,\n transformGlobalDocumentReference,\n transformReference,\n} from './referenceTransformer.js'\nimport {\n getCustomFields,\n getDefinedTypeName,\n isCrossDatasetReference,\n isCustomized,\n isDefined,\n isGlobalDocumentReference,\n isPrimitive,\n isRecord,\n isReference,\n} from './schemaTypeHelpers.js'\nimport {\n type Context,\n ensureConditional,\n ensureCustomTitle,\n ensureString,\n type SerializableProp,\n} from './transformerUtils.js'\nimport {\n type ManifestField,\n type ManifestFieldset,\n type ManifestSchemaType,\n type ManifestSerializable,\n} from './types.js'\nimport {transformValidation} from './validationTransformer.js'\n\ntype SchemaTypeKey =\n | 'group' // we strip this from fields\n | keyof ArraySchemaType\n | keyof BlockDefinition\n | keyof BooleanSchemaType\n | keyof FileSchemaType\n | keyof NumberSchemaType\n | keyof ObjectSchemaType\n | keyof ReferenceSchemaType\n | keyof StringSchemaType\n\ntype ObjectFields = Record<string, never> | {fields: ManifestField[]}\n\nconst MAX_CUSTOM_PROPERTY_DEPTH = 5\n\n/**\n * Transforms a SchemaType to its manifest representation\n */\nexport function transformType(type: SchemaType, context: Context): ManifestSchemaType {\n const typeName = type.type ? type.type.name : type.jsonType\n\n return {\n ...transformCommonTypeFields(type, typeName, context),\n name: type.name,\n type: typeName,\n ...ensureCustomTitle(type.name, type.title),\n }\n}\n\n/**\n * Transforms common fields shared across all schema types\n */\nfunction transformCommonTypeFields(\n type: SchemaType & {fieldset?: string},\n typeName: string,\n context: Context,\n): Omit<ManifestSchemaType, 'name' | 'title' | 'type'> {\n const arrayProps =\n typeName === 'array' && type.jsonType === 'array' ? transformArrayMember(type, context) : {}\n\n const referenceProps = isReference(type) ? transformReference(type, retainCustomTypeProps) : {}\n const crossDatasetRefProps = isCrossDatasetReference(type)\n ? transformCrossDatasetReference(type)\n : {}\n const globalRefProps = isGlobalDocumentReference(type)\n ? transformGlobalDocumentReference(type)\n : {}\n\n const objectFields: ObjectFields =\n type.jsonType === 'object' && type.type && isCustomized(type)\n ? {\n fields: getCustomFields(type).map((objectField) => transformField(objectField, context)),\n }\n : {}\n\n return {\n ...retainCustomTypeProps(type),\n ...transformValidation(type.validation, retainSerializableProps),\n ...ensureString('description', type.description),\n ...objectFields,\n ...arrayProps,\n ...referenceProps,\n ...crossDatasetRefProps,\n ...globalRefProps,\n ...ensureConditional('readOnly', type.readOnly),\n ...ensureConditional('hidden', type.hidden),\n ...transformFieldsets(type),\n // fieldset prop gets instrumented via getCustomFields\n ...ensureString('fieldset', type.fieldset),\n ...transformBlockType(type, context, transformType),\n }\n}\n\n/**\n * Transforms fieldsets from a schema type\n */\nfunction transformFieldsets(\n type: SchemaType,\n): Record<string, never> | {fieldsets: ManifestFieldset[]} {\n if (type.jsonType !== 'object') {\n return {}\n }\n const fieldsets = type.fieldsets\n ?.filter((fs): fs is MultiFieldSet => !fs.single)\n .map((fs) => {\n const options = isRecord(fs.options) ? {options: retainSerializableProps(fs.options)} : {}\n return {\n name: fs.name,\n ...ensureCustomTitle(fs.name, fs.title),\n ...ensureString('description', fs.description),\n ...ensureConditional('readOnly', fs.readOnly),\n ...ensureConditional('hidden', fs.hidden),\n ...options,\n }\n })\n\n return fieldsets?.length ? {fieldsets} : {}\n}\n\n/**\n * Retains custom type properties that should be included in the manifest\n */\nfunction retainCustomTypeProps(type: SchemaType): Record<string, SerializableProp> {\n const manuallySerializedFields = new Set<SchemaTypeKey>([\n '__experimental_actions',\n '__experimental_formPreviewTitle',\n '__experimental_omnisearch_visibility',\n '__experimental_search',\n 'components',\n 'description',\n 'fields',\n 'fieldsets',\n //only exists on fields\n 'group',\n 'groups',\n 'hidden',\n 'icon',\n 'jsonType',\n //explicitly added\n 'name',\n 'of',\n 'orderings',\n 'preview',\n 'readOnly',\n 'title',\n 'to',\n // not serialized\n 'type',\n 'validation',\n // we know about these, but let them be generically handled\n // deprecated\n // rows (from text)\n // initialValue\n // options\n // crossDatasetReference props\n ])\n const typeWithoutManuallyHandledFields = Object.fromEntries(\n Object.entries(type).filter(\n ([key]) => !manuallySerializedFields.has(key as unknown as SchemaTypeKey),\n ),\n )\n return retainSerializableProps(typeWithoutManuallyHandledFields) as Record<\n string,\n SerializableProp\n >\n}\n\n/**\n * Retains serializable properties from an unknown value, recursively processing objects and arrays\n * @internal Exported for testing purposes only\n */\nexport function retainSerializableProps(maybeSerializable: unknown, depth = 0): SerializableProp {\n if (depth > MAX_CUSTOM_PROPERTY_DEPTH) {\n return undefined\n }\n\n if (!isDefined(maybeSerializable)) {\n return undefined\n }\n\n if (isPrimitive(maybeSerializable)) {\n // cull empty strings\n if (maybeSerializable === '') {\n return undefined\n }\n return maybeSerializable\n }\n\n // url-schemes ect..\n if (maybeSerializable instanceof RegExp) {\n return maybeSerializable.toString()\n }\n\n if (Array.isArray(maybeSerializable)) {\n const arrayItems = maybeSerializable\n .map((item) => retainSerializableProps(item, depth + 1))\n .filter((item): item is ManifestSerializable => isDefined(item))\n return arrayItems.length > 0 ? arrayItems : undefined\n }\n\n if (isRecord(maybeSerializable)) {\n const serializableEntries = Object.entries(maybeSerializable)\n .map(([key, value]) => {\n return [key, retainSerializableProps(value, depth + 1)]\n })\n .filter(([, value]) => isDefined(value))\n return serializableEntries.length > 0 ? Object.fromEntries(serializableEntries) : undefined\n }\n\n return undefined\n}\n\n/**\n * Transforms an ObjectField to its manifest representation\n */\nfunction transformField(field: ObjectField & {fieldset?: string}, context: Context): ManifestField {\n const fieldType = field.type\n const typeName = getDefinedTypeName(fieldType) ?? fieldType.name\n return {\n ...transformCommonTypeFields(fieldType, typeName, context),\n name: field.name,\n type: typeName,\n ...ensureCustomTitle(field.name, fieldType.title),\n // this prop gets added synthetically via getCustomFields\n ...ensureString('fieldset', field.fieldset),\n }\n}\n\n/**\n * Transforms array member types to their manifest representation\n */\nfunction transformArrayMember(\n arrayMember: ArraySchemaType,\n context: Context,\n): Pick<ManifestField, 'of'> {\n return {\n of: arrayMember.of.map((type) => {\n const typeName = getDefinedTypeName(type) ?? type.name\n return {\n ...transformCommonTypeFields(type, typeName, context),\n type: typeName,\n ...(typeName === type.name ? {} : {name: type.name}),\n ...ensureCustomTitle(type.name, type.title),\n }\n }),\n }\n}\n"],"names":["transformBlockType","transformCrossDatasetReference","transformGlobalDocumentReference","transformReference","getCustomFields","getDefinedTypeName","isCrossDatasetReference","isCustomized","isDefined","isGlobalDocumentReference","isPrimitive","isRecord","isReference","ensureConditional","ensureCustomTitle","ensureString","transformValidation","MAX_CUSTOM_PROPERTY_DEPTH","transformType","type","context","typeName","name","jsonType","transformCommonTypeFields","title","arrayProps","transformArrayMember","referenceProps","retainCustomTypeProps","crossDatasetRefProps","globalRefProps","objectFields","fields","map","objectField","transformField","validation","retainSerializableProps","description","readOnly","hidden","transformFieldsets","fieldset","fieldsets","filter","fs","single","options","length","manuallySerializedFields","Set","typeWithoutManuallyHandledFields","Object","fromEntries","entries","key","has","maybeSerializable","depth","undefined","RegExp","toString","Array","isArray","arrayItems","item","serializableEntries","value","field","fieldType","arrayMember","of"],"mappings":"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"}
@@ -12,10 +12,10 @@ const NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server f
12
12
  * Main MCP setup orchestration
13
13
  * Opt-out by default: runs automatically unless skip option is set
14
14
  */ export async function setupMCP(options) {
15
- const { explicit = false, skip = false } = options ?? {};
15
+ const { explicit = false, mode = 'prompt' } = options ?? {};
16
16
  // 1. Check for explicit opt-out
17
- if (skip) {
18
- ux.warn('Skipping MCP configuration due to --no-mcp flag');
17
+ if (mode === 'skip') {
18
+ mcpDebug('Skipping MCP configuration (mode: skip)');
19
19
  return {
20
20
  alreadyConfiguredEditors: [],
21
21
  configuredEditors: [],
@@ -57,8 +57,8 @@ const NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server f
57
57
  }
58
58
  // Non-actionable editors are already configured with valid credentials
59
59
  const alreadyConfiguredEditors = editors.filter((e)=>!actionable.includes(e)).map((e)=>e.name);
60
- // 5. Prompt user (shows only actionable editors, annotates auth issues)
61
- const selected = await promptForMCPSetup(actionable);
60
+ // 5. Select editors to configure prompt interactively or auto-select all
61
+ const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable);
62
62
  if (!selected || selected.length === 0) {
63
63
  // User deselected all editors
64
64
  ux.stdout('MCP configuration skipped');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * If true, skip MCP configuration entirely (e.g. --no-mcp flag).\n */\n skip?: boolean\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, skip = false} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (skip) {\n ux.warn('Skipping MCP configuration due to --no-mcp flag')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Prompt user (shows only actionable editors, annotates auth issues)\n const selected = await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n // Fall back to creating a new token\n if (!token) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","skip","warn","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","error","err","Error","String","message","editor","push","join"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * Controls how MCP setup behaves:\n * - 'prompt': Ask the user which editors to configure (default)\n * - 'auto': Auto-configure all detected editors without prompting\n * - 'skip': Skip MCP configuration entirely\n */\n mode?: 'auto' | 'prompt' | 'skip'\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, mode = 'prompt'} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (mode === 'skip') {\n mcpDebug('Skipping MCP configuration (mode: skip)')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Select editors to configure prompt interactively or auto-select all\n const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n // Fall back to creating a new token\n if (!token) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","mode","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","warn","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","error","err","Error","String","message","editor","push","join"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/schema/getExtractOptions.ts"],"sourcesContent":["import {existsSync, statSync} from 'node:fs'\nimport {extname, join, resolve} from 'node:path'\n\nimport {type CliConfig, ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ExtractSchemaCommand} from '../../commands/schema/extract.js'\n\nexport interface ExtractOptions {\n configPath: string\n enforceRequiredFields: boolean\n format: string\n outputPath: string\n watchPatterns: string[]\n workspace: string | undefined\n}\n\ninterface GetExtractionOptions {\n flags: ExtractSchemaCommand['flags']\n projectRoot: ProjectRootResult\n schemaExtraction: CliConfig['schemaExtraction']\n}\n\nexport function getExtractOptions({\n flags,\n projectRoot,\n schemaExtraction,\n}: GetExtractionOptions): ExtractOptions {\n const pathFlag = flags.path ?? schemaExtraction?.path\n let outputPath: string\n if (pathFlag) {\n const resolved = resolve(join(projectRoot.directory, pathFlag))\n const isExistingDirectory = existsSync(resolved) && statSync(resolved).isDirectory()\n\n outputPath =\n isExistingDirectory || !extname(resolved) ? join(resolved, 'schema.json') : resolved\n } else {\n outputPath = resolve(join(projectRoot.directory, 'schema.json'))\n }\n\n return {\n configPath: projectRoot.path,\n enforceRequiredFields:\n flags['enforce-required-fields'] ?? schemaExtraction?.enforceRequiredFields ?? false,\n format: flags.format ?? 'groq-type-nodes',\n outputPath,\n watchPatterns: flags['watch-patterns'] ?? schemaExtraction?.watchPatterns ?? [],\n workspace: flags.workspace ?? schemaExtraction?.workspace,\n }\n}\n"],"names":["existsSync","statSync","extname","join","resolve","getExtractOptions","flags","projectRoot","schemaExtraction","pathFlag","path","outputPath","resolved","directory","isExistingDirectory","isDirectory","configPath","enforceRequiredFields","format","watchPatterns","workspace"],"mappings":"AAAA,SAAQA,UAAU,EAAEC,QAAQ,QAAO,UAAS;AAC5C,SAAQC,OAAO,EAAEC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAqBhD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,gBAAgB,EACK;IACrB,MAAMC,WAAWH,MAAMI,IAAI,IAAIF,kBAAkBE;IACjD,IAAIC;IACJ,IAAIF,UAAU;QACZ,MAAMG,WAAWR,QAAQD,KAAKI,YAAYM,SAAS,EAAEJ;QACrD,MAAMK,sBAAsBd,WAAWY,aAAaX,SAASW,UAAUG,WAAW;QAElFJ,aACEG,uBAAuB,CAACZ,QAAQU,YAAYT,KAAKS,UAAU,iBAAiBA;IAChF,OAAO;QACLD,aAAaP,QAAQD,KAAKI,YAAYM,SAAS,EAAE;IACnD;IAEA,OAAO;QACLG,YAAYT,YAAYG,IAAI;QAC5BO,uBACEX,KAAK,CAAC,0BAA0B,IAAIE,kBAAkBS,yBAAyB;QACjFC,QAAQZ,MAAMY,MAAM,IAAI;QACxBP;QACAQ,eAAeb,KAAK,CAAC,iBAAiB,IAAIE,kBAAkBW,iBAAiB,EAAE;QAC/EC,WAAWd,MAAMc,SAAS,IAAIZ,kBAAkBY;IAClD;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/schema/getExtractOptions.ts"],"sourcesContent":["import {existsSync, statSync} from 'node:fs'\nimport {extname, join, resolve} from 'node:path'\n\nimport {type CliConfig, ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ExtractSchemaCommand} from '../../commands/schemas/extract.js'\n\nexport interface ExtractOptions {\n configPath: string\n enforceRequiredFields: boolean\n format: string\n outputPath: string\n watchPatterns: string[]\n workspace: string | undefined\n}\n\ninterface GetExtractionOptions {\n flags: ExtractSchemaCommand['flags']\n projectRoot: ProjectRootResult\n schemaExtraction: CliConfig['schemaExtraction']\n}\n\nexport function getExtractOptions({\n flags,\n projectRoot,\n schemaExtraction,\n}: GetExtractionOptions): ExtractOptions {\n const pathFlag = flags.path ?? schemaExtraction?.path\n let outputPath: string\n if (pathFlag) {\n const resolved = resolve(join(projectRoot.directory, pathFlag))\n const isExistingDirectory = existsSync(resolved) && statSync(resolved).isDirectory()\n\n outputPath =\n isExistingDirectory || !extname(resolved) ? join(resolved, 'schema.json') : resolved\n } else {\n outputPath = resolve(join(projectRoot.directory, 'schema.json'))\n }\n\n return {\n configPath: projectRoot.path,\n enforceRequiredFields:\n flags['enforce-required-fields'] ?? schemaExtraction?.enforceRequiredFields ?? false,\n format: flags.format ?? 'groq-type-nodes',\n outputPath,\n watchPatterns: flags['watch-patterns'] ?? schemaExtraction?.watchPatterns ?? [],\n workspace: flags.workspace ?? schemaExtraction?.workspace,\n }\n}\n"],"names":["existsSync","statSync","extname","join","resolve","getExtractOptions","flags","projectRoot","schemaExtraction","pathFlag","path","outputPath","resolved","directory","isExistingDirectory","isDirectory","configPath","enforceRequiredFields","format","watchPatterns","workspace"],"mappings":"AAAA,SAAQA,UAAU,EAAEC,QAAQ,QAAO,UAAS;AAC5C,SAAQC,OAAO,EAAEC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAqBhD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,gBAAgB,EACK;IACrB,MAAMC,WAAWH,MAAMI,IAAI,IAAIF,kBAAkBE;IACjD,IAAIC;IACJ,IAAIF,UAAU;QACZ,MAAMG,WAAWR,QAAQD,KAAKI,YAAYM,SAAS,EAAEJ;QACrD,MAAMK,sBAAsBd,WAAWY,aAAaX,SAASW,UAAUG,WAAW;QAElFJ,aACEG,uBAAuB,CAACZ,QAAQU,YAAYT,KAAKS,UAAU,iBAAiBA;IAChF,OAAO;QACLD,aAAaP,QAAQD,KAAKI,YAAYM,SAAS,EAAE;IACnD;IAEA,OAAO;QACLG,YAAYT,YAAYG,IAAI;QAC5BO,uBACEX,KAAK,CAAC,0BAA0B,IAAIE,kBAAkBS,yBAAyB;QACjFC,QAAQZ,MAAMY,MAAM,IAAI;QACxBP;QACAQ,eAAeb,KAAK,CAAC,iBAAiB,IAAIE,kBAAkBW,iBAAiB,EAAE;QAC/EC,WAAWd,MAAMc,SAAS,IAAIZ,kBAAkBY;IAClD;AACF"}
@@ -32,6 +32,9 @@ export class DisableBackupCommand extends SanityCommand {
32
32
  semantics: 'override'
33
33
  })
34
34
  };
35
+ static hiddenAliases = [
36
+ 'backup:disable'
37
+ ];
35
38
  async run() {
36
39
  const { args } = await this.parse(DisableBackupCommand);
37
40
  let { dataset } = args;
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/commands/backups/disable.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {setBackup} from '../../services/backup.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst disableBackupDebug = subdebug('backup:disable')\n\nexport class DisableBackupCommand extends SanityCommand<typeof DisableBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to disable backup for',\n required: false,\n }),\n }\n\n static override description = 'Disable backup for a dataset.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively disable backup for a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Disable backup for the production dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to disable backups for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['backup:disable']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DisableBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n disableBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: 1})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset)\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n try {\n await setBackup({dataset, projectId, status: false})\n\n this.log(`${styleText('green', `Disabled daily backups for dataset ${dataset}.\\n`)}`)\n this.log(\n `${styleText('yellow', 'Note: Existing backups will be retained according to your retention policy.\\n')}`,\n )\n\n disableBackupDebug(`Successfully disabled backup for dataset ${dataset}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n disableBackupDebug(`Failed to disable backup for dataset`, error)\n this.error(`Disabling dataset backup failed: ${message}`, {exit: 1})\n }\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n const err = error as Error\n disableBackupDebug(`Error fetching datasets`, err)\n this.error(`Failed to fetch datasets:\\n${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["styleText","Args","SanityCommand","subdebug","select","assertDatasetExists","promptForProject","setBackup","listDatasets","getProjectIdFlag","disableBackupDebug","DisableBackupCommand","args","dataset","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","error","message","Error","String","exit","length","promptForDataset","status","log","choices","map","name","value","err"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,MAAM,QAAO,sBAAqB;AAG1C,SAAQC,mBAAmB,QAAO,6CAA4C;AAC9E,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,SAAS,QAAO,2BAA0B;AAClD,SAAQC,YAAY,QAAO,6BAA4B;AACvD,SAAQC,gBAAgB,QAAO,4BAA2B;AAE1D,MAAMC,qBAAqBP,SAAS;AAEpC,OAAO,MAAMQ,6BAA6BT;IACxC,OAAgBU,OAAO;QACrBC,SAASZ,KAAKa,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,gCAA+B;IAE7D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAiB,CAAA;IAE5D,MAAaC,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAC,GAAG,MAAM,IAAI,CAACW,KAAK,CAACZ;QAChC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAEhB,MAAMY,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRpB,iBAAiB;oBACfqB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,IAAIC;QAEJ,IAAI;YACFA,WAAW,MAAMtB,aAAagB;QAChC,EAAE,OAAOO,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChErB,mBAAmB,CAAC,yBAAyB,EAAEsB,SAAS,EAAED;YAC1D,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QAC5D;QAEA,IAAIL,SAASM,MAAM,KAAK,GAAG;YACzB,IAAI,CAACL,KAAK,CAAC,sCAAsC;gBAACI,MAAM;YAAC;QAC3D;QAEA,IAAItB,SAAS;YACXR,oBAAoByB,UAAUjB;QAChC,OAAO;YACLA,UAAU,MAAM,IAAI,CAACwB,gBAAgB,CAACP;QACxC;QAEA,IAAI;YACF,MAAMvB,UAAU;gBAACM;gBAASW;gBAAWc,QAAQ;YAAK;YAElD,IAAI,CAACC,GAAG,CAAC,GAAGvC,UAAU,SAAS,CAAC,mCAAmC,EAAEa,QAAQ,GAAG,CAAC,GAAG;YACpF,IAAI,CAAC0B,GAAG,CACN,GAAGvC,UAAU,UAAU,kFAAkF;YAG3GU,mBAAmB,CAAC,yCAAyC,EAAEG,SAAS;QAC1E,EAAE,OAAOkB,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChErB,mBAAmB,CAAC,oCAAoC,CAAC,EAAEqB;YAC3D,IAAI,CAACA,KAAK,CAAC,CAAC,iCAAiC,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QACpE;IACF;IAEA,MAAcE,iBAAiBP,QAA0B,EAAmB;QAC1E,IAAI;YACF,MAAMU,UAAUV,SAASW,GAAG,CAAC,CAAC5B,UAAa,CAAA;oBACzC6B,MAAM7B,QAAQ6B,IAAI;oBAClBC,OAAO9B,QAAQ6B,IAAI;gBACrB,CAAA;YAEA,OAAOtC,OAAO;gBACZoC;gBACAR,SAAS;YACX;QACF,EAAE,OAAOD,OAAO;YACd,MAAMa,MAAMb;YACZrB,mBAAmB,CAAC,uBAAuB,CAAC,EAAEkC;YAC9C,IAAI,CAACb,KAAK,CAAC,CAAC,2BAA2B,EAAEa,IAAIZ,OAAO,EAAE,EAAE;gBAACG,MAAM;YAAC;QAClE;IACF;AACF"}
@@ -73,6 +73,9 @@ export class DownloadBackupCommand extends SanityCommand {
73
73
  description: 'Allows overwriting of existing backup file'
74
74
  })
75
75
  };
76
+ static hiddenAliases = [
77
+ 'backup:download'
78
+ ];
76
79
  async run() {
77
80
  const { args } = await this.parse(DownloadBackupCommand);
78
81
  let { dataset } = args;