@sanity/cli 6.0.0-alpha.17 → 6.0.0-alpha.19

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 (249) hide show
  1. package/README.md +833 -912
  2. package/dist/SanityHelp.js +74 -21
  3. package/dist/SanityHelp.js.map +1 -1
  4. package/dist/actions/build/buildApp.js +42 -15
  5. package/dist/actions/build/buildApp.js.map +1 -1
  6. package/dist/actions/build/buildStudio.js +21 -9
  7. package/dist/actions/build/buildStudio.js.map +1 -1
  8. package/dist/actions/build/buildVendorDependencies.js +3 -16
  9. package/dist/actions/build/buildVendorDependencies.js.map +1 -1
  10. package/dist/actions/build/checkStudioDependencyVersions.js +7 -7
  11. package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
  12. package/dist/actions/build/createExternalFromImportMap.js +1 -1
  13. package/dist/actions/build/createExternalFromImportMap.js.map +1 -1
  14. package/dist/actions/build/determineBasePath.js +5 -2
  15. package/dist/actions/build/determineBasePath.js.map +1 -1
  16. package/dist/actions/build/getViteConfig.js +47 -4
  17. package/dist/actions/build/getViteConfig.js.map +1 -1
  18. package/dist/actions/build/handlePrereleaseVersions.js +44 -0
  19. package/dist/actions/build/handlePrereleaseVersions.js.map +1 -0
  20. package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js +1 -0
  21. package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js.map +1 -1
  22. package/dist/actions/build/types.js.map +1 -1
  23. package/dist/actions/build/writeSanityRuntime.js +4 -3
  24. package/dist/actions/build/writeSanityRuntime.js.map +1 -1
  25. package/dist/actions/dataset/create.js +7 -1
  26. package/dist/actions/dataset/create.js.map +1 -1
  27. package/dist/actions/dataset/resolveDataset.js +26 -0
  28. package/dist/actions/dataset/resolveDataset.js.map +1 -0
  29. package/dist/actions/deploy/deployApp.js +1 -8
  30. package/dist/actions/deploy/deployApp.js.map +1 -1
  31. package/dist/actions/deploy/deployStudio.js +1 -0
  32. package/dist/actions/deploy/deployStudio.js.map +1 -1
  33. package/dist/actions/dev/getDashboardAppUrl.js +48 -0
  34. package/dist/actions/dev/getDashboardAppUrl.js.map +1 -0
  35. package/dist/actions/dev/getDevServerConfig.js +7 -3
  36. package/dist/actions/dev/getDevServerConfig.js.map +1 -1
  37. package/dist/actions/dev/startAppDevServer.js +3 -3
  38. package/dist/actions/dev/startAppDevServer.js.map +1 -1
  39. package/dist/actions/dev/startStudioDevServer.js +12 -12
  40. package/dist/actions/dev/startStudioDevServer.js.map +1 -1
  41. package/dist/actions/documents/types.js.map +1 -1
  42. package/dist/actions/documents/validate.js +11 -2
  43. package/dist/actions/documents/validate.js.map +1 -1
  44. package/dist/actions/documents/validateDocuments.worker.js +2 -2
  45. package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
  46. package/dist/actions/documents/validation/reporters/jsonReporter.js +1 -1
  47. package/dist/actions/documents/validation/reporters/jsonReporter.js.map +1 -1
  48. package/dist/actions/documents/validation/reporters/ndjsonReporter.js +1 -1
  49. package/dist/actions/documents/validation/reporters/ndjsonReporter.js.map +1 -1
  50. package/dist/actions/graphql/SchemaError.js +1 -1
  51. package/dist/actions/graphql/SchemaError.js.map +1 -1
  52. package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js +540 -0
  53. package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js.map +1 -0
  54. package/dist/actions/graphql/__tests__/fixtures/test-studio.js +1143 -0
  55. package/dist/actions/graphql/__tests__/fixtures/test-studio.js.map +1 -0
  56. package/dist/actions/graphql/__tests__/fixtures/union-refs.js +591 -0
  57. package/dist/actions/graphql/__tests__/fixtures/union-refs.js.map +1 -0
  58. package/dist/actions/graphql/__tests__/helpers.js +23 -0
  59. package/dist/actions/graphql/__tests__/helpers.js.map +1 -0
  60. package/dist/actions/graphql/extractFromSanitySchema.js +2 -1
  61. package/dist/actions/graphql/extractFromSanitySchema.js.map +1 -1
  62. package/dist/actions/graphql/gen1/generateTypeFilters.js +1 -1
  63. package/dist/actions/graphql/gen1/generateTypeFilters.js.map +1 -1
  64. package/dist/actions/graphql/gen1/generateTypeQueries.js +2 -1
  65. package/dist/actions/graphql/gen1/generateTypeQueries.js.map +1 -1
  66. package/dist/actions/graphql/gen2/generateTypeQueries.js +1 -1
  67. package/dist/actions/graphql/gen2/generateTypeQueries.js.map +1 -1
  68. package/dist/actions/graphql/gen3/generateTypeQueries.js +1 -1
  69. package/dist/actions/graphql/gen3/generateTypeQueries.js.map +1 -1
  70. package/dist/actions/graphql/getGraphQLAPIs.js +2 -10
  71. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  72. package/dist/actions/graphql/getGraphQLAPIs.worker.js +1 -1
  73. package/dist/actions/graphql/getGraphQLAPIs.worker.js.map +1 -1
  74. package/dist/actions/graphql/types.js.map +1 -1
  75. package/dist/actions/init/bootstrapLocalTemplate.js +1 -1
  76. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  77. package/dist/actions/manifest/extractAppManifest.js.map +1 -1
  78. package/dist/actions/manifest/extractManifest.js +1 -22
  79. package/dist/actions/manifest/extractManifest.js.map +1 -1
  80. package/dist/actions/manifest/types.js.map +1 -1
  81. package/dist/actions/schema/deploySchemas.js +57 -80
  82. package/dist/actions/schema/deploySchemas.js.map +1 -1
  83. package/dist/actions/schema/extractSanityWorkspace.worker.js +24 -0
  84. package/dist/actions/schema/extractSanityWorkspace.worker.js.map +1 -0
  85. package/dist/actions/schema/extractSchemaWatcher.js +9 -7
  86. package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
  87. package/dist/actions/schema/matchSchemaPattern.js +22 -0
  88. package/dist/actions/schema/matchSchemaPattern.js.map +1 -0
  89. package/dist/actions/schema/runSchemaExtraction.js.map +1 -1
  90. package/dist/actions/schema/types.js +4 -0
  91. package/dist/actions/schema/types.js.map +1 -1
  92. package/dist/actions/schema/utils/schemaStoreValidation.js +1 -7
  93. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  94. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +1 -1
  95. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -1
  96. package/dist/actions/schema/watchExtractSchema.js +2 -1
  97. package/dist/actions/schema/watchExtractSchema.js.map +1 -1
  98. package/dist/actions/versions/getFormatters.js +1 -1
  99. package/dist/actions/versions/getFormatters.js.map +1 -1
  100. package/dist/commands/backup/disable.js +0 -6
  101. package/dist/commands/backup/disable.js.map +1 -1
  102. package/dist/commands/backup/download.js +0 -6
  103. package/dist/commands/backup/download.js.map +1 -1
  104. package/dist/commands/backup/enable.js +0 -6
  105. package/dist/commands/backup/enable.js.map +1 -1
  106. package/dist/commands/backup/list.js +4 -7
  107. package/dist/commands/backup/list.js.map +1 -1
  108. package/dist/commands/cors/add.js +0 -6
  109. package/dist/commands/cors/add.js.map +1 -1
  110. package/dist/commands/cors/delete.js +0 -6
  111. package/dist/commands/cors/delete.js.map +1 -1
  112. package/dist/commands/cors/list.js +0 -6
  113. package/dist/commands/cors/list.js.map +1 -1
  114. package/dist/commands/dataset/alias/create.js +23 -7
  115. package/dist/commands/dataset/alias/create.js.map +1 -1
  116. package/dist/commands/dataset/alias/delete.js +17 -7
  117. package/dist/commands/dataset/alias/delete.js.map +1 -1
  118. package/dist/commands/dataset/alias/link.js +17 -7
  119. package/dist/commands/dataset/alias/link.js.map +1 -1
  120. package/dist/commands/dataset/alias/unlink.js +17 -7
  121. package/dist/commands/dataset/alias/unlink.js.map +1 -1
  122. package/dist/commands/dataset/copy.js +42 -30
  123. package/dist/commands/dataset/copy.js.map +1 -1
  124. package/dist/commands/dataset/create.js +29 -7
  125. package/dist/commands/dataset/create.js.map +1 -1
  126. package/dist/commands/dataset/delete.js +13 -7
  127. package/dist/commands/dataset/delete.js.map +1 -1
  128. package/dist/commands/dataset/embeddings/disable.js +74 -0
  129. package/dist/commands/dataset/embeddings/disable.js.map +1 -0
  130. package/dist/commands/dataset/embeddings/enable.js +138 -0
  131. package/dist/commands/dataset/embeddings/enable.js.map +1 -0
  132. package/dist/commands/dataset/embeddings/status.js +69 -0
  133. package/dist/commands/dataset/embeddings/status.js.map +1 -0
  134. package/dist/commands/dataset/export.js +30 -18
  135. package/dist/commands/dataset/export.js.map +1 -1
  136. package/dist/commands/dataset/list.js +19 -7
  137. package/dist/commands/dataset/list.js.map +1 -1
  138. package/dist/commands/dataset/visibility/get.js +15 -7
  139. package/dist/commands/dataset/visibility/get.js.map +1 -1
  140. package/dist/commands/dataset/visibility/set.js +19 -7
  141. package/dist/commands/dataset/visibility/set.js.map +1 -1
  142. package/dist/commands/debug.js +2 -1
  143. package/dist/commands/debug.js.map +1 -1
  144. package/dist/commands/documents/create.js +2 -7
  145. package/dist/commands/documents/create.js.map +1 -1
  146. package/dist/commands/documents/delete.js +0 -6
  147. package/dist/commands/documents/delete.js.map +1 -1
  148. package/dist/commands/documents/get.js +0 -6
  149. package/dist/commands/documents/get.js.map +1 -1
  150. package/dist/commands/documents/query.js +0 -6
  151. package/dist/commands/documents/query.js.map +1 -1
  152. package/dist/commands/graphql/deploy.js +1 -1
  153. package/dist/commands/graphql/deploy.js.map +1 -1
  154. package/dist/commands/graphql/list.js +0 -6
  155. package/dist/commands/graphql/list.js.map +1 -1
  156. package/dist/commands/graphql/undeploy.js +0 -6
  157. package/dist/commands/graphql/undeploy.js.map +1 -1
  158. package/dist/commands/hook/attempt.js +0 -6
  159. package/dist/commands/hook/attempt.js.map +1 -1
  160. package/dist/commands/hook/create.js +0 -6
  161. package/dist/commands/hook/create.js.map +1 -1
  162. package/dist/commands/hook/delete.js +0 -6
  163. package/dist/commands/hook/delete.js.map +1 -1
  164. package/dist/commands/hook/list.js +0 -6
  165. package/dist/commands/hook/list.js.map +1 -1
  166. package/dist/commands/hook/logs.js +1 -7
  167. package/dist/commands/hook/logs.js.map +1 -1
  168. package/dist/commands/init.js +13 -7
  169. package/dist/commands/init.js.map +1 -1
  170. package/dist/commands/manage.js +0 -1
  171. package/dist/commands/manage.js.map +1 -1
  172. package/dist/commands/media/create-aspect.js +1 -1
  173. package/dist/commands/media/create-aspect.js.map +1 -1
  174. package/dist/commands/media/delete-aspect.js +0 -6
  175. package/dist/commands/media/delete-aspect.js.map +1 -1
  176. package/dist/commands/media/deploy-aspect.js +1 -6
  177. package/dist/commands/media/deploy-aspect.js.map +1 -1
  178. package/dist/commands/media/export.js +0 -6
  179. package/dist/commands/media/export.js.map +1 -1
  180. package/dist/commands/media/import.js +0 -6
  181. package/dist/commands/media/import.js.map +1 -1
  182. package/dist/commands/projects/list.js +2 -1
  183. package/dist/commands/projects/list.js.map +1 -1
  184. package/dist/commands/schema/delete.js +0 -6
  185. package/dist/commands/schema/delete.js.map +1 -1
  186. package/dist/commands/schema/deploy.js +11 -27
  187. package/dist/commands/schema/deploy.js.map +1 -1
  188. package/dist/commands/tokens/add.js +0 -6
  189. package/dist/commands/tokens/add.js.map +1 -1
  190. package/dist/commands/tokens/delete.js +0 -6
  191. package/dist/commands/tokens/delete.js.map +1 -1
  192. package/dist/commands/tokens/list.js +0 -6
  193. package/dist/commands/tokens/list.js.map +1 -1
  194. package/dist/commands/users/invite.js +0 -6
  195. package/dist/commands/users/invite.js.map +1 -1
  196. package/dist/commands/users/list.js +1 -7
  197. package/dist/commands/users/list.js.map +1 -1
  198. package/dist/commands/versions.js +1 -1
  199. package/dist/commands/versions.js.map +1 -1
  200. package/dist/exports/index.d.ts +62 -2
  201. package/dist/exports/index.js.map +1 -1
  202. package/dist/prompts/promptForProject.js +64 -0
  203. package/dist/prompts/promptForProject.js.map +1 -0
  204. package/dist/prompts/selectMediaLibrary.js +1 -1
  205. package/dist/prompts/selectMediaLibrary.js.map +1 -1
  206. package/dist/server/devServer.js +4 -2
  207. package/dist/server/devServer.js.map +1 -1
  208. package/dist/server/vite/plugin-schema-extraction.js +201 -0
  209. package/dist/server/vite/plugin-schema-extraction.js.map +1 -0
  210. package/dist/server/vite/plugin-typegen.js +217 -0
  211. package/dist/server/vite/plugin-typegen.js.map +1 -0
  212. package/dist/services/datasets.js +7 -5
  213. package/dist/services/datasets.js.map +1 -1
  214. package/dist/services/embeddings.js +25 -0
  215. package/dist/services/embeddings.js.map +1 -0
  216. package/dist/services/grants.js +13 -0
  217. package/dist/services/grants.js.map +1 -0
  218. package/dist/services/graphql.js.map +1 -1
  219. package/dist/services/schemas.js +1 -1
  220. package/dist/services/schemas.js.map +1 -1
  221. package/dist/types/grants.js +3 -0
  222. package/dist/types/grants.js.map +1 -0
  223. package/dist/types.js.map +1 -1
  224. package/dist/util/checkProjectPermissions.js +21 -0
  225. package/dist/util/checkProjectPermissions.js.map +1 -0
  226. package/dist/util/compareDependencyVersions.js +28 -7
  227. package/dist/util/compareDependencyVersions.js.map +1 -1
  228. package/dist/util/errorMessages.js +0 -1
  229. package/dist/util/errorMessages.js.map +1 -1
  230. package/dist/util/getSharedServerConfig.js +1 -0
  231. package/dist/util/getSharedServerConfig.js.map +1 -1
  232. package/dist/util/packageManager/getPeerDependencies.js +44 -0
  233. package/dist/util/packageManager/getPeerDependencies.js.map +1 -0
  234. package/dist/util/sharedFlags.js +19 -0
  235. package/dist/util/sharedFlags.js.map +1 -0
  236. package/dist/util/toForwardSlashes.js +8 -0
  237. package/dist/util/toForwardSlashes.js.map +1 -0
  238. package/oclif.manifest.json +639 -379
  239. package/package.json +23 -22
  240. package/dist/actions/dev/getCoreAppUrl.js +0 -10
  241. package/dist/actions/dev/getCoreAppUrl.js.map +0 -1
  242. package/dist/actions/schema/schemaStoreTypes.js +0 -19
  243. package/dist/actions/schema/schemaStoreTypes.js.map +0 -1
  244. package/dist/actions/schema/utils/manifestExtractor.js +0 -29
  245. package/dist/actions/schema/utils/manifestExtractor.js.map +0 -1
  246. package/dist/actions/schema/utils/manifestReader.js +0 -71
  247. package/dist/actions/schema/utils/manifestReader.js.map +0 -1
  248. package/dist/util/workerChannels.js +0 -172
  249. package/dist/util/workerChannels.js.map +0 -1
@@ -0,0 +1,138 @@
1
+ import { styleText } from 'node:util';
2
+ import { Args, Flags } from '@oclif/core';
3
+ import { SanityCommand, subdebug, waitForAsync } from '@sanity/cli-core';
4
+ import { spinner } from '@sanity/cli-core/ux';
5
+ import { resolveDataset } from '../../../actions/dataset/resolveDataset.js';
6
+ import { promptForProject } from '../../../prompts/promptForProject.js';
7
+ import { getEmbeddingsSettings, setEmbeddingsSettings } from '../../../services/embeddings.js';
8
+ import { projectIdFlag } from '../../../util/sharedFlags.js';
9
+ const debug = subdebug('dataset:embeddings:enable');
10
+ const INITIAL_POLL_INTERVAL_MS = 10_000;
11
+ const MAX_POLL_INTERVAL_MS = 10 * 60 * 1000;
12
+ const POLL_TIMEOUT_MS = 24 * 60 * 60 * 1000;
13
+ export class DatasetEmbeddingsEnableCommand extends SanityCommand {
14
+ static args = {
15
+ dataset: Args.string({
16
+ description: 'Dataset name to enable embeddings for',
17
+ required: false
18
+ })
19
+ };
20
+ static description = 'Enable embeddings for a dataset';
21
+ static examples = [
22
+ {
23
+ command: '<%= config.bin %> <%= command.id %> production',
24
+ description: 'Enable embeddings for the production dataset'
25
+ },
26
+ {
27
+ command: '<%= config.bin %> <%= command.id %> production --projection "{ title, body }"',
28
+ description: 'Enable embeddings with a specific projection'
29
+ },
30
+ {
31
+ command: '<%= config.bin %> <%= command.id %> production --wait',
32
+ description: 'Enable embeddings and wait for processing to complete'
33
+ }
34
+ ];
35
+ static flags = {
36
+ ...projectIdFlag,
37
+ projection: Flags.string({
38
+ description: 'GROQ projection defining which fields to embed (e.g. "{ title, body }")',
39
+ required: false
40
+ }),
41
+ wait: Flags.boolean({
42
+ default: false,
43
+ description: 'Wait for embeddings processing to complete before returning'
44
+ })
45
+ };
46
+ async run() {
47
+ const { args, flags } = await this.parse(DatasetEmbeddingsEnableCommand);
48
+ let { dataset } = args;
49
+ const { projection, wait } = flags;
50
+ const projectId = await this.getProjectId({
51
+ fallback: ()=>promptForProject({
52
+ requiredPermissions: [
53
+ {
54
+ grant: 'read',
55
+ permission: 'sanity.project.datasets'
56
+ },
57
+ {
58
+ grant: 'update',
59
+ permission: 'sanity.project.datasets'
60
+ }
61
+ ]
62
+ })
63
+ });
64
+ try {
65
+ ;
66
+ ({ dataset } = await resolveDataset({
67
+ dataset,
68
+ projectId
69
+ }));
70
+ } catch (error) {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ debug(`Failed to resolve dataset: ${message}`, error);
73
+ this.error(message, {
74
+ exit: 1
75
+ });
76
+ }
77
+ try {
78
+ await setEmbeddingsSettings({
79
+ dataset,
80
+ enabled: true,
81
+ projectId,
82
+ projection
83
+ });
84
+ } catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ debug(`Failed to enable embeddings: ${message}`, error);
87
+ this.error(`Failed to enable embeddings: ${message}`, {
88
+ exit: 1
89
+ });
90
+ }
91
+ this.log(styleText('green', `Embeddings enabled for dataset ${dataset}.`));
92
+ if (projection) {
93
+ this.log(`Projection: ${projection}`);
94
+ }
95
+ if (wait) {
96
+ await this.waitForReady(projectId, dataset);
97
+ } else {
98
+ this.log('Processing documents in the background. Use --wait to wait for completion.');
99
+ }
100
+ }
101
+ async waitForReady(projectId, dataset) {
102
+ const spin = spinner('Waiting for embeddings to be ready...').start();
103
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
104
+ let interval = INITIAL_POLL_INTERVAL_MS;
105
+ while(Date.now() < deadline){
106
+ await waitForAsync(interval);
107
+ interval = Math.min(interval * 1.5, MAX_POLL_INTERVAL_MS);
108
+ let settings;
109
+ try {
110
+ settings = await getEmbeddingsSettings(projectId, dataset);
111
+ } catch (error) {
112
+ const message = error instanceof Error ? error.message : String(error);
113
+ spin.fail('Failed while waiting for embeddings.');
114
+ this.error(`Failed while waiting for embeddings: ${message}`, {
115
+ exit: 1
116
+ });
117
+ }
118
+ debug(`Poll status: ${settings.status}, next interval: ${Math.round(interval)}ms`);
119
+ if (settings.status === 'ready') {
120
+ spin.succeed('Embeddings ready.');
121
+ return;
122
+ }
123
+ if (settings.status !== 'updating') {
124
+ spin.fail(`Unexpected status: ${settings.status}`);
125
+ this.error(`Embeddings entered unexpected status: ${settings.status}`, {
126
+ exit: 1
127
+ });
128
+ }
129
+ spin.text = 'Still processing...';
130
+ }
131
+ spin.fail('Timed out waiting for embeddings.');
132
+ this.error('Timed out. Check status with: sanity dataset embeddings status', {
133
+ exit: 1
134
+ });
135
+ }
136
+ }
137
+
138
+ //# sourceMappingURL=enable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/commands/dataset/embeddings/enable.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug, waitForAsync} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {resolveDataset} from '../../../actions/dataset/resolveDataset.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {getEmbeddingsSettings, setEmbeddingsSettings} from '../../../services/embeddings.js'\nimport {projectIdFlag} from '../../../util/sharedFlags.js'\n\nconst debug = subdebug('dataset:embeddings:enable')\n\nconst INITIAL_POLL_INTERVAL_MS = 10_000\nconst MAX_POLL_INTERVAL_MS = 10 * 60 * 1000\nconst POLL_TIMEOUT_MS = 24 * 60 * 60 * 1000\n\nexport class DatasetEmbeddingsEnableCommand extends SanityCommand<\n typeof DatasetEmbeddingsEnableCommand\n> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to enable embeddings for',\n required: false,\n }),\n }\n\n static override description = 'Enable embeddings for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Enable embeddings for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --projection \"{ title, body }\"',\n description: 'Enable embeddings with a specific projection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --wait',\n description: 'Enable embeddings and wait for processing to complete',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n projection: Flags.string({\n description: 'GROQ projection defining which fields to embed (e.g. \"{ title, body }\")',\n required: false,\n }),\n wait: Flags.boolean({\n default: false,\n description: 'Wait for embeddings processing to complete before returning',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetEmbeddingsEnableCommand)\n let {dataset} = args\n const {projection, wait} = flags\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 try {\n ;({dataset} = await resolveDataset({dataset, projectId}))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to resolve dataset: ${message}`, error)\n this.error(message, {exit: 1})\n }\n\n try {\n await setEmbeddingsSettings({dataset, enabled: true, projectId, projection})\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to enable embeddings: ${message}`, error)\n this.error(`Failed to enable embeddings: ${message}`, {exit: 1})\n }\n\n this.log(styleText('green', `Embeddings enabled for dataset ${dataset}.`))\n if (projection) {\n this.log(`Projection: ${projection}`)\n }\n\n if (wait) {\n await this.waitForReady(projectId, dataset)\n } else {\n this.log('Processing documents in the background. Use --wait to wait for completion.')\n }\n }\n\n private async waitForReady(projectId: string, dataset: string): Promise<void> {\n const spin = spinner('Waiting for embeddings to be ready...').start()\n const deadline = Date.now() + POLL_TIMEOUT_MS\n let interval = INITIAL_POLL_INTERVAL_MS\n\n while (Date.now() < deadline) {\n await waitForAsync(interval)\n interval = Math.min(interval * 1.5, MAX_POLL_INTERVAL_MS)\n\n let settings\n try {\n settings = await getEmbeddingsSettings(projectId, dataset)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n spin.fail('Failed while waiting for embeddings.')\n this.error(`Failed while waiting for embeddings: ${message}`, {exit: 1})\n }\n debug(`Poll status: ${settings.status}, next interval: ${Math.round(interval)}ms`)\n\n if (settings.status === 'ready') {\n spin.succeed('Embeddings ready.')\n return\n }\n\n if (settings.status !== 'updating') {\n spin.fail(`Unexpected status: ${settings.status}`)\n this.error(`Embeddings entered unexpected status: ${settings.status}`, {exit: 1})\n }\n\n spin.text = 'Still processing...'\n }\n\n spin.fail('Timed out waiting for embeddings.')\n this.error('Timed out. Check status with: sanity dataset embeddings status', {exit: 1})\n }\n}\n"],"names":["styleText","Args","Flags","SanityCommand","subdebug","waitForAsync","spinner","resolveDataset","promptForProject","getEmbeddingsSettings","setEmbeddingsSettings","projectIdFlag","debug","INITIAL_POLL_INTERVAL_MS","MAX_POLL_INTERVAL_MS","POLL_TIMEOUT_MS","DatasetEmbeddingsEnableCommand","args","dataset","string","description","required","examples","command","flags","projection","wait","boolean","default","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","error","message","Error","String","exit","enabled","log","waitForReady","spin","start","deadline","Date","now","interval","Math","min","settings","fail","status","round","succeed","text"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,EAAEC,YAAY,QAAO,mBAAkB;AACtE,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,cAAc,QAAO,6CAA4C;AACzE,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,qBAAqB,EAAEC,qBAAqB,QAAO,kCAAiC;AAC5F,SAAQC,aAAa,QAAO,+BAA8B;AAE1D,MAAMC,QAAQR,SAAS;AAEvB,MAAMS,2BAA2B;AACjC,MAAMC,uBAAuB,KAAK,KAAK;AACvC,MAAMC,kBAAkB,KAAK,KAAK,KAAK;AAEvC,OAAO,MAAMC,uCAAuCb;IAGlD,OAAgBc,OAAO;QACrBC,SAASjB,KAAKkB,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGb,aAAa;QAChBc,YAAYvB,MAAMiB,MAAM,CAAC;YACvBC,aAAa;YACbC,UAAU;QACZ;QACAK,MAAMxB,MAAMyB,OAAO,CAAC;YAClBC,SAAS;YACTR,aAAa;QACf;IACF,EAAC;IAED,MAAaS,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACM,KAAK,CAACd;QACvC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAChB,MAAM,EAACQ,UAAU,EAAEC,IAAI,EAAC,GAAGF;QAE3B,MAAMO,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRzB,iBAAiB;oBACf0B,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,IAAI;;YACA,CAAA,EAAClB,OAAO,EAAC,GAAG,MAAMX,eAAe;gBAACW;gBAASa;YAAS,EAAC;QACzD,EAAE,OAAOM,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChEzB,MAAM,CAAC,2BAA2B,EAAE0B,SAAS,EAAED;YAC/C,IAAI,CAACA,KAAK,CAACC,SAAS;gBAACG,MAAM;YAAC;QAC9B;QAEA,IAAI;YACF,MAAM/B,sBAAsB;gBAACQ;gBAASwB,SAAS;gBAAMX;gBAAWN;YAAU;QAC5E,EAAE,OAAOY,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChEzB,MAAM,CAAC,6BAA6B,EAAE0B,SAAS,EAAED;YACjD,IAAI,CAACA,KAAK,CAAC,CAAC,6BAA6B,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QAChE;QAEA,IAAI,CAACE,GAAG,CAAC3C,UAAU,SAAS,CAAC,+BAA+B,EAAEkB,QAAQ,CAAC,CAAC;QACxE,IAAIO,YAAY;YACd,IAAI,CAACkB,GAAG,CAAC,CAAC,YAAY,EAAElB,YAAY;QACtC;QAEA,IAAIC,MAAM;YACR,MAAM,IAAI,CAACkB,YAAY,CAACb,WAAWb;QACrC,OAAO;YACL,IAAI,CAACyB,GAAG,CAAC;QACX;IACF;IAEA,MAAcC,aAAab,SAAiB,EAAEb,OAAe,EAAiB;QAC5E,MAAM2B,OAAOvC,QAAQ,yCAAyCwC,KAAK;QACnE,MAAMC,WAAWC,KAAKC,GAAG,KAAKlC;QAC9B,IAAImC,WAAWrC;QAEf,MAAOmC,KAAKC,GAAG,KAAKF,SAAU;YAC5B,MAAM1C,aAAa6C;YACnBA,WAAWC,KAAKC,GAAG,CAACF,WAAW,KAAKpC;YAEpC,IAAIuC;YACJ,IAAI;gBACFA,WAAW,MAAM5C,sBAAsBsB,WAAWb;YACpD,EAAE,OAAOmB,OAAO;gBACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;gBAChEQ,KAAKS,IAAI,CAAC;gBACV,IAAI,CAACjB,KAAK,CAAC,CAAC,qCAAqC,EAAEC,SAAS,EAAE;oBAACG,MAAM;gBAAC;YACxE;YACA7B,MAAM,CAAC,aAAa,EAAEyC,SAASE,MAAM,CAAC,iBAAiB,EAAEJ,KAAKK,KAAK,CAACN,UAAU,EAAE,CAAC;YAEjF,IAAIG,SAASE,MAAM,KAAK,SAAS;gBAC/BV,KAAKY,OAAO,CAAC;gBACb;YACF;YAEA,IAAIJ,SAASE,MAAM,KAAK,YAAY;gBAClCV,KAAKS,IAAI,CAAC,CAAC,mBAAmB,EAAED,SAASE,MAAM,EAAE;gBACjD,IAAI,CAAClB,KAAK,CAAC,CAAC,sCAAsC,EAAEgB,SAASE,MAAM,EAAE,EAAE;oBAACd,MAAM;gBAAC;YACjF;YAEAI,KAAKa,IAAI,GAAG;QACd;QAEAb,KAAKS,IAAI,CAAC;QACV,IAAI,CAACjB,KAAK,CAAC,kEAAkE;YAACI,MAAM;QAAC;IACvF;AACF"}
@@ -0,0 +1,69 @@
1
+ import { Args } from '@oclif/core';
2
+ import { SanityCommand, subdebug } from '@sanity/cli-core';
3
+ import { resolveDataset } from '../../../actions/dataset/resolveDataset.js';
4
+ import { promptForProject } from '../../../prompts/promptForProject.js';
5
+ import { getEmbeddingsSettings } from '../../../services/embeddings.js';
6
+ import { projectIdFlag } from '../../../util/sharedFlags.js';
7
+ const debug = subdebug('dataset:embeddings:status');
8
+ export class DatasetEmbeddingsStatusCommand extends SanityCommand {
9
+ static args = {
10
+ dataset: Args.string({
11
+ description: 'The name of the dataset to check embeddings status for',
12
+ required: false
13
+ })
14
+ };
15
+ static description = 'Show embeddings settings and status for a dataset';
16
+ static examples = [
17
+ {
18
+ command: '<%= config.bin %> <%= command.id %> production',
19
+ description: 'Show embeddings status for the production dataset'
20
+ }
21
+ ];
22
+ static flags = {
23
+ ...projectIdFlag
24
+ };
25
+ async run() {
26
+ const { args } = await this.parse(DatasetEmbeddingsStatusCommand);
27
+ let { dataset } = args;
28
+ const projectId = await this.getProjectId({
29
+ fallback: ()=>promptForProject({
30
+ requiredPermissions: [
31
+ {
32
+ grant: 'read',
33
+ permission: 'sanity.project.datasets'
34
+ }
35
+ ]
36
+ })
37
+ });
38
+ try {
39
+ ;
40
+ ({ dataset } = await resolveDataset({
41
+ dataset,
42
+ projectId
43
+ }));
44
+ } catch (error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ debug(`Failed to resolve dataset: ${message}`, error);
47
+ this.error(message, {
48
+ exit: 1
49
+ });
50
+ }
51
+ try {
52
+ const settings = await getEmbeddingsSettings(projectId, dataset);
53
+ this.log(`Dataset: ${dataset}`);
54
+ this.log(`Embeddings: ${settings.enabled ? 'enabled' : 'disabled'}`);
55
+ if (settings.projection) {
56
+ this.log(`Projection: ${settings.projection}`);
57
+ }
58
+ this.log(`Status: ${settings.status}`);
59
+ } catch (error) {
60
+ const message = error instanceof Error ? error.message : String(error);
61
+ debug(`Failed to get embeddings settings: ${message}`, error);
62
+ this.error(`Failed to get embeddings settings: ${message}`, {
63
+ exit: 1
64
+ });
65
+ }
66
+ }
67
+ }
68
+
69
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/commands/dataset/embeddings/status.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {resolveDataset} from '../../../actions/dataset/resolveDataset.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {getEmbeddingsSettings} from '../../../services/embeddings.js'\nimport {projectIdFlag} from '../../../util/sharedFlags.js'\n\nconst debug = subdebug('dataset:embeddings:status')\n\nexport class DatasetEmbeddingsStatusCommand extends SanityCommand<\n typeof DatasetEmbeddingsStatusCommand\n> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to check embeddings status for',\n required: false,\n }),\n }\n\n static override description = 'Show embeddings settings and status for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Show embeddings status for the production dataset',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n }\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetEmbeddingsStatusCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n try {\n ;({dataset} = await resolveDataset({dataset, projectId}))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to resolve dataset: ${message}`, error)\n this.error(message, {exit: 1})\n }\n\n try {\n const settings = await getEmbeddingsSettings(projectId, dataset)\n\n this.log(`Dataset: ${dataset}`)\n this.log(`Embeddings: ${settings.enabled ? 'enabled' : 'disabled'}`)\n if (settings.projection) {\n this.log(`Projection: ${settings.projection}`)\n }\n this.log(`Status: ${settings.status}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to get embeddings settings: ${message}`, error)\n this.error(`Failed to get embeddings settings: ${message}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","SanityCommand","subdebug","resolveDataset","promptForProject","getEmbeddingsSettings","projectIdFlag","debug","DatasetEmbeddingsStatusCommand","args","dataset","string","description","required","examples","command","flags","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","error","message","Error","String","exit","settings","log","enabled","projection","status"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,cAAc,QAAO,6CAA4C;AACzE,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,qBAAqB,QAAO,kCAAiC;AACrE,SAAQC,aAAa,QAAO,+BAA8B;AAE1D,MAAMC,QAAQL,SAAS;AAEvB,OAAO,MAAMM,uCAAuCP;IAGlD,OAAgBQ,OAAO;QACrBC,SAASV,KAAKW,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oDAAmD;IAEjF,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,aAAa;IAClB,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACR,IAAI,EAAC,GAAG,MAAM,IAAI,CAACS,KAAK,CAACV;QAChC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAEhB,MAAMU,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRjB,iBAAiB;oBACfkB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,IAAI;;YACA,CAAA,EAACd,OAAO,EAAC,GAAG,MAAMP,eAAe;gBAACO;gBAASS;YAAS,EAAC;QACzD,EAAE,OAAOM,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChElB,MAAM,CAAC,2BAA2B,EAAEmB,SAAS,EAAED;YAC/C,IAAI,CAACA,KAAK,CAACC,SAAS;gBAACG,MAAM;YAAC;QAC9B;QAEA,IAAI;YACF,MAAMC,WAAW,MAAMzB,sBAAsBc,WAAWT;YAExD,IAAI,CAACqB,GAAG,CAAC,CAAC,YAAY,EAAErB,SAAS;YACjC,IAAI,CAACqB,GAAG,CAAC,CAAC,YAAY,EAAED,SAASE,OAAO,GAAG,YAAY,YAAY;YACnE,IAAIF,SAASG,UAAU,EAAE;gBACvB,IAAI,CAACF,GAAG,CAAC,CAAC,YAAY,EAAED,SAASG,UAAU,EAAE;YAC/C;YACA,IAAI,CAACF,GAAG,CAAC,CAAC,YAAY,EAAED,SAASI,MAAM,EAAE;QAC3C,EAAE,OAAOT,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChElB,MAAM,CAAC,mCAAmC,EAAEmB,SAAS,EAAED;YACvD,IAAI,CAACA,KAAK,CAAC,CAAC,mCAAmC,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QACtE;IACF;AACF"}
@@ -1,15 +1,16 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { Args, Flags } from '@oclif/core';
4
- import { getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
4
+ import { getProjectCliClient, ProjectRootNotFoundError, SanityCommand, subdebug } from '@sanity/cli-core';
5
5
  import { boxen, input, spinner } from '@sanity/cli-core/ux';
6
6
  import { exportDataset } from '@sanity/export';
7
7
  import prettyMs from 'pretty-ms';
8
8
  import { validateDatasetName } from '../../actions/dataset/validateDatasetName.js';
9
9
  import { promptForDataset } from '../../prompts/promptForDataset.js';
10
+ import { promptForProject } from '../../prompts/promptForProject.js';
10
11
  import { listDatasets } from '../../services/datasets.js';
11
12
  import { absolutify } from '../../util/absolutify.js';
12
- import { NO_PROJECT_ID } from '../../util/errorMessages.js';
13
+ import { projectIdFlag } from '../../util/sharedFlags.js';
13
14
  const noop = ()=>null;
14
15
  const exportDebug = subdebug('dataset:export');
15
16
  export class DatasetExportCommand extends SanityCommand {
@@ -43,6 +44,7 @@ export class DatasetExportCommand extends SanityCommand {
43
44
  }
44
45
  ];
45
46
  static flags = {
47
+ ...projectIdFlag,
46
48
  'asset-concurrency': Flags.integer({
47
49
  default: 8,
48
50
  description: 'Concurrent number of asset downloads'
@@ -83,13 +85,16 @@ export class DatasetExportCommand extends SanityCommand {
83
85
  const { args, flags } = await this.parse(DatasetExportCommand);
84
86
  const { destination: targetDestination, name: targetDataset } = args;
85
87
  // Get project configuration
86
- const cliConfig = await this.getCliConfig();
87
- const projectId = await this.getProjectId();
88
- if (!projectId) {
89
- this.error(NO_PROJECT_ID, {
90
- exit: 1
91
- });
92
- }
88
+ const projectId = await this.getProjectId({
89
+ fallback: ()=>promptForProject({
90
+ requiredPermissions: [
91
+ {
92
+ grant: 'read',
93
+ permission: 'sanity.project.datasets'
94
+ }
95
+ ]
96
+ })
97
+ });
93
98
  const projectClient = await getProjectCliClient({
94
99
  apiVersion: '2023-05-26',
95
100
  projectId,
@@ -106,10 +111,17 @@ export class DatasetExportCommand extends SanityCommand {
106
111
  }
107
112
  // Determine dataset name
108
113
  let dataset = targetDataset;
109
- try {
110
- if (!dataset) {
111
- // Get default dataset from config
112
- const defaultDataset = cliConfig.api?.dataset;
114
+ if (!dataset) {
115
+ try {
116
+ // Get default dataset from config (only available when running from a project directory)
117
+ let defaultDataset;
118
+ try {
119
+ const cliConfig = await this.getCliConfig();
120
+ defaultDataset = cliConfig.api?.dataset;
121
+ } catch (err) {
122
+ if (!(err instanceof ProjectRootNotFoundError)) throw err;
123
+ // Not inside a project directory — no default dataset available
124
+ }
113
125
  if (defaultDataset) {
114
126
  dataset = defaultDataset;
115
127
  this.log(`Using default dataset: ${dataset}`);
@@ -119,12 +131,12 @@ export class DatasetExportCommand extends SanityCommand {
119
131
  datasets
120
132
  });
121
133
  }
134
+ } catch (error) {
135
+ exportDebug('Error selecting dataset', error);
136
+ this.error(`Failed to select dataset:\n${error instanceof Error ? error.message : error}`, {
137
+ exit: 1
138
+ });
122
139
  }
123
- } catch (error) {
124
- exportDebug('Error selecting dataset', error);
125
- this.error(`Failed to select dataset:\n${error instanceof Error ? error.message : error}`, {
126
- exit: 1
127
- });
128
140
  }
129
141
  // Validate dataset name
130
142
  const dsError = validateDatasetName(dataset);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/dataset/export.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {type Writable} from 'node:stream'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {boxen, input, spinner} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {exportDataset, type ExportOptions, type ExportProgress} from '@sanity/export'\nimport prettyMs from 'pretty-ms'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {absolutify} from '../../util/absolutify.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst noop = () => null\nconst exportDebug = subdebug('dataset:export')\n\nexport class DatasetExportCommand extends SanityCommand<typeof DatasetExportCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to export',\n }),\n // Args are order dependent\n // eslint-disable-next-line perfectionist/sort-objects\n destination: Args.string({\n description: 'Output destination file path',\n }),\n }\n\n static override description =\n 'Export dataset to local filesystem as a gzipped tarball. Assets failing with HTTP status codes 401, 403 and 404 upon download are ignored and excluded from export.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> moviedb localPath.tar.gz',\n description: 'Export dataset \"moviedb\" to localPath.tar.gz',\n },\n {\n command: '<%= config.bin %> <%= command.id %> moviedb assetless.tar.gz --no-assets',\n description: 'Export dataset without assets',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --raw',\n description: 'Export raw documents without asset reference rewriting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --types products,shops',\n description: 'Export specific document types',\n },\n ]\n\n static override flags = {\n 'asset-concurrency': Flags.integer({\n default: 8,\n description: 'Concurrent number of asset downloads',\n }),\n mode: Flags.string({\n default: 'stream',\n description:\n 'Mode to export documents with `cursor` might be more performant for larger datasets, but might not be as accurate if the dataset is being modified during export',\n options: ['stream', 'cursor'],\n }),\n 'no-assets': Flags.boolean({\n default: false,\n description: 'Export only non-asset documents and remove references to image assets',\n }),\n 'no-compress': Flags.boolean({\n default: false,\n description: 'Skips compressing tarball entries (still generates a gzip file)',\n }),\n 'no-drafts': Flags.boolean({\n default: false,\n description: 'Export only published versions of documents',\n }),\n overwrite: Flags.boolean({\n default: false,\n description: 'Overwrite any file with the same name',\n }),\n raw: Flags.boolean({\n default: false,\n description: 'Extract only documents, without rewriting asset references',\n }),\n types: Flags.string({\n description: 'Defines which document types to export (comma-separated)',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetExportCommand)\n const {destination: targetDestination, name: targetDataset} = args\n\n // Get project configuration\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId()\n\n if (!projectId) {\n this.error(NO_PROJECT_ID, {\n exit: 1,\n })\n }\n\n const projectClient = await getProjectCliClient({\n apiVersion: '2023-05-26',\n projectId,\n requireUser: true,\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n exportDebug('Error listing datasets', error)\n this.error(`Failed to list datasets:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n\n // Determine dataset name\n let dataset = targetDataset\n try {\n if (!dataset) {\n // Get default dataset from config\n const defaultDataset = cliConfig.api?.dataset\n if (defaultDataset) {\n dataset = defaultDataset\n this.log(`Using default dataset: ${dataset}`)\n } else {\n dataset = await promptForDataset({allowCreation: false, datasets})\n }\n }\n } catch (error) {\n exportDebug('Error selecting dataset', error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n\n // Validate dataset name\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n // Verify existence of dataset before trying to export from it\n if (!datasets.some((set) => set.name === dataset)) {\n this.error(`Dataset with name \"${dataset}\" not found`, {exit: 1})\n }\n\n this.log(\n boxen(\n `Exporting from:\nprojectId: ${projectId.padEnd(44)}\ndataset: ${dataset.padEnd(46)}`,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n // Determine output path\n let destinationPath = targetDestination\n if (!destinationPath) {\n destinationPath = await this.promptForDestination({dataset})\n }\n\n const outputPath = await this.getOutputPath(destinationPath, dataset, flags)\n if (!outputPath) {\n this.error('Cancelled', {exit: 1})\n }\n\n // Prepare export options\n const {fail, onProgress, succeed} = this.createProgressHandler()\n const exportOptions: ExportOptions = {\n assetConcurrency: flags['asset-concurrency'],\n assets: !flags['no-assets'],\n client: projectClient,\n compress: !flags['no-compress'],\n dataset,\n drafts: !flags['no-drafts'],\n mode: flags.mode === 'cursor' || flags.mode === 'stream' ? flags.mode : undefined,\n onProgress,\n outputPath,\n raw: flags.raw,\n types: flags.types ? flags.types.split(',') : undefined,\n }\n\n const start = Date.now()\n try {\n await exportDataset(exportOptions)\n succeed()\n this.log(`Export finished (${prettyMs(Date.now() - start)})`)\n } catch (error) {\n fail()\n const err = error instanceof Error ? error : new Error(String(error))\n exportDebug('Export failed', err)\n this.error(`Export failed: ${err.message}`, {exit: 1})\n }\n }\n\n private createProgressHandler() {\n let currentSpinner: ReturnType<typeof spinner> | null = null\n let currentStep = ''\n\n const onProgress = (progress: ExportProgress) => {\n if (progress.step !== currentStep) {\n // Complete previous step\n succeed()\n\n // Start new step\n currentStep = progress.step\n currentSpinner = spinner(progress.step).start()\n } else if (progress.step === currentStep && progress.update && currentSpinner) {\n // Update current step with progress info\n currentSpinner.text = `${progress.step} (${progress.current}/${progress.total})`\n }\n }\n\n const succeed = () => {\n currentSpinner?.succeed()\n }\n\n const fail = () => {\n currentSpinner?.fail()\n }\n\n return {fail, onProgress, succeed}\n }\n\n private async getOutputPath(\n destination: string,\n dataset: string,\n flags: {overwrite?: boolean},\n ): Promise<string | Writable> {\n if (destination === '-') {\n return process.stdout\n }\n\n const dstPath = path.isAbsolute(destination)\n ? destination\n : path.resolve(process.cwd(), destination)\n\n const dstStats = await fs.stat(dstPath).catch(noop)\n const looksLikeFile = dstStats ? dstStats.isFile() : path.basename(dstPath).includes('.')\n\n if (!dstStats) {\n const createPath = looksLikeFile ? path.dirname(dstPath) : dstPath\n try {\n await fs.mkdir(createPath, {recursive: true})\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n const errorWithCode = err as Error & {code?: string}\n if (errorWithCode.code === 'EACCES') {\n this.error(\n `Permission denied: Cannot create directory \"${createPath}\". Please check write permissions.`,\n {\n exit: 1,\n },\n )\n } else {\n this.error(`Failed to create directory \"${createPath}\": ${err.message}`, {\n exit: 1,\n })\n }\n }\n }\n\n const finalPath = looksLikeFile ? dstPath : path.join(dstPath, `${dataset}.tar.gz`)\n const finalPathStats = await fs.stat(finalPath).catch(noop)\n\n if (!flags.overwrite && finalPathStats && finalPathStats.isFile()) {\n this.error(`File \"${finalPath}\" already exists. Use --overwrite flag to overwrite it.`, {\n exit: 1,\n })\n }\n\n return finalPath\n }\n\n private promptForDestination(options: {dataset: string; workDir?: string}): Promise<string> {\n const {dataset, workDir = process.cwd()} = options\n\n const defaultPath = path.join(workDir, `${dataset}.tar.gz`)\n\n return input({\n default: defaultPath,\n message: 'Output path:',\n transformer: (value: string) => absolutify(value.trim()),\n validate: (value: string) => {\n const trimmed = value.trim()\n if (!trimmed) {\n return 'Please provide a valid output path'\n }\n return true\n },\n })\n }\n}\n"],"names":["fs","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","boxen","input","spinner","exportDataset","prettyMs","validateDatasetName","promptForDataset","listDatasets","absolutify","NO_PROJECT_ID","noop","exportDebug","DatasetExportCommand","args","name","string","description","destination","examples","command","flags","integer","default","mode","options","boolean","overwrite","raw","types","run","parse","targetDestination","targetDataset","cliConfig","getCliConfig","projectId","getProjectId","error","exit","projectClient","apiVersion","requireUser","datasets","Error","message","dataset","defaultDataset","api","log","allowCreation","dsError","some","set","padEnd","borderColor","borderStyle","destinationPath","promptForDestination","outputPath","getOutputPath","fail","onProgress","succeed","createProgressHandler","exportOptions","assetConcurrency","assets","client","compress","drafts","undefined","split","start","Date","now","err","String","currentSpinner","currentStep","progress","step","update","text","current","total","process","stdout","dstPath","isAbsolute","resolve","cwd","dstStats","stat","catch","looksLikeFile","isFile","basename","includes","createPath","dirname","mkdir","recursive","errorWithCode","code","finalPath","join","finalPathStats","workDir","defaultPath","transformer","value","trim","validate","trimmed"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/dataset/export.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {type Writable} from 'node:stream'\n\nimport {Args, Flags} from '@oclif/core'\nimport {\n getProjectCliClient,\n ProjectRootNotFoundError,\n SanityCommand,\n subdebug,\n} from '@sanity/cli-core'\nimport {boxen, input, spinner} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {exportDataset, type ExportOptions, type ExportProgress} from '@sanity/export'\nimport prettyMs from 'pretty-ms'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {absolutify} from '../../util/absolutify.js'\nimport {projectIdFlag} from '../../util/sharedFlags.js'\n\nconst noop = () => null\nconst exportDebug = subdebug('dataset:export')\n\nexport class DatasetExportCommand extends SanityCommand<typeof DatasetExportCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to export',\n }),\n // Args are order dependent\n // eslint-disable-next-line perfectionist/sort-objects\n destination: Args.string({\n description: 'Output destination file path',\n }),\n }\n\n static override description =\n 'Export dataset to local filesystem as a gzipped tarball. Assets failing with HTTP status codes 401, 403 and 404 upon download are ignored and excluded from export.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> moviedb localPath.tar.gz',\n description: 'Export dataset \"moviedb\" to localPath.tar.gz',\n },\n {\n command: '<%= config.bin %> <%= command.id %> moviedb assetless.tar.gz --no-assets',\n description: 'Export dataset without assets',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --raw',\n description: 'Export raw documents without asset reference rewriting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --types products,shops',\n description: 'Export specific document types',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n 'asset-concurrency': Flags.integer({\n default: 8,\n description: 'Concurrent number of asset downloads',\n }),\n mode: Flags.string({\n default: 'stream',\n description:\n 'Mode to export documents with `cursor` might be more performant for larger datasets, but might not be as accurate if the dataset is being modified during export',\n options: ['stream', 'cursor'],\n }),\n 'no-assets': Flags.boolean({\n default: false,\n description: 'Export only non-asset documents and remove references to image assets',\n }),\n 'no-compress': Flags.boolean({\n default: false,\n description: 'Skips compressing tarball entries (still generates a gzip file)',\n }),\n 'no-drafts': Flags.boolean({\n default: false,\n description: 'Export only published versions of documents',\n }),\n overwrite: Flags.boolean({\n default: false,\n description: 'Overwrite any file with the same name',\n }),\n raw: Flags.boolean({\n default: false,\n description: 'Extract only documents, without rewriting asset references',\n }),\n types: Flags.string({\n description: 'Defines which document types to export (comma-separated)',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetExportCommand)\n const {destination: targetDestination, name: targetDataset} = args\n\n // Get project configuration\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const projectClient = await getProjectCliClient({\n apiVersion: '2023-05-26',\n projectId,\n requireUser: true,\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n exportDebug('Error listing datasets', error)\n this.error(`Failed to list datasets:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n\n // Determine dataset name\n let dataset = targetDataset\n if (!dataset) {\n try {\n // Get default dataset from config (only available when running from a project directory)\n let defaultDataset: string | undefined\n try {\n const cliConfig = await this.getCliConfig()\n defaultDataset = cliConfig.api?.dataset\n } catch (err) {\n if (!(err instanceof ProjectRootNotFoundError)) throw err\n // Not inside a project directory — no default dataset available\n }\n\n if (defaultDataset) {\n dataset = defaultDataset\n this.log(`Using default dataset: ${dataset}`)\n } else {\n dataset = await promptForDataset({allowCreation: false, datasets})\n }\n } catch (error) {\n exportDebug('Error selecting dataset', error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n }\n\n // Validate dataset name\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n // Verify existence of dataset before trying to export from it\n if (!datasets.some((set) => set.name === dataset)) {\n this.error(`Dataset with name \"${dataset}\" not found`, {exit: 1})\n }\n\n this.log(\n boxen(\n `Exporting from:\nprojectId: ${projectId.padEnd(44)}\ndataset: ${dataset.padEnd(46)}`,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n // Determine output path\n let destinationPath = targetDestination\n if (!destinationPath) {\n destinationPath = await this.promptForDestination({dataset})\n }\n\n const outputPath = await this.getOutputPath(destinationPath, dataset, flags)\n if (!outputPath) {\n this.error('Cancelled', {exit: 1})\n }\n\n // Prepare export options\n const {fail, onProgress, succeed} = this.createProgressHandler()\n const exportOptions: ExportOptions = {\n assetConcurrency: flags['asset-concurrency'],\n assets: !flags['no-assets'],\n client: projectClient,\n compress: !flags['no-compress'],\n dataset,\n drafts: !flags['no-drafts'],\n mode: flags.mode === 'cursor' || flags.mode === 'stream' ? flags.mode : undefined,\n onProgress,\n outputPath,\n raw: flags.raw,\n types: flags.types ? flags.types.split(',') : undefined,\n }\n\n const start = Date.now()\n try {\n await exportDataset(exportOptions)\n succeed()\n this.log(`Export finished (${prettyMs(Date.now() - start)})`)\n } catch (error) {\n fail()\n const err = error instanceof Error ? error : new Error(String(error))\n exportDebug('Export failed', err)\n this.error(`Export failed: ${err.message}`, {exit: 1})\n }\n }\n\n private createProgressHandler() {\n let currentSpinner: ReturnType<typeof spinner> | null = null\n let currentStep = ''\n\n const onProgress = (progress: ExportProgress) => {\n if (progress.step !== currentStep) {\n // Complete previous step\n succeed()\n\n // Start new step\n currentStep = progress.step\n currentSpinner = spinner(progress.step).start()\n } else if (progress.step === currentStep && progress.update && currentSpinner) {\n // Update current step with progress info\n currentSpinner.text = `${progress.step} (${progress.current}/${progress.total})`\n }\n }\n\n const succeed = () => {\n currentSpinner?.succeed()\n }\n\n const fail = () => {\n currentSpinner?.fail()\n }\n\n return {fail, onProgress, succeed}\n }\n\n private async getOutputPath(\n destination: string,\n dataset: string,\n flags: {overwrite?: boolean},\n ): Promise<string | Writable> {\n if (destination === '-') {\n return process.stdout\n }\n\n const dstPath = path.isAbsolute(destination)\n ? destination\n : path.resolve(process.cwd(), destination)\n\n const dstStats = await fs.stat(dstPath).catch(noop)\n const looksLikeFile = dstStats ? dstStats.isFile() : path.basename(dstPath).includes('.')\n\n if (!dstStats) {\n const createPath = looksLikeFile ? path.dirname(dstPath) : dstPath\n try {\n await fs.mkdir(createPath, {recursive: true})\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n const errorWithCode = err as Error & {code?: string}\n if (errorWithCode.code === 'EACCES') {\n this.error(\n `Permission denied: Cannot create directory \"${createPath}\". Please check write permissions.`,\n {\n exit: 1,\n },\n )\n } else {\n this.error(`Failed to create directory \"${createPath}\": ${err.message}`, {\n exit: 1,\n })\n }\n }\n }\n\n const finalPath = looksLikeFile ? dstPath : path.join(dstPath, `${dataset}.tar.gz`)\n const finalPathStats = await fs.stat(finalPath).catch(noop)\n\n if (!flags.overwrite && finalPathStats && finalPathStats.isFile()) {\n this.error(`File \"${finalPath}\" already exists. Use --overwrite flag to overwrite it.`, {\n exit: 1,\n })\n }\n\n return finalPath\n }\n\n private promptForDestination(options: {dataset: string; workDir?: string}): Promise<string> {\n const {dataset, workDir = process.cwd()} = options\n\n const defaultPath = path.join(workDir, `${dataset}.tar.gz`)\n\n return input({\n default: defaultPath,\n message: 'Output path:',\n transformer: (value: string) => absolutify(value.trim()),\n validate: (value: string) => {\n const trimmed = value.trim()\n if (!trimmed) {\n return 'Please provide a valid output path'\n }\n return true\n },\n })\n }\n}\n"],"names":["fs","path","Args","Flags","getProjectCliClient","ProjectRootNotFoundError","SanityCommand","subdebug","boxen","input","spinner","exportDataset","prettyMs","validateDatasetName","promptForDataset","promptForProject","listDatasets","absolutify","projectIdFlag","noop","exportDebug","DatasetExportCommand","args","name","string","description","destination","examples","command","flags","integer","default","mode","options","boolean","overwrite","raw","types","run","parse","targetDestination","targetDataset","projectId","getProjectId","fallback","requiredPermissions","grant","permission","projectClient","apiVersion","requireUser","datasets","error","Error","message","exit","dataset","defaultDataset","cliConfig","getCliConfig","api","err","log","allowCreation","dsError","some","set","padEnd","borderColor","borderStyle","destinationPath","promptForDestination","outputPath","getOutputPath","fail","onProgress","succeed","createProgressHandler","exportOptions","assetConcurrency","assets","client","compress","drafts","undefined","split","start","Date","now","String","currentSpinner","currentStep","progress","step","update","text","current","total","process","stdout","dstPath","isAbsolute","resolve","cwd","dstStats","stat","catch","looksLikeFile","isFile","basename","includes","createPath","dirname","mkdir","recursive","errorWithCode","code","finalPath","join","finalPathStats","workDir","defaultPath","transformer","value","trim","validate","trimmed"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { promptForProject } from '../../prompts/promptForProject.js';
2
3
  import { listDatasetAliases, listDatasets } from '../../services/datasets.js';
3
- import { NO_PROJECT_ID } from '../../util/errorMessages.js';
4
+ import { projectIdFlag } from '../../util/sharedFlags.js';
4
5
  const listDatasetDebug = subdebug('dataset:list');
5
6
  export class ListDatasetCommand extends SanityCommand {
6
7
  static description = 'List datasets of your project';
@@ -8,15 +9,26 @@ export class ListDatasetCommand extends SanityCommand {
8
9
  {
9
10
  command: '<%= config.bin %> <%= command.id %>',
10
11
  description: 'List datasets of your project'
12
+ },
13
+ {
14
+ command: '<%= config.bin %> <%= command.id %> --project-id abc123',
15
+ description: 'List datasets for a specific project'
11
16
  }
12
17
  ];
18
+ static flags = {
19
+ ...projectIdFlag
20
+ };
13
21
  async run() {
14
- const projectId = await this.getProjectId();
15
- if (!projectId) {
16
- this.error(NO_PROJECT_ID, {
17
- exit: 1
18
- });
19
- }
22
+ const projectId = await this.getProjectId({
23
+ fallback: ()=>promptForProject({
24
+ requiredPermissions: [
25
+ {
26
+ grant: 'read',
27
+ permission: 'sanity.project.datasets'
28
+ }
29
+ ]
30
+ })
31
+ });
20
32
  const [datasets, aliases] = await Promise.allSettled([
21
33
  listDatasets(projectId),
22
34
  listDatasetAliases(projectId)
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/dataset/list.ts"],"sourcesContent":["import {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {listDatasetAliases, listDatasets} from '../../services/datasets.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst listDatasetDebug = subdebug('dataset:list')\n\nexport class ListDatasetCommand extends SanityCommand<typeof ListDatasetCommand> {\n static override description = 'List datasets of your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List datasets of your project',\n },\n ]\n\n public async run(): Promise<void> {\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n const [datasets, aliases] = await Promise.allSettled([\n listDatasets(projectId),\n listDatasetAliases(projectId),\n ])\n\n if (datasets.status === 'rejected') {\n const err = datasets.reason as Error\n listDatasetDebug(`Error listing datasets for project ${projectId}`, err)\n this.error(`Dataset list retrieval failed: ${err.message}`, {exit: 1})\n }\n\n const datasetList = datasets.value\n if (datasetList.length === 0) {\n this.log('No datasets found for this project.')\n } else {\n for (const dataset of datasetList) {\n this.log(dataset.name)\n }\n }\n\n if (aliases.status === 'fulfilled' && aliases.value.length > 0) {\n for (const alias of aliases.value) {\n const targetDataset = alias.datasetName || '<unlinked>'\n this.log(`~${alias.name} -> ${targetDataset}`)\n }\n } else if (aliases.status === 'rejected') {\n listDatasetDebug(`Warning: Could not fetch aliases for project ${projectId}`, aliases.reason)\n }\n }\n}\n"],"names":["SanityCommand","subdebug","listDatasetAliases","listDatasets","NO_PROJECT_ID","listDatasetDebug","ListDatasetCommand","description","examples","command","run","projectId","getProjectId","error","exit","datasets","aliases","Promise","allSettled","status","err","reason","message","datasetList","value","length","log","dataset","name","alias","targetDataset","datasetName"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,kBAAkB,EAAEC,YAAY,QAAO,6BAA4B;AAC3E,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,mBAAmBJ,SAAS;AAElC,OAAO,MAAMK,2BAA2BN;IACtC,OAAgBO,cAAc,gCAA+B;IAE7D,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAqB;QAChC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACT,eAAe;gBAACU,MAAM;YAAC;QACpC;QAEA,MAAM,CAACC,UAAUC,QAAQ,GAAG,MAAMC,QAAQC,UAAU,CAAC;YACnDf,aAAaQ;YACbT,mBAAmBS;SACpB;QAED,IAAII,SAASI,MAAM,KAAK,YAAY;YAClC,MAAMC,MAAML,SAASM,MAAM;YAC3BhB,iBAAiB,CAAC,mCAAmC,EAAEM,WAAW,EAAES;YACpE,IAAI,CAACP,KAAK,CAAC,CAAC,+BAA+B,EAAEO,IAAIE,OAAO,EAAE,EAAE;gBAACR,MAAM;YAAC;QACtE;QAEA,MAAMS,cAAcR,SAASS,KAAK;QAClC,IAAID,YAAYE,MAAM,KAAK,GAAG;YAC5B,IAAI,CAACC,GAAG,CAAC;QACX,OAAO;YACL,KAAK,MAAMC,WAAWJ,YAAa;gBACjC,IAAI,CAACG,GAAG,CAACC,QAAQC,IAAI;YACvB;QACF;QAEA,IAAIZ,QAAQG,MAAM,KAAK,eAAeH,QAAQQ,KAAK,CAACC,MAAM,GAAG,GAAG;YAC9D,KAAK,MAAMI,SAASb,QAAQQ,KAAK,CAAE;gBACjC,MAAMM,gBAAgBD,MAAME,WAAW,IAAI;gBAC3C,IAAI,CAACL,GAAG,CAAC,CAAC,CAAC,EAAEG,MAAMD,IAAI,CAAC,IAAI,EAAEE,eAAe;YAC/C;QACF,OAAO,IAAId,QAAQG,MAAM,KAAK,YAAY;YACxCd,iBAAiB,CAAC,6CAA6C,EAAEM,WAAW,EAAEK,QAAQK,MAAM;QAC9F;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/dataset/list.ts"],"sourcesContent":["import {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasetAliases, listDatasets} from '../../services/datasets.js'\nimport {projectIdFlag} from '../../util/sharedFlags.js'\n\nconst listDatasetDebug = subdebug('dataset:list')\n\nexport class ListDatasetCommand extends SanityCommand<typeof ListDatasetCommand> {\n static override description = 'List datasets of your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List datasets of your project',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123',\n description: 'List datasets for a specific project',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n }\n\n public async run(): Promise<void> {\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const [datasets, aliases] = await Promise.allSettled([\n listDatasets(projectId),\n listDatasetAliases(projectId),\n ])\n\n if (datasets.status === 'rejected') {\n const err = datasets.reason as Error\n listDatasetDebug(`Error listing datasets for project ${projectId}`, err)\n this.error(`Dataset list retrieval failed: ${err.message}`, {exit: 1})\n }\n\n const datasetList = datasets.value\n if (datasetList.length === 0) {\n this.log('No datasets found for this project.')\n } else {\n for (const dataset of datasetList) {\n this.log(dataset.name)\n }\n }\n\n if (aliases.status === 'fulfilled' && aliases.value.length > 0) {\n for (const alias of aliases.value) {\n const targetDataset = alias.datasetName || '<unlinked>'\n this.log(`~${alias.name} -> ${targetDataset}`)\n }\n } else if (aliases.status === 'rejected') {\n listDatasetDebug(`Warning: Could not fetch aliases for project ${projectId}`, aliases.reason)\n }\n }\n}\n"],"names":["SanityCommand","subdebug","promptForProject","listDatasetAliases","listDatasets","projectIdFlag","listDatasetDebug","ListDatasetCommand","description","examples","command","flags","run","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","aliases","Promise","allSettled","status","err","reason","error","message","exit","datasetList","value","length","log","dataset","name","alias","targetDataset","datasetName"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,kBAAkB,EAAEC,YAAY,QAAO,6BAA4B;AAC3E,SAAQC,aAAa,QAAO,4BAA2B;AAEvD,MAAMC,mBAAmBL,SAAS;AAElC,OAAO,MAAMM,2BAA2BP;IACtC,OAAgBQ,cAAc,gCAA+B;IAE7D,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,GAAGN,aAAa;IAClB,EAAC;IAED,MAAaO,MAAqB;QAChC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRb,iBAAiB;oBACfc,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAM,CAACC,UAAUC,QAAQ,GAAG,MAAMC,QAAQC,UAAU,CAAC;YACnDlB,aAAaS;YACbV,mBAAmBU;SACpB;QAED,IAAIM,SAASI,MAAM,KAAK,YAAY;YAClC,MAAMC,MAAML,SAASM,MAAM;YAC3BnB,iBAAiB,CAAC,mCAAmC,EAAEO,WAAW,EAAEW;YACpE,IAAI,CAACE,KAAK,CAAC,CAAC,+BAA+B,EAAEF,IAAIG,OAAO,EAAE,EAAE;gBAACC,MAAM;YAAC;QACtE;QAEA,MAAMC,cAAcV,SAASW,KAAK;QAClC,IAAID,YAAYE,MAAM,KAAK,GAAG;YAC5B,IAAI,CAACC,GAAG,CAAC;QACX,OAAO;YACL,KAAK,MAAMC,WAAWJ,YAAa;gBACjC,IAAI,CAACG,GAAG,CAACC,QAAQC,IAAI;YACvB;QACF;QAEA,IAAId,QAAQG,MAAM,KAAK,eAAeH,QAAQU,KAAK,CAACC,MAAM,GAAG,GAAG;YAC9D,KAAK,MAAMI,SAASf,QAAQU,KAAK,CAAE;gBACjC,MAAMM,gBAAgBD,MAAME,WAAW,IAAI;gBAC3C,IAAI,CAACL,GAAG,CAAC,CAAC,CAAC,EAAEG,MAAMD,IAAI,CAAC,IAAI,EAAEE,eAAe;YAC/C;QACF,OAAO,IAAIhB,QAAQG,MAAM,KAAK,YAAY;YACxCjB,iBAAiB,CAAC,6CAA6C,EAAEO,WAAW,EAAEO,QAAQK,MAAM;QAC9F;IACF;AACF"}
@@ -1,8 +1,9 @@
1
1
  import { Args } from '@oclif/core';
2
2
  import { SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { validateDatasetName } from '../../../actions/dataset/validateDatasetName.js';
4
+ import { promptForProject } from '../../../prompts/promptForProject.js';
4
5
  import { listDatasets } from '../../../services/datasets.js';
5
- import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
6
+ import { projectIdFlag } from '../../../util/sharedFlags.js';
6
7
  const getDebug = subdebug('dataset:visibility:get');
7
8
  export class DatasetVisibilityGetCommand extends SanityCommand {
8
9
  static args = {
@@ -18,15 +19,22 @@ export class DatasetVisibilityGetCommand extends SanityCommand {
18
19
  description: 'Check the visibility of a dataset'
19
20
  }
20
21
  ];
22
+ static flags = {
23
+ ...projectIdFlag
24
+ };
21
25
  async run() {
22
26
  const { args } = await this.parse(DatasetVisibilityGetCommand);
23
27
  const { dataset } = args;
24
- const projectId = await this.getProjectId();
25
- if (!projectId) {
26
- this.error(NO_PROJECT_ID, {
27
- exit: 1
28
- });
29
- }
28
+ const projectId = await this.getProjectId({
29
+ fallback: ()=>promptForProject({
30
+ requiredPermissions: [
31
+ {
32
+ grant: 'read',
33
+ permission: 'sanity.project.datasets'
34
+ }
35
+ ]
36
+ })
37
+ });
30
38
  const dsError = validateDatasetName(dataset);
31
39
  if (dsError) {
32
40
  this.error(dsError, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/dataset/visibility/get.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {listDatasets} from '../../../services/datasets.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\n\nconst getDebug = subdebug('dataset:visibility:get')\n\nexport class DatasetVisibilityGetCommand extends SanityCommand<typeof DatasetVisibilityGetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to get visibility for',\n required: true,\n }),\n }\n\n static override description = 'Get the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Check the visibility of a dataset',\n },\n ]\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilityGetCommand)\n const {dataset} = args\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let current\n try {\n const datasets = await listDatasets(projectId)\n current = datasets.find((curr: {name: string}) => curr.name === dataset)\n } catch (error) {\n getDebug(`Error listing datasets`, error)\n this.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n\n if (!current) {\n this.error(`Dataset not found: ${dataset}`, {exit: 1})\n }\n\n this.log(current.aclMode)\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","listDatasets","NO_PROJECT_ID","getDebug","DatasetVisibilityGetCommand","args","dataset","string","description","required","examples","command","run","parse","projectId","getProjectId","error","exit","dsError","current","datasets","find","curr","name","Error","message","String","log","aclMode"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,YAAY,QAAO,gCAA+B;AAC1D,SAAQC,aAAa,QAAO,iCAAgC;AAE5D,MAAMC,WAAWJ,SAAS;AAE1B,OAAO,MAAMK,oCAAoCN;IAC/C,OAAgBO,OAAO;QACrBC,SAAST,KAAKU,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,MAAaI,MAAqB;QAChC,MAAM,EAACP,IAAI,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAACT;QAChC,MAAM,EAACE,OAAO,EAAC,GAAGD;QAElB,MAAMS,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACd,eAAe;gBAACe,MAAM;YAAC;QACpC;QAEA,MAAMC,UAAUlB,oBAAoBM;QACpC,IAAIY,SAAS;YACX,IAAI,CAACF,KAAK,CAACE,SAAS;gBAACD,MAAM;YAAC;QAC9B;QAEA,IAAIE;QACJ,IAAI;YACF,MAAMC,WAAW,MAAMnB,aAAaa;YACpCK,UAAUC,SAASC,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAKjB;QAClE,EAAE,OAAOU,OAAO;YACdb,SAAS,CAAC,sBAAsB,CAAC,EAAEa;YACnC,IAAI,CAACA,KAAK,CACR,CAAC,yBAAyB,EAAEA,iBAAiBQ,QAAQR,MAAMS,OAAO,GAAGC,OAAOV,QAAQ,EACpF;gBAACC,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACE,SAAS;YACZ,IAAI,CAACH,KAAK,CAAC,CAAC,mBAAmB,EAAEV,SAAS,EAAE;gBAACW,MAAM;YAAC;QACtD;QAEA,IAAI,CAACU,GAAG,CAACR,QAAQS,OAAO;IAC1B;AACF"}
1
+ {"version":3,"sources":["../../../../src/commands/dataset/visibility/get.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listDatasets} from '../../../services/datasets.js'\nimport {projectIdFlag} from '../../../util/sharedFlags.js'\n\nconst getDebug = subdebug('dataset:visibility:get')\n\nexport class DatasetVisibilityGetCommand extends SanityCommand<typeof DatasetVisibilityGetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to get visibility for',\n required: true,\n }),\n }\n\n static override description = 'Get the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Check the visibility of a dataset',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n }\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilityGetCommand)\n const {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let current\n try {\n const datasets = await listDatasets(projectId)\n current = datasets.find((curr: {name: string}) => curr.name === dataset)\n } catch (error) {\n getDebug(`Error listing datasets`, error)\n this.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n\n if (!current) {\n this.error(`Dataset not found: ${dataset}`, {exit: 1})\n }\n\n this.log(current.aclMode)\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","promptForProject","listDatasets","projectIdFlag","getDebug","DatasetVisibilityGetCommand","args","dataset","string","description","required","examples","command","flags","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","current","datasets","find","curr","name","Error","message","String","log","aclMode"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,YAAY,QAAO,gCAA+B;AAC1D,SAAQC,aAAa,QAAO,+BAA8B;AAE1D,MAAMC,WAAWL,SAAS;AAE1B,OAAO,MAAMM,oCAAoCP;IAC/C,OAAgBQ,OAAO;QACrBC,SAASV,KAAKW,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,aAAa;IAClB,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACR,IAAI,EAAC,GAAG,MAAM,IAAI,CAACS,KAAK,CAACV;QAChC,MAAM,EAACE,OAAO,EAAC,GAAGD;QAElB,MAAMU,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRjB,iBAAiB;oBACfkB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAMC,UAAUtB,oBAAoBO;QACpC,IAAIe,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM;YAAC;QAC9B;QAEA,IAAIC;QACJ,IAAI;YACF,MAAMC,WAAW,MAAMxB,aAAac;YACpCS,UAAUC,SAASC,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAKtB;QAClE,EAAE,OAAOgB,OAAO;YACdnB,SAAS,CAAC,sBAAsB,CAAC,EAAEmB;YACnC,IAAI,CAACA,KAAK,CACR,CAAC,yBAAyB,EAAEA,iBAAiBO,QAAQP,MAAMQ,OAAO,GAAGC,OAAOT,QAAQ,EACpF;gBAACC,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACC,SAAS;YACZ,IAAI,CAACF,KAAK,CAAC,CAAC,mBAAmB,EAAEhB,SAAS,EAAE;gBAACiB,MAAM;YAAC;QACtD;QAEA,IAAI,CAACS,GAAG,CAACR,QAAQS,OAAO;IAC1B;AACF"}
@@ -1,8 +1,9 @@
1
1
  import { Args } from '@oclif/core';
2
2
  import { SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { validateDatasetName } from '../../../actions/dataset/validateDatasetName.js';
4
+ import { promptForProject } from '../../../prompts/promptForProject.js';
4
5
  import { editDatasetAcl, listDatasets } from '../../../services/datasets.js';
5
- import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
6
+ import { projectIdFlag } from '../../../util/sharedFlags.js';
6
7
  const setDatasetVisibilityDebug = subdebug('dataset:visibility:set');
7
8
  export class DatasetVisibilitySetCommand extends SanityCommand {
8
9
  static args = {
@@ -30,15 +31,26 @@ export class DatasetVisibilitySetCommand extends SanityCommand {
30
31
  description: 'Make a dataset public'
31
32
  }
32
33
  ];
34
+ static flags = {
35
+ ...projectIdFlag
36
+ };
33
37
  async run() {
34
38
  const { args } = await this.parse(DatasetVisibilitySetCommand);
35
39
  const { dataset, mode } = args;
36
- const projectId = await this.getProjectId();
37
- if (!projectId) {
38
- this.error(NO_PROJECT_ID, {
39
- exit: 1
40
- });
41
- }
40
+ const projectId = await this.getProjectId({
41
+ fallback: ()=>promptForProject({
42
+ requiredPermissions: [
43
+ {
44
+ grant: 'read',
45
+ permission: 'sanity.project.datasets'
46
+ },
47
+ {
48
+ grant: 'update',
49
+ permission: 'sanity.project.datasets'
50
+ }
51
+ ]
52
+ })
53
+ });
42
54
  const dsError = validateDatasetName(dataset);
43
55
  if (dsError) {
44
56
  this.error(dsError, {