@sanity/cli 6.0.0-alpha.3 → 6.0.0-alpha.5

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 (376) hide show
  1. package/dist/actions/auth/login/{index.js → login.js} +1 -1
  2. package/dist/actions/auth/login/{index.js.map → login.js.map} +1 -1
  3. package/dist/actions/dev/startStudioDevServer.js +3 -8
  4. package/dist/actions/dev/startStudioDevServer.js.map +1 -1
  5. package/dist/actions/dev/types.d.ts +1 -3
  6. package/dist/actions/dev/types.js.map +1 -1
  7. package/dist/actions/documents/validate.d.ts +0 -2
  8. package/dist/actions/documents/validate.js +21 -1
  9. package/dist/actions/documents/validate.js.map +1 -1
  10. package/dist/actions/exec/execScript.js +1 -1
  11. package/dist/actions/exec/execScript.js.map +1 -1
  12. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js +1 -1
  13. package/dist/actions/graphql/__tests__/getGraphQLAPIs.test.js.map +1 -1
  14. package/dist/actions/graphql/getGraphQLAPIs.js +1 -1
  15. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  16. package/dist/actions/manifest/extractManifest.js +1 -4
  17. package/dist/actions/manifest/extractManifest.js.map +1 -1
  18. package/dist/actions/organizations/getOrganizationChoices.d.ts +6 -0
  19. package/dist/actions/organizations/getOrganizationChoices.js +23 -0
  20. package/dist/actions/organizations/getOrganizationChoices.js.map +1 -0
  21. package/dist/actions/organizations/getOrganizationsWithAttachGrantInfo.d.ts +2 -0
  22. package/dist/actions/organizations/getOrganizationsWithAttachGrantInfo.js +9 -0
  23. package/dist/actions/organizations/getOrganizationsWithAttachGrantInfo.js.map +1 -0
  24. package/dist/actions/organizations/hasProjectAttachGrant.d.ts +1 -0
  25. package/dist/actions/organizations/hasProjectAttachGrant.js +24 -0
  26. package/dist/actions/organizations/hasProjectAttachGrant.js.map +1 -0
  27. package/dist/actions/schema/deleteSchemaAction.d.ts +13 -5
  28. package/dist/actions/schema/deleteSchemaAction.js +12 -17
  29. package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
  30. package/dist/actions/schema/deploySchemas.d.ts +15 -0
  31. package/dist/actions/schema/deploySchemas.js +98 -0
  32. package/dist/actions/schema/deploySchemas.js.map +1 -0
  33. package/dist/actions/schema/listSchemas.d.ts +12 -0
  34. package/dist/actions/schema/listSchemas.js +119 -0
  35. package/dist/actions/schema/listSchemas.js.map +1 -0
  36. package/dist/actions/schema/schemaStoreTypes.d.ts +0 -11
  37. package/dist/actions/schema/schemaStoreTypes.js.map +1 -1
  38. package/dist/actions/schema/utils/debug.d.ts +2 -0
  39. package/dist/actions/schema/utils/debug.js +5 -0
  40. package/dist/actions/schema/utils/debug.js.map +1 -0
  41. package/dist/actions/schema/utils/manifestExtractor.d.ts +3 -8
  42. package/dist/actions/schema/utils/manifestExtractor.js +12 -17
  43. package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
  44. package/dist/actions/schema/utils/manifestReader.d.ts +2 -9
  45. package/dist/actions/schema/utils/manifestReader.js +6 -12
  46. package/dist/actions/schema/utils/manifestReader.js.map +1 -1
  47. package/dist/actions/schema/utils/schemaStoreOutStrings.d.ts +0 -1
  48. package/dist/actions/schema/utils/schemaStoreOutStrings.js +1 -1
  49. package/dist/actions/schema/utils/schemaStoreOutStrings.js.map +1 -1
  50. package/dist/actions/schema/utils/schemaStoreValidation.d.ts +10 -62
  51. package/dist/actions/schema/utils/schemaStoreValidation.js +40 -127
  52. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  53. package/dist/actions/schema/utils/uniqByProjectIdDataset.d.ts +14 -0
  54. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +9 -0
  55. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -0
  56. package/dist/actions/users/getMembersForProject.d.ts +1 -3
  57. package/dist/actions/users/getMembersForProject.js +6 -17
  58. package/dist/actions/users/getMembersForProject.js.map +1 -1
  59. package/dist/actions/users/types.d.ts +0 -11
  60. package/dist/actions/users/types.js.map +1 -1
  61. package/dist/commands/__tests__/debug.test.js +113 -220
  62. package/dist/commands/__tests__/debug.test.js.map +1 -1
  63. package/dist/commands/__tests__/deploy.test.js +325 -293
  64. package/dist/commands/__tests__/deploy.test.js.map +1 -1
  65. package/dist/commands/__tests__/dev.test.js +62 -19
  66. package/dist/commands/__tests__/dev.test.js.map +1 -1
  67. package/dist/commands/__tests__/init/init.authentication.test.js +73 -0
  68. package/dist/commands/__tests__/init/init.authentication.test.js.map +1 -0
  69. package/dist/commands/__tests__/init/init.create-new-project.test.js +195 -0
  70. package/dist/commands/__tests__/init/init.create-new-project.test.js.map +1 -0
  71. package/dist/commands/__tests__/init/init.plan.test.js +279 -0
  72. package/dist/commands/__tests__/init/init.plan.test.js.map +1 -0
  73. package/dist/commands/__tests__/init/init.setup.test.js +335 -0
  74. package/dist/commands/__tests__/init/init.setup.test.js.map +1 -0
  75. package/dist/commands/__tests__/install.test.js +46 -22
  76. package/dist/commands/__tests__/install.test.js.map +1 -1
  77. package/dist/commands/__tests__/logout.test.js +8 -5
  78. package/dist/commands/__tests__/logout.test.js.map +1 -1
  79. package/dist/commands/__tests__/manage.test.js +29 -24
  80. package/dist/commands/__tests__/manage.test.js.map +1 -1
  81. package/dist/commands/__tests__/migration.test.js +119 -0
  82. package/dist/commands/__tests__/migration.test.js.map +1 -0
  83. package/dist/commands/__tests__/versions.test.js +22 -14
  84. package/dist/commands/__tests__/versions.test.js.map +1 -1
  85. package/dist/commands/backup/__tests__/disable.test.js +72 -75
  86. package/dist/commands/backup/__tests__/disable.test.js.map +1 -1
  87. package/dist/commands/backup/__tests__/download.test.js +169 -80
  88. package/dist/commands/backup/__tests__/download.test.js.map +1 -1
  89. package/dist/commands/backup/__tests__/enable.test.js +109 -140
  90. package/dist/commands/backup/__tests__/enable.test.js.map +1 -1
  91. package/dist/commands/backup/__tests__/list.test.js +84 -75
  92. package/dist/commands/backup/__tests__/list.test.js.map +1 -1
  93. package/dist/commands/backup/disable.js +5 -11
  94. package/dist/commands/backup/disable.js.map +1 -1
  95. package/dist/commands/backup/enable.js +5 -11
  96. package/dist/commands/backup/enable.js.map +1 -1
  97. package/dist/commands/backup/list.js +7 -8
  98. package/dist/commands/backup/list.js.map +1 -1
  99. package/dist/commands/cors/__tests__/add.test.js +68 -38
  100. package/dist/commands/cors/__tests__/add.test.js.map +1 -1
  101. package/dist/commands/cors/__tests__/delete.test.js +52 -37
  102. package/dist/commands/cors/__tests__/delete.test.js.map +1 -1
  103. package/dist/commands/cors/__tests__/list.test.js +80 -57
  104. package/dist/commands/cors/__tests__/list.test.js.map +1 -1
  105. package/dist/commands/cors/add.js +5 -13
  106. package/dist/commands/cors/add.js.map +1 -1
  107. package/dist/commands/cors/delete.js +7 -15
  108. package/dist/commands/cors/delete.js.map +1 -1
  109. package/dist/commands/cors/list.js +2 -10
  110. package/dist/commands/cors/list.js.map +1 -1
  111. package/dist/commands/dataset/__tests__/copy.test.js +197 -89
  112. package/dist/commands/dataset/__tests__/copy.test.js.map +1 -1
  113. package/dist/commands/dataset/__tests__/create.test.js +147 -117
  114. package/dist/commands/dataset/__tests__/create.test.js.map +1 -1
  115. package/dist/commands/dataset/__tests__/delete.test.js +75 -68
  116. package/dist/commands/dataset/__tests__/delete.test.js.map +1 -1
  117. package/dist/commands/dataset/__tests__/export.test.js +123 -83
  118. package/dist/commands/dataset/__tests__/export.test.js.map +1 -1
  119. package/dist/commands/dataset/__tests__/import.test.js +2 -2
  120. package/dist/commands/dataset/__tests__/import.test.js.map +1 -1
  121. package/dist/commands/dataset/__tests__/list.test.js +107 -65
  122. package/dist/commands/dataset/__tests__/list.test.js.map +1 -1
  123. package/dist/commands/dataset/alias/__tests__/create.test.js +114 -74
  124. package/dist/commands/dataset/alias/__tests__/create.test.js.map +1 -1
  125. package/dist/commands/dataset/alias/__tests__/delete.test.js +40 -29
  126. package/dist/commands/dataset/alias/__tests__/delete.test.js.map +1 -1
  127. package/dist/commands/dataset/alias/__tests__/link.test.js +114 -74
  128. package/dist/commands/dataset/alias/__tests__/link.test.js.map +1 -1
  129. package/dist/commands/dataset/alias/__tests__/unlink.test.js +44 -29
  130. package/dist/commands/dataset/alias/__tests__/unlink.test.js.map +1 -1
  131. package/dist/commands/dataset/export.js +4 -4
  132. package/dist/commands/dataset/export.js.map +1 -1
  133. package/dist/commands/dataset/visibility/__tests__/get.test.js +48 -67
  134. package/dist/commands/dataset/visibility/__tests__/get.test.js.map +1 -1
  135. package/dist/commands/dataset/visibility/__tests__/set.test.js +76 -123
  136. package/dist/commands/dataset/visibility/__tests__/set.test.js.map +1 -1
  137. package/dist/commands/dev.js +0 -1
  138. package/dist/commands/dev.js.map +1 -1
  139. package/dist/commands/docs/__tests__/search.test.js +8 -7
  140. package/dist/commands/docs/__tests__/search.test.js.map +1 -1
  141. package/dist/commands/documents/__tests__/create.test.js +328 -265
  142. package/dist/commands/documents/__tests__/create.test.js.map +1 -1
  143. package/dist/commands/documents/__tests__/delete.test.js +119 -87
  144. package/dist/commands/documents/__tests__/delete.test.js.map +1 -1
  145. package/dist/commands/documents/__tests__/get.test.js +68 -95
  146. package/dist/commands/documents/__tests__/get.test.js.map +1 -1
  147. package/dist/commands/documents/__tests__/query.test.js +87 -192
  148. package/dist/commands/documents/__tests__/query.test.js.map +1 -1
  149. package/dist/commands/documents/__tests__/validate.test.js +52 -29
  150. package/dist/commands/documents/__tests__/validate.test.js.map +1 -1
  151. package/dist/commands/documents/create.d.ts +1 -0
  152. package/dist/commands/documents/create.js +10 -9
  153. package/dist/commands/documents/create.js.map +1 -1
  154. package/dist/commands/documents/delete.js +2 -3
  155. package/dist/commands/documents/delete.js.map +1 -1
  156. package/dist/commands/documents/get.js +2 -3
  157. package/dist/commands/documents/get.js.map +1 -1
  158. package/dist/commands/documents/query.js +2 -3
  159. package/dist/commands/documents/query.js.map +1 -1
  160. package/dist/commands/documents/validate.js +0 -20
  161. package/dist/commands/documents/validate.js.map +1 -1
  162. package/dist/commands/graphql/__tests__/list.test.js +57 -45
  163. package/dist/commands/graphql/__tests__/list.test.js.map +1 -1
  164. package/dist/commands/graphql/__tests__/undeploy.test.js +85 -59
  165. package/dist/commands/graphql/__tests__/undeploy.test.js.map +1 -1
  166. package/dist/commands/graphql/list.js +2 -2
  167. package/dist/commands/graphql/list.js.map +1 -1
  168. package/dist/commands/graphql/undeploy.js +4 -9
  169. package/dist/commands/graphql/undeploy.js.map +1 -1
  170. package/dist/commands/hook/__tests__/attempt.test.js +48 -33
  171. package/dist/commands/hook/__tests__/attempt.test.js.map +1 -1
  172. package/dist/commands/hook/__tests__/create.test.js +49 -51
  173. package/dist/commands/hook/__tests__/create.test.js.map +1 -1
  174. package/dist/commands/hook/__tests__/delete.test.js +43 -30
  175. package/dist/commands/hook/__tests__/delete.test.js.map +1 -1
  176. package/dist/commands/hook/__tests__/list.test.js +38 -31
  177. package/dist/commands/hook/__tests__/list.test.js.map +1 -1
  178. package/dist/commands/hook/__tests__/logs.test.js +68 -40
  179. package/dist/commands/hook/__tests__/logs.test.js.map +1 -1
  180. package/dist/commands/hook/create.js +2 -6
  181. package/dist/commands/hook/create.js.map +1 -1
  182. package/dist/commands/hook/delete.js +5 -17
  183. package/dist/commands/hook/delete.js.map +1 -1
  184. package/dist/commands/hook/list.js +2 -8
  185. package/dist/commands/hook/list.js.map +1 -1
  186. package/dist/commands/init.d.ts +4 -0
  187. package/dist/commands/init.js +151 -18
  188. package/dist/commands/init.js.map +1 -1
  189. package/dist/commands/login.js +1 -1
  190. package/dist/commands/login.js.map +1 -1
  191. package/dist/commands/manifest/__tests__/extract.test.js +22 -13
  192. package/dist/commands/manifest/__tests__/extract.test.js.map +1 -1
  193. package/dist/commands/media/__tests__/create-aspect.test.js +41 -28
  194. package/dist/commands/media/__tests__/create-aspect.test.js.map +1 -1
  195. package/dist/commands/media/__tests__/delete-aspect.test.js +44 -35
  196. package/dist/commands/media/__tests__/delete-aspect.test.js.map +1 -1
  197. package/dist/commands/media/__tests__/deploy-aspect.test.js +67 -80
  198. package/dist/commands/media/__tests__/deploy-aspect.test.js.map +1 -1
  199. package/dist/commands/media/__tests__/export.test.js +365 -66
  200. package/dist/commands/media/__tests__/export.test.js.map +1 -1
  201. package/dist/commands/media/__tests__/import.test.js +171 -105
  202. package/dist/commands/media/__tests__/import.test.js.map +1 -1
  203. package/dist/commands/media/export.js +2 -2
  204. package/dist/commands/media/export.js.map +1 -1
  205. package/dist/commands/media/import.js +2 -2
  206. package/dist/commands/media/import.js.map +1 -1
  207. package/dist/commands/projects/__tests__/list.test.js +5 -4
  208. package/dist/commands/projects/__tests__/list.test.js.map +1 -1
  209. package/dist/commands/projects/list.js +2 -6
  210. package/dist/commands/projects/list.js.map +1 -1
  211. package/dist/commands/schema/__tests__/delete.test.js +396 -151
  212. package/dist/commands/schema/__tests__/delete.test.js.map +1 -1
  213. package/dist/commands/schema/__tests__/deploy.test.js +348 -0
  214. package/dist/commands/schema/__tests__/deploy.test.js.map +1 -0
  215. package/dist/commands/schema/__tests__/extract.test.js +19 -11
  216. package/dist/commands/schema/__tests__/extract.test.js.map +1 -1
  217. package/dist/commands/schema/__tests__/list.test.js +399 -0
  218. package/dist/commands/schema/__tests__/list.test.js.map +1 -0
  219. package/dist/commands/schema/__tests__/validate.test.js +27 -10
  220. package/dist/commands/schema/__tests__/validate.test.js.map +1 -1
  221. package/dist/commands/schema/delete.d.ts +1 -1
  222. package/dist/commands/schema/delete.js +20 -23
  223. package/dist/commands/schema/delete.js.map +1 -1
  224. package/dist/commands/schema/deploy.d.ts +16 -0
  225. package/dist/commands/schema/deploy.js +98 -0
  226. package/dist/commands/schema/deploy.js.map +1 -0
  227. package/dist/commands/schema/list.d.ts +15 -0
  228. package/dist/commands/schema/list.js +104 -0
  229. package/dist/commands/schema/list.js.map +1 -0
  230. package/dist/commands/telemetry/__tests__/disable.test.js +7 -5
  231. package/dist/commands/telemetry/__tests__/disable.test.js.map +1 -1
  232. package/dist/commands/telemetry/__tests__/enable.test.js +7 -5
  233. package/dist/commands/telemetry/__tests__/enable.test.js.map +1 -1
  234. package/dist/commands/telemetry/__tests__/status.test.js +7 -5
  235. package/dist/commands/telemetry/__tests__/status.test.js.map +1 -1
  236. package/dist/commands/tokens/__tests__/add.test.js +55 -40
  237. package/dist/commands/tokens/__tests__/add.test.js.map +1 -1
  238. package/dist/commands/tokens/__tests__/delete.test.js +72 -42
  239. package/dist/commands/tokens/__tests__/delete.test.js.map +1 -1
  240. package/dist/commands/tokens/__tests__/list.test.js +87 -60
  241. package/dist/commands/tokens/__tests__/list.test.js.map +1 -1
  242. package/dist/commands/tokens/add.js +3 -5
  243. package/dist/commands/tokens/add.js.map +1 -1
  244. package/dist/commands/users/__tests__/invite.test.js +100 -79
  245. package/dist/commands/users/__tests__/invite.test.js.map +1 -1
  246. package/dist/commands/users/__tests__/list.test.js +186 -180
  247. package/dist/commands/users/__tests__/list.test.js.map +1 -1
  248. package/dist/commands/users/invite.js +6 -17
  249. package/dist/commands/users/invite.js.map +1 -1
  250. package/dist/commands/users/list.js +4 -7
  251. package/dist/commands/users/list.js.map +1 -1
  252. package/dist/config/createCliConfig.d.ts +4 -4
  253. package/dist/services/backup.d.ts +8 -0
  254. package/dist/services/backup.js +19 -0
  255. package/dist/services/backup.js.map +1 -1
  256. package/dist/services/cors.d.ts +23 -0
  257. package/dist/services/cors.js +38 -0
  258. package/dist/services/cors.js.map +1 -0
  259. package/dist/services/graphql.d.ts +7 -0
  260. package/dist/services/graphql.js +11 -0
  261. package/dist/services/graphql.js.map +1 -1
  262. package/dist/services/hooks.d.ts +2 -0
  263. package/dist/services/hooks.js +19 -0
  264. package/dist/services/hooks.js.map +1 -1
  265. package/dist/services/organizations.d.ts +40 -0
  266. package/dist/services/organizations.js +41 -0
  267. package/dist/services/organizations.js.map +1 -0
  268. package/dist/services/projects.d.ts +31 -0
  269. package/dist/services/projects.js +71 -1
  270. package/dist/services/projects.js.map +1 -1
  271. package/dist/services/schemas.d.ts +4 -0
  272. package/dist/services/schemas.js +40 -0
  273. package/dist/services/schemas.js.map +1 -0
  274. package/dist/services/user.d.ts +10 -0
  275. package/dist/services/user.js +24 -0
  276. package/dist/services/user.js.map +1 -0
  277. package/dist/util/__tests__/getCliVersion.test.js +2 -2
  278. package/dist/util/__tests__/getCliVersion.test.js.map +1 -1
  279. package/dist/util/errorMessages.d.ts +1 -0
  280. package/dist/util/errorMessages.js +1 -0
  281. package/dist/util/errorMessages.js.map +1 -1
  282. package/dist/util/getCliVersion.js +1 -1
  283. package/dist/util/getCliVersion.js.map +1 -1
  284. package/dist/util/readPackageJson.d.ts +1 -15
  285. package/dist/util/readPackageJson.js +1 -1
  286. package/dist/util/readPackageJson.js.map +1 -1
  287. package/dist/util/uniqBy.d.ts +1 -0
  288. package/dist/util/uniqBy.js +14 -0
  289. package/dist/util/uniqBy.js.map +1 -0
  290. package/oclif.config.js +6 -1
  291. package/oclif.manifest.json +152 -158
  292. package/package.json +30 -31
  293. package/dist/actions/cors/constants.d.ts +0 -1
  294. package/dist/actions/cors/constants.js +0 -3
  295. package/dist/actions/cors/constants.js.map +0 -1
  296. package/dist/actions/cors/types.d.ts +0 -9
  297. package/dist/actions/cors/types.js +0 -3
  298. package/dist/actions/cors/types.js.map +0 -1
  299. package/dist/actions/migration/getMigrationRootDirectory.d.ts +0 -2
  300. package/dist/actions/migration/getMigrationRootDirectory.js +0 -14
  301. package/dist/actions/migration/getMigrationRootDirectory.js.map +0 -1
  302. package/dist/actions/migration/resolveMigrations.d.ts +0 -19
  303. package/dist/actions/migration/resolveMigrations.js +0 -43
  304. package/dist/actions/migration/resolveMigrations.js.map +0 -1
  305. package/dist/actions/migration/templates/__tests__/minimalAdvanced.test.js +0 -65
  306. package/dist/actions/migration/templates/__tests__/minimalAdvanced.test.js.map +0 -1
  307. package/dist/actions/migration/templates/__tests__/minimalSimple.test.js +0 -145
  308. package/dist/actions/migration/templates/__tests__/minimalSimple.test.js.map +0 -1
  309. package/dist/actions/migration/templates/__tests__/renameField.test.js +0 -63
  310. package/dist/actions/migration/templates/__tests__/renameField.test.js.map +0 -1
  311. package/dist/actions/migration/templates/__tests__/renameType.test.js +0 -61
  312. package/dist/actions/migration/templates/__tests__/renameType.test.js.map +0 -1
  313. package/dist/actions/migration/templates/__tests__/stringToPTE.test.js +0 -87
  314. package/dist/actions/migration/templates/__tests__/stringToPTE.test.js.map +0 -1
  315. package/dist/actions/migration/templates/index.d.ts +0 -5
  316. package/dist/actions/migration/templates/index.js +0 -7
  317. package/dist/actions/migration/templates/index.js.map +0 -1
  318. package/dist/actions/migration/templates/minimalAdvanced.d.ts +0 -4
  319. package/dist/actions/migration/templates/minimalAdvanced.js +0 -21
  320. package/dist/actions/migration/templates/minimalAdvanced.js.map +0 -1
  321. package/dist/actions/migration/templates/minimalSimple.d.ts +0 -4
  322. package/dist/actions/migration/templates/minimalSimple.js +0 -61
  323. package/dist/actions/migration/templates/minimalSimple.js.map +0 -1
  324. package/dist/actions/migration/templates/renameField.d.ts +0 -4
  325. package/dist/actions/migration/templates/renameField.js +0 -20
  326. package/dist/actions/migration/templates/renameField.js.map +0 -1
  327. package/dist/actions/migration/templates/renameType.d.ts +0 -4
  328. package/dist/actions/migration/templates/renameType.js +0 -19
  329. package/dist/actions/migration/templates/renameType.js.map +0 -1
  330. package/dist/actions/migration/templates/stringToPTE.d.ts +0 -4
  331. package/dist/actions/migration/templates/stringToPTE.js +0 -32
  332. package/dist/actions/migration/templates/stringToPTE.js.map +0 -1
  333. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js +0 -294
  334. package/dist/actions/schema/__tests__/deleteSchemaAction.test.js.map +0 -1
  335. package/dist/actions/schema/schemaStoreConstants.d.ts +0 -1
  336. package/dist/actions/schema/schemaStoreConstants.js +0 -4
  337. package/dist/actions/schema/schemaStoreConstants.js.map +0 -1
  338. package/dist/actions/schema/utils/schemaActionHelpers.d.ts +0 -1
  339. package/dist/actions/schema/utils/schemaActionHelpers.js +0 -5
  340. package/dist/actions/schema/utils/schemaActionHelpers.js.map +0 -1
  341. package/dist/actions/schema/utils/schemaApiClient.d.ts +0 -6
  342. package/dist/actions/schema/utils/schemaApiClient.js +0 -17
  343. package/dist/actions/schema/utils/schemaApiClient.js.map +0 -1
  344. package/dist/actions/users/apiVersion.d.ts +0 -6
  345. package/dist/actions/users/apiVersion.js +0 -7
  346. package/dist/actions/users/apiVersion.js.map +0 -1
  347. package/dist/commands/__tests__/init.test.js +0 -411
  348. package/dist/commands/__tests__/init.test.js.map +0 -1
  349. package/dist/commands/migration/__tests__/create.test.js +0 -296
  350. package/dist/commands/migration/__tests__/create.test.js.map +0 -1
  351. package/dist/commands/migration/__tests__/list.test.js +0 -166
  352. package/dist/commands/migration/__tests__/list.test.js.map +0 -1
  353. package/dist/commands/migration/__tests__/run.test.js +0 -481
  354. package/dist/commands/migration/__tests__/run.test.js.map +0 -1
  355. package/dist/commands/migration/create.d.ts +0 -17
  356. package/dist/commands/migration/create.js +0 -143
  357. package/dist/commands/migration/create.js.map +0 -1
  358. package/dist/commands/migration/list.d.ts +0 -9
  359. package/dist/commands/migration/list.js +0 -61
  360. package/dist/commands/migration/list.js.map +0 -1
  361. package/dist/commands/migration/run.d.ts +0 -26
  362. package/dist/commands/migration/run.js +0 -271
  363. package/dist/commands/migration/run.js.map +0 -1
  364. package/dist/util/migration/constants.d.ts +0 -3
  365. package/dist/util/migration/constants.js +0 -10
  366. package/dist/util/migration/constants.js.map +0 -1
  367. package/dist/util/migration/ensureApiVersionFormat.d.ts +0 -9
  368. package/dist/util/migration/ensureApiVersionFormat.js +0 -16
  369. package/dist/util/migration/ensureApiVersionFormat.js.map +0 -1
  370. package/dist/util/migration/prettyMutationFormatter.d.ts +0 -8
  371. package/dist/util/migration/prettyMutationFormatter.js +0 -141
  372. package/dist/util/migration/prettyMutationFormatter.js.map +0 -1
  373. package/dist/utils/migration/resolveMigrationScript.d.ts +0 -44
  374. package/dist/utils/migration/resolveMigrationScript.js +0 -74
  375. package/dist/utils/migration/resolveMigrationScript.js.map +0 -1
  376. /package/dist/actions/auth/login/{index.d.ts → login.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/backup/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {Table} from 'console-table-printer'\nimport {isAfter, isValid, lightFormat, parse} from 'date-fns'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {BACKUP_API_VERSION} from '../../actions/backup/constants.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst listBackupDebug = subdebug('backup:list')\n\nconst DEFAULT_LIST_BACKUP_LIMIT = 30\n\ntype ListBackupRequestQueryParams = {\n after?: string\n before?: string\n limit: string\n}\n\ntype ListBackupResponse = {\n backups: ListBackupResponseItem[]\n}\n\ntype ListBackupResponseItem = {\n createdAt: string\n id: string\n}\n\nexport class ListBackupCommand extends SanityCommand<typeof ListBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to list backups for',\n required: false,\n }),\n }\n\n static override description = 'List available backups for a dataset.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List backups for a dataset interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'List backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --limit 50',\n description: 'List up to 50 backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --after 2024-01-31 --limit 10',\n description: 'List up to 10 backups created after 2024-01-31',\n },\n ]\n\n static override flags = {\n after: Flags.string({\n description: 'Only return backups after this date (inclusive, YYYY-MM-DD format)',\n }),\n before: Flags.string({\n description: 'Only return backups before this date (exclusive, YYYY-MM-DD format)',\n }),\n limit: Flags.integer({\n char: 'l',\n default: DEFAULT_LIST_BACKUP_LIMIT,\n description: 'Maximum number of backups returned',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ListBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n const client = await this.getGlobalApiClient({\n apiVersion: BACKUP_API_VERSION,\n requireUser: true,\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: 1})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset)\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n // Validate date flags\n if (flags.before || flags.after) {\n try {\n const parsedBefore = this.processDateFlag(flags.before, 'before')\n const parsedAfter = this.processDateFlag(flags.after, 'after')\n\n if (parsedAfter && parsedBefore && isAfter(parsedAfter, parsedBefore)) {\n this.error('--after date must be before --before', {exit: 1})\n }\n } catch (err) {\n this.error(`Parsing date flags: ${err instanceof Error ? err.message : err}`, {exit: 1})\n }\n }\n\n // Validate limit flag\n if (flags.limit < 1 || flags.limit > Number.MAX_SAFE_INTEGER) {\n this.error(`Parsing --limit: must be an integer between 1 and ${Number.MAX_SAFE_INTEGER}`, {\n exit: 1,\n })\n }\n\n const query: ListBackupRequestQueryParams = {\n limit: flags.limit.toString(),\n }\n\n if (flags.after) {\n query.after = flags.after\n }\n\n if (flags.before) {\n query.before = flags.before\n }\n\n try {\n const response = await client.request<ListBackupResponse>({\n query,\n uri: `/projects/${projectId}/datasets/${dataset}/backups`,\n })\n\n if (response.backups.length === 0) {\n this.log('No backups found.')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'resource', title: 'RESOURCE'},\n {alignment: 'left', name: 'createdAt', title: 'CREATED AT'},\n {alignment: 'left', name: 'backupId', title: 'BACKUP ID'},\n ],\n })\n\n for (const backup of response.backups) {\n const {createdAt, id} = backup\n table.addRow({\n backupId: id,\n createdAt: lightFormat(Date.parse(createdAt), 'yyyy-MM-dd HH:mm:ss'),\n resource: 'Dataset',\n })\n }\n\n table.printTable()\n\n listBackupDebug(\n `Successfully listed ${response.backups.length} backups for dataset ${dataset}`,\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list backups for dataset ${dataset}:`, error)\n this.error(`List dataset backup failed: ${message}`, {exit: 1})\n }\n }\n\n private processDateFlag(date: string | undefined, flagName: string): Date | undefined {\n if (!date) return undefined\n const parsedDate = parse(date, 'yyyy-MM-dd', new Date())\n if (isValid(parsedDate)) {\n return parsedDate\n }\n\n throw new Error(`Invalid date format for '--${flagName}' flag. Use YYYY-MM-DD`)\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n listBackupDebug(`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"],"names":["Args","Flags","SanityCommand","subdebug","select","Table","isAfter","isValid","lightFormat","parse","assertDatasetExists","BACKUP_API_VERSION","listDatasets","NO_PROJECT_ID","listBackupDebug","DEFAULT_LIST_BACKUP_LIMIT","ListBackupCommand","args","dataset","string","description","required","examples","command","flags","after","before","limit","integer","char","default","run","projectId","getProjectId","error","exit","client","getGlobalApiClient","apiVersion","requireUser","datasets","message","Error","String","length","promptForDataset","parsedBefore","processDateFlag","parsedAfter","err","Number","MAX_SAFE_INTEGER","query","toString","response","request","uri","backups","log","table","columns","alignment","name","title","backup","createdAt","id","addRow","backupId","Date","resource","printTable","date","flagName","undefined","parsedDate","choices","map","value"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/backup/list.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {Table} from 'console-table-printer'\nimport {isAfter, isValid, lightFormat, parse} from 'date-fns'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {listBackups} from '../../services/backup.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst listBackupDebug = subdebug('backup:list')\n\nconst DEFAULT_LIST_BACKUP_LIMIT = 30\n\ntype ListBackupRequestQueryParams = {\n after?: string\n before?: string\n limit: string\n}\n\nexport class ListBackupCommand extends SanityCommand<typeof ListBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to list backups for',\n required: false,\n }),\n }\n\n static override description = 'List available backups for a dataset.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List backups for a dataset interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'List backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --limit 50',\n description: 'List up to 50 backups for the production dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production --after 2024-01-31 --limit 10',\n description: 'List up to 10 backups created after 2024-01-31',\n },\n ]\n\n static override flags = {\n after: Flags.string({\n description: 'Only return backups after this date (inclusive, YYYY-MM-DD format)',\n }),\n before: Flags.string({\n description: 'Only return backups before this date (exclusive, YYYY-MM-DD format)',\n }),\n limit: Flags.integer({\n char: 'l',\n default: DEFAULT_LIST_BACKUP_LIMIT,\n description: 'Maximum number of backups returned',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ListBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: 1})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset)\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n // Validate date flags\n if (flags.before || flags.after) {\n try {\n const parsedBefore = this.processDateFlag(flags.before, 'before')\n const parsedAfter = this.processDateFlag(flags.after, 'after')\n\n if (parsedAfter && parsedBefore && isAfter(parsedAfter, parsedBefore)) {\n this.error('--after date must be before --before', {exit: 1})\n }\n } catch (err) {\n this.error(`Parsing date flags: ${err instanceof Error ? err.message : err}`, {exit: 1})\n }\n }\n\n // Validate limit flag\n if (flags.limit < 1 || flags.limit > Number.MAX_SAFE_INTEGER) {\n this.error(`Parsing --limit: must be an integer between 1 and ${Number.MAX_SAFE_INTEGER}`, {\n exit: 1,\n })\n }\n\n const query: ListBackupRequestQueryParams = {\n limit: flags.limit.toString(),\n }\n\n if (flags.after) {\n query.after = flags.after\n }\n\n if (flags.before) {\n query.before = flags.before\n }\n\n try {\n const response = await listBackups({\n after: flags.after,\n before: flags.before,\n datasetName: dataset,\n limit: flags.limit,\n projectId,\n })\n\n if (response.backups.length === 0) {\n this.log('No backups found.')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'resource', title: 'RESOURCE'},\n {alignment: 'left', name: 'createdAt', title: 'CREATED AT'},\n {alignment: 'left', name: 'backupId', title: 'BACKUP ID'},\n ],\n })\n\n for (const backup of response.backups) {\n const {createdAt, id} = backup\n table.addRow({\n backupId: id,\n createdAt: lightFormat(Date.parse(createdAt), 'yyyy-MM-dd HH:mm:ss'),\n resource: 'Dataset',\n })\n }\n\n table.printTable()\n\n listBackupDebug(\n `Successfully listed ${response.backups.length} backups for dataset ${dataset}`,\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n listBackupDebug(`Failed to list backups for dataset ${dataset}:`, error)\n this.error(`List dataset backup failed: ${message}`, {exit: 1})\n }\n }\n\n private processDateFlag(date: string | undefined, flagName: string): Date | undefined {\n if (!date) return undefined\n const parsedDate = parse(date, 'yyyy-MM-dd', new Date())\n if (isValid(parsedDate)) {\n return parsedDate\n }\n\n throw new Error(`Invalid date format for '--${flagName}' flag. Use YYYY-MM-DD`)\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n listBackupDebug(`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"],"names":["Args","Flags","SanityCommand","subdebug","select","Table","isAfter","isValid","lightFormat","parse","assertDatasetExists","listBackups","listDatasets","NO_PROJECT_ID","listBackupDebug","DEFAULT_LIST_BACKUP_LIMIT","ListBackupCommand","args","dataset","string","description","required","examples","command","flags","after","before","limit","integer","char","default","run","projectId","getProjectId","error","exit","datasets","message","Error","String","length","promptForDataset","parsedBefore","processDateFlag","parsedAfter","err","Number","MAX_SAFE_INTEGER","query","toString","response","datasetName","backups","log","table","columns","alignment","name","title","backup","createdAt","id","addRow","backupId","Date","resource","printTable","date","flagName","undefined","parsedDate","choices","map","value"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,MAAM,QAAO,sBAAqB;AAE1C,SAAQC,KAAK,QAAO,wBAAuB;AAC3C,SAAQC,OAAO,EAAEC,OAAO,EAAEC,WAAW,EAAEC,KAAK,QAAO,WAAU;AAE7D,SAAQC,mBAAmB,QAAO,6CAA4C;AAC9E,SAAQC,WAAW,QAAO,2BAA0B;AACpD,SAAQC,YAAY,QAAO,6BAA4B;AACvD,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,kBAAkBX,SAAS;AAEjC,MAAMY,4BAA4B;AAQlC,OAAO,MAAMC,0BAA0Bd;IACrC,OAAgBe,OAAO;QACrBC,SAASlB,KAAKmB,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,wCAAuC;IAErE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,OAAOxB,MAAMkB,MAAM,CAAC;YAClBC,aAAa;QACf;QACAM,QAAQzB,MAAMkB,MAAM,CAAC;YACnBC,aAAa;QACf;QACAO,OAAO1B,MAAM2B,OAAO,CAAC;YACnBC,MAAM;YACNC,SAASf;YACTK,aAAa;QACf;IACF,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACd,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACf,KAAK,CAACO;QACvC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAEhB,MAAMe,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAACrB,eAAe;gBAACsB,MAAM;YAAC;QACpC;QAEA,IAAIC;QAEJ,IAAI;YACFA,WAAW,MAAMxB,aAAaoB;QAChC,EAAE,OAAOE,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEpB,gBAAgB,CAAC,yBAAyB,EAAEuB,SAAS,EAAEH;YACvD,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC5D;QAEA,IAAIC,SAASI,MAAM,KAAK,GAAG;YACzB,IAAI,CAACN,KAAK,CAAC,sCAAsC;gBAACC,MAAM;YAAC;QAC3D;QAEA,IAAIjB,SAAS;YACXR,oBAAoB0B,UAAUlB;QAChC,OAAO;YACLA,UAAU,MAAM,IAAI,CAACuB,gBAAgB,CAACL;QACxC;QAEA,sBAAsB;QACtB,IAAIZ,MAAME,MAAM,IAAIF,MAAMC,KAAK,EAAE;YAC/B,IAAI;gBACF,MAAMiB,eAAe,IAAI,CAACC,eAAe,CAACnB,MAAME,MAAM,EAAE;gBACxD,MAAMkB,cAAc,IAAI,CAACD,eAAe,CAACnB,MAAMC,KAAK,EAAE;gBAEtD,IAAImB,eAAeF,gBAAgBpC,QAAQsC,aAAaF,eAAe;oBACrE,IAAI,CAACR,KAAK,CAAC,wCAAwC;wBAACC,MAAM;oBAAC;gBAC7D;YACF,EAAE,OAAOU,KAAK;gBACZ,IAAI,CAACX,KAAK,CAAC,CAAC,oBAAoB,EAAEW,eAAeP,QAAQO,IAAIR,OAAO,GAAGQ,KAAK,EAAE;oBAACV,MAAM;gBAAC;YACxF;QACF;QAEA,sBAAsB;QACtB,IAAIX,MAAMG,KAAK,GAAG,KAAKH,MAAMG,KAAK,GAAGmB,OAAOC,gBAAgB,EAAE;YAC5D,IAAI,CAACb,KAAK,CAAC,CAAC,kDAAkD,EAAEY,OAAOC,gBAAgB,EAAE,EAAE;gBACzFZ,MAAM;YACR;QACF;QAEA,MAAMa,QAAsC;YAC1CrB,OAAOH,MAAMG,KAAK,CAACsB,QAAQ;QAC7B;QAEA,IAAIzB,MAAMC,KAAK,EAAE;YACfuB,MAAMvB,KAAK,GAAGD,MAAMC,KAAK;QAC3B;QAEA,IAAID,MAAME,MAAM,EAAE;YAChBsB,MAAMtB,MAAM,GAAGF,MAAME,MAAM;QAC7B;QAEA,IAAI;YACF,MAAMwB,WAAW,MAAMvC,YAAY;gBACjCc,OAAOD,MAAMC,KAAK;gBAClBC,QAAQF,MAAME,MAAM;gBACpByB,aAAajC;gBACbS,OAAOH,MAAMG,KAAK;gBAClBK;YACF;YAEA,IAAIkB,SAASE,OAAO,CAACZ,MAAM,KAAK,GAAG;gBACjC,IAAI,CAACa,GAAG,CAAC;gBACT;YACF;YAEA,MAAMC,QAAQ,IAAIjD,MAAM;gBACtBkD,SAAS;oBACP;wBAACC,WAAW;wBAAQC,MAAM;wBAAYC,OAAO;oBAAU;oBACvD;wBAACF,WAAW;wBAAQC,MAAM;wBAAaC,OAAO;oBAAY;oBAC1D;wBAACF,WAAW;wBAAQC,MAAM;wBAAYC,OAAO;oBAAW;iBACzD;YACH;YAEA,KAAK,MAAMC,UAAUT,SAASE,OAAO,CAAE;gBACrC,MAAM,EAACQ,SAAS,EAAEC,EAAE,EAAC,GAAGF;gBACxBL,MAAMQ,MAAM,CAAC;oBACXC,UAAUF;oBACVD,WAAWpD,YAAYwD,KAAKvD,KAAK,CAACmD,YAAY;oBAC9CK,UAAU;gBACZ;YACF;YAEAX,MAAMY,UAAU;YAEhBpD,gBACE,CAAC,oBAAoB,EAAEoC,SAASE,OAAO,CAACZ,MAAM,CAAC,qBAAqB,EAAEtB,SAAS;QAEnF,EAAE,OAAOgB,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEpB,gBAAgB,CAAC,mCAAmC,EAAEI,QAAQ,CAAC,CAAC,EAAEgB;YAClE,IAAI,CAACA,KAAK,CAAC,CAAC,4BAA4B,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC/D;IACF;IAEQQ,gBAAgBwB,IAAwB,EAAEC,QAAgB,EAAoB;QACpF,IAAI,CAACD,MAAM,OAAOE;QAClB,MAAMC,aAAa7D,MAAM0D,MAAM,cAAc,IAAIH;QACjD,IAAIzD,QAAQ+D,aAAa;YACvB,OAAOA;QACT;QAEA,MAAM,IAAIhC,MAAM,CAAC,2BAA2B,EAAE8B,SAAS,sBAAsB,CAAC;IAChF;IAEA,MAAc3B,iBAAiBL,QAA0B,EAAmB;QAC1E,IAAI;YACF,MAAMmC,UAAUnC,SAASoC,GAAG,CAAC,CAACtD,UAAa,CAAA;oBACzCuC,MAAMvC,QAAQuC,IAAI;oBAClBgB,OAAOvD,QAAQuC,IAAI;gBACrB,CAAA;YAEA,OAAOrD,OAAO;gBACZmE;gBACAlC,SAAS;YACX;QACF,EAAE,OAAOH,OAAO;YACdpB,gBAAgB,CAAC,uBAAuB,CAAC,EAAEoB;YAC3C,IAAI,CAACA,KAAK,CAAC,CAAC,2BAA2B,EAAEA,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGH,OAAO,EAAE;gBACzFC,MAAM;YACR;QACF;IACF;AACF"}
@@ -1,10 +1,9 @@
1
1
  import fs from 'node:fs';
2
- import { getCliConfig } from '@sanity/cli-core';
3
2
  import { confirm } from '@sanity/cli-core/ux';
4
3
  import { mockApi, testCommand } from '@sanity/cli-test';
5
4
  import nock from 'nock';
6
5
  import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
7
- import { CORS_API_VERSION } from '../../../actions/cors/constants.js';
6
+ import { CORS_API_VERSION } from '../../../services/cors.js';
8
7
  import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
9
8
  import { Add } from '../add.js';
10
9
  vi.mock('@sanity/cli-core/ux', async ()=>{
@@ -19,25 +18,20 @@ vi.mock('node:fs', ()=>({
19
18
  existsSync: vi.fn()
20
19
  }
21
20
  }));
22
- vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', ()=>({
23
- findProjectRoot: vi.fn().mockResolvedValue({
24
- directory: '/test/path',
25
- root: '/test/path',
26
- type: 'studio'
27
- })
28
- }));
29
- vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
30
- getCliConfig: vi.fn().mockResolvedValue({
31
- api: {
32
- projectId: 'test-project'
33
- }
34
- })
35
- }));
36
- vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
37
- getCliToken: vi.fn().mockResolvedValue('test-token')
38
- }));
21
+ const defaultMocks = {
22
+ cliConfig: {
23
+ api: {
24
+ projectId: 'test-project'
25
+ }
26
+ },
27
+ projectRoot: {
28
+ directory: '/test/path',
29
+ path: '/test/path/sanity.config.ts',
30
+ type: 'studio'
31
+ },
32
+ token: 'test-token'
33
+ };
39
34
  const mockConfirm = vi.mocked(confirm);
40
- const mockGetCliConfig = vi.mocked(getCliConfig);
41
35
  const mockExistsSync = vi.mocked(fs.existsSync);
42
36
  const setupSuccessfulApiMock = ()=>{
43
37
  return mockApi({
@@ -89,7 +83,9 @@ describe('#cors:add', ()=>{
89
83
  const { stdout } = await testCommand(Add, [
90
84
  origin,
91
85
  '--credentials'
92
- ]);
86
+ ], {
87
+ mocks: defaultMocks
88
+ });
93
89
  expect(stdout).toContain('CORS origin added successfully');
94
90
  });
95
91
  test('adds CORS origin with no-credentials flag', async ()=>{
@@ -117,16 +113,26 @@ describe('#cors:add', ()=>{
117
113
  const { stdout } = await testCommand(Add, [
118
114
  origin,
119
115
  '--no-credentials'
120
- ]);
116
+ ], {
117
+ mocks: defaultMocks
118
+ });
121
119
  expect(stdout).toContain('CORS origin added successfully');
122
120
  });
123
121
  test('fails when no project ID is available', async ()=>{
124
- mockGetCliConfig.mockResolvedValueOnce({
125
- api: {}
126
- });
127
122
  const { error } = await testCommand(Add, [
128
123
  'https://example.com'
129
- ]);
124
+ ], {
125
+ mocks: {
126
+ cliConfig: {
127
+ api: {}
128
+ },
129
+ projectRoot: {
130
+ directory: '/test/path',
131
+ path: '/test/path/sanity.config.ts',
132
+ type: 'studio'
133
+ }
134
+ }
135
+ });
130
136
  expect(error?.message).toContain(NO_PROJECT_ID);
131
137
  });
132
138
  const errorHandlingCases = [
@@ -156,7 +162,9 @@ describe('#cors:add', ()=>{
156
162
  const { error } = await testCommand(Add, [
157
163
  'https://example.com',
158
164
  '--credentials'
159
- ]);
165
+ ], {
166
+ mocks: defaultMocks
167
+ });
160
168
  expect(error?.message).toContain(expectedError);
161
169
  expect(error?.oclif?.exit).toBe(1);
162
170
  });
@@ -166,7 +174,9 @@ describe('#cors:add', ()=>{
166
174
  const { stderr } = await testCommand(Add, [
167
175
  'https://example.com',
168
176
  '--credentials'
169
- ]);
177
+ ], {
178
+ mocks: defaultMocks
179
+ });
170
180
  expect(stderr).toContain('Remember to quote values');
171
181
  });
172
182
  describe('wildcard origins', ()=>{
@@ -193,7 +203,9 @@ describe('#cors:add', ()=>{
193
203
  setupMocks();
194
204
  const result = await testCommand(Add, [
195
205
  'https://*.example.com'
196
- ]);
206
+ ], {
207
+ mocks: defaultMocks
208
+ });
197
209
  expect(confirm).toHaveBeenCalledWith(expect.objectContaining({
198
210
  default: false,
199
211
  message: expect.stringContaining('absolutely sure')
@@ -211,7 +223,9 @@ describe('#cors:add', ()=>{
211
223
  setupSuccessfulApiMock();
212
224
  const { stdout } = await testCommand(Add, [
213
225
  '*'
214
- ]);
226
+ ], {
227
+ mocks: defaultMocks
228
+ });
215
229
  expect(stdout).toContain('http://www.some-malicious.site');
216
230
  expect(stdout).toContain('https://not.what-you-were-expecting.com');
217
231
  });
@@ -222,7 +236,9 @@ describe('#cors:add', ()=>{
222
236
  setupSuccessfulApiMock();
223
237
  const { stdout } = await testCommand(Add, [
224
238
  'https://example.com'
225
- ]);
239
+ ], {
240
+ mocks: defaultMocks
241
+ });
226
242
  expect(confirm).toHaveBeenCalledWith(expect.objectContaining({
227
243
  default: false,
228
244
  message: expect.stringContaining('Allow credentials')
@@ -235,7 +251,9 @@ describe('#cors:add', ()=>{
235
251
  setupSuccessfulApiMock();
236
252
  const { stdout } = await testCommand(Add, [
237
253
  'https://*.example.com'
238
- ]);
254
+ ], {
255
+ mocks: defaultMocks
256
+ });
239
257
  expect(stdout).toContain('HIGHLY');
240
258
  expect(stdout).toContain('recommend NOT allowing credentials');
241
259
  expect(stdout).toContain('on origins containing wildcards');
@@ -258,7 +276,9 @@ describe('#cors:add', ()=>{
258
276
  const { error, stdout } = await testCommand(Add, [
259
277
  origin,
260
278
  '--credentials'
261
- ]);
279
+ ], {
280
+ mocks: defaultMocks
281
+ });
262
282
  expect(error).toBeUndefined();
263
283
  expect(stdout).toContain('CORS origin added successfully');
264
284
  });
@@ -268,7 +288,9 @@ describe('#cors:add', ()=>{
268
288
  const { error, stdout } = await testCommand(Add, [
269
289
  origin,
270
290
  '--credentials'
271
- ]);
291
+ ], {
292
+ mocks: defaultMocks
293
+ });
272
294
  expect(error).toBeUndefined();
273
295
  expect(stdout).toContain('CORS origin added successfully');
274
296
  });
@@ -280,7 +302,9 @@ describe('#cors:add', ()=>{
280
302
  const { error } = await testCommand(Add, [
281
303
  origin,
282
304
  '--credentials'
283
- ]);
305
+ ], {
306
+ mocks: defaultMocks
307
+ });
284
308
  expect(error).toBeDefined();
285
309
  expect(error?.message).toContain('Invalid origin');
286
310
  expect(error?.oclif?.exit).toBe(1);
@@ -289,7 +313,9 @@ describe('#cors:add', ()=>{
289
313
  const { error } = await testCommand(Add, [
290
314
  'file://localhost/path',
291
315
  '--credentials'
292
- ]);
316
+ ], {
317
+ mocks: defaultMocks
318
+ });
293
319
  expect(error).toBeDefined();
294
320
  expect(error?.message).toContain('Only a local file wildcard is currently allowed: file:///*');
295
321
  expect(error?.oclif?.exit).toBe(1);
@@ -319,7 +345,9 @@ describe('#cors:add', ()=>{
319
345
  const { stdout } = await testCommand(Add, [
320
346
  input,
321
347
  '--credentials'
322
- ]);
348
+ ], {
349
+ mocks: defaultMocks
350
+ });
323
351
  if (shouldNormalize) {
324
352
  expect(stdout).toContain(expectedOutput);
325
353
  } else {
@@ -337,7 +365,9 @@ describe('#cors:add', ()=>{
337
365
  const { stdout } = await testCommand(Add, [
338
366
  'https://example.com',
339
367
  '--credentials'
340
- ]);
368
+ ], {
369
+ mocks: defaultMocks
370
+ });
341
371
  expect(stdout).toContain('CORS origin added successfully');
342
372
  });
343
373
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/cors/__tests__/add.test.ts"],"sourcesContent":["import fs from 'node:fs'\n\nimport {getCliConfig} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, beforeEach, describe, expect, test, vi} from 'vitest'\n\nimport {CORS_API_VERSION} from '../../../actions/cors/constants.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {Add} from '../add.js'\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n confirm: vi.fn(),\n }\n})\n\nvi.mock('node:fs', () => ({\n default: {\n existsSync: vi.fn(),\n },\n}))\n\nvi.mock('../../../../../cli-core/src/config/findProjectRoot.js', () => ({\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/path',\n root: '/test/path',\n type: 'studio',\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', () => ({\n getCliConfig: vi.fn().mockResolvedValue({\n api: {\n projectId: 'test-project',\n },\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\n\nconst mockConfirm = vi.mocked(confirm)\nconst mockGetCliConfig = vi.mocked(getCliConfig)\nconst mockExistsSync = vi.mocked(fs.existsSync)\n\nconst setupSuccessfulApiMock = () => {\n return mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, {\n allowCredentials: true,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 1,\n origin: 'https://example.com',\n projectId: 'test-project',\n updatedAt: null,\n })\n}\n\ndescribe('#cors:add', () => {\n beforeEach(() => {\n mockExistsSync.mockReturnValue(false)\n })\n\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('adds CORS origin with credentials flag', async () => {\n const origin = 'https://example.com'\n const expectedAllowCredentials = true\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, function (_, requestBody) {\n expect(requestBody).toEqual({\n allowCredentials: expectedAllowCredentials,\n origin: origin,\n })\n\n return {\n allowCredentials: expectedAllowCredentials,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 1,\n origin: origin,\n projectId: 'test-project',\n updatedAt: null,\n }\n })\n\n const {stdout} = await testCommand(Add, [origin, '--credentials'])\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('adds CORS origin with no-credentials flag', async () => {\n const origin = 'http://localhost:3000'\n const expectedAllowCredentials = false\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, function (_, requestBody) {\n expect(requestBody).toEqual({\n allowCredentials: expectedAllowCredentials,\n origin: origin,\n })\n\n return {\n allowCredentials: expectedAllowCredentials,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 2,\n origin: origin,\n projectId: 'test-project',\n updatedAt: null,\n }\n })\n\n const {stdout} = await testCommand(Add, [origin, '--no-credentials'])\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('fails when no project ID is available', async () => {\n mockGetCliConfig.mockResolvedValueOnce({\n api: {},\n })\n\n const {error} = await testCommand(Add, ['https://example.com'])\n\n expect(error?.message).toContain(NO_PROJECT_ID)\n })\n\n const errorHandlingCases = [\n {\n description: 'handles API errors gracefully',\n expectedError: 'CORS origin addition failed',\n setupMock: () =>\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(400, {message: 'Invalid origin'}),\n },\n {\n description: 'handles network errors during API call',\n expectedError: 'CORS origin addition failed',\n setupMock: () =>\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).replyWithError(new Error('Network Error')),\n },\n ]\n\n test.each(errorHandlingCases)('$description', async ({expectedError, setupMock}) => {\n setupMock()\n\n const {error} = await testCommand(Add, ['https://example.com', '--credentials'])\n\n expect(error?.message).toContain(expectedError)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('warns when origin looks like a file path', async () => {\n mockExistsSync.mockReturnValue(true)\n setupSuccessfulApiMock()\n\n const {stderr} = await testCommand(Add, ['https://example.com', '--credentials'])\n\n expect(stderr).toContain('Remember to quote values')\n })\n\n describe('wildcard origins', () => {\n const wildcardConfirmationCases = [\n {\n confirmWildcard: true,\n description: 'prompts for confirmation with wildcard origins and proceeds',\n expectedError: undefined,\n expectedOutput: 'CORS origin added successfully',\n setupMocks: () => {\n mockConfirm.mockResolvedValueOnce(true).mockResolvedValueOnce(false)\n setupSuccessfulApiMock()\n },\n },\n {\n confirmWildcard: false,\n description: 'cancels operation when wildcard confirmation is denied',\n expectedError: 'Operation cancelled',\n expectedOutput: undefined,\n setupMocks: () => mockConfirm.mockResolvedValueOnce(false),\n },\n ]\n\n test.each(wildcardConfirmationCases)(\n '$description',\n async ({expectedError, expectedOutput, setupMocks}) => {\n setupMocks()\n\n const result = await testCommand(Add, ['https://*.example.com'])\n\n expect(confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n default: false,\n message: expect.stringContaining('absolutely sure'),\n }),\n )\n\n if (expectedOutput) {\n expect(result.stdout).toContain(expectedOutput)\n }\n if (expectedError) {\n expect(result.error?.message).toContain(expectedError)\n expect(result.error?.oclif?.exit).toBe(1)\n }\n },\n )\n\n test('shows specific examples for full wildcard', async () => {\n mockConfirm.mockResolvedValueOnce(true).mockResolvedValueOnce(false)\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['*'])\n\n expect(stdout).toContain('http://www.some-malicious.site')\n expect(stdout).toContain('https://not.what-you-were-expecting.com')\n })\n })\n\n describe('credentials prompts', () => {\n test('prompts for credentials when flag not provided', async () => {\n mockConfirm.mockResolvedValueOnce(true)\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://example.com'])\n\n expect(confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n default: false,\n message: expect.stringContaining('Allow credentials'),\n }),\n )\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('shows warning about wildcard credentials', async () => {\n mockConfirm\n .mockResolvedValueOnce(true) // Confirm wildcard\n .mockResolvedValueOnce(false) // Deny credentials\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://*.example.com'])\n\n expect(stdout).toContain('HIGHLY')\n expect(stdout).toContain('recommend NOT allowing credentials')\n expect(stdout).toContain('on origins containing wildcards')\n })\n })\n\n describe('origin validation and filtering', () => {\n const validNonWildcardOrigins = [\n 'https://example.com',\n 'http://localhost:3000',\n 'https://sub.example.com:8080',\n 'null',\n ]\n\n const validWildcardOrigins = ['https://*.example.com', '*', 'file:///*']\n\n test.each(validNonWildcardOrigins)('accepts valid non-wildcard origin: %s', async (origin) => {\n setupSuccessfulApiMock()\n\n const {error, stdout} = await testCommand(Add, [origin, '--credentials'])\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test.each(validWildcardOrigins)('accepts valid wildcard origin: %s', async (origin) => {\n mockConfirm.mockResolvedValueOnce(true)\n setupSuccessfulApiMock()\n\n const {error, stdout} = await testCommand(Add, [origin, '--credentials'])\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n const invalidOrigins = [\n 'not-a-url',\n 'example.com', // missing protocol\n ]\n\n test.each(invalidOrigins)('rejects invalid origin: %s', async (origin) => {\n const {error} = await testCommand(Add, [origin, '--credentials'])\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Invalid origin')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('rejects file:// origins other than file:///*', async () => {\n const {error} = await testCommand(Add, ['file://localhost/path', '--credentials'])\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Only a local file wildcard is currently allowed: file:///*')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n const portNormalizationCases = [\n {\n description: 'normalizes HTTPS default port',\n expectedOutput: 'Normalized origin to: https://example.com',\n input: 'https://example.com:443',\n shouldNormalize: true,\n },\n {\n description: 'normalizes HTTP default port',\n expectedOutput: 'Normalized origin to: http://example.com',\n input: 'http://example.com:80',\n shouldNormalize: true,\n },\n {\n description: 'preserves non-default ports',\n expectedOutput: 'CORS origin added successfully',\n input: 'https://example.com:8080',\n shouldNormalize: false,\n },\n ]\n\n test.each(portNormalizationCases)(\n '$description',\n async ({expectedOutput, input, shouldNormalize}) => {\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, [input, '--credentials'])\n\n if (shouldNormalize) {\n expect(stdout).toContain(expectedOutput)\n } else {\n expect(stdout).not.toContain('Normalized origin')\n expect(stdout).toContain(expectedOutput)\n }\n },\n )\n })\n\n describe('edge cases', () => {\n test('handles file system check errors gracefully', async () => {\n mockExistsSync.mockImplementation(() => {\n throw new Error('Permission denied')\n })\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://example.com', '--credentials'])\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n })\n})\n"],"names":["fs","getCliConfig","confirm","mockApi","testCommand","nock","afterEach","beforeEach","describe","expect","test","vi","CORS_API_VERSION","NO_PROJECT_ID","Add","mock","actual","importActual","fn","default","existsSync","findProjectRoot","mockResolvedValue","directory","root","type","api","projectId","getCliToken","mockConfirm","mocked","mockGetCliConfig","mockExistsSync","setupSuccessfulApiMock","apiVersion","method","uri","reply","allowCredentials","createdAt","deletedAt","id","origin","updatedAt","mockReturnValue","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","expectedAllowCredentials","_","requestBody","stdout","toContain","mockResolvedValueOnce","error","message","errorHandlingCases","description","expectedError","setupMock","replyWithError","Error","each","oclif","exit","toBe","stderr","wildcardConfirmationCases","confirmWildcard","undefined","expectedOutput","setupMocks","result","toHaveBeenCalledWith","objectContaining","stringContaining","validNonWildcardOrigins","validWildcardOrigins","toBeUndefined","invalidOrigins","toBeDefined","portNormalizationCases","input","shouldNormalize","not","mockImplementation"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/cors/__tests__/add.test.ts"],"sourcesContent":["import fs from 'node:fs'\n\nimport {confirm} from '@sanity/cli-core/ux'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, beforeEach, describe, expect, test, vi} from 'vitest'\n\nimport {CORS_API_VERSION} from '../../../services/cors.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {Add} from '../add.js'\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n confirm: vi.fn(),\n }\n})\n\nvi.mock('node:fs', () => ({\n default: {\n existsSync: vi.fn(),\n },\n}))\n\nconst defaultMocks = {\n cliConfig: {api: {projectId: 'test-project'}},\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n token: 'test-token',\n}\n\nconst mockConfirm = vi.mocked(confirm)\nconst mockExistsSync = vi.mocked(fs.existsSync)\n\nconst setupSuccessfulApiMock = () => {\n return mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, {\n allowCredentials: true,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 1,\n origin: 'https://example.com',\n projectId: 'test-project',\n updatedAt: null,\n })\n}\n\ndescribe('#cors:add', () => {\n beforeEach(() => {\n mockExistsSync.mockReturnValue(false)\n })\n\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('adds CORS origin with credentials flag', async () => {\n const origin = 'https://example.com'\n const expectedAllowCredentials = true\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, function (_, requestBody) {\n expect(requestBody).toEqual({\n allowCredentials: expectedAllowCredentials,\n origin: origin,\n })\n\n return {\n allowCredentials: expectedAllowCredentials,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 1,\n origin: origin,\n projectId: 'test-project',\n updatedAt: null,\n }\n })\n\n const {stdout} = await testCommand(Add, [origin, '--credentials'], {mocks: defaultMocks})\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('adds CORS origin with no-credentials flag', async () => {\n const origin = 'http://localhost:3000'\n const expectedAllowCredentials = false\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(201, function (_, requestBody) {\n expect(requestBody).toEqual({\n allowCredentials: expectedAllowCredentials,\n origin: origin,\n })\n\n return {\n allowCredentials: expectedAllowCredentials,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n id: 2,\n origin: origin,\n projectId: 'test-project',\n updatedAt: null,\n }\n })\n\n const {stdout} = await testCommand(Add, [origin, '--no-credentials'], {mocks: defaultMocks})\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('fails when no project ID is available', async () => {\n const {error} = await testCommand(Add, ['https://example.com'], {\n mocks: {\n cliConfig: {api: {}},\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n },\n })\n\n expect(error?.message).toContain(NO_PROJECT_ID)\n })\n\n const errorHandlingCases = [\n {\n description: 'handles API errors gracefully',\n expectedError: 'CORS origin addition failed',\n setupMock: () =>\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).reply(400, {message: 'Invalid origin'}),\n },\n {\n description: 'handles network errors during API call',\n expectedError: 'CORS origin addition failed',\n setupMock: () =>\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'post',\n uri: '/projects/test-project/cors',\n }).replyWithError(new Error('Network Error')),\n },\n ]\n\n test.each(errorHandlingCases)('$description', async ({expectedError, setupMock}) => {\n setupMock()\n\n const {error} = await testCommand(Add, ['https://example.com', '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(error?.message).toContain(expectedError)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('warns when origin looks like a file path', async () => {\n mockExistsSync.mockReturnValue(true)\n setupSuccessfulApiMock()\n\n const {stderr} = await testCommand(Add, ['https://example.com', '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(stderr).toContain('Remember to quote values')\n })\n\n describe('wildcard origins', () => {\n const wildcardConfirmationCases = [\n {\n confirmWildcard: true,\n description: 'prompts for confirmation with wildcard origins and proceeds',\n expectedError: undefined,\n expectedOutput: 'CORS origin added successfully',\n setupMocks: () => {\n mockConfirm.mockResolvedValueOnce(true).mockResolvedValueOnce(false)\n setupSuccessfulApiMock()\n },\n },\n {\n confirmWildcard: false,\n description: 'cancels operation when wildcard confirmation is denied',\n expectedError: 'Operation cancelled',\n expectedOutput: undefined,\n setupMocks: () => mockConfirm.mockResolvedValueOnce(false),\n },\n ]\n\n test.each(wildcardConfirmationCases)(\n '$description',\n async ({expectedError, expectedOutput, setupMocks}) => {\n setupMocks()\n\n const result = await testCommand(Add, ['https://*.example.com'], {mocks: defaultMocks})\n\n expect(confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n default: false,\n message: expect.stringContaining('absolutely sure'),\n }),\n )\n\n if (expectedOutput) {\n expect(result.stdout).toContain(expectedOutput)\n }\n if (expectedError) {\n expect(result.error?.message).toContain(expectedError)\n expect(result.error?.oclif?.exit).toBe(1)\n }\n },\n )\n\n test('shows specific examples for full wildcard', async () => {\n mockConfirm.mockResolvedValueOnce(true).mockResolvedValueOnce(false)\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['*'], {mocks: defaultMocks})\n\n expect(stdout).toContain('http://www.some-malicious.site')\n expect(stdout).toContain('https://not.what-you-were-expecting.com')\n })\n })\n\n describe('credentials prompts', () => {\n test('prompts for credentials when flag not provided', async () => {\n mockConfirm.mockResolvedValueOnce(true)\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://example.com'], {mocks: defaultMocks})\n\n expect(confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n default: false,\n message: expect.stringContaining('Allow credentials'),\n }),\n )\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test('shows warning about wildcard credentials', async () => {\n mockConfirm\n .mockResolvedValueOnce(true) // Confirm wildcard\n .mockResolvedValueOnce(false) // Deny credentials\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://*.example.com'], {mocks: defaultMocks})\n\n expect(stdout).toContain('HIGHLY')\n expect(stdout).toContain('recommend NOT allowing credentials')\n expect(stdout).toContain('on origins containing wildcards')\n })\n })\n\n describe('origin validation and filtering', () => {\n const validNonWildcardOrigins = [\n 'https://example.com',\n 'http://localhost:3000',\n 'https://sub.example.com:8080',\n 'null',\n ]\n\n const validWildcardOrigins = ['https://*.example.com', '*', 'file:///*']\n\n test.each(validNonWildcardOrigins)('accepts valid non-wildcard origin: %s', async (origin) => {\n setupSuccessfulApiMock()\n\n const {error, stdout} = await testCommand(Add, [origin, '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n test.each(validWildcardOrigins)('accepts valid wildcard origin: %s', async (origin) => {\n mockConfirm.mockResolvedValueOnce(true)\n setupSuccessfulApiMock()\n\n const {error, stdout} = await testCommand(Add, [origin, '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(error).toBeUndefined()\n expect(stdout).toContain('CORS origin added successfully')\n })\n\n const invalidOrigins = [\n 'not-a-url',\n 'example.com', // missing protocol\n ]\n\n test.each(invalidOrigins)('rejects invalid origin: %s', async (origin) => {\n const {error} = await testCommand(Add, [origin, '--credentials'], {mocks: defaultMocks})\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Invalid origin')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('rejects file:// origins other than file:///*', async () => {\n const {error} = await testCommand(Add, ['file://localhost/path', '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(error).toBeDefined()\n expect(error?.message).toContain('Only a local file wildcard is currently allowed: file:///*')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n const portNormalizationCases = [\n {\n description: 'normalizes HTTPS default port',\n expectedOutput: 'Normalized origin to: https://example.com',\n input: 'https://example.com:443',\n shouldNormalize: true,\n },\n {\n description: 'normalizes HTTP default port',\n expectedOutput: 'Normalized origin to: http://example.com',\n input: 'http://example.com:80',\n shouldNormalize: true,\n },\n {\n description: 'preserves non-default ports',\n expectedOutput: 'CORS origin added successfully',\n input: 'https://example.com:8080',\n shouldNormalize: false,\n },\n ]\n\n test.each(portNormalizationCases)(\n '$description',\n async ({expectedOutput, input, shouldNormalize}) => {\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, [input, '--credentials'], {mocks: defaultMocks})\n\n if (shouldNormalize) {\n expect(stdout).toContain(expectedOutput)\n } else {\n expect(stdout).not.toContain('Normalized origin')\n expect(stdout).toContain(expectedOutput)\n }\n },\n )\n })\n\n describe('edge cases', () => {\n test('handles file system check errors gracefully', async () => {\n mockExistsSync.mockImplementation(() => {\n throw new Error('Permission denied')\n })\n setupSuccessfulApiMock()\n\n const {stdout} = await testCommand(Add, ['https://example.com', '--credentials'], {\n mocks: defaultMocks,\n })\n\n expect(stdout).toContain('CORS origin added successfully')\n })\n })\n})\n"],"names":["fs","confirm","mockApi","testCommand","nock","afterEach","beforeEach","describe","expect","test","vi","CORS_API_VERSION","NO_PROJECT_ID","Add","mock","actual","importActual","fn","default","existsSync","defaultMocks","cliConfig","api","projectId","projectRoot","directory","path","type","token","mockConfirm","mocked","mockExistsSync","setupSuccessfulApiMock","apiVersion","method","uri","reply","allowCredentials","createdAt","deletedAt","id","origin","updatedAt","mockReturnValue","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","expectedAllowCredentials","_","requestBody","stdout","mocks","toContain","error","message","errorHandlingCases","description","expectedError","setupMock","replyWithError","Error","each","oclif","exit","toBe","stderr","wildcardConfirmationCases","confirmWildcard","undefined","expectedOutput","setupMocks","mockResolvedValueOnce","result","toHaveBeenCalledWith","objectContaining","stringContaining","validNonWildcardOrigins","validWildcardOrigins","toBeUndefined","invalidOrigins","toBeDefined","portNormalizationCases","input","shouldNormalize","not","mockImplementation"],"mappings":"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"}
@@ -2,10 +2,9 @@ import { runCommand } from '@oclif/test';
2
2
  import { mockApi, testCommand } from '@sanity/cli-test';
3
3
  import nock from 'nock';
4
4
  import { afterEach, describe, expect, test, vi } from 'vitest';
5
- import { CORS_API_VERSION } from '../../../actions/cors/constants.js';
5
+ import { CORS_API_VERSION } from '../../../services/cors.js';
6
6
  import { NO_PROJECT_ID } from '../../../util/errorMessages.js';
7
7
  import { Delete } from '../delete.js';
8
- // Test fixtures
9
8
  const createCorsOrigin = (overrides)=>({
10
9
  allowCredentials: true,
11
10
  createdAt: '2023-01-01T00:00:00Z',
@@ -37,25 +36,20 @@ const TEST_ORIGINS = {
37
36
  origin: 'https://café.example.com'
38
37
  })
39
38
  };
40
- // Mock the config functions with relative paths
41
- vi.mock('../../../../../cli-core/src/config/findProjectRoot.js', ()=>({
42
- findProjectRoot: vi.fn().mockResolvedValue({
43
- directory: '/test/path',
44
- root: '/test/path',
45
- type: 'studio'
46
- })
47
- }));
48
- vi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', ()=>({
49
- getCliConfig: vi.fn().mockResolvedValue({
50
- api: {
51
- projectId: 'test-project'
52
- }
53
- })
54
- }));
55
- vi.mock('../../../../../cli-core/src/services/getCliToken.js', ()=>({
56
- getCliToken: vi.fn().mockResolvedValue('test-token')
57
- }));
58
- // Mock inquirer prompts
39
+ const testProjectId = 'test-project';
40
+ const defaultMocks = {
41
+ cliConfig: {
42
+ api: {
43
+ projectId: testProjectId
44
+ }
45
+ },
46
+ projectRoot: {
47
+ directory: '/test/path',
48
+ path: '/test/path/sanity.config.ts',
49
+ type: 'studio'
50
+ },
51
+ token: 'test-token'
52
+ };
59
53
  vi.mock('@sanity/cli-core/ux', async ()=>{
60
54
  const actual = await vi.importActual('@sanity/cli-core/ux');
61
55
  return {
@@ -92,7 +86,9 @@ describe('#cors:delete', ()=>{
92
86
  }).reply(204);
93
87
  const { stdout } = await testCommand(Delete, [
94
88
  'https://example.com'
95
- ]);
89
+ ], {
90
+ mocks: defaultMocks
91
+ });
96
92
  expect(stdout).toBe('Origin deleted\n');
97
93
  });
98
94
  test('prompts user to select origin when none specified', async ()=>{
@@ -110,7 +106,9 @@ describe('#cors:delete', ()=>{
110
106
  method: 'delete',
111
107
  uri: '/projects/test-project/cors/2'
112
108
  }).reply(204);
113
- const { stdout } = await testCommand(Delete);
109
+ const { stdout } = await testCommand(Delete, [], {
110
+ mocks: defaultMocks
111
+ });
114
112
  expect(stdout).toBe('Origin deleted\n');
115
113
  expect(select).toHaveBeenCalledWith({
116
114
  choices: [
@@ -140,7 +138,9 @@ describe('#cors:delete', ()=>{
140
138
  }).reply(204);
141
139
  const { stdout } = await testCommand(Delete, [
142
140
  'https://example.com'
143
- ]);
141
+ ], {
142
+ mocks: defaultMocks
143
+ });
144
144
  expect(stdout).toBe('Origin deleted\n');
145
145
  });
146
146
  test('throws error when specified origin is not found', async ()=>{
@@ -152,7 +152,9 @@ describe('#cors:delete', ()=>{
152
152
  ]);
153
153
  const { error } = await testCommand(Delete, [
154
154
  'https://nonexistent.com'
155
- ]);
155
+ ], {
156
+ mocks: defaultMocks
157
+ });
156
158
  expect(error).toBeInstanceOf(Error);
157
159
  expect(error?.message).toEqual('Origin "https://nonexistent.com" not found');
158
160
  expect(error?.oclif?.exit).toBe(1);
@@ -164,7 +166,9 @@ describe('#cors:delete', ()=>{
164
166
  }).reply(200, []);
165
167
  const { error } = await testCommand(Delete, [
166
168
  'https://example.com'
167
- ]);
169
+ ], {
170
+ mocks: defaultMocks
171
+ });
168
172
  expect(error).toBeInstanceOf(Error);
169
173
  expect(error?.message).toEqual('No CORS origins configured for this project.');
170
174
  expect(error?.oclif?.exit).toBe(1);
@@ -189,7 +193,9 @@ describe('#cors:delete', ()=>{
189
193
  });
190
194
  const { error } = await testCommand(Delete, [
191
195
  'https://example.com'
192
- ]);
196
+ ], {
197
+ mocks: defaultMocks
198
+ });
193
199
  expect(error).toBeInstanceOf(Error);
194
200
  expect(error?.message).toContain('Failed to fetch CORS origins');
195
201
  expect(error?.message).toContain(message);
@@ -222,7 +228,9 @@ describe('#cors:delete', ()=>{
222
228
  });
223
229
  const { error } = await testCommand(Delete, [
224
230
  'https://example.com'
225
- ]);
231
+ ], {
232
+ mocks: defaultMocks
233
+ });
226
234
  expect(error).toBeInstanceOf(Error);
227
235
  expect(error?.message).toContain('Origin deletion failed');
228
236
  expect(error?.message).toContain(message);
@@ -238,15 +246,18 @@ describe('#cors:delete', ()=>{
238
246
  projectId: ''
239
247
  }
240
248
  ])('throws error when $desc', async ({ projectId })=>{
241
- const { getCliConfig } = await import('../../../../../cli-core/src/config/cli/getCliConfig.js');
242
- vi.mocked(getCliConfig).mockResolvedValueOnce({
243
- api: {
244
- projectId
245
- }
246
- });
247
249
  const { error } = await testCommand(Delete, [
248
250
  'https://example.com'
249
- ]);
251
+ ], {
252
+ mocks: {
253
+ ...defaultMocks,
254
+ cliConfig: {
255
+ api: {
256
+ projectId
257
+ }
258
+ }
259
+ }
260
+ });
250
261
  expect(error).toBeInstanceOf(Error);
251
262
  expect(error?.message).toEqual(NO_PROJECT_ID);
252
263
  expect(error?.oclif?.exit).toBe(1);
@@ -255,7 +266,9 @@ describe('#cors:delete', ()=>{
255
266
  // Don't set up any mock to simulate network failure
256
267
  const { error } = await testCommand(Delete, [
257
268
  'https://example.com'
258
- ]);
269
+ ], {
270
+ mocks: defaultMocks
271
+ });
259
272
  expect(error).toBeInstanceOf(Error);
260
273
  expect(error?.message).toContain('Failed to fetch CORS origins');
261
274
  expect(error?.oclif?.exit).toBe(1);
@@ -285,7 +298,9 @@ describe('#cors:delete', ()=>{
285
298
  }).reply(204);
286
299
  const { stdout } = await testCommand(Delete, [
287
300
  input
288
- ]);
301
+ ], {
302
+ mocks: defaultMocks
303
+ });
289
304
  expect(stdout).toBe('Origin deleted\n');
290
305
  });
291
306
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/cors/__tests__/delete.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {CORS_API_VERSION} from '../../../actions/cors/constants.js'\nimport {type CorsOrigin} from '../../../actions/cors/types.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {Delete} from '../delete.js'\n\n// Test fixtures\nconst createCorsOrigin = (\n overrides: Partial<CorsOrigin> & {id: number; origin: string},\n): CorsOrigin => ({\n allowCredentials: true,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n projectId: 'test-project',\n updatedAt: null,\n ...overrides,\n})\n\nconst TEST_ORIGINS = {\n APP_EXAMPLE: createCorsOrigin({\n allowCredentials: false,\n id: 2,\n origin: 'https://app.example.com',\n }),\n CASE_MIXED: createCorsOrigin({id: 1, origin: 'https://Example.Com'}),\n EXAMPLE: createCorsOrigin({id: 1, origin: 'https://example.com'}),\n LOCALHOST: createCorsOrigin({id: 1, origin: 'http://localhost:3000'}),\n SPECIAL_CHARS: createCorsOrigin({id: 1, origin: 'https://café.example.com'}),\n} as const\n\n// Mock the config functions with relative paths\nvi.mock('../../../../../cli-core/src/config/findProjectRoot.js', () => ({\n findProjectRoot: vi.fn().mockResolvedValue({\n directory: '/test/path',\n root: '/test/path',\n type: 'studio',\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/config/cli/getCliConfig.js', () => ({\n getCliConfig: vi.fn().mockResolvedValue({\n api: {\n projectId: 'test-project',\n },\n }),\n}))\n\nvi.mock('../../../../../cli-core/src/services/getCliToken.js', () => ({\n getCliToken: vi.fn().mockResolvedValue('test-token'),\n}))\n\n// Mock inquirer prompts\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n select: vi.fn(),\n }\n})\n\ndescribe('#cors:delete', () => {\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['cors delete', '--help'])\n expect(stdout).toContain('Delete an existing CORS origin from your project')\n })\n\n test('deletes a specific CORS origin', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE, TEST_ORIGINS.APP_EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, ['https://example.com'])\n expect(stdout).toBe('Origin deleted\\n')\n })\n\n test('prompts user to select origin when none specified', async () => {\n const {select} = await import('@sanity/cli-core/ux')\n vi.mocked(select).mockResolvedValue(2)\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE, TEST_ORIGINS.APP_EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/2',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete)\n expect(stdout).toBe('Origin deleted\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [\n {name: 'https://example.com', value: 1},\n {name: 'https://app.example.com', value: 2},\n ],\n message: 'Select origin to delete',\n })\n })\n\n test('handles case-insensitive origin matching', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.CASE_MIXED])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, ['https://example.com'])\n expect(stdout).toBe('Origin deleted\\n')\n })\n\n test('throws error when specified origin is not found', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE])\n\n const {error} = await testCommand(Delete, ['https://nonexistent.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual('Origin \"https://nonexistent.com\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no CORS origins exist', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [])\n\n const {error} = await testCommand(Delete, ['https://example.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual('No CORS origins configured for this project.')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when fetching origins', message: 'Internal Server Error', statusCode: 500},\n {desc: 'with 404 error when fetching origins', message: 'Project not found', statusCode: 404},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(Delete, ['https://example.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Failed to fetch CORS origins')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when deleting origin', message: 'Failed to delete', statusCode: 500},\n {desc: 'with 404 error when deleting origin', message: 'Origin not found', statusCode: 404},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(Delete, ['https://example.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Origin deletion failed')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'no project ID is found', projectId: undefined},\n {desc: 'project ID is empty string', projectId: ''},\n ])('throws error when $desc', async ({projectId}) => {\n const {getCliConfig} = await import('../../../../../cli-core/src/config/cli/getCliConfig.js')\n vi.mocked(getCliConfig).mockResolvedValueOnce({\n api: {projectId},\n })\n\n const {error} = await testCommand(Delete, ['https://example.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when fetching origins', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(Delete, ['https://example.com'])\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Failed to fetch CORS origins')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {\n desc: 'special characters',\n input: 'https://café.example.com',\n origin: TEST_ORIGINS.SPECIAL_CHARS,\n },\n {desc: 'ports', input: 'http://localhost:3000', origin: TEST_ORIGINS.LOCALHOST},\n ])('handles $desc in origin names', async ({input, origin}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [origin])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, [input])\n expect(stdout).toBe('Origin deleted\\n')\n })\n})\n"],"names":["runCommand","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","CORS_API_VERSION","NO_PROJECT_ID","Delete","createCorsOrigin","overrides","allowCredentials","createdAt","deletedAt","projectId","updatedAt","TEST_ORIGINS","APP_EXAMPLE","id","origin","CASE_MIXED","EXAMPLE","LOCALHOST","SPECIAL_CHARS","mock","findProjectRoot","fn","mockResolvedValue","directory","root","type","getCliConfig","api","getCliToken","actual","importActual","select","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","apiVersion","uri","reply","method","toBe","mocked","toHaveBeenCalledWith","choices","name","value","message","error","toBeInstanceOf","Error","oclif","exit","each","desc","statusCode","undefined","mockResolvedValueOnce","input"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/cors/__tests__/delete.test.ts"],"sourcesContent":["import {runCommand} from '@oclif/test'\nimport {mockApi, testCommand} from '@sanity/cli-test'\nimport nock from 'nock'\nimport {afterEach, describe, expect, test, vi} from 'vitest'\n\nimport {CORS_API_VERSION, type CorsOrigin} from '../../../services/cors.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\nimport {Delete} from '../delete.js'\n\nconst createCorsOrigin = (\n overrides: Partial<CorsOrigin> & {id: number; origin: string},\n): CorsOrigin => ({\n allowCredentials: true,\n createdAt: '2023-01-01T00:00:00Z',\n deletedAt: null,\n projectId: 'test-project',\n updatedAt: null,\n ...overrides,\n})\n\nconst TEST_ORIGINS = {\n APP_EXAMPLE: createCorsOrigin({\n allowCredentials: false,\n id: 2,\n origin: 'https://app.example.com',\n }),\n CASE_MIXED: createCorsOrigin({id: 1, origin: 'https://Example.Com'}),\n EXAMPLE: createCorsOrigin({id: 1, origin: 'https://example.com'}),\n LOCALHOST: createCorsOrigin({id: 1, origin: 'http://localhost:3000'}),\n SPECIAL_CHARS: createCorsOrigin({id: 1, origin: 'https://café.example.com'}),\n} as const\n\nconst testProjectId = 'test-project'\n\nconst defaultMocks = {\n cliConfig: {api: {projectId: testProjectId}},\n projectRoot: {\n directory: '/test/path',\n path: '/test/path/sanity.config.ts',\n type: 'studio' as const,\n },\n token: 'test-token',\n}\n\nvi.mock('@sanity/cli-core/ux', async () => {\n const actual = await vi.importActual<typeof import('@sanity/cli-core/ux')>('@sanity/cli-core/ux')\n return {\n ...actual,\n select: vi.fn(),\n }\n})\n\ndescribe('#cors:delete', () => {\n afterEach(() => {\n vi.clearAllMocks()\n const pending = nock.pendingMocks()\n nock.cleanAll()\n expect(pending, 'pending mocks').toEqual([])\n })\n\n test('--help works', async () => {\n const {stdout} = await runCommand(['cors delete', '--help'])\n expect(stdout).toContain('Delete an existing CORS origin from your project')\n })\n\n test('deletes a specific CORS origin', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE, TEST_ORIGINS.APP_EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(stdout).toBe('Origin deleted\\n')\n })\n\n test('prompts user to select origin when none specified', async () => {\n const {select} = await import('@sanity/cli-core/ux')\n vi.mocked(select).mockResolvedValue(2)\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE, TEST_ORIGINS.APP_EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/2',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, [], {mocks: defaultMocks})\n expect(stdout).toBe('Origin deleted\\n')\n expect(select).toHaveBeenCalledWith({\n choices: [\n {name: 'https://example.com', value: 1},\n {name: 'https://app.example.com', value: 2},\n ],\n message: 'Select origin to delete',\n })\n })\n\n test('handles case-insensitive origin matching', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.CASE_MIXED])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(stdout).toBe('Origin deleted\\n')\n })\n\n test('throws error when specified origin is not found', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE])\n\n const {error} = await testCommand(Delete, ['https://nonexistent.com'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual('Origin \"https://nonexistent.com\" not found')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('throws error when no CORS origins exist', async () => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [])\n\n const {error} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual('No CORS origins configured for this project.')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when fetching origins', message: 'Internal Server Error', statusCode: 500},\n {desc: 'with 404 error when fetching origins', message: 'Project not found', statusCode: 404},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Failed to fetch CORS origins')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'when deleting origin', message: 'Failed to delete', statusCode: 500},\n {desc: 'with 404 error when deleting origin', message: 'Origin not found', statusCode: 404},\n ])('handles API error $desc', async ({message, statusCode}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [TEST_ORIGINS.EXAMPLE])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(statusCode, {message})\n\n const {error} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Origin deletion failed')\n expect(error?.message).toContain(message)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {desc: 'no project ID is found', projectId: undefined},\n {desc: 'project ID is empty string', projectId: ''},\n ])('throws error when $desc', async ({projectId}) => {\n const {error} = await testCommand(Delete, ['https://example.com'], {\n mocks: {\n ...defaultMocks,\n cliConfig: {api: {projectId}},\n },\n })\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toEqual(NO_PROJECT_ID)\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test('handles network errors when fetching origins', async () => {\n // Don't set up any mock to simulate network failure\n const {error} = await testCommand(Delete, ['https://example.com'], {mocks: defaultMocks})\n expect(error).toBeInstanceOf(Error)\n expect(error?.message).toContain('Failed to fetch CORS origins')\n expect(error?.oclif?.exit).toBe(1)\n })\n\n test.each([\n {\n desc: 'special characters',\n input: 'https://café.example.com',\n origin: TEST_ORIGINS.SPECIAL_CHARS,\n },\n {desc: 'ports', input: 'http://localhost:3000', origin: TEST_ORIGINS.LOCALHOST},\n ])('handles $desc in origin names', async ({input, origin}) => {\n mockApi({\n apiVersion: CORS_API_VERSION,\n uri: '/projects/test-project/cors',\n }).reply(200, [origin])\n\n mockApi({\n apiVersion: CORS_API_VERSION,\n method: 'delete',\n uri: '/projects/test-project/cors/1',\n }).reply(204)\n\n const {stdout} = await testCommand(Delete, [input], {mocks: defaultMocks})\n expect(stdout).toBe('Origin deleted\\n')\n })\n})\n"],"names":["runCommand","mockApi","testCommand","nock","afterEach","describe","expect","test","vi","CORS_API_VERSION","NO_PROJECT_ID","Delete","createCorsOrigin","overrides","allowCredentials","createdAt","deletedAt","projectId","updatedAt","TEST_ORIGINS","APP_EXAMPLE","id","origin","CASE_MIXED","EXAMPLE","LOCALHOST","SPECIAL_CHARS","testProjectId","defaultMocks","cliConfig","api","projectRoot","directory","path","type","token","mock","actual","importActual","select","fn","clearAllMocks","pending","pendingMocks","cleanAll","toEqual","stdout","toContain","apiVersion","uri","reply","method","mocks","toBe","mocked","mockResolvedValue","toHaveBeenCalledWith","choices","name","value","message","error","toBeInstanceOf","Error","oclif","exit","each","desc","statusCode","undefined","input"],"mappings":"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"}