@sanity/cli 7.9.0 → 7.11.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 (188) hide show
  1. package/README.md +163 -22
  2. package/dist/actions/auth/ensureAuthenticated.js +2 -0
  3. package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
  4. package/dist/actions/auth/login/getProvider.js +7 -2
  5. package/dist/actions/auth/login/getProvider.js.map +1 -1
  6. package/dist/actions/auth/login/loginInstructions.js +19 -0
  7. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  8. package/dist/actions/dataset/create.js +2 -2
  9. package/dist/actions/dataset/create.js.map +1 -1
  10. package/dist/actions/dataset/resolveDataset.js +7 -1
  11. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  12. package/dist/actions/deploy/createUserApplication.js +8 -5
  13. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  14. package/dist/actions/deploy/deployApp.js +47 -24
  15. package/dist/actions/deploy/deployApp.js.map +1 -1
  16. package/dist/actions/deploy/deployStudio.js +2 -0
  17. package/dist/actions/deploy/deployStudio.js.map +1 -1
  18. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  19. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  20. package/dist/actions/init/initAction.js +23 -15
  21. package/dist/actions/init/initAction.js.map +1 -1
  22. package/dist/actions/manifest/extractCoreAppManifest.js +11 -4
  23. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  24. package/dist/actions/migration/constants.js +10 -0
  25. package/dist/actions/migration/constants.js.map +1 -0
  26. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  27. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  28. package/dist/actions/migration/fileExists.js +13 -0
  29. package/dist/actions/migration/fileExists.js.map +1 -0
  30. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  31. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  32. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  33. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  34. package/dist/actions/migration/resolveMigrations.js +50 -0
  35. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  36. package/dist/actions/migration/templates/index.js +7 -0
  37. package/dist/actions/migration/templates/index.js.map +1 -0
  38. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  39. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  40. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  41. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  42. package/dist/actions/migration/templates/renameField.js +20 -0
  43. package/dist/actions/migration/templates/renameField.js.map +1 -0
  44. package/dist/actions/migration/templates/renameType.js +19 -0
  45. package/dist/actions/migration/templates/renameType.js.map +1 -0
  46. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  47. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  48. package/dist/actions/migration/tree.js +111 -0
  49. package/dist/actions/migration/tree.js.map +1 -0
  50. package/dist/actions/organizations/getOrganization.js +7 -3
  51. package/dist/actions/organizations/getOrganization.js.map +1 -1
  52. package/dist/actions/organizations/validateOrganizationSlug.js +20 -0
  53. package/dist/actions/organizations/validateOrganizationSlug.js.map +1 -0
  54. package/dist/actions/preview/previewAction.js +33 -1
  55. package/dist/actions/preview/previewAction.js.map +1 -1
  56. package/dist/actions/schema/listSchemas.js +6 -4
  57. package/dist/actions/schema/listSchemas.js.map +1 -1
  58. package/dist/actions/tokens/validateRole.js +2 -1
  59. package/dist/actions/tokens/validateRole.js.map +1 -1
  60. package/dist/actions/undeploy/runUndeploy.js +13 -4
  61. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  62. package/dist/commands/backups/disable.js +5 -1
  63. package/dist/commands/backups/disable.js.map +1 -1
  64. package/dist/commands/backups/download.js +30 -6
  65. package/dist/commands/backups/download.js.map +1 -1
  66. package/dist/commands/backups/enable.js +5 -1
  67. package/dist/commands/backups/enable.js.map +1 -1
  68. package/dist/commands/backups/list.js +5 -1
  69. package/dist/commands/backups/list.js.map +1 -1
  70. package/dist/commands/cors/add.js +15 -7
  71. package/dist/commands/cors/add.js.map +1 -1
  72. package/dist/commands/cors/delete.js +6 -1
  73. package/dist/commands/cors/delete.js.map +1 -1
  74. package/dist/commands/datasets/alias/create.js +25 -18
  75. package/dist/commands/datasets/alias/create.js.map +1 -1
  76. package/dist/commands/datasets/alias/delete.js +15 -8
  77. package/dist/commands/datasets/alias/delete.js.map +1 -1
  78. package/dist/commands/datasets/alias/link.js +39 -17
  79. package/dist/commands/datasets/alias/link.js.map +1 -1
  80. package/dist/commands/datasets/alias/unlink.js +23 -2
  81. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  82. package/dist/commands/datasets/copy.js +18 -2
  83. package/dist/commands/datasets/copy.js.map +1 -1
  84. package/dist/commands/datasets/create.js +8 -2
  85. package/dist/commands/datasets/create.js.map +1 -1
  86. package/dist/commands/datasets/delete.js +14 -17
  87. package/dist/commands/datasets/delete.js.map +1 -1
  88. package/dist/commands/datasets/embeddings/disable.js +3 -0
  89. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  90. package/dist/commands/datasets/embeddings/enable.js +5 -2
  91. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  92. package/dist/commands/datasets/embeddings/status.js +3 -0
  93. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  94. package/dist/commands/datasets/export.js +27 -15
  95. package/dist/commands/datasets/export.js.map +1 -1
  96. package/dist/commands/datasets/import.js +3 -3
  97. package/dist/commands/datasets/import.js.map +1 -1
  98. package/dist/commands/datasets/visibility/get.js +2 -2
  99. package/dist/commands/datasets/visibility/get.js.map +1 -1
  100. package/dist/commands/datasets/visibility/set.js +2 -2
  101. package/dist/commands/datasets/visibility/set.js.map +1 -1
  102. package/dist/commands/docs/read.js +3 -3
  103. package/dist/commands/docs/read.js.map +1 -1
  104. package/dist/commands/documents/create.js +18 -13
  105. package/dist/commands/documents/create.js.map +1 -1
  106. package/dist/commands/documents/delete.js +3 -3
  107. package/dist/commands/documents/delete.js.map +1 -1
  108. package/dist/commands/documents/get.js +3 -3
  109. package/dist/commands/documents/get.js.map +1 -1
  110. package/dist/commands/documents/query.js +3 -3
  111. package/dist/commands/documents/query.js.map +1 -1
  112. package/dist/commands/documents/validate.js +29 -26
  113. package/dist/commands/documents/validate.js.map +1 -1
  114. package/dist/commands/graphql/deploy.js +20 -16
  115. package/dist/commands/graphql/deploy.js.map +1 -1
  116. package/dist/commands/graphql/undeploy.js +15 -18
  117. package/dist/commands/graphql/undeploy.js.map +1 -1
  118. package/dist/commands/hooks/create.js +4 -0
  119. package/dist/commands/hooks/create.js.map +1 -1
  120. package/dist/commands/hooks/delete.js +6 -1
  121. package/dist/commands/hooks/delete.js.map +1 -1
  122. package/dist/commands/hooks/logs.js +6 -1
  123. package/dist/commands/hooks/logs.js.map +1 -1
  124. package/dist/commands/install.js +1 -1
  125. package/dist/commands/install.js.map +1 -1
  126. package/dist/commands/login.js +2 -1
  127. package/dist/commands/login.js.map +1 -1
  128. package/dist/commands/media/create-aspect.js +20 -8
  129. package/dist/commands/media/create-aspect.js.map +1 -1
  130. package/dist/commands/media/delete-aspect.js +31 -16
  131. package/dist/commands/media/delete-aspect.js.map +1 -1
  132. package/dist/commands/media/deploy-aspect.js +10 -5
  133. package/dist/commands/media/deploy-aspect.js.map +1 -1
  134. package/dist/commands/media/export.js +9 -4
  135. package/dist/commands/media/export.js.map +1 -1
  136. package/dist/commands/media/import.js +6 -1
  137. package/dist/commands/media/import.js.map +1 -1
  138. package/dist/commands/migrations/create.js +150 -0
  139. package/dist/commands/migrations/create.js.map +1 -0
  140. package/dist/commands/migrations/list.js +64 -0
  141. package/dist/commands/migrations/list.js.map +1 -0
  142. package/dist/commands/migrations/run.js +306 -0
  143. package/dist/commands/migrations/run.js.map +1 -0
  144. package/dist/commands/organizations/create.js +79 -0
  145. package/dist/commands/organizations/create.js.map +1 -0
  146. package/dist/commands/organizations/delete.js +100 -0
  147. package/dist/commands/organizations/delete.js.map +1 -0
  148. package/dist/commands/organizations/get.js +48 -0
  149. package/dist/commands/organizations/get.js.map +1 -0
  150. package/dist/commands/organizations/list.js +60 -0
  151. package/dist/commands/organizations/list.js.map +1 -0
  152. package/dist/commands/organizations/update.js +115 -0
  153. package/dist/commands/organizations/update.js.map +1 -0
  154. package/dist/commands/preview.js +1 -0
  155. package/dist/commands/preview.js.map +1 -1
  156. package/dist/commands/projects/create.js +3 -1
  157. package/dist/commands/projects/create.js.map +1 -1
  158. package/dist/commands/schemas/delete.js +23 -2
  159. package/dist/commands/schemas/delete.js.map +1 -1
  160. package/dist/commands/schemas/deploy.js +6 -4
  161. package/dist/commands/schemas/deploy.js.map +1 -1
  162. package/dist/commands/schemas/extract.js +22 -1
  163. package/dist/commands/schemas/extract.js.map +1 -1
  164. package/dist/commands/schemas/list.js +8 -8
  165. package/dist/commands/schemas/list.js.map +1 -1
  166. package/dist/commands/tokens/{add.js → create.js} +25 -18
  167. package/dist/commands/tokens/create.js.map +1 -0
  168. package/dist/commands/tokens/delete.js +41 -23
  169. package/dist/commands/tokens/delete.js.map +1 -1
  170. package/dist/commands/undeploy.js +2 -7
  171. package/dist/commands/undeploy.js.map +1 -1
  172. package/dist/commands/users/invite.js +25 -3
  173. package/dist/commands/users/invite.js.map +1 -1
  174. package/dist/prompts/promptForOrganizationName.js +2 -1
  175. package/dist/prompts/promptForOrganizationName.js.map +1 -1
  176. package/dist/services/organizations.js +45 -2
  177. package/dist/services/organizations.js.map +1 -1
  178. package/dist/services/userApplications.js.map +1 -1
  179. package/dist/topicAliases.js +10 -0
  180. package/dist/topicAliases.js.map +1 -1
  181. package/dist/util/formatCliErrorMessages.js +5 -0
  182. package/dist/util/formatCliErrorMessages.js.map +1 -0
  183. package/dist/util/organizationAliases.js +12 -0
  184. package/dist/util/organizationAliases.js.map +1 -0
  185. package/oclif.config.js +6 -1
  186. package/oclif.manifest.json +464 -11
  187. package/package.json +28 -28
  188. package/dist/commands/tokens/add.js.map +0 -1
@@ -0,0 +1,21 @@
1
+ export const minimalAdvanced = ({ documentTypes, migrationName })=>`import {defineMigration, patch, at, setIfMissing} from 'sanity/migrate'
2
+
3
+ /**
4
+ * this migration will set \`Default title\` on all documents that are missing a title
5
+ * and make \`true\` the default value for the \`enabled\` field
6
+ */
7
+ export default defineMigration({
8
+ title: ${JSON.stringify(migrationName)},
9
+ ${documentTypes.length > 0 ? ` documentTypes: [${documentTypes.map((t)=>JSON.stringify(t)).join(', ')}],\n` : ''}
10
+ async *migrate(documents, context) {
11
+ for await (const document of documents()) {
12
+ yield patch(document._id, [
13
+ at('title', setIfMissing('Default title')),
14
+ at('enabled', setIfMissing(true)),
15
+ ])
16
+ }
17
+ }
18
+ })
19
+ `;
20
+
21
+ //# sourceMappingURL=minimalAdvanced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/migration/templates/minimalAdvanced.ts"],"sourcesContent":["export const minimalAdvanced = ({\n documentTypes,\n migrationName,\n}: {\n documentTypes: string[]\n migrationName: string\n}) => `import {defineMigration, patch, at, setIfMissing} from 'sanity/migrate'\n\n/**\n * this migration will set \\`Default title\\` on all documents that are missing a title\n * and make \\`true\\` the default value for the \\`enabled\\` field\n */\nexport default defineMigration({\n title: ${JSON.stringify(migrationName)},\n${\n documentTypes.length > 0\n ? ` documentTypes: [${documentTypes.map((t) => JSON.stringify(t)).join(', ')}],\\n`\n : ''\n}\n async *migrate(documents, context) {\n for await (const document of documents()) {\n yield patch(document._id, [\n at('title', setIfMissing('Default title')),\n at('enabled', setIfMissing(true)),\n ])\n }\n }\n})\n`\n"],"names":["minimalAdvanced","documentTypes","migrationName","JSON","stringify","length","map","t","join"],"mappings":"AAAA,OAAO,MAAMA,kBAAkB,CAAC,EAC9BC,aAAa,EACbC,aAAa,EAId,GAAK,CAAC;;;;;;;SAOE,EAAEC,KAAKC,SAAS,CAACF,eAAe;AACzC,EACED,cAAcI,MAAM,GAAG,IACnB,CAAC,kBAAkB,EAAEJ,cAAcK,GAAG,CAAC,CAACC,IAAMJ,KAAKC,SAAS,CAACG,IAAIC,IAAI,CAAC,MAAM,IAAI,CAAC,GACjF,GACL;;;;;;;;;;AAUD,CAAC,CAAA"}
@@ -0,0 +1,61 @@
1
+ export const minimalSimple = ({ documentTypes, migrationName })=>`import {at, defineMigration, setIfMissing, unset} from 'sanity/migrate'
2
+
3
+ export default defineMigration({
4
+ title: ${JSON.stringify(migrationName)},
5
+ ${documentTypes.length > 0 ? ` documentTypes: [${documentTypes.map((t)=>JSON.stringify(t)).join(', ')}],\n` : ''}
6
+ migrate: {
7
+ document(doc, context) {
8
+ // this will be called for every document of the matching type
9
+ // any patch returned will be applied to the document
10
+ // you can also return mutations that touches other documents
11
+
12
+ return at('title', setIfMissing('Default title'))
13
+ },
14
+ node(node, path, context) {
15
+ // this will be called for every node in every document of the matching type
16
+ // any patch returned will be applied to the document
17
+ // you can also return mutations that touches other documents
18
+
19
+ if (typeof node === 'string' && node === 'deleteme') {
20
+ return unset()
21
+ }
22
+ },
23
+ object(node, path, context) {
24
+ // this will be called for every object node in every document of the matching type
25
+ // any patch returned will be applied to the document
26
+ // you can also return mutations that touches other documents
27
+ if (node._type === 'author') {
28
+ // make sure all authors objects have a books array
29
+ return at('books', setIfMissing([]))
30
+ }
31
+ },
32
+ array(node, path, context) {
33
+ // this will be called for every array node in every document of the matching type
34
+ // any patch returned will be applied to the document
35
+ // you can also return mutations that touches other documents
36
+ },
37
+ string(node, path, context) {
38
+ // this will be called for every string node in every document of the matching type
39
+ // any patch returned will be applied to the document
40
+ // you can also return mutations that touches other documents
41
+ },
42
+ number(node, path, context) {
43
+ // this will be called for every number node in every document of the matching type
44
+ // any patch returned will be applied to the document
45
+ // you can also return mutations that touches other documents
46
+ },
47
+ boolean(node, path, context) {
48
+ // this will be called for every boolean node in every document of the matching type
49
+ // any patch returned will be applied to the document
50
+ // you can also return mutations that touches other documents
51
+ },
52
+ null(node, path, context) {
53
+ // this will be called for every null node in every document of the matching type
54
+ // any patch returned will be applied to the document
55
+ // you can also return mutations that touches other documents
56
+ },
57
+ },
58
+ })
59
+ `;
60
+
61
+ //# sourceMappingURL=minimalSimple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/migration/templates/minimalSimple.ts"],"sourcesContent":["export const minimalSimple = ({\n documentTypes,\n migrationName,\n}: {\n documentTypes: string[]\n migrationName: string\n}) => `import {at, defineMigration, setIfMissing, unset} from 'sanity/migrate'\n\nexport default defineMigration({\n title: ${JSON.stringify(migrationName)},\n${\n documentTypes.length > 0\n ? ` documentTypes: [${documentTypes.map((t) => JSON.stringify(t)).join(', ')}],\\n`\n : ''\n}\n migrate: {\n document(doc, context) {\n // this will be called for every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n\n return at('title', setIfMissing('Default title'))\n },\n node(node, path, context) {\n // this will be called for every node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n\n if (typeof node === 'string' && node === 'deleteme') {\n return unset()\n }\n },\n object(node, path, context) {\n // this will be called for every object node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n if (node._type === 'author') {\n // make sure all authors objects have a books array\n return at('books', setIfMissing([]))\n }\n },\n array(node, path, context) {\n // this will be called for every array node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n string(node, path, context) {\n // this will be called for every string node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n number(node, path, context) {\n // this will be called for every number node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n boolean(node, path, context) {\n // this will be called for every boolean node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n null(node, path, context) {\n // this will be called for every null node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n },\n})\n`\n"],"names":["minimalSimple","documentTypes","migrationName","JSON","stringify","length","map","t","join"],"mappings":"AAAA,OAAO,MAAMA,gBAAgB,CAAC,EAC5BC,aAAa,EACbC,aAAa,EAId,GAAK,CAAC;;;SAGE,EAAEC,KAAKC,SAAS,CAACF,eAAe;AACzC,EACED,cAAcI,MAAM,GAAG,IACnB,CAAC,kBAAkB,EAAEJ,cAAcK,GAAG,CAAC,CAACC,IAAMJ,KAAKC,SAAS,CAACG,IAAIC,IAAI,CAAC,MAAM,IAAI,CAAC,GACjF,GACL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDD,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ export const renameField = ({ documentTypes, migrationName })=>`import {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'
2
+
3
+ const from = 'oldFieldName'
4
+ const to = 'newFieldName'
5
+
6
+ export default defineMigration({
7
+ title: ${JSON.stringify(migrationName)},
8
+ ${documentTypes.length > 0 ? ` documentTypes: [${documentTypes.map((t)=>JSON.stringify(t)).join(', ')}],\n` : ''}
9
+ migrate: {
10
+ document(doc, context) {
11
+ return [
12
+ at(to, setIfMissing(doc[from])),
13
+ at(from, unset())
14
+ ]
15
+ }
16
+ }
17
+ })
18
+ `;
19
+
20
+ //# sourceMappingURL=renameField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/migration/templates/renameField.ts"],"sourcesContent":["export const renameField = ({\n documentTypes,\n migrationName,\n}: {\n documentTypes: string[]\n migrationName: string\n}) => `import {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'\n\nconst from = 'oldFieldName'\nconst to = 'newFieldName'\n\nexport default defineMigration({\n title: ${JSON.stringify(migrationName)},\n${\n documentTypes.length > 0\n ? ` documentTypes: [${documentTypes.map((t) => JSON.stringify(t)).join(', ')}],\\n`\n : ''\n}\n migrate: {\n document(doc, context) {\n return [\n at(to, setIfMissing(doc[from])),\n at(from, unset())\n ]\n }\n }\n})\n`\n"],"names":["renameField","documentTypes","migrationName","JSON","stringify","length","map","t","join"],"mappings":"AAAA,OAAO,MAAMA,cAAc,CAAC,EAC1BC,aAAa,EACbC,aAAa,EAId,GAAK,CAAC;;;;;;SAME,EAAEC,KAAKC,SAAS,CAACF,eAAe;AACzC,EACED,cAAcI,MAAM,GAAG,IACnB,CAAC,kBAAkB,EAAEJ,cAAcK,GAAG,CAAC,CAACC,IAAMJ,KAAKC,SAAS,CAACG,IAAIC,IAAI,CAAC,MAAM,IAAI,CAAC,GACjF,GACL;;;;;;;;;;AAUD,CAAC,CAAA"}
@@ -0,0 +1,19 @@
1
+ export const renameType = ({ documentTypes, migrationName })=>`import {defineMigration, at, set} from 'sanity/migrate'
2
+
3
+ const oldType = 'old'
4
+ const newType = 'new'
5
+
6
+ export default defineMigration({
7
+ title: ${JSON.stringify(migrationName)},
8
+ ${documentTypes.length > 0 ? ` documentTypes: [${documentTypes.map((t)=>JSON.stringify(t)).join(', ')}],\n` : ''}
9
+ migrate: {
10
+ object(object, path, context) {
11
+ if (object._type === oldType) {
12
+ return at('_type', set(newType))
13
+ }
14
+ }
15
+ }
16
+ })
17
+ `;
18
+
19
+ //# sourceMappingURL=renameType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/migration/templates/renameType.ts"],"sourcesContent":["export const renameType = ({\n documentTypes,\n migrationName,\n}: {\n documentTypes: string[]\n migrationName: string\n}) => `import {defineMigration, at, set} from 'sanity/migrate'\n\nconst oldType = 'old'\nconst newType = 'new'\n\nexport default defineMigration({\n title: ${JSON.stringify(migrationName)},\n${\n documentTypes.length > 0\n ? ` documentTypes: [${documentTypes.map((t) => JSON.stringify(t)).join(', ')}],\\n`\n : ''\n}\n migrate: {\n object(object, path, context) {\n if (object._type === oldType) {\n return at('_type', set(newType))\n }\n }\n }\n})\n`\n"],"names":["renameType","documentTypes","migrationName","JSON","stringify","length","map","t","join"],"mappings":"AAAA,OAAO,MAAMA,aAAa,CAAC,EACzBC,aAAa,EACbC,aAAa,EAId,GAAK,CAAC;;;;;;SAME,EAAEC,KAAKC,SAAS,CAACF,eAAe;AACzC,EACED,cAAcI,MAAM,GAAG,IACnB,CAAC,kBAAkB,EAAEJ,cAAcK,GAAG,CAAC,CAACC,IAAMJ,KAAKC,SAAS,CAACG,IAAIC,IAAI,CAAC,MAAM,IAAI,CAAC,GACjF,GACL;;;;;;;;;AASD,CAAC,CAAA"}
@@ -0,0 +1,32 @@
1
+ export const stringToPTE = ({ documentTypes, migrationName })=>`import {pathsAreEqual, stringToPath} from 'sanity'
2
+ import {defineMigration, set} from 'sanity/migrate'
3
+
4
+ const targetPath = stringToPath('some.path')
5
+
6
+ export default defineMigration({
7
+ title: ${JSON.stringify(migrationName)},
8
+ ${documentTypes.length > 0 ? ` documentTypes: [${documentTypes.map((t)=>JSON.stringify(t)).join(', ')}],\n` : ''}
9
+ migrate: {
10
+ string(node, path, ctx) {
11
+ if (pathsAreEqual(path, targetPath)) {
12
+ return set([
13
+ {
14
+ style: 'normal',
15
+ _type: 'block',
16
+ children: [
17
+ {
18
+ _type: 'span',
19
+ marks: [],
20
+ text: node,
21
+ },
22
+ ],
23
+ markDefs: [],
24
+ },
25
+ ])
26
+ }
27
+ },
28
+ },
29
+ })
30
+ `;
31
+
32
+ //# sourceMappingURL=stringToPTE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/migration/templates/stringToPTE.ts"],"sourcesContent":["export const stringToPTE = ({\n documentTypes,\n migrationName,\n}: {\n documentTypes: string[]\n migrationName: string\n}) => `import {pathsAreEqual, stringToPath} from 'sanity'\nimport {defineMigration, set} from 'sanity/migrate'\n\nconst targetPath = stringToPath('some.path')\n\nexport default defineMigration({\n title: ${JSON.stringify(migrationName)},\n${\n documentTypes.length > 0\n ? ` documentTypes: [${documentTypes.map((t) => JSON.stringify(t)).join(', ')}],\\n`\n : ''\n}\n migrate: {\n string(node, path, ctx) {\n if (pathsAreEqual(path, targetPath)) {\n return set([\n {\n style: 'normal',\n _type: 'block',\n children: [\n {\n _type: 'span',\n marks: [],\n text: node,\n },\n ],\n markDefs: [],\n },\n ])\n }\n },\n },\n})\n`\n"],"names":["stringToPTE","documentTypes","migrationName","JSON","stringify","length","map","t","join"],"mappings":"AAAA,OAAO,MAAMA,cAAc,CAAC,EAC1BC,aAAa,EACbC,aAAa,EAId,GAAK,CAAC;;;;;;SAME,EAAEC,KAAKC,SAAS,CAACF,eAAe;AACzC,EACED,cAAcI,MAAM,GAAG,IACnB,CAAC,kBAAkB,EAAEJ,cAAcK,GAAG,CAAC,CAACC,IAAMJ,KAAKC,SAAS,CAACG,IAAIC,IAAI,CAAC,MAAM,IAAI,CAAC,GACjF,GACL;;;;;;;;;;;;;;;;;;;;;;AAsBD,CAAC,CAAA"}
@@ -0,0 +1,111 @@
1
+ import { isIndexSegment, isIndexTuple, isKeySegment } from '@sanity/types';
2
+ // copy/paste of `pathToString` from 'sanity' to prevent circular imports
3
+ function pathToString(path) {
4
+ if (!Array.isArray(path)) {
5
+ throw new TypeError('Path is not an array');
6
+ }
7
+ let target = '';
8
+ let i = 0;
9
+ for (const segment of path){
10
+ if (isIndexSegment(segment)) {
11
+ target = `${target}[${segment}]`;
12
+ } else if (isKeySegment(segment) && segment._key) {
13
+ target = `${target}[_key=="${segment._key}"]`;
14
+ } else if (isIndexTuple(segment)) {
15
+ const [from, to] = segment;
16
+ target = `${target}[${from}:${to}]`;
17
+ } else if (typeof segment === 'string') {
18
+ const separator = i === 0 ? '' : '.';
19
+ target = `${target}${separator}${segment}`;
20
+ } else {
21
+ throw new TypeError(`Unsupported path segment \`${JSON.stringify(segment)}\``);
22
+ }
23
+ i++;
24
+ }
25
+ return target;
26
+ }
27
+ /**
28
+ * Recursively calculates the max length of all the keys in the given validation
29
+ * tree respecting extra length due to indentation depth. Used to calculate the
30
+ * padding for the rest of the tree.
31
+ */ export const maxKeyLength = (children = {}, depth = 0)=>{
32
+ let max = 0;
33
+ for (const [key, child] of Object.entries(children)){
34
+ const currentMax = Math.max(key.length + depth * 2, maxKeyLength(child.children, depth + 1));
35
+ max = Math.max(max, currentMax);
36
+ }
37
+ return max;
38
+ };
39
+ /**
40
+ * Recursively formats a given tree into a printed user-friendly tree structure
41
+ */ export const formatTree = ({ getMessage, getNodes: getLeaves = ({ nodes })=>nodes, indent = '', node = {}, paddingLength })=>{
42
+ const entries = Object.entries(node);
43
+ return entries.map(([key, child], index)=>{
44
+ const isLast = index === entries.length - 1;
45
+ const nextIndent = `${indent}${isLast ? ' ' : '│ '}`;
46
+ const leaves = getLeaves(child);
47
+ const nested = formatTree({
48
+ getMessage,
49
+ getNodes: getLeaves,
50
+ indent: nextIndent,
51
+ node: child.children,
52
+ paddingLength
53
+ });
54
+ if (!leaves?.length) {
55
+ const current = `${indent}${isLast ? '└' : '├'}─ ${key}`;
56
+ return [
57
+ current,
58
+ nested
59
+ ].filter(Boolean).join('\n');
60
+ }
61
+ const first = leaves[0];
62
+ const rest = leaves.slice(1);
63
+ if (!first) return '';
64
+ const firstPadding = '.'.repeat(paddingLength - indent.length - key.length);
65
+ const elbow = isLast ? '└' : '├';
66
+ const subsequentPadding = ' '.repeat(paddingLength - indent.length + 2);
67
+ const firstMessage = `${indent}${elbow}─ ${key} ${firstPadding} ${getMessage(first)}`;
68
+ const subsequentMessages = rest.map((marker)=>`${nextIndent}${subsequentPadding} ${getMessage(marker)}`).join('\n');
69
+ const current = [
70
+ firstMessage,
71
+ subsequentMessages
72
+ ].filter(Boolean).join('\n');
73
+ return [
74
+ current,
75
+ nested
76
+ ].filter(Boolean).join('\n');
77
+ }).join('\n');
78
+ };
79
+ /**
80
+ * Converts a set of markers with paths into a tree of markers where the paths
81
+ * are embedded in the tree
82
+ */ export function convertToTree(nodes) {
83
+ const root = {};
84
+ // add the markers to the tree
85
+ function addNode(node, tree = root) {
86
+ // if we've traversed the whole path
87
+ if (node.path.length === 0) {
88
+ if (!tree.nodes) tree.nodes = []; // ensure markers is defined
89
+ // then add the marker to the front
90
+ tree.nodes.push(node);
91
+ return;
92
+ }
93
+ const current = node.path[0];
94
+ const rest = node.path.slice(1);
95
+ if (!current) return;
96
+ const key = pathToString([
97
+ current
98
+ ]);
99
+ // ensure the current node has children and the next node
100
+ if (!tree.children) tree.children = {};
101
+ if (!(key in tree.children)) tree.children[key] = {};
102
+ addNode({
103
+ ...node,
104
+ path: rest
105
+ }, tree.children[key]);
106
+ }
107
+ for (const node of nodes)addNode(node);
108
+ return root;
109
+ }
110
+
111
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/migration/tree.ts"],"sourcesContent":["import {isIndexSegment, isIndexTuple, isKeySegment, type Path} from '@sanity/types'\n\n// copy/paste of `pathToString` from 'sanity' to prevent circular imports\nfunction pathToString(path: Path): string {\n if (!Array.isArray(path)) {\n throw new TypeError('Path is not an array')\n }\n\n let target = ''\n let i = 0\n for (const segment of path) {\n if (isIndexSegment(segment)) {\n target = `${target}[${segment}]`\n } else if (isKeySegment(segment) && segment._key) {\n target = `${target}[_key==\"${segment._key}\"]`\n } else if (isIndexTuple(segment)) {\n const [from, to] = segment\n target = `${target}[${from}:${to}]`\n } else if (typeof segment === 'string') {\n const separator = i === 0 ? '' : '.'\n target = `${target}${separator}${segment}`\n } else {\n throw new TypeError(`Unsupported path segment \\`${JSON.stringify(segment)}\\``)\n }\n i++\n }\n return target\n}\n\ninterface BaseNode {\n path: Path\n}\n\ninterface Tree<Node extends BaseNode> {\n children?: Record<string, Tree<Node>>\n nodes?: Node[]\n}\n\n/**\n * Recursively calculates the max length of all the keys in the given validation\n * tree respecting extra length due to indentation depth. Used to calculate the\n * padding for the rest of the tree.\n */\nexport const maxKeyLength = (children: Record<string, Tree<BaseNode>> = {}, depth = 0): number => {\n let max = 0\n for (const [key, child] of Object.entries(children)) {\n const currentMax = Math.max(key.length + depth * 2, maxKeyLength(child.children, depth + 1))\n max = Math.max(max, currentMax)\n }\n return max\n}\n\ninterface Options<Node extends BaseNode> {\n getMessage: (node: Node) => string\n paddingLength: number\n\n getNodes?: (node: Tree<Node>) => Node[] | undefined\n indent?: string\n node?: Record<string, Tree<Node>>\n}\n\n/**\n * Recursively formats a given tree into a printed user-friendly tree structure\n */\nexport const formatTree = <Node extends BaseNode>({\n getMessage,\n getNodes: getLeaves = ({nodes}) => nodes,\n indent = '',\n node = {},\n paddingLength,\n}: Options<Node>): string => {\n const entries = Object.entries(node)\n\n return entries\n .map(([key, child], index) => {\n const isLast = index === entries.length - 1\n const nextIndent = `${indent}${isLast ? ' ' : '│ '}`\n const leaves = getLeaves(child)\n\n const nested = formatTree({\n getMessage,\n getNodes: getLeaves,\n indent: nextIndent,\n node: child.children,\n paddingLength,\n })\n\n if (!leaves?.length) {\n const current = `${indent}${isLast ? '└' : '├'}─ ${key}`\n return [current, nested].filter(Boolean).join('\\n')\n }\n\n const first = leaves[0]\n const rest = leaves.slice(1)\n if (!first) return ''\n const firstPadding = '.'.repeat(paddingLength - indent.length - key.length)\n const elbow = isLast ? '└' : '├'\n const subsequentPadding = ' '.repeat(paddingLength - indent.length + 2)\n\n const firstMessage = `${indent}${elbow}─ ${key} ${firstPadding} ${getMessage(first)}`\n const subsequentMessages = rest\n .map((marker) => `${nextIndent}${subsequentPadding} ${getMessage(marker)}`)\n .join('\\n')\n\n const current = [firstMessage, subsequentMessages].filter(Boolean).join('\\n')\n return [current, nested].filter(Boolean).join('\\n')\n })\n .join('\\n')\n}\n\n/**\n * Converts a set of markers with paths into a tree of markers where the paths\n * are embedded in the tree\n */\nexport function convertToTree<const Node extends BaseNode>(nodes: Node[]): Tree<Node> {\n const root: Tree<Node> = {}\n\n // add the markers to the tree\n function addNode(node: Node, tree: Tree<Node> = root) {\n // if we've traversed the whole path\n if (node.path.length === 0) {\n if (!tree.nodes) tree.nodes = [] // ensure markers is defined\n\n // then add the marker to the front\n tree.nodes.push(node)\n return\n }\n\n const current = node.path[0]\n const rest = node.path.slice(1)\n if (!current) return\n const key = pathToString([current])\n\n // ensure the current node has children and the next node\n if (!tree.children) tree.children = {}\n if (!(key in tree.children)) tree.children[key] = {}\n\n addNode({...node, path: rest}, tree.children[key])\n }\n\n for (const node of nodes) addNode(node)\n return root\n}\n"],"names":["isIndexSegment","isIndexTuple","isKeySegment","pathToString","path","Array","isArray","TypeError","target","i","segment","_key","from","to","separator","JSON","stringify","maxKeyLength","children","depth","max","key","child","Object","entries","currentMax","Math","length","formatTree","getMessage","getNodes","getLeaves","nodes","indent","node","paddingLength","map","index","isLast","nextIndent","leaves","nested","current","filter","Boolean","join","first","rest","slice","firstPadding","repeat","elbow","subsequentPadding","firstMessage","subsequentMessages","marker","convertToTree","root","addNode","tree","push"],"mappings":"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"}
@@ -34,6 +34,9 @@ export async function getOrganization({ isUnattended, output, requestedId, user
34
34
  // If the user has no organizations, prompt them to create one with the same name as
35
35
  // their user, but allow them to customize it if they want
36
36
  if (organizations.length === 0) {
37
+ if (isUnattended) {
38
+ throw new Error('No organizations are available. Create an organization at https://www.sanity.io/manage, then pass its ID or slug with --organization.');
39
+ }
37
40
  output.log('You need to create an organization to create projects.');
38
41
  return promptAndCreateNewOrganization(user);
39
42
  }
@@ -45,10 +48,11 @@ export async function getOrganization({ isUnattended, output, requestedId, user
45
48
  const withAttach = withGrantInfo.filter(({ hasAttachGrant })=>hasAttachGrant);
46
49
  debug('User has attach access to %d organizations.', withAttach.length);
47
50
  const organizationChoices = getOrganizationChoices(withGrantInfo);
48
- // In unattended mode use defaults without prompting
49
51
  if (isUnattended) {
50
- // Use the first organization with attach permissions
51
- return withAttach.length > 0 ? withAttach[0].organization : undefined;
52
+ if (withAttach.length > 1) {
53
+ throw new Error('Multiple organizations are available. Select one with --organization <slug|id>.');
54
+ }
55
+ return withAttach[0]?.organization;
52
56
  }
53
57
  // If the user only has a single organization (and they have attach access to it),
54
58
  // we'll default to that one. Otherwise, we'll default to the organization with the
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/organizations/getOrganization.ts"],"sourcesContent":["import {subdebug} from '@sanity/cli-core/debug'\nimport {type Output, type SanityOrgUser} from '@sanity/cli-core/types'\nimport {select, spinner} from '@sanity/cli-core/ux'\n\nimport {promptForOrganizationName} from '../../prompts/promptForOrganizationName.js'\nimport {\n createOrganization,\n listOrganizations,\n type ProjectOrganization,\n} from '../../services/organizations.js'\nimport {findOrganizationByUserName} from './findOrganizationByUserName.js'\nimport {getOrganizationChoices} from './getOrganizationChoices.js'\nimport {getOrganizationsWithAttachGrantInfo} from './getOrganizationsWithAttachGrantInfo.js'\n\nconst debug = subdebug('getOrganizationId')\n\ninterface GetOrganizationOptions {\n isUnattended: boolean\n output: Output\n requestedId: string | undefined\n user: SanityOrgUser\n}\n\nconst promptAndCreateNewOrganization = async (user: SanityOrgUser) => {\n const organizationName = await promptForOrganizationName(user)\n const spin = spinner('Creating organization').start()\n const newOrganization = await createOrganization(organizationName)\n spin.succeed()\n return newOrganization\n}\n\nexport async function getOrganization({\n isUnattended,\n output,\n requestedId,\n user,\n}: GetOrganizationOptions) {\n // Get available organizations\n const spin = spinner('Loading organizations').start()\n let organizations: ProjectOrganization[]\n try {\n organizations = await listOrganizations()\n spin.succeed()\n } catch (error) {\n spin.fail()\n debug('Error retrieving organization list', error)\n throw error\n }\n\n // If organization is specified, validate it\n if (requestedId) {\n const org = organizations.find((o) => o.id === requestedId || o.slug === requestedId)\n if (org) return org\n\n throw new Error(`Organization \"${requestedId}\" not found or you don't have access to it`)\n }\n\n // If the user has no organizations, prompt them to create one with the same name as\n // their user, but allow them to customize it if they want\n if (organizations.length === 0) {\n output.log('You need to create an organization to create projects.')\n return promptAndCreateNewOrganization(user)\n }\n\n // If the user has organizations, let them choose from them, but also allow them to\n // create a new one in case they do not have access to any of them, or they want to\n // create a personal/other organization.\n debug(`User has ${organizations.length} organization(s), checking attach access`)\n const withGrantInfo = await getOrganizationsWithAttachGrantInfo(organizations)\n const withAttach = withGrantInfo.filter(({hasAttachGrant}) => hasAttachGrant)\n\n debug('User has attach access to %d organizations.', withAttach.length)\n const organizationChoices = getOrganizationChoices(withGrantInfo)\n\n // In unattended mode use defaults without prompting\n if (isUnattended) {\n // Use the first organization with attach permissions\n return withAttach.length > 0 ? withAttach[0].organization : undefined\n }\n\n // If the user only has a single organization (and they have attach access to it),\n // we'll default to that one. Otherwise, we'll default to the organization with the\n // same name as the user if it exists.\n const defaultOrganizationId =\n withAttach.length === 1\n ? withAttach[0].organization.id\n : findOrganizationByUserName(organizations, user)\n\n const chosenOrg = await select({\n choices: organizationChoices,\n default: defaultOrganizationId || undefined,\n message: 'Select organization:',\n })\n\n if (chosenOrg === '-new-') {\n return promptAndCreateNewOrganization(user)\n }\n\n return organizations.find((org) => org.id === chosenOrg)\n}\n"],"names":["subdebug","select","spinner","promptForOrganizationName","createOrganization","listOrganizations","findOrganizationByUserName","getOrganizationChoices","getOrganizationsWithAttachGrantInfo","debug","promptAndCreateNewOrganization","user","organizationName","spin","start","newOrganization","succeed","getOrganization","isUnattended","output","requestedId","organizations","error","fail","org","find","o","id","slug","Error","length","log","withGrantInfo","withAttach","filter","hasAttachGrant","organizationChoices","organization","undefined","defaultOrganizationId","chosenOrg","choices","default","message"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,yBAAwB;AAE/C,SAAQC,MAAM,EAAEC,OAAO,QAAO,sBAAqB;AAEnD,SAAQC,yBAAyB,QAAO,6CAA4C;AACpF,SACEC,kBAAkB,EAClBC,iBAAiB,QAEZ,kCAAiC;AACxC,SAAQC,0BAA0B,QAAO,kCAAiC;AAC1E,SAAQC,sBAAsB,QAAO,8BAA6B;AAClE,SAAQC,mCAAmC,QAAO,2CAA0C;AAE5F,MAAMC,QAAQT,SAAS;AASvB,MAAMU,iCAAiC,OAAOC;IAC5C,MAAMC,mBAAmB,MAAMT,0BAA0BQ;IACzD,MAAME,OAAOX,QAAQ,yBAAyBY,KAAK;IACnD,MAAMC,kBAAkB,MAAMX,mBAAmBQ;IACjDC,KAAKG,OAAO;IACZ,OAAOD;AACT;AAEA,OAAO,eAAeE,gBAAgB,EACpCC,YAAY,EACZC,MAAM,EACNC,WAAW,EACXT,IAAI,EACmB;IACvB,8BAA8B;IAC9B,MAAME,OAAOX,QAAQ,yBAAyBY,KAAK;IACnD,IAAIO;IACJ,IAAI;QACFA,gBAAgB,MAAMhB;QACtBQ,KAAKG,OAAO;IACd,EAAE,OAAOM,OAAO;QACdT,KAAKU,IAAI;QACTd,MAAM,sCAAsCa;QAC5C,MAAMA;IACR;IAEA,4CAA4C;IAC5C,IAAIF,aAAa;QACf,MAAMI,MAAMH,cAAcI,IAAI,CAAC,CAACC,IAAMA,EAAEC,EAAE,KAAKP,eAAeM,EAAEE,IAAI,KAAKR;QACzE,IAAII,KAAK,OAAOA;QAEhB,MAAM,IAAIK,MAAM,CAAC,cAAc,EAAET,YAAY,0CAA0C,CAAC;IAC1F;IAEA,oFAAoF;IACpF,0DAA0D;IAC1D,IAAIC,cAAcS,MAAM,KAAK,GAAG;QAC9BX,OAAOY,GAAG,CAAC;QACX,OAAOrB,+BAA+BC;IACxC;IAEA,mFAAmF;IACnF,mFAAmF;IACnF,wCAAwC;IACxCF,MAAM,CAAC,SAAS,EAAEY,cAAcS,MAAM,CAAC,wCAAwC,CAAC;IAChF,MAAME,gBAAgB,MAAMxB,oCAAoCa;IAChE,MAAMY,aAAaD,cAAcE,MAAM,CAAC,CAAC,EAACC,cAAc,EAAC,GAAKA;IAE9D1B,MAAM,+CAA+CwB,WAAWH,MAAM;IACtE,MAAMM,sBAAsB7B,uBAAuByB;IAEnD,qDAAqD;IACrD,IAAId,cAAc;QAChB,qDAAqD;QACrD,OAAOe,WAAWH,MAAM,GAAG,IAAIG,UAAU,CAAC,EAAE,CAACI,YAAY,GAAGC;IAC9D;IAEA,kFAAkF;IAClF,mFAAmF;IACnF,sCAAsC;IACtC,MAAMC,wBACJN,WAAWH,MAAM,KAAK,IAClBG,UAAU,CAAC,EAAE,CAACI,YAAY,CAACV,EAAE,GAC7BrB,2BAA2Be,eAAeV;IAEhD,MAAM6B,YAAY,MAAMvC,OAAO;QAC7BwC,SAASL;QACTM,SAASH,yBAAyBD;QAClCK,SAAS;IACX;IAEA,IAAIH,cAAc,SAAS;QACzB,OAAO9B,+BAA+BC;IACxC;IAEA,OAAOU,cAAcI,IAAI,CAAC,CAACD,MAAQA,IAAIG,EAAE,KAAKa;AAChD"}
1
+ {"version":3,"sources":["../../../src/actions/organizations/getOrganization.ts"],"sourcesContent":["import {subdebug} from '@sanity/cli-core/debug'\nimport {type Output, type SanityOrgUser} from '@sanity/cli-core/types'\nimport {select, spinner} from '@sanity/cli-core/ux'\n\nimport {promptForOrganizationName} from '../../prompts/promptForOrganizationName.js'\nimport {\n createOrganization,\n listOrganizations,\n type ProjectOrganization,\n} from '../../services/organizations.js'\nimport {findOrganizationByUserName} from './findOrganizationByUserName.js'\nimport {getOrganizationChoices} from './getOrganizationChoices.js'\nimport {getOrganizationsWithAttachGrantInfo} from './getOrganizationsWithAttachGrantInfo.js'\n\nconst debug = subdebug('getOrganizationId')\n\ninterface GetOrganizationOptions {\n isUnattended: boolean\n output: Output\n requestedId: string | undefined\n user: SanityOrgUser\n}\n\nconst promptAndCreateNewOrganization = async (user: SanityOrgUser) => {\n const organizationName = await promptForOrganizationName(user)\n const spin = spinner('Creating organization').start()\n const newOrganization = await createOrganization(organizationName)\n spin.succeed()\n return newOrganization\n}\n\nexport async function getOrganization({\n isUnattended,\n output,\n requestedId,\n user,\n}: GetOrganizationOptions) {\n // Get available organizations\n const spin = spinner('Loading organizations').start()\n let organizations: ProjectOrganization[]\n try {\n organizations = await listOrganizations()\n spin.succeed()\n } catch (error) {\n spin.fail()\n debug('Error retrieving organization list', error)\n throw error\n }\n\n // If organization is specified, validate it\n if (requestedId) {\n const org = organizations.find((o) => o.id === requestedId || o.slug === requestedId)\n if (org) return org\n\n throw new Error(`Organization \"${requestedId}\" not found or you don't have access to it`)\n }\n\n // If the user has no organizations, prompt them to create one with the same name as\n // their user, but allow them to customize it if they want\n if (organizations.length === 0) {\n if (isUnattended) {\n throw new Error(\n 'No organizations are available. Create an organization at https://www.sanity.io/manage, then pass its ID or slug with --organization.',\n )\n }\n\n output.log('You need to create an organization to create projects.')\n return promptAndCreateNewOrganization(user)\n }\n\n // If the user has organizations, let them choose from them, but also allow them to\n // create a new one in case they do not have access to any of them, or they want to\n // create a personal/other organization.\n debug(`User has ${organizations.length} organization(s), checking attach access`)\n const withGrantInfo = await getOrganizationsWithAttachGrantInfo(organizations)\n const withAttach = withGrantInfo.filter(({hasAttachGrant}) => hasAttachGrant)\n\n debug('User has attach access to %d organizations.', withAttach.length)\n const organizationChoices = getOrganizationChoices(withGrantInfo)\n\n if (isUnattended) {\n if (withAttach.length > 1) {\n throw new Error(\n 'Multiple organizations are available. Select one with --organization <slug|id>.',\n )\n }\n\n return withAttach[0]?.organization\n }\n\n // If the user only has a single organization (and they have attach access to it),\n // we'll default to that one. Otherwise, we'll default to the organization with the\n // same name as the user if it exists.\n const defaultOrganizationId =\n withAttach.length === 1\n ? withAttach[0].organization.id\n : findOrganizationByUserName(organizations, user)\n\n const chosenOrg = await select({\n choices: organizationChoices,\n default: defaultOrganizationId || undefined,\n message: 'Select organization:',\n })\n\n if (chosenOrg === '-new-') {\n return promptAndCreateNewOrganization(user)\n }\n\n return organizations.find((org) => org.id === chosenOrg)\n}\n"],"names":["subdebug","select","spinner","promptForOrganizationName","createOrganization","listOrganizations","findOrganizationByUserName","getOrganizationChoices","getOrganizationsWithAttachGrantInfo","debug","promptAndCreateNewOrganization","user","organizationName","spin","start","newOrganization","succeed","getOrganization","isUnattended","output","requestedId","organizations","error","fail","org","find","o","id","slug","Error","length","log","withGrantInfo","withAttach","filter","hasAttachGrant","organizationChoices","organization","defaultOrganizationId","chosenOrg","choices","default","undefined","message"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,yBAAwB;AAE/C,SAAQC,MAAM,EAAEC,OAAO,QAAO,sBAAqB;AAEnD,SAAQC,yBAAyB,QAAO,6CAA4C;AACpF,SACEC,kBAAkB,EAClBC,iBAAiB,QAEZ,kCAAiC;AACxC,SAAQC,0BAA0B,QAAO,kCAAiC;AAC1E,SAAQC,sBAAsB,QAAO,8BAA6B;AAClE,SAAQC,mCAAmC,QAAO,2CAA0C;AAE5F,MAAMC,QAAQT,SAAS;AASvB,MAAMU,iCAAiC,OAAOC;IAC5C,MAAMC,mBAAmB,MAAMT,0BAA0BQ;IACzD,MAAME,OAAOX,QAAQ,yBAAyBY,KAAK;IACnD,MAAMC,kBAAkB,MAAMX,mBAAmBQ;IACjDC,KAAKG,OAAO;IACZ,OAAOD;AACT;AAEA,OAAO,eAAeE,gBAAgB,EACpCC,YAAY,EACZC,MAAM,EACNC,WAAW,EACXT,IAAI,EACmB;IACvB,8BAA8B;IAC9B,MAAME,OAAOX,QAAQ,yBAAyBY,KAAK;IACnD,IAAIO;IACJ,IAAI;QACFA,gBAAgB,MAAMhB;QACtBQ,KAAKG,OAAO;IACd,EAAE,OAAOM,OAAO;QACdT,KAAKU,IAAI;QACTd,MAAM,sCAAsCa;QAC5C,MAAMA;IACR;IAEA,4CAA4C;IAC5C,IAAIF,aAAa;QACf,MAAMI,MAAMH,cAAcI,IAAI,CAAC,CAACC,IAAMA,EAAEC,EAAE,KAAKP,eAAeM,EAAEE,IAAI,KAAKR;QACzE,IAAII,KAAK,OAAOA;QAEhB,MAAM,IAAIK,MAAM,CAAC,cAAc,EAAET,YAAY,0CAA0C,CAAC;IAC1F;IAEA,oFAAoF;IACpF,0DAA0D;IAC1D,IAAIC,cAAcS,MAAM,KAAK,GAAG;QAC9B,IAAIZ,cAAc;YAChB,MAAM,IAAIW,MACR;QAEJ;QAEAV,OAAOY,GAAG,CAAC;QACX,OAAOrB,+BAA+BC;IACxC;IAEA,mFAAmF;IACnF,mFAAmF;IACnF,wCAAwC;IACxCF,MAAM,CAAC,SAAS,EAAEY,cAAcS,MAAM,CAAC,wCAAwC,CAAC;IAChF,MAAME,gBAAgB,MAAMxB,oCAAoCa;IAChE,MAAMY,aAAaD,cAAcE,MAAM,CAAC,CAAC,EAACC,cAAc,EAAC,GAAKA;IAE9D1B,MAAM,+CAA+CwB,WAAWH,MAAM;IACtE,MAAMM,sBAAsB7B,uBAAuByB;IAEnD,IAAId,cAAc;QAChB,IAAIe,WAAWH,MAAM,GAAG,GAAG;YACzB,MAAM,IAAID,MACR;QAEJ;QAEA,OAAOI,UAAU,CAAC,EAAE,EAAEI;IACxB;IAEA,kFAAkF;IAClF,mFAAmF;IACnF,sCAAsC;IACtC,MAAMC,wBACJL,WAAWH,MAAM,KAAK,IAClBG,UAAU,CAAC,EAAE,CAACI,YAAY,CAACV,EAAE,GAC7BrB,2BAA2Be,eAAeV;IAEhD,MAAM4B,YAAY,MAAMtC,OAAO;QAC7BuC,SAASJ;QACTK,SAASH,yBAAyBI;QAClCC,SAAS;IACX;IAEA,IAAIJ,cAAc,SAAS;QACzB,OAAO7B,+BAA+BC;IACxC;IAEA,OAAOU,cAAcI,IAAI,CAAC,CAACD,MAAQA,IAAIG,EAAE,KAAKY;AAChD"}
@@ -0,0 +1,20 @@
1
+ export function validateOrganizationSlug(input) {
2
+ if (!input || input.trim() === '') {
3
+ return 'Organization slug cannot be empty';
4
+ }
5
+ if (input !== input.toLowerCase()) {
6
+ return 'Organization slug must be lowercase';
7
+ }
8
+ if (/\s/.test(input)) {
9
+ return 'Organization slug cannot contain spaces';
10
+ }
11
+ if (!/^[a-z0-9-]+$/.test(input)) {
12
+ return 'Organization slug may only contain lowercase letters, numbers, and dashes';
13
+ }
14
+ if (input.startsWith('-') || input.endsWith('-')) {
15
+ return 'Organization slug cannot start or end with a dash';
16
+ }
17
+ return true;
18
+ }
19
+
20
+ //# sourceMappingURL=validateOrganizationSlug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/organizations/validateOrganizationSlug.ts"],"sourcesContent":["export function validateOrganizationSlug(input: string): string | true {\n if (!input || input.trim() === '') {\n return 'Organization slug cannot be empty'\n }\n if (input !== input.toLowerCase()) {\n return 'Organization slug must be lowercase'\n }\n if (/\\s/.test(input)) {\n return 'Organization slug cannot contain spaces'\n }\n if (!/^[a-z0-9-]+$/.test(input)) {\n return 'Organization slug may only contain lowercase letters, numbers, and dashes'\n }\n if (input.startsWith('-') || input.endsWith('-')) {\n return 'Organization slug cannot start or end with a dash'\n }\n return true\n}\n"],"names":["validateOrganizationSlug","input","trim","toLowerCase","test","startsWith","endsWith"],"mappings":"AAAA,OAAO,SAASA,yBAAyBC,KAAa;IACpD,IAAI,CAACA,SAASA,MAAMC,IAAI,OAAO,IAAI;QACjC,OAAO;IACT;IACA,IAAID,UAAUA,MAAME,WAAW,IAAI;QACjC,OAAO;IACT;IACA,IAAI,KAAKC,IAAI,CAACH,QAAQ;QACpB,OAAO;IACT;IACA,IAAI,CAAC,eAAeG,IAAI,CAACH,QAAQ;QAC/B,OAAO;IACT;IACA,IAAIA,MAAMI,UAAU,CAAC,QAAQJ,MAAMK,QAAQ,CAAC,MAAM;QAChD,OAAO;IACT;IACA,OAAO;AACT"}
@@ -1,14 +1,46 @@
1
+ import { SANITY_CACHE_DIR } from '@sanity/cli-build/_internal/build';
2
+ import { isWorkbenchApp } from '@sanity/workbench-cli';
1
3
  import { gracefulServerDeath } from '../../server/gracefulServerDeath.js';
2
4
  import { startPreviewServer } from '../../server/previewServer.js';
5
+ import { checkForDeprecatedAppId } from '../../util/appId.js';
6
+ import { determineIsApp } from '../../util/determineIsApp.js';
7
+ import { resolveReactStrictMode } from '../../util/resolveReactStrictMode.js';
8
+ import { extractCoreAppManifest } from '../manifest/extractCoreAppManifest.js';
9
+ import { extractStudioManifest } from '../manifest/extractStudioManifest.js';
3
10
  import { getPreviewServerConfig } from './getPreviewServerConfig.js';
4
11
  export async function previewAction(options) {
5
- const { cliConfig, flags, outDir, workDir } = options;
12
+ const { cliConfig, flags, outDir, output, workDir } = options;
6
13
  const config = getPreviewServerConfig({
7
14
  cliConfig,
8
15
  flags,
9
16
  rootDir: outDir,
10
17
  workDir
11
18
  });
19
+ if (isWorkbenchApp(cliConfig?.app)) {
20
+ const isApp = determineIsApp(cliConfig);
21
+ // Lazy so a non-workbench `sanity start` never loads the package. `doImport`
22
+ // is path-based and doesn't apply to a bare specifier.
23
+ // eslint-disable-next-line no-restricted-syntax
24
+ const { startWorkbenchPreview } = await import('@sanity/workbench-cli/preview');
25
+ return startWorkbenchPreview({
26
+ cacheDir: `${SANITY_CACHE_DIR}/vite`,
27
+ checkForDeprecatedAppId: ()=>checkForDeprecatedAppId({
28
+ cliConfig,
29
+ output
30
+ }),
31
+ cliConfig,
32
+ extractManifest: isApp ? ({ workDir: wd })=>extractCoreAppManifest({
33
+ workDir: wd
34
+ }) : (params)=>extractStudioManifest(params),
35
+ httpHost: config.httpHost,
36
+ httpPort: config.httpPort,
37
+ isApp,
38
+ outDir,
39
+ output,
40
+ reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,
41
+ workDir
42
+ });
43
+ }
12
44
  try {
13
45
  const server = await startPreviewServer(config);
14
46
  return server;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/preview/previewAction.ts"],"sourcesContent":["import {type CliConfig} from '@sanity/cli-core'\n\nimport {gracefulServerDeath} from '../../server/gracefulServerDeath.js'\nimport {startPreviewServer} from '../../server/previewServer.js'\nimport {getPreviewServerConfig} from './getPreviewServerConfig.js'\nimport {type PreviewFlags} from './types.js'\n\ninterface PreviewActionOptions {\n cliConfig: CliConfig\n flags: PreviewFlags\n outDir: string\n workDir: string\n}\n\nexport async function previewAction(options: PreviewActionOptions) {\n const {cliConfig, flags, outDir, workDir} = options\n\n const config = getPreviewServerConfig({cliConfig, flags, rootDir: outDir, workDir})\n\n try {\n const server = await startPreviewServer(config)\n return server\n } catch (err) {\n throw gracefulServerDeath('preview', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["gracefulServerDeath","startPreviewServer","getPreviewServerConfig","previewAction","options","cliConfig","flags","outDir","workDir","config","rootDir","server","err","httpHost","httpPort"],"mappings":"AAEA,SAAQA,mBAAmB,QAAO,sCAAqC;AACvE,SAAQC,kBAAkB,QAAO,gCAA+B;AAChE,SAAQC,sBAAsB,QAAO,8BAA6B;AAUlE,OAAO,eAAeC,cAAcC,OAA6B;IAC/D,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGJ;IAE5C,MAAMK,SAASP,uBAAuB;QAACG;QAAWC;QAAOI,SAASH;QAAQC;IAAO;IAEjF,IAAI;QACF,MAAMG,SAAS,MAAMV,mBAAmBQ;QACxC,OAAOE;IACT,EAAE,OAAOC,KAAK;QACZ,MAAMZ,oBAAoB,WAAWS,OAAOI,QAAQ,EAAEJ,OAAOK,QAAQ,EAAEF;IACzE;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/preview/previewAction.ts"],"sourcesContent":["import {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\nimport {type CliConfig, type Output} from '@sanity/cli-core'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {gracefulServerDeath} from '../../server/gracefulServerDeath.js'\nimport {type PreviewServer, startPreviewServer} from '../../server/previewServer.js'\nimport {checkForDeprecatedAppId} from '../../util/appId.js'\nimport {determineIsApp} from '../../util/determineIsApp.js'\nimport {resolveReactStrictMode} from '../../util/resolveReactStrictMode.js'\nimport {extractCoreAppManifest} from '../manifest/extractCoreAppManifest.js'\nimport {extractStudioManifest} from '../manifest/extractStudioManifest.js'\nimport {getPreviewServerConfig} from './getPreviewServerConfig.js'\nimport {type PreviewFlags} from './types.js'\n\ninterface PreviewActionOptions {\n cliConfig: CliConfig\n flags: PreviewFlags\n outDir: string\n output: Output\n workDir: string\n}\n\nexport async function previewAction(\n options: PreviewActionOptions,\n): Promise<PreviewServer | {close: () => Promise<void>}> {\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const config = getPreviewServerConfig({cliConfig, flags, rootDir: outDir, workDir})\n\n if (isWorkbenchApp(cliConfig?.app)) {\n const isApp = determineIsApp(cliConfig)\n // Lazy so a non-workbench `sanity start` never loads the package. `doImport`\n // is path-based and doesn't apply to a bare specifier.\n // eslint-disable-next-line no-restricted-syntax\n const {startWorkbenchPreview} = await import('@sanity/workbench-cli/preview')\n return startWorkbenchPreview({\n cacheDir: `${SANITY_CACHE_DIR}/vite`,\n checkForDeprecatedAppId: () => checkForDeprecatedAppId({cliConfig, output}),\n cliConfig,\n extractManifest: isApp\n ? ({workDir: wd}) => extractCoreAppManifest({workDir: wd})\n : (params) => extractStudioManifest(params),\n httpHost: config.httpHost,\n httpPort: config.httpPort,\n isApp,\n outDir,\n output,\n reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,\n workDir,\n })\n }\n\n try {\n const server = await startPreviewServer(config)\n return server\n } catch (err) {\n throw gracefulServerDeath('preview', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["SANITY_CACHE_DIR","isWorkbenchApp","gracefulServerDeath","startPreviewServer","checkForDeprecatedAppId","determineIsApp","resolveReactStrictMode","extractCoreAppManifest","extractStudioManifest","getPreviewServerConfig","previewAction","options","cliConfig","flags","outDir","output","workDir","config","rootDir","app","isApp","startWorkbenchPreview","cacheDir","extractManifest","wd","params","httpHost","httpPort","reactStrictMode","server","err"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,oCAAmC;AAElE,SAAQC,cAAc,QAAO,wBAAuB;AAEpD,SAAQC,mBAAmB,QAAO,sCAAqC;AACvE,SAA4BC,kBAAkB,QAAO,gCAA+B;AACpF,SAAQC,uBAAuB,QAAO,sBAAqB;AAC3D,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,sBAAsB,QAAO,uCAAsC;AAC3E,SAAQC,sBAAsB,QAAO,wCAAuC;AAC5E,SAAQC,qBAAqB,QAAO,uCAAsC;AAC1E,SAAQC,sBAAsB,QAAO,8BAA6B;AAWlE,OAAO,eAAeC,cACpBC,OAA6B;IAE7B,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEpD,MAAMM,SAASR,uBAAuB;QAACG;QAAWC;QAAOK,SAASJ;QAAQE;IAAO;IAEjF,IAAIf,eAAeW,WAAWO,MAAM;QAClC,MAAMC,QAAQf,eAAeO;QAC7B,6EAA6E;QAC7E,uDAAuD;QACvD,gDAAgD;QAChD,MAAM,EAACS,qBAAqB,EAAC,GAAG,MAAM,MAAM,CAAC;QAC7C,OAAOA,sBAAsB;YAC3BC,UAAU,GAAGtB,iBAAiB,KAAK,CAAC;YACpCI,yBAAyB,IAAMA,wBAAwB;oBAACQ;oBAAWG;gBAAM;YACzEH;YACAW,iBAAiBH,QACb,CAAC,EAACJ,SAASQ,EAAE,EAAC,GAAKjB,uBAAuB;oBAACS,SAASQ;gBAAE,KACtD,CAACC,SAAWjB,sBAAsBiB;YACtCC,UAAUT,OAAOS,QAAQ;YACzBC,UAAUV,OAAOU,QAAQ;YACzBP;YACAN;YACAC;YACAa,iBAAiBtB,uBAAuBM,cAAc;YACtDI;QACF;IACF;IAEA,IAAI;QACF,MAAMa,SAAS,MAAM1B,mBAAmBc;QACxC,OAAOY;IACT,EAAE,OAAOC,KAAK;QACZ,MAAM5B,oBAAoB,WAAWe,OAAOS,QAAQ,EAAET,OAAOU,QAAQ,EAAEG;IACzE;AACF"}
@@ -26,7 +26,7 @@ export async function listSchemas(options) {
26
26
  }
27
27
  });
28
28
  const schemas = await getDatasetSchemas(projectDatasets, id);
29
- const parsedSchemas = parseSchemas(schemas, output);
29
+ const parsedSchemas = parseSchemas(schemas, output, json);
30
30
  if (parsedSchemas.length === 0) {
31
31
  const datasetString = getDatasetsOutString(projectDatasets.map((dataset)=>dataset.dataset));
32
32
  throw new Error(id ? `Schema for id "${id}" not found in ${datasetString}` : `No schemas found in ${datasetString}`);
@@ -56,16 +56,18 @@ async function getDatasetSchemas(projectDatasets, id) {
56
56
  }
57
57
  }));
58
58
  }
59
- function parseSchemas(schemas, output) {
59
+ function parseSchemas(schemas, output, json) {
60
60
  return schemas.map((schema)=>{
61
61
  if (schema.status === 'fulfilled') return schema.value;
62
62
  const error = schema.reason;
63
63
  if (error instanceof DatasetError) {
64
64
  if ('cause' in error && error.cause && typeof error.cause === 'object' && 'statusCode' in error.cause && error.cause.statusCode === 401) {
65
- output.log(styleText('yellow', `${logSymbols.warning} No permissions to read schema from "${error.dataset}". ${SCHEMA_PERMISSION_HELP_TEXT}:\n ${styleText('red', `${error.message}`)}`));
65
+ const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output);
66
+ logDiagnostic(styleText('yellow', `${logSymbols.warning} ↳ No permissions to read schema from "${error.dataset}". ${SCHEMA_PERMISSION_HELP_TEXT}:\n ${styleText('red', `${error.message}`)}`));
66
67
  return [];
67
68
  }
68
- output.log(styleText('red', `↳ Failed to fetch schema from "${error.dataset}":\n ${error.message}`));
69
+ const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output);
70
+ logDiagnostic(styleText('red', `↳ Failed to fetch schema from "${error.dataset}":\n ${error.message}`));
69
71
  return [];
70
72
  } else {
71
73
  //hubris inc: given the try-catch wrapping all the full promise "this should never happen"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/schema/listSchemas.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, studioWorkerTask} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {type Workspace} from 'sanity'\n\nimport {getSchemas} from '../../services/schemas.js'\nimport {isDefined} from '../manifest/schemaTypeHelpers.js'\nimport {type StoredWorkspaceSchema} from '../manifest/types.js'\nimport {type UniqWorkspaceWorkerData} from './types.js'\nimport {getDatasetsOutString} from './utils/schemaStoreOutStrings.js'\nimport {SCHEMA_PERMISSION_HELP_TEXT} from './utils/schemaStoreValidation.js'\n\ninterface ListSchemasOptions {\n configPath: string\n json: boolean\n output: Output\n workDir: string\n\n id?: string\n}\n\nclass DatasetError extends Error {\n public dataset: string\n public projectId: string\n constructor(args: {dataset: string; options?: ErrorOptions; projectId: string}) {\n super((args.options?.cause as {message?: string})?.message, args.options)\n this.projectId = args.projectId\n this.dataset = args.dataset\n this.name = 'DatasetError'\n }\n}\n\nexport async function listSchemas(options: ListSchemasOptions): Promise<void> {\n const {configPath, id, json, output, workDir} = options\n\n const projectDatasets = await studioWorkerTask<(Workspace & {key: string})[]>(\n new URL('uniqueWorkspaces.worker.js', import.meta.url),\n {\n name: 'uniqueWorkspaces',\n studioRootPath: workDir,\n workerData: {configPath} satisfies UniqWorkspaceWorkerData,\n },\n )\n\n const schemas = await getDatasetSchemas(projectDatasets, id)\n const parsedSchemas = parseSchemas(schemas, output)\n\n if (parsedSchemas.length === 0) {\n const datasetString = getDatasetsOutString(projectDatasets.map((dataset) => dataset.dataset))\n\n throw new Error(\n id\n ? `Schema for id \"${id}\" not found in ${datasetString}`\n : `No schemas found in ${datasetString}`,\n )\n }\n\n if (json) {\n output.log(JSON.stringify(id ? parsedSchemas[0] : parsedSchemas, null, 2))\n } else {\n printSchemas({output, schemas: parsedSchemas, workspaces: projectDatasets})\n }\n}\n\nasync function getDatasetSchemas(projectDatasets: Workspace[], id?: string) {\n return Promise.allSettled(\n projectDatasets.map(async ({dataset, projectId}) => {\n try {\n return await getSchemas(dataset, projectId, id)\n } catch (error) {\n throw new DatasetError({dataset, options: {cause: error}, projectId})\n }\n }),\n )\n}\n\nfunction parseSchemas(schemas: PromiseSettledResult<StoredWorkspaceSchema[]>[], output: Output) {\n return schemas\n .map((schema) => {\n if (schema.status === 'fulfilled') return schema.value\n\n const error = schema.reason\n\n if (error instanceof DatasetError) {\n if (\n 'cause' in error &&\n error.cause &&\n typeof error.cause === 'object' &&\n 'statusCode' in error.cause &&\n error.cause.statusCode === 401\n ) {\n output.log(\n styleText(\n 'yellow',\n `${logSymbols.warning} ↳ No permissions to read schema from \"${error.dataset}\". ${\n SCHEMA_PERMISSION_HELP_TEXT\n }:\\n ${styleText('red', `${error.message}`)}`,\n ),\n )\n return []\n }\n\n output.log(\n styleText('red', `↳ Failed to fetch schema from \"${error.dataset}\":\\n ${error.message}`),\n )\n return []\n } else {\n //hubris inc: given the try-catch wrapping all the full promise \"this should never happen\"\n throw error\n }\n })\n .filter((schema) => isDefined(schema))\n .flat()\n}\n\nfunction printSchemas({\n output,\n schemas,\n workspaces,\n}: {\n output: Output\n schemas: StoredWorkspaceSchema[]\n workspaces: Workspace[]\n}) {\n const rows = schemas\n .toSorted((a, b) => -(a._createdAt || '').localeCompare(b._createdAt || ''))\n .map(({_createdAt: createdAt, _id: id, workspace}) => {\n const workspaceData = workspaces.find((w) => w.name === workspace.name)\n if (!workspaceData) return\n\n return {\n CreatedAt: createdAt,\n Dataset: workspaceData.dataset,\n Id: id,\n ProjectId: workspaceData.projectId,\n Workspace: workspace.name,\n }\n })\n .filter((schema) => isDefined(schema))\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'Id'},\n {alignment: 'left', name: 'Workspace'},\n {alignment: 'left', name: 'Dataset'},\n {alignment: 'left', name: 'ProjectId'},\n {alignment: 'left', name: 'CreatedAt'},\n ],\n })\n\n table.addRows(rows)\n output.log(table.render())\n}\n"],"names":["styleText","studioWorkerTask","logSymbols","Table","getSchemas","isDefined","getDatasetsOutString","SCHEMA_PERMISSION_HELP_TEXT","DatasetError","Error","dataset","projectId","args","options","cause","message","name","listSchemas","configPath","id","json","output","workDir","projectDatasets","URL","url","studioRootPath","workerData","schemas","getDatasetSchemas","parsedSchemas","parseSchemas","length","datasetString","map","log","JSON","stringify","printSchemas","workspaces","Promise","allSettled","error","schema","status","value","reason","statusCode","warning","filter","flat","rows","toSorted","a","b","_createdAt","localeCompare","createdAt","_id","workspace","workspaceData","find","w","CreatedAt","Dataset","Id","ProjectId","Workspace","table","columns","alignment","addRows","render"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/schema/listSchemas.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, studioWorkerTask} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {type Workspace} from 'sanity'\n\nimport {getSchemas} from '../../services/schemas.js'\nimport {isDefined} from '../manifest/schemaTypeHelpers.js'\nimport {type StoredWorkspaceSchema} from '../manifest/types.js'\nimport {type UniqWorkspaceWorkerData} from './types.js'\nimport {getDatasetsOutString} from './utils/schemaStoreOutStrings.js'\nimport {SCHEMA_PERMISSION_HELP_TEXT} from './utils/schemaStoreValidation.js'\n\ninterface ListSchemasOptions {\n configPath: string\n json: boolean\n output: Output\n workDir: string\n\n id?: string\n}\n\nclass DatasetError extends Error {\n public dataset: string\n public projectId: string\n constructor(args: {dataset: string; options?: ErrorOptions; projectId: string}) {\n super((args.options?.cause as {message?: string})?.message, args.options)\n this.projectId = args.projectId\n this.dataset = args.dataset\n this.name = 'DatasetError'\n }\n}\n\nexport async function listSchemas(options: ListSchemasOptions): Promise<void> {\n const {configPath, id, json, output, workDir} = options\n\n const projectDatasets = await studioWorkerTask<(Workspace & {key: string})[]>(\n new URL('uniqueWorkspaces.worker.js', import.meta.url),\n {\n name: 'uniqueWorkspaces',\n studioRootPath: workDir,\n workerData: {configPath} satisfies UniqWorkspaceWorkerData,\n },\n )\n\n const schemas = await getDatasetSchemas(projectDatasets, id)\n const parsedSchemas = parseSchemas(schemas, output, json)\n\n if (parsedSchemas.length === 0) {\n const datasetString = getDatasetsOutString(projectDatasets.map((dataset) => dataset.dataset))\n\n throw new Error(\n id\n ? `Schema for id \"${id}\" not found in ${datasetString}`\n : `No schemas found in ${datasetString}`,\n )\n }\n\n if (json) {\n output.log(JSON.stringify(id ? parsedSchemas[0] : parsedSchemas, null, 2))\n } else {\n printSchemas({output, schemas: parsedSchemas, workspaces: projectDatasets})\n }\n}\n\nasync function getDatasetSchemas(projectDatasets: Workspace[], id?: string) {\n return Promise.allSettled(\n projectDatasets.map(async ({dataset, projectId}) => {\n try {\n return await getSchemas(dataset, projectId, id)\n } catch (error) {\n throw new DatasetError({dataset, options: {cause: error}, projectId})\n }\n }),\n )\n}\n\nfunction parseSchemas(\n schemas: PromiseSettledResult<StoredWorkspaceSchema[]>[],\n output: Output,\n json: boolean,\n) {\n return schemas\n .map((schema) => {\n if (schema.status === 'fulfilled') return schema.value\n\n const error = schema.reason\n\n if (error instanceof DatasetError) {\n if (\n 'cause' in error &&\n error.cause &&\n typeof error.cause === 'object' &&\n 'statusCode' in error.cause &&\n error.cause.statusCode === 401\n ) {\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText(\n 'yellow',\n `${logSymbols.warning} ↳ No permissions to read schema from \"${error.dataset}\". ${\n SCHEMA_PERMISSION_HELP_TEXT\n }:\\n ${styleText('red', `${error.message}`)}`,\n ),\n )\n return []\n }\n\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText('red', `↳ Failed to fetch schema from \"${error.dataset}\":\\n ${error.message}`),\n )\n return []\n } else {\n //hubris inc: given the try-catch wrapping all the full promise \"this should never happen\"\n throw error\n }\n })\n .filter((schema) => isDefined(schema))\n .flat()\n}\n\nfunction printSchemas({\n output,\n schemas,\n workspaces,\n}: {\n output: Output\n schemas: StoredWorkspaceSchema[]\n workspaces: Workspace[]\n}) {\n const rows = schemas\n .toSorted((a, b) => -(a._createdAt || '').localeCompare(b._createdAt || ''))\n .map(({_createdAt: createdAt, _id: id, workspace}) => {\n const workspaceData = workspaces.find((w) => w.name === workspace.name)\n if (!workspaceData) return\n\n return {\n CreatedAt: createdAt,\n Dataset: workspaceData.dataset,\n Id: id,\n ProjectId: workspaceData.projectId,\n Workspace: workspace.name,\n }\n })\n .filter((schema) => isDefined(schema))\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'Id'},\n {alignment: 'left', name: 'Workspace'},\n {alignment: 'left', name: 'Dataset'},\n {alignment: 'left', name: 'ProjectId'},\n {alignment: 'left', name: 'CreatedAt'},\n ],\n })\n\n table.addRows(rows)\n output.log(table.render())\n}\n"],"names":["styleText","studioWorkerTask","logSymbols","Table","getSchemas","isDefined","getDatasetsOutString","SCHEMA_PERMISSION_HELP_TEXT","DatasetError","Error","dataset","projectId","args","options","cause","message","name","listSchemas","configPath","id","json","output","workDir","projectDatasets","URL","url","studioRootPath","workerData","schemas","getDatasetSchemas","parsedSchemas","parseSchemas","length","datasetString","map","log","JSON","stringify","printSchemas","workspaces","Promise","allSettled","error","schema","status","value","reason","statusCode","logDiagnostic","warn","bind","warning","filter","flat","rows","toSorted","a","b","_createdAt","localeCompare","createdAt","_id","workspace","workspaceData","find","w","CreatedAt","Dataset","Id","ProjectId","Workspace","table","columns","alignment","addRows","render"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAqBC,gBAAgB,QAAO,mBAAkB;AAC9D,SAAQC,UAAU,QAAO,sBAAqB;AAC9C,SAAQC,KAAK,QAAO,wBAAuB;AAG3C,SAAQC,UAAU,QAAO,4BAA2B;AACpD,SAAQC,SAAS,QAAO,mCAAkC;AAG1D,SAAQC,oBAAoB,QAAO,mCAAkC;AACrE,SAAQC,2BAA2B,QAAO,mCAAkC;AAW5E,MAAMC,qBAAqBC;IAClBC,QAAe;IACfC,UAAiB;IACxB,YAAYC,IAAkE,CAAE;QAC9E,KAAK,CAAEA,KAAKC,OAAO,EAAEC,OAA8BC,SAASH,KAAKC,OAAO;QACxE,IAAI,CAACF,SAAS,GAAGC,KAAKD,SAAS;QAC/B,IAAI,CAACD,OAAO,GAAGE,KAAKF,OAAO;QAC3B,IAAI,CAACM,IAAI,GAAG;IACd;AACF;AAEA,OAAO,eAAeC,YAAYJ,OAA2B;IAC3D,MAAM,EAACK,UAAU,EAAEC,EAAE,EAAEC,IAAI,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGT;IAEhD,MAAMU,kBAAkB,MAAMtB,iBAC5B,IAAIuB,IAAI,8BAA8B,YAAYC,GAAG,GACrD;QACET,MAAM;QACNU,gBAAgBJ;QAChBK,YAAY;YAACT;QAAU;IACzB;IAGF,MAAMU,UAAU,MAAMC,kBAAkBN,iBAAiBJ;IACzD,MAAMW,gBAAgBC,aAAaH,SAASP,QAAQD;IAEpD,IAAIU,cAAcE,MAAM,KAAK,GAAG;QAC9B,MAAMC,gBAAgB3B,qBAAqBiB,gBAAgBW,GAAG,CAAC,CAACxB,UAAYA,QAAQA,OAAO;QAE3F,MAAM,IAAID,MACRU,KACI,CAAC,eAAe,EAAEA,GAAG,eAAe,EAAEc,eAAe,GACrD,CAAC,oBAAoB,EAAEA,eAAe;IAE9C;IAEA,IAAIb,MAAM;QACRC,OAAOc,GAAG,CAACC,KAAKC,SAAS,CAAClB,KAAKW,aAAa,CAAC,EAAE,GAAGA,eAAe,MAAM;IACzE,OAAO;QACLQ,aAAa;YAACjB;YAAQO,SAASE;YAAeS,YAAYhB;QAAe;IAC3E;AACF;AAEA,eAAeM,kBAAkBN,eAA4B,EAAEJ,EAAW;IACxE,OAAOqB,QAAQC,UAAU,CACvBlB,gBAAgBW,GAAG,CAAC,OAAO,EAACxB,OAAO,EAAEC,SAAS,EAAC;QAC7C,IAAI;YACF,OAAO,MAAMP,WAAWM,SAASC,WAAWQ;QAC9C,EAAE,OAAOuB,OAAO;YACd,MAAM,IAAIlC,aAAa;gBAACE;gBAASG,SAAS;oBAACC,OAAO4B;gBAAK;gBAAG/B;YAAS;QACrE;IACF;AAEJ;AAEA,SAASoB,aACPH,OAAwD,EACxDP,MAAc,EACdD,IAAa;IAEb,OAAOQ,QACJM,GAAG,CAAC,CAACS;QACJ,IAAIA,OAAOC,MAAM,KAAK,aAAa,OAAOD,OAAOE,KAAK;QAEtD,MAAMH,QAAQC,OAAOG,MAAM;QAE3B,IAAIJ,iBAAiBlC,cAAc;YACjC,IACE,WAAWkC,SACXA,MAAM5B,KAAK,IACX,OAAO4B,MAAM5B,KAAK,KAAK,YACvB,gBAAgB4B,MAAM5B,KAAK,IAC3B4B,MAAM5B,KAAK,CAACiC,UAAU,KAAK,KAC3B;gBACA,MAAMC,gBAAgB5B,OAAOC,OAAO4B,IAAI,CAACC,IAAI,CAAC7B,UAAUA,OAAOc,GAAG,CAACe,IAAI,CAAC7B;gBACxE2B,cACEhD,UACE,UACA,GAAGE,WAAWiD,OAAO,CAAC,uCAAuC,EAAET,MAAMhC,OAAO,CAAC,GAAG,EAC9EH,4BACD,KAAK,EAAEP,UAAU,OAAO,GAAG0C,MAAM3B,OAAO,EAAE,GAAG;gBAGlD,OAAO,EAAE;YACX;YAEA,MAAMiC,gBAAgB5B,OAAOC,OAAO4B,IAAI,CAACC,IAAI,CAAC7B,UAAUA,OAAOc,GAAG,CAACe,IAAI,CAAC7B;YACxE2B,cACEhD,UAAU,OAAO,CAAC,+BAA+B,EAAE0C,MAAMhC,OAAO,CAAC,MAAM,EAAEgC,MAAM3B,OAAO,EAAE;YAE1F,OAAO,EAAE;QACX,OAAO;YACL,0FAA0F;YAC1F,MAAM2B;QACR;IACF,GACCU,MAAM,CAAC,CAACT,SAAWtC,UAAUsC,SAC7BU,IAAI;AACT;AAEA,SAASf,aAAa,EACpBjB,MAAM,EACNO,OAAO,EACPW,UAAU,EAKX;IACC,MAAMe,OAAO1B,QACV2B,QAAQ,CAAC,CAACC,GAAGC,IAAM,CAAC,AAACD,CAAAA,EAAEE,UAAU,IAAI,EAAC,EAAGC,aAAa,CAACF,EAAEC,UAAU,IAAI,KACvExB,GAAG,CAAC,CAAC,EAACwB,YAAYE,SAAS,EAAEC,KAAK1C,EAAE,EAAE2C,SAAS,EAAC;QAC/C,MAAMC,gBAAgBxB,WAAWyB,IAAI,CAAC,CAACC,IAAMA,EAAEjD,IAAI,KAAK8C,UAAU9C,IAAI;QACtE,IAAI,CAAC+C,eAAe;QAEpB,OAAO;YACLG,WAAWN;YACXO,SAASJ,cAAcrD,OAAO;YAC9B0D,IAAIjD;YACJkD,WAAWN,cAAcpD,SAAS;YAClC2D,WAAWR,UAAU9C,IAAI;QAC3B;IACF,GACCoC,MAAM,CAAC,CAACT,SAAWtC,UAAUsC;IAEhC,MAAM4B,QAAQ,IAAIpE,MAAM;QACtBqE,SAAS;YACP;gBAACC,WAAW;gBAAQzD,MAAM;YAAI;YAC9B;gBAACyD,WAAW;gBAAQzD,MAAM;YAAW;YACrC;gBAACyD,WAAW;gBAAQzD,MAAM;YAAS;YACnC;gBAACyD,WAAW;gBAAQzD,MAAM;YAAW;YACrC;gBAACyD,WAAW;gBAAQzD,MAAM;YAAW;SACtC;IACH;IAEAuD,MAAMG,OAAO,CAACpB;IACdjC,OAAOc,GAAG,CAACoC,MAAMI,MAAM;AACzB"}
@@ -1,3 +1,4 @@
1
+ import { exitCodes } from '@sanity/cli-core';
1
2
  import { getTokenRoles } from '../../services/tokens.js';
2
3
  /**
3
4
  * Validate a role name
@@ -16,7 +17,7 @@ import { getTokenRoles } from '../../services/tokens.js';
16
17
  }
17
18
  const availableRoles = robotRoles.map((r)=>r.name).join(', ');
18
19
  return output.error(`Invalid role "${roleName}". Available roles: ${availableRoles}`, {
19
- exit: 1
20
+ exit: exitCodes.USAGE_ERROR
20
21
  });
21
22
  }
22
23
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/tokens/validateRole.ts"],"sourcesContent":["import {type Output} from '@sanity/cli-core'\n\nimport {getTokenRoles} from '../../services/tokens.js'\n\n/**\n * Validate a role name\n * @param roleName - The role name to validate\n * @param projectId - The project ID\n * @param output - Output to raise the error through the calling command\n * @returns A promise that resolves to the validated role name\n *\n * @internal\n */\nexport async function validateRole(\n roleName: string,\n projectId: string,\n output: Output,\n): Promise<string> {\n const roles = await getTokenRoles(projectId)\n const robotRoles = roles.filter((role) => role.appliesToRobots)\n\n const role = robotRoles.find((r) => r.name === roleName)\n if (role) {\n return roleName\n }\n\n const availableRoles = robotRoles.map((r) => r.name).join(', ')\n return output.error(`Invalid role \"${roleName}\". Available roles: ${availableRoles}`, {exit: 1})\n}\n"],"names":["getTokenRoles","validateRole","roleName","projectId","output","roles","robotRoles","filter","role","appliesToRobots","find","r","name","availableRoles","map","join","error","exit"],"mappings":"AAEA,SAAQA,aAAa,QAAO,2BAA0B;AAEtD;;;;;;;;CAQC,GACD,OAAO,eAAeC,aACpBC,QAAgB,EAChBC,SAAiB,EACjBC,MAAc;IAEd,MAAMC,QAAQ,MAAML,cAAcG;IAClC,MAAMG,aAAaD,MAAME,MAAM,CAAC,CAACC,OAASA,KAAKC,eAAe;IAE9D,MAAMD,OAAOF,WAAWI,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKV;IAC/C,IAAIM,MAAM;QACR,OAAON;IACT;IAEA,MAAMW,iBAAiBP,WAAWQ,GAAG,CAAC,CAACH,IAAMA,EAAEC,IAAI,EAAEG,IAAI,CAAC;IAC1D,OAAOX,OAAOY,KAAK,CAAC,CAAC,cAAc,EAAEd,SAAS,oBAAoB,EAAEW,gBAAgB,EAAE;QAACI,MAAM;IAAC;AAChG"}
1
+ {"version":3,"sources":["../../../src/actions/tokens/validateRole.ts"],"sourcesContent":["import {exitCodes, type Output} from '@sanity/cli-core'\n\nimport {getTokenRoles} from '../../services/tokens.js'\n\n/**\n * Validate a role name\n * @param roleName - The role name to validate\n * @param projectId - The project ID\n * @param output - Output to raise the error through the calling command\n * @returns A promise that resolves to the validated role name\n *\n * @internal\n */\nexport async function validateRole(\n roleName: string,\n projectId: string,\n output: Output,\n): Promise<string> {\n const roles = await getTokenRoles(projectId)\n const robotRoles = roles.filter((role) => role.appliesToRobots)\n\n const role = robotRoles.find((r) => r.name === roleName)\n if (role) {\n return roleName\n }\n\n const availableRoles = robotRoles.map((r) => r.name).join(', ')\n return output.error(`Invalid role \"${roleName}\". Available roles: ${availableRoles}`, {\n exit: exitCodes.USAGE_ERROR,\n })\n}\n"],"names":["exitCodes","getTokenRoles","validateRole","roleName","projectId","output","roles","robotRoles","filter","role","appliesToRobots","find","r","name","availableRoles","map","join","error","exit","USAGE_ERROR"],"mappings":"AAAA,SAAQA,SAAS,QAAoB,mBAAkB;AAEvD,SAAQC,aAAa,QAAO,2BAA0B;AAEtD;;;;;;;;CAQC,GACD,OAAO,eAAeC,aACpBC,QAAgB,EAChBC,SAAiB,EACjBC,MAAc;IAEd,MAAMC,QAAQ,MAAML,cAAcG;IAClC,MAAMG,aAAaD,MAAME,MAAM,CAAC,CAACC,OAASA,KAAKC,eAAe;IAE9D,MAAMD,OAAOF,WAAWI,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKV;IAC/C,IAAIM,MAAM;QACR,OAAON;IACT;IAEA,MAAMW,iBAAiBP,WAAWQ,GAAG,CAAC,CAACH,IAAMA,EAAEC,IAAI,EAAEG,IAAI,CAAC;IAC1D,OAAOX,OAAOY,KAAK,CAAC,CAAC,cAAc,EAAEd,SAAS,oBAAoB,EAAEW,gBAAgB,EAAE;QACpFI,MAAMlB,UAAUmB,WAAW;IAC7B;AACF"}