@sanity/cli 6.1.7 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +105 -103
  2. package/dist/actions/build/buildStudio.js +1 -1
  3. package/dist/actions/build/buildStudio.js.map +1 -1
  4. package/dist/actions/debug/gatherDebugInfo.js +130 -81
  5. package/dist/actions/debug/gatherDebugInfo.js.map +1 -1
  6. package/dist/actions/debug/output.js +25 -0
  7. package/dist/actions/debug/output.js.map +1 -0
  8. package/dist/actions/debug/types.js.map +1 -1
  9. package/dist/actions/mcp/setupMCP.js +5 -5
  10. package/dist/actions/mcp/setupMCP.js.map +1 -1
  11. package/dist/actions/schema/getExtractOptions.js.map +1 -1
  12. package/dist/commands/{backup → backups}/disable.js +3 -0
  13. package/dist/commands/backups/disable.js.map +1 -0
  14. package/dist/commands/{backup → backups}/download.js +3 -0
  15. package/dist/commands/backups/download.js.map +1 -0
  16. package/dist/commands/{backup → backups}/enable.js +3 -0
  17. package/dist/commands/backups/enable.js.map +1 -0
  18. package/dist/commands/{backup → backups}/list.js +3 -0
  19. package/dist/commands/backups/list.js.map +1 -0
  20. package/dist/commands/{dataset → datasets}/alias/create.js +3 -0
  21. package/dist/commands/datasets/alias/create.js.map +1 -0
  22. package/dist/commands/{dataset → datasets}/alias/delete.js +3 -0
  23. package/dist/commands/datasets/alias/delete.js.map +1 -0
  24. package/dist/commands/{dataset → datasets}/alias/link.js +3 -0
  25. package/dist/commands/datasets/alias/link.js.map +1 -0
  26. package/dist/commands/{dataset → datasets}/alias/unlink.js +3 -0
  27. package/dist/commands/datasets/alias/unlink.js.map +1 -0
  28. package/dist/commands/{dataset → datasets}/copy.js +3 -0
  29. package/dist/commands/datasets/copy.js.map +1 -0
  30. package/dist/commands/{dataset → datasets}/create.js +3 -0
  31. package/dist/commands/datasets/create.js.map +1 -0
  32. package/dist/commands/{dataset → datasets}/delete.js +3 -0
  33. package/dist/commands/datasets/delete.js.map +1 -0
  34. package/dist/commands/{dataset → datasets}/embeddings/disable.js +3 -0
  35. package/dist/commands/datasets/embeddings/disable.js.map +1 -0
  36. package/dist/commands/{dataset → datasets}/embeddings/enable.js +3 -0
  37. package/dist/commands/datasets/embeddings/enable.js.map +1 -0
  38. package/dist/commands/{dataset → datasets}/embeddings/status.js +3 -0
  39. package/dist/commands/datasets/embeddings/status.js.map +1 -0
  40. package/dist/commands/{dataset → datasets}/export.js +3 -0
  41. package/dist/commands/datasets/export.js.map +1 -0
  42. package/dist/commands/{dataset → datasets}/import.js +3 -0
  43. package/dist/commands/datasets/import.js.map +1 -0
  44. package/dist/commands/{dataset → datasets}/list.js +3 -0
  45. package/dist/commands/datasets/list.js.map +1 -0
  46. package/dist/commands/{dataset → datasets}/visibility/get.js +3 -0
  47. package/dist/commands/datasets/visibility/get.js.map +1 -0
  48. package/dist/commands/{dataset → datasets}/visibility/set.js +3 -0
  49. package/dist/commands/datasets/visibility/set.js.map +1 -0
  50. package/dist/commands/debug.js +189 -74
  51. package/dist/commands/debug.js.map +1 -1
  52. package/dist/commands/documents/create.js +3 -0
  53. package/dist/commands/documents/create.js.map +1 -1
  54. package/dist/commands/documents/delete.js +3 -0
  55. package/dist/commands/documents/delete.js.map +1 -1
  56. package/dist/commands/documents/get.js +3 -0
  57. package/dist/commands/documents/get.js.map +1 -1
  58. package/dist/commands/documents/query.js +3 -0
  59. package/dist/commands/documents/query.js.map +1 -1
  60. package/dist/commands/documents/validate.js +3 -0
  61. package/dist/commands/documents/validate.js.map +1 -1
  62. package/dist/commands/{hook → hooks}/attempt.js +3 -0
  63. package/dist/commands/hooks/attempt.js.map +1 -0
  64. package/dist/commands/{hook → hooks}/create.js +3 -0
  65. package/dist/commands/hooks/create.js.map +1 -0
  66. package/dist/commands/{hook → hooks}/delete.js +3 -0
  67. package/dist/commands/hooks/delete.js.map +1 -0
  68. package/dist/commands/{hook → hooks}/list.js +3 -0
  69. package/dist/commands/hooks/list.js.map +1 -0
  70. package/dist/commands/{hook → hooks}/logs.js +3 -0
  71. package/dist/commands/hooks/logs.js.map +1 -0
  72. package/dist/commands/init.js +65 -13
  73. package/dist/commands/init.js.map +1 -1
  74. package/dist/commands/mcp/configure.js +3 -2
  75. package/dist/commands/mcp/configure.js.map +1 -1
  76. package/dist/commands/preview.js +1 -0
  77. package/dist/commands/preview.js.map +1 -1
  78. package/dist/commands/projects/create.js +3 -0
  79. package/dist/commands/projects/create.js.map +1 -1
  80. package/dist/commands/projects/list.js +3 -0
  81. package/dist/commands/projects/list.js.map +1 -1
  82. package/dist/commands/{schema → schemas}/delete.js +3 -0
  83. package/dist/commands/schemas/delete.js.map +1 -0
  84. package/dist/commands/{schema → schemas}/deploy.js +3 -0
  85. package/dist/commands/schemas/deploy.js.map +1 -0
  86. package/dist/commands/{schema → schemas}/extract.js +3 -0
  87. package/dist/commands/schemas/extract.js.map +1 -0
  88. package/dist/commands/{schema → schemas}/list.js +3 -0
  89. package/dist/commands/schemas/list.js.map +1 -0
  90. package/dist/commands/{schema → schemas}/validate.js +3 -0
  91. package/dist/commands/schemas/validate.js.map +1 -0
  92. package/dist/commands/tokens/add.js +3 -0
  93. package/dist/commands/tokens/add.js.map +1 -1
  94. package/dist/commands/tokens/delete.js +3 -0
  95. package/dist/commands/tokens/delete.js.map +1 -1
  96. package/dist/commands/tokens/list.js +3 -0
  97. package/dist/commands/tokens/list.js.map +1 -1
  98. package/dist/commands/users/invite.js +3 -0
  99. package/dist/commands/users/invite.js.map +1 -1
  100. package/dist/commands/users/list.js +3 -0
  101. package/dist/commands/users/list.js.map +1 -1
  102. package/dist/hooks/commandNotFound/topicAliases.js +71 -0
  103. package/dist/hooks/commandNotFound/topicAliases.js.map +1 -0
  104. package/dist/services/mcp.js +32 -44
  105. package/dist/services/mcp.js.map +1 -1
  106. package/dist/topicAliases.js +51 -0
  107. package/dist/topicAliases.js.map +1 -0
  108. package/oclif.config.js +20 -7
  109. package/oclif.manifest.json +321 -209
  110. package/package.json +22 -21
  111. package/dist/actions/debug/formatters.js +0 -22
  112. package/dist/actions/debug/formatters.js.map +0 -1
  113. package/dist/actions/debug/getGlobalConfigLocation.js +0 -7
  114. package/dist/actions/debug/getGlobalConfigLocation.js.map +0 -1
  115. package/dist/commands/backup/disable.js.map +0 -1
  116. package/dist/commands/backup/download.js.map +0 -1
  117. package/dist/commands/backup/enable.js.map +0 -1
  118. package/dist/commands/backup/list.js.map +0 -1
  119. package/dist/commands/dataset/alias/create.js.map +0 -1
  120. package/dist/commands/dataset/alias/delete.js.map +0 -1
  121. package/dist/commands/dataset/alias/link.js.map +0 -1
  122. package/dist/commands/dataset/alias/unlink.js.map +0 -1
  123. package/dist/commands/dataset/copy.js.map +0 -1
  124. package/dist/commands/dataset/create.js.map +0 -1
  125. package/dist/commands/dataset/delete.js.map +0 -1
  126. package/dist/commands/dataset/embeddings/disable.js.map +0 -1
  127. package/dist/commands/dataset/embeddings/enable.js.map +0 -1
  128. package/dist/commands/dataset/embeddings/status.js.map +0 -1
  129. package/dist/commands/dataset/export.js.map +0 -1
  130. package/dist/commands/dataset/import.js.map +0 -1
  131. package/dist/commands/dataset/list.js.map +0 -1
  132. package/dist/commands/dataset/visibility/get.js.map +0 -1
  133. package/dist/commands/dataset/visibility/set.js.map +0 -1
  134. package/dist/commands/hook/attempt.js.map +0 -1
  135. package/dist/commands/hook/create.js.map +0 -1
  136. package/dist/commands/hook/delete.js.map +0 -1
  137. package/dist/commands/hook/list.js.map +0 -1
  138. package/dist/commands/hook/logs.js.map +0 -1
  139. package/dist/commands/schema/delete.js.map +0 -1
  140. package/dist/commands/schema/deploy.js.map +0 -1
  141. package/dist/commands/schema/extract.js.map +0 -1
  142. package/dist/commands/schema/list.js.map +0 -1
  143. package/dist/commands/schema/validate.js.map +0 -1
@@ -1,23 +1,9 @@
1
1
  import { getGlobalCliClient, subdebug } from '@sanity/cli-core';
2
- import { createRequester } from '@sanity/cli-core/request';
2
+ import { isHttpError } from '@sanity/client';
3
3
  export const MCP_API_VERSION = '2025-12-09';
4
4
  export const MCP_SERVER_URL = 'https://mcp.sanity.io';
5
5
  export const MCP_JOURNEY_API_VERSION = 'v2024-02-23';
6
6
  const debug = subdebug('mcp:service');
7
- let mcpRequester;
8
- function getMCPRequester() {
9
- if (!mcpRequester) {
10
- mcpRequester = createRequester({
11
- middleware: {
12
- httpErrors: false,
13
- promise: {
14
- onlyBody: false
15
- }
16
- }
17
- });
18
- }
19
- return mcpRequester;
20
- }
21
7
  /**
22
8
  * Create a child token for MCP usage
23
9
  * This token is tied to the parent CLI token and will be invalidated
@@ -48,42 +34,44 @@ function getMCPRequester() {
48
34
  return tokenResponse.token;
49
35
  }
50
36
  /**
51
- * Validate an MCP token against the MCP server.
37
+ * Validate an MCP token by checking it against the Sanity API.
52
38
  *
53
- * MCP tokens are scoped to mcp.sanity.io and are not valid against
54
- * api.sanity.io, so we validate against the MCP server itself.
39
+ * MCP tokens are standard Sanity session tokens (`sk…`), so we validate
40
+ * by calling `/users/me` on `api.sanity.io`. A 200 means the token is
41
+ * alive; a 401/403 means it is dead and the caller should prompt for
42
+ * re-configuration.
55
43
  *
56
- * Sends a minimal POST with just the Authorization header the server
57
- * checks auth before content negotiation, so a valid token gets 406
58
- * (missing Accept header) while an invalid token gets 401. This avoids
59
- * the cost of a full initialize handshake.
44
+ * Transient errors (5xx, network failures, timeouts) are rethrown so the
45
+ * caller can decide how to handle them typically by assuming the token
46
+ * is still valid rather than falsely marking it as expired.
47
+ *
48
+ * We intentionally do NOT probe `mcp.sanity.io` because the MCP server
49
+ * lets invalid bearer tokens through for protocol-compatibility reasons,
50
+ * which causes the CLI to falsely treat dead tokens as valid.
60
51
  *
61
52
  * @internal
62
53
  */ export async function validateMCPToken(token) {
63
- const request = getMCPRequester();
64
- // Use a 2500ms timeout — long enough for VPN/proxy/distant-region latency,
65
- // short enough to not stall the init flow. If the request times out or the
66
- // server returns an unexpected status, we assume the token is valid rather
67
- // than falsely marking it as expired (see below).
68
- const res = await request({
69
- body: '{}',
70
- headers: {
71
- Authorization: `Bearer ${token}`,
72
- 'Content-Type': 'application/json'
73
- },
74
- method: 'POST',
75
- timeout: 2500,
76
- url: MCP_SERVER_URL
54
+ const client = await getGlobalCliClient({
55
+ apiVersion: MCP_API_VERSION,
56
+ requireUser: false,
57
+ token
77
58
  });
78
- // 401/403 are the only responses that definitively mean "bad token".
79
- // Everything else (406 = valid, 5xx = server issue, 2xx = unexpected)
80
- // is treated as "assume valid" — we'd rather skip a re-auth prompt
81
- // than force users to re-configure because of a transient server error.
82
- if (res.statusCode === 401 || res.statusCode === 403) {
83
- debug('MCP token validation failed with %d', res.statusCode);
84
- return false;
59
+ try {
60
+ await client.request({
61
+ timeout: 2500,
62
+ uri: '/users/me'
63
+ });
64
+ return true;
65
+ } catch (err) {
66
+ // 401/403 definitively mean "dead token"
67
+ if (isHttpError(err) && (err.statusCode === 401 || err.statusCode === 403)) {
68
+ debug('MCP token validation failed with %d', err.statusCode);
69
+ return false;
70
+ }
71
+ // Everything else (5xx, network errors, timeouts) is rethrown so the
72
+ // caller can decide — typically assumes valid rather than forcing re-auth.
73
+ throw err;
85
74
  }
86
- return true;
87
75
  }
88
76
  /**
89
77
  * Fetches the post-init MCP prompt from the Journey API and interpolates editor names.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/mcp.ts"],"sourcesContent":["import {getGlobalCliClient, subdebug} from '@sanity/cli-core'\nimport {createRequester, type Requester} from '@sanity/cli-core/request'\n\nexport const MCP_API_VERSION = '2025-12-09'\nexport const MCP_SERVER_URL = 'https://mcp.sanity.io'\nexport const MCP_JOURNEY_API_VERSION = 'v2024-02-23'\n\nconst debug = subdebug('mcp:service')\n\nlet mcpRequester: Requester | undefined\n\nfunction getMCPRequester(): Requester {\n if (!mcpRequester) {\n mcpRequester = createRequester({\n middleware: {httpErrors: false, promise: {onlyBody: false}},\n })\n }\n return mcpRequester\n}\n\ninterface PostInitPromptResponse {\n message?: string\n}\n\n/**\n * Create a child token for MCP usage\n * This token is tied to the parent CLI token and will be invalidated\n * when the parent token is invalidated (e.g., on logout)\n *\n * @returns The MCP token string\n * @internal\n */\nexport async function createMCPToken(): Promise<string> {\n const client = await getGlobalCliClient({\n apiVersion: MCP_API_VERSION,\n requireUser: true,\n })\n\n const sessionResponse = await client.request<{id: string; sid: string}>({\n body: {\n sourceId: 'sanity-mcp',\n withStamp: false,\n },\n method: 'POST',\n uri: '/auth/session/create',\n })\n\n const tokenResponse = await client.request<{label: string; token: string}>({\n method: 'GET',\n query: {sid: sessionResponse.sid},\n uri: '/auth/fetch',\n })\n\n return tokenResponse.token\n}\n\n/**\n * Validate an MCP token against the MCP server.\n *\n * MCP tokens are scoped to mcp.sanity.io and are not valid against\n * api.sanity.io, so we validate against the MCP server itself.\n *\n * Sends a minimal POST with just the Authorization header the server\n * checks auth before content negotiation, so a valid token gets 406\n * (missing Accept header) while an invalid token gets 401. This avoids\n * the cost of a full initialize handshake.\n *\n * @internal\n */\nexport async function validateMCPToken(token: string): Promise<boolean> {\n const request = getMCPRequester()\n\n // Use a 2500ms timeout long enough for VPN/proxy/distant-region latency,\n // short enough to not stall the init flow. If the request times out or the\n // server returns an unexpected status, we assume the token is valid rather\n // than falsely marking it as expired (see below).\n const res = await request({\n body: '{}',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n timeout: 2500,\n url: MCP_SERVER_URL,\n })\n\n // 401/403 are the only responses that definitively mean \"bad token\".\n // Everything else (406 = valid, 5xx = server issue, 2xx = unexpected)\n // is treated as \"assume valid\" — we'd rather skip a re-auth prompt\n // than force users to re-configure because of a transient server error.\n if (res.statusCode === 401 || res.statusCode === 403) {\n debug('MCP token validation failed with %d', res.statusCode)\n return false\n }\n\n return true\n}\n\n/**\n * Fetches the post-init MCP prompt from the Journey API and interpolates editor names.\n * Falls back to a hardcoded default if the API call fails, times out, or returns empty.\n * Text wrapped in **markers** will be formatted with cyan color.\n */\nexport async function getPostInitPrompt() {\n const client = await getGlobalCliClient({apiVersion: MCP_JOURNEY_API_VERSION, requireUser: false})\n return await client.request<PostInitPromptResponse | null>({\n method: 'GET',\n timeout: 1000,\n uri: '/journey/mcp/post-init-prompt',\n })\n}\n"],"names":["getGlobalCliClient","subdebug","createRequester","MCP_API_VERSION","MCP_SERVER_URL","MCP_JOURNEY_API_VERSION","debug","mcpRequester","getMCPRequester","middleware","httpErrors","promise","onlyBody","createMCPToken","client","apiVersion","requireUser","sessionResponse","request","body","sourceId","withStamp","method","uri","tokenResponse","query","sid","token","validateMCPToken","res","headers","Authorization","timeout","url","statusCode","getPostInitPrompt"],"mappings":"AAAA,SAAQA,kBAAkB,EAAEC,QAAQ,QAAO,mBAAkB;AAC7D,SAAQC,eAAe,QAAuB,2BAA0B;AAExE,OAAO,MAAMC,kBAAkB,aAAY;AAC3C,OAAO,MAAMC,iBAAiB,wBAAuB;AACrD,OAAO,MAAMC,0BAA0B,cAAa;AAEpD,MAAMC,QAAQL,SAAS;AAEvB,IAAIM;AAEJ,SAASC;IACP,IAAI,CAACD,cAAc;QACjBA,eAAeL,gBAAgB;YAC7BO,YAAY;gBAACC,YAAY;gBAAOC,SAAS;oBAACC,UAAU;gBAAK;YAAC;QAC5D;IACF;IACA,OAAOL;AACT;AAMA;;;;;;;CAOC,GACD,OAAO,eAAeM;IACpB,MAAMC,SAAS,MAAMd,mBAAmB;QACtCe,YAAYZ;QACZa,aAAa;IACf;IAEA,MAAMC,kBAAkB,MAAMH,OAAOI,OAAO,CAA4B;QACtEC,MAAM;YACJC,UAAU;YACVC,WAAW;QACb;QACAC,QAAQ;QACRC,KAAK;IACP;IAEA,MAAMC,gBAAgB,MAAMV,OAAOI,OAAO,CAAiC;QACzEI,QAAQ;QACRG,OAAO;YAACC,KAAKT,gBAAgBS,GAAG;QAAA;QAChCH,KAAK;IACP;IAEA,OAAOC,cAAcG,KAAK;AAC5B;AAEA;;;;;;;;;;;;CAYC,GACD,OAAO,eAAeC,iBAAiBD,KAAa;IAClD,MAAMT,UAAUV;IAEhB,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,kDAAkD;IAClD,MAAMqB,MAAM,MAAMX,QAAQ;QACxBC,MAAM;QACNW,SAAS;YACPC,eAAe,CAAC,OAAO,EAAEJ,OAAO;YAChC,gBAAgB;QAClB;QACAL,QAAQ;QACRU,SAAS;QACTC,KAAK7B;IACP;IAEA,qEAAqE;IACrE,sEAAsE;IACtE,mEAAmE;IACnE,wEAAwE;IACxE,IAAIyB,IAAIK,UAAU,KAAK,OAAOL,IAAIK,UAAU,KAAK,KAAK;QACpD5B,MAAM,uCAAuCuB,IAAIK,UAAU;QAC3D,OAAO;IACT;IAEA,OAAO;AACT;AAEA;;;;CAIC,GACD,OAAO,eAAeC;IACpB,MAAMrB,SAAS,MAAMd,mBAAmB;QAACe,YAAYV;QAAyBW,aAAa;IAAK;IAChG,OAAO,MAAMF,OAAOI,OAAO,CAAgC;QACzDI,QAAQ;QACRU,SAAS;QACTT,KAAK;IACP;AACF"}
1
+ {"version":3,"sources":["../../src/services/mcp.ts"],"sourcesContent":["import {getGlobalCliClient, subdebug} from '@sanity/cli-core'\nimport {isHttpError} from '@sanity/client'\n\nexport const MCP_API_VERSION = '2025-12-09'\nexport const MCP_SERVER_URL = 'https://mcp.sanity.io'\nexport const MCP_JOURNEY_API_VERSION = 'v2024-02-23'\n\nconst debug = subdebug('mcp:service')\n\ninterface PostInitPromptResponse {\n message?: string\n}\n\n/**\n * Create a child token for MCP usage\n * This token is tied to the parent CLI token and will be invalidated\n * when the parent token is invalidated (e.g., on logout)\n *\n * @returns The MCP token string\n * @internal\n */\nexport async function createMCPToken(): Promise<string> {\n const client = await getGlobalCliClient({\n apiVersion: MCP_API_VERSION,\n requireUser: true,\n })\n\n const sessionResponse = await client.request<{id: string; sid: string}>({\n body: {\n sourceId: 'sanity-mcp',\n withStamp: false,\n },\n method: 'POST',\n uri: '/auth/session/create',\n })\n\n const tokenResponse = await client.request<{label: string; token: string}>({\n method: 'GET',\n query: {sid: sessionResponse.sid},\n uri: '/auth/fetch',\n })\n\n return tokenResponse.token\n}\n\n/**\n * Validate an MCP token by checking it against the Sanity API.\n *\n * MCP tokens are standard Sanity session tokens (`sk…`), so we validate\n * by calling `/users/me` on `api.sanity.io`. A 200 means the token is\n * alive; a 401/403 means it is dead and the caller should prompt for\n * re-configuration.\n *\n * Transient errors (5xx, network failures, timeouts) are rethrown so the\n * caller can decide how to handle them typically by assuming the token\n * is still valid rather than falsely marking it as expired.\n *\n * We intentionally do NOT probe `mcp.sanity.io` because the MCP server\n * lets invalid bearer tokens through for protocol-compatibility reasons,\n * which causes the CLI to falsely treat dead tokens as valid.\n *\n * @internal\n */\nexport async function validateMCPToken(token: string): Promise<boolean> {\n const client = await getGlobalCliClient({\n apiVersion: MCP_API_VERSION,\n requireUser: false,\n token,\n })\n\n try {\n await client.request({timeout: 2500, uri: '/users/me'})\n return true\n } catch (err) {\n // 401/403 definitively mean \"dead token\"\n if (isHttpError(err) && (err.statusCode === 401 || err.statusCode === 403)) {\n debug('MCP token validation failed with %d', err.statusCode)\n return false\n }\n\n // Everything else (5xx, network errors, timeouts) is rethrown so the\n // caller can decide — typically assumes valid rather than forcing re-auth.\n throw err\n }\n}\n\n/**\n * Fetches the post-init MCP prompt from the Journey API and interpolates editor names.\n * Falls back to a hardcoded default if the API call fails, times out, or returns empty.\n * Text wrapped in **markers** will be formatted with cyan color.\n */\nexport async function getPostInitPrompt() {\n const client = await getGlobalCliClient({apiVersion: MCP_JOURNEY_API_VERSION, requireUser: false})\n return await client.request<PostInitPromptResponse | null>({\n method: 'GET',\n timeout: 1000,\n uri: '/journey/mcp/post-init-prompt',\n })\n}\n"],"names":["getGlobalCliClient","subdebug","isHttpError","MCP_API_VERSION","MCP_SERVER_URL","MCP_JOURNEY_API_VERSION","debug","createMCPToken","client","apiVersion","requireUser","sessionResponse","request","body","sourceId","withStamp","method","uri","tokenResponse","query","sid","token","validateMCPToken","timeout","err","statusCode","getPostInitPrompt"],"mappings":"AAAA,SAAQA,kBAAkB,EAAEC,QAAQ,QAAO,mBAAkB;AAC7D,SAAQC,WAAW,QAAO,iBAAgB;AAE1C,OAAO,MAAMC,kBAAkB,aAAY;AAC3C,OAAO,MAAMC,iBAAiB,wBAAuB;AACrD,OAAO,MAAMC,0BAA0B,cAAa;AAEpD,MAAMC,QAAQL,SAAS;AAMvB;;;;;;;CAOC,GACD,OAAO,eAAeM;IACpB,MAAMC,SAAS,MAAMR,mBAAmB;QACtCS,YAAYN;QACZO,aAAa;IACf;IAEA,MAAMC,kBAAkB,MAAMH,OAAOI,OAAO,CAA4B;QACtEC,MAAM;YACJC,UAAU;YACVC,WAAW;QACb;QACAC,QAAQ;QACRC,KAAK;IACP;IAEA,MAAMC,gBAAgB,MAAMV,OAAOI,OAAO,CAAiC;QACzEI,QAAQ;QACRG,OAAO;YAACC,KAAKT,gBAAgBS,GAAG;QAAA;QAChCH,KAAK;IACP;IAEA,OAAOC,cAAcG,KAAK;AAC5B;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,eAAeC,iBAAiBD,KAAa;IAClD,MAAMb,SAAS,MAAMR,mBAAmB;QACtCS,YAAYN;QACZO,aAAa;QACbW;IACF;IAEA,IAAI;QACF,MAAMb,OAAOI,OAAO,CAAC;YAACW,SAAS;YAAMN,KAAK;QAAW;QACrD,OAAO;IACT,EAAE,OAAOO,KAAK;QACZ,yCAAyC;QACzC,IAAItB,YAAYsB,QAASA,CAAAA,IAAIC,UAAU,KAAK,OAAOD,IAAIC,UAAU,KAAK,GAAE,GAAI;YAC1EnB,MAAM,uCAAuCkB,IAAIC,UAAU;YAC3D,OAAO;QACT;QAEA,qEAAqE;QACrE,2EAA2E;QAC3E,MAAMD;IACR;AACF;AAEA;;;;CAIC,GACD,OAAO,eAAeE;IACpB,MAAMlB,SAAS,MAAMR,mBAAmB;QAACS,YAAYJ;QAAyBK,aAAa;IAAK;IAChG,OAAO,MAAMF,OAAOI,OAAO,CAAgC;QACzDI,QAAQ;QACRO,SAAS;QACTN,KAAK;IACP;AACF"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Topic Alias Configuration
3
+ *
4
+ * Maps canonical topic names to their aliases. Used by:
5
+ * - The command_not_found hook (runtime alias resolution)
6
+ * - The check-topic-aliases script (build-time validation)
7
+ *
8
+ * Every topic with aliases must be listed here. The key is the canonical
9
+ * topic name (the actual directory under commands/), and values are
10
+ * alternative names that should resolve to it.
11
+ *
12
+ * Convention: prefer plural canonical names with singular aliases.
13
+ * datasets: ['dataset'] - "sanity dataset create" works
14
+ * cors: [] - no alias needed (no natural singular/plural pair)
15
+ *
16
+ * While the config technically supports any direction, keeping it consistent
17
+ * (plural to singular) makes the CLI predictable for users.
18
+ */ export const topicAliases = {
19
+ backups: [
20
+ 'backup'
21
+ ],
22
+ blueprints: [
23
+ 'blueprint'
24
+ ],
25
+ datasets: [
26
+ 'dataset'
27
+ ],
28
+ documents: [
29
+ 'document'
30
+ ],
31
+ functions: [
32
+ 'function'
33
+ ],
34
+ hooks: [
35
+ 'hook'
36
+ ],
37
+ projects: [
38
+ 'project'
39
+ ],
40
+ schemas: [
41
+ 'schema'
42
+ ],
43
+ tokens: [
44
+ 'token'
45
+ ],
46
+ users: [
47
+ 'user'
48
+ ]
49
+ };
50
+
51
+ //# sourceMappingURL=topicAliases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/topicAliases.ts"],"sourcesContent":["/**\n * Topic Alias Configuration\n *\n * Maps canonical topic names to their aliases. Used by:\n * - The command_not_found hook (runtime alias resolution)\n * - The check-topic-aliases script (build-time validation)\n *\n * Every topic with aliases must be listed here. The key is the canonical\n * topic name (the actual directory under commands/), and values are\n * alternative names that should resolve to it.\n *\n * Convention: prefer plural canonical names with singular aliases.\n * datasets: ['dataset'] - \"sanity dataset create\" works\n * cors: [] - no alias needed (no natural singular/plural pair)\n *\n * While the config technically supports any direction, keeping it consistent\n * (plural to singular) makes the CLI predictable for users.\n */\nexport const topicAliases: Record<string, string[]> = {\n backups: ['backup'],\n blueprints: ['blueprint'],\n datasets: ['dataset'],\n documents: ['document'],\n functions: ['function'],\n hooks: ['hook'],\n projects: ['project'],\n schemas: ['schema'],\n tokens: ['token'],\n users: ['user'],\n}\n"],"names":["topicAliases","backups","blueprints","datasets","documents","functions","hooks","projects","schemas","tokens","users"],"mappings":"AAAA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,MAAMA,eAAyC;IACpDC,SAAS;QAAC;KAAS;IACnBC,YAAY;QAAC;KAAY;IACzBC,UAAU;QAAC;KAAU;IACrBC,WAAW;QAAC;KAAW;IACvBC,WAAW;QAAC;KAAW;IACvBC,OAAO;QAAC;KAAO;IACfC,UAAU;QAAC;KAAU;IACrBC,SAAS;QAAC;KAAS;IACnBC,QAAQ;QAAC;KAAQ;IACjBC,OAAO;QAAC;KAAO;AACjB,EAAC"}
package/oclif.config.js CHANGED
@@ -4,6 +4,7 @@ export default {
4
4
  dirname: 'sanity',
5
5
  helpClass: './dist/SanityHelp',
6
6
  hooks: {
7
+ command_not_found: ['./dist/hooks/commandNotFound/topicAliases.js'],
7
8
  init: ['./dist/hooks/init/checkForUpdates.js'],
8
9
  prerun: [
9
10
  './dist/hooks/prerun/injectEnvVariables.js',
@@ -11,12 +12,24 @@ export default {
11
12
  './dist/hooks/prerun/warnings.js',
12
13
  ],
13
14
  },
14
- plugins: [
15
- '@oclif/plugin-help',
16
- '@oclif/plugin-not-found',
17
- '@sanity/runtime-cli',
18
- '@sanity/migrate',
19
- '@sanity/codegen',
20
- ],
15
+ plugins: ['@oclif/plugin-help', '@sanity/runtime-cli', '@sanity/migrate', '@sanity/codegen'],
16
+ topics: {
17
+ backups: {description: 'Manage dataset backups'},
18
+ cors: {description: 'Manage CORS origins for your project'},
19
+ datasets: {description: 'Manage datasets in your project'},
20
+ docs: {description: 'Browse and search Sanity documentation'},
21
+ documents: {description: 'Manage documents in a dataset'},
22
+ graphql: {description: 'Manage GraphQL APIs for your project'},
23
+ hooks: {description: 'Manage webhooks for your project'},
24
+ manifest: {description: 'Extract studio configuration as JSON manifests'},
25
+ mcp: {description: 'Configure Sanity MCP server for AI editors'},
26
+ media: {description: 'Manage media assets and aspect definitions'},
27
+ openapi: {description: 'Manage OpenAPI specifications'},
28
+ projects: {description: 'Manage Sanity projects'},
29
+ schemas: {description: 'Manage and validate schemas'},
30
+ telemetry: {description: 'Manage telemetry consent'},
31
+ tokens: {description: 'Manage API tokens for your project'},
32
+ users: {description: 'Manage project users and invitations'},
33
+ },
21
34
  topicSeparator: ' ',
22
35
  }