@sanity/cli 7.10.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +31 -22
  2. package/dist/actions/auth/ensureAuthenticated.js +2 -0
  3. package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
  4. package/dist/actions/auth/login/loginInstructions.js +19 -0
  5. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  6. package/dist/actions/build/buildApp.js +10 -7
  7. package/dist/actions/build/buildApp.js.map +1 -1
  8. package/dist/actions/build/buildStudio.js +9 -6
  9. package/dist/actions/build/buildStudio.js.map +1 -1
  10. package/dist/actions/build/types.js.map +1 -1
  11. package/dist/actions/dataset/resolveDataset.js +7 -1
  12. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  13. package/dist/actions/deploy/deployApp.js +205 -157
  14. package/dist/actions/deploy/deployApp.js.map +1 -1
  15. package/dist/actions/deploy/deployChecks.js +1 -1
  16. package/dist/actions/deploy/deployChecks.js.map +1 -1
  17. package/dist/actions/deploy/deployStudio.js +127 -86
  18. package/dist/actions/deploy/deployStudio.js.map +1 -1
  19. package/dist/actions/deploy/resolveDeployTarget.js +5 -9
  20. package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
  21. package/dist/actions/dev/devAction.js +1 -2
  22. package/dist/actions/dev/devAction.js.map +1 -1
  23. package/dist/actions/dev/servers/getDevServerConfig.js +8 -2
  24. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  25. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  26. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  27. package/dist/actions/init/bootstrapLocalTemplate.js +18 -9
  28. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  29. package/dist/actions/init/createAppCliConfig.js.map +1 -1
  30. package/dist/actions/init/createCliConfig.js.map +1 -1
  31. package/dist/actions/init/initAction.js +23 -15
  32. package/dist/actions/init/initAction.js.map +1 -1
  33. package/dist/actions/manifest/extractCoreAppManifest.js +5 -3
  34. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  35. package/dist/actions/migration/constants.js +10 -0
  36. package/dist/actions/migration/constants.js.map +1 -0
  37. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  38. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  39. package/dist/actions/migration/fileExists.js +13 -0
  40. package/dist/actions/migration/fileExists.js.map +1 -0
  41. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  42. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  43. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  44. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  45. package/dist/actions/migration/resolveMigrations.js +50 -0
  46. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  47. package/dist/actions/migration/templates/index.js +7 -0
  48. package/dist/actions/migration/templates/index.js.map +1 -0
  49. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  50. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  51. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  52. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  53. package/dist/actions/migration/templates/renameField.js +20 -0
  54. package/dist/actions/migration/templates/renameField.js.map +1 -0
  55. package/dist/actions/migration/templates/renameType.js +19 -0
  56. package/dist/actions/migration/templates/renameType.js.map +1 -0
  57. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  58. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  59. package/dist/actions/migration/tree.js +111 -0
  60. package/dist/actions/migration/tree.js.map +1 -0
  61. package/dist/actions/preview/previewAction.js +33 -1
  62. package/dist/actions/preview/previewAction.js.map +1 -1
  63. package/dist/actions/schema/listSchemas.js +6 -4
  64. package/dist/actions/schema/listSchemas.js.map +1 -1
  65. package/dist/actions/tokens/validateRole.js +2 -1
  66. package/dist/actions/tokens/validateRole.js.map +1 -1
  67. package/dist/actions/undeploy/runUndeploy.js +13 -4
  68. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  69. package/dist/commands/backups/disable.js +5 -1
  70. package/dist/commands/backups/disable.js.map +1 -1
  71. package/dist/commands/backups/download.js +30 -6
  72. package/dist/commands/backups/download.js.map +1 -1
  73. package/dist/commands/backups/enable.js +5 -1
  74. package/dist/commands/backups/enable.js.map +1 -1
  75. package/dist/commands/backups/list.js +5 -1
  76. package/dist/commands/backups/list.js.map +1 -1
  77. package/dist/commands/cors/add.js +15 -7
  78. package/dist/commands/cors/add.js.map +1 -1
  79. package/dist/commands/cors/delete.js +6 -1
  80. package/dist/commands/cors/delete.js.map +1 -1
  81. package/dist/commands/datasets/alias/create.js +25 -18
  82. package/dist/commands/datasets/alias/create.js.map +1 -1
  83. package/dist/commands/datasets/alias/delete.js +15 -8
  84. package/dist/commands/datasets/alias/delete.js.map +1 -1
  85. package/dist/commands/datasets/alias/link.js +39 -17
  86. package/dist/commands/datasets/alias/link.js.map +1 -1
  87. package/dist/commands/datasets/alias/unlink.js +23 -2
  88. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  89. package/dist/commands/datasets/copy.js +18 -2
  90. package/dist/commands/datasets/copy.js.map +1 -1
  91. package/dist/commands/datasets/create.js +8 -2
  92. package/dist/commands/datasets/create.js.map +1 -1
  93. package/dist/commands/datasets/delete.js +14 -17
  94. package/dist/commands/datasets/delete.js.map +1 -1
  95. package/dist/commands/datasets/embeddings/disable.js +3 -0
  96. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  97. package/dist/commands/datasets/embeddings/enable.js +5 -2
  98. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  99. package/dist/commands/datasets/embeddings/status.js +3 -0
  100. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  101. package/dist/commands/datasets/export.js +27 -15
  102. package/dist/commands/datasets/export.js.map +1 -1
  103. package/dist/commands/datasets/import.js +3 -3
  104. package/dist/commands/datasets/import.js.map +1 -1
  105. package/dist/commands/datasets/visibility/get.js +2 -2
  106. package/dist/commands/datasets/visibility/get.js.map +1 -1
  107. package/dist/commands/datasets/visibility/set.js +2 -2
  108. package/dist/commands/datasets/visibility/set.js.map +1 -1
  109. package/dist/commands/docs/read.js +3 -3
  110. package/dist/commands/docs/read.js.map +1 -1
  111. package/dist/commands/documents/create.js +18 -13
  112. package/dist/commands/documents/create.js.map +1 -1
  113. package/dist/commands/documents/delete.js +3 -3
  114. package/dist/commands/documents/delete.js.map +1 -1
  115. package/dist/commands/documents/get.js +3 -3
  116. package/dist/commands/documents/get.js.map +1 -1
  117. package/dist/commands/documents/query.js +3 -3
  118. package/dist/commands/documents/query.js.map +1 -1
  119. package/dist/commands/documents/validate.js +29 -26
  120. package/dist/commands/documents/validate.js.map +1 -1
  121. package/dist/commands/graphql/deploy.js +20 -16
  122. package/dist/commands/graphql/deploy.js.map +1 -1
  123. package/dist/commands/graphql/undeploy.js +15 -18
  124. package/dist/commands/graphql/undeploy.js.map +1 -1
  125. package/dist/commands/hooks/delete.js +2 -2
  126. package/dist/commands/hooks/delete.js.map +1 -1
  127. package/dist/commands/hooks/logs.js +2 -2
  128. package/dist/commands/hooks/logs.js.map +1 -1
  129. package/dist/commands/login.js +2 -1
  130. package/dist/commands/login.js.map +1 -1
  131. package/dist/commands/media/create-aspect.js +20 -8
  132. package/dist/commands/media/create-aspect.js.map +1 -1
  133. package/dist/commands/media/delete-aspect.js +31 -16
  134. package/dist/commands/media/delete-aspect.js.map +1 -1
  135. package/dist/commands/media/deploy-aspect.js +10 -5
  136. package/dist/commands/media/deploy-aspect.js.map +1 -1
  137. package/dist/commands/media/export.js +9 -4
  138. package/dist/commands/media/export.js.map +1 -1
  139. package/dist/commands/media/import.js +6 -1
  140. package/dist/commands/media/import.js.map +1 -1
  141. package/dist/commands/migrations/create.js +150 -0
  142. package/dist/commands/migrations/create.js.map +1 -0
  143. package/dist/commands/migrations/list.js +64 -0
  144. package/dist/commands/migrations/list.js.map +1 -0
  145. package/dist/commands/migrations/run.js +306 -0
  146. package/dist/commands/migrations/run.js.map +1 -0
  147. package/dist/commands/preview.js +1 -0
  148. package/dist/commands/preview.js.map +1 -1
  149. package/dist/commands/projects/create.js +2 -1
  150. package/dist/commands/projects/create.js.map +1 -1
  151. package/dist/commands/schemas/delete.js +23 -2
  152. package/dist/commands/schemas/delete.js.map +1 -1
  153. package/dist/commands/schemas/deploy.js +6 -4
  154. package/dist/commands/schemas/deploy.js.map +1 -1
  155. package/dist/commands/schemas/extract.js +22 -1
  156. package/dist/commands/schemas/extract.js.map +1 -1
  157. package/dist/commands/schemas/list.js +8 -8
  158. package/dist/commands/schemas/list.js.map +1 -1
  159. package/dist/commands/tokens/{add.js → create.js} +25 -18
  160. package/dist/commands/tokens/create.js.map +1 -0
  161. package/dist/commands/tokens/delete.js +41 -23
  162. package/dist/commands/tokens/delete.js.map +1 -1
  163. package/dist/commands/undeploy.js +2 -7
  164. package/dist/commands/undeploy.js.map +1 -1
  165. package/dist/commands/users/invite.js +25 -3
  166. package/dist/commands/users/invite.js.map +1 -1
  167. package/dist/topicAliases.js +3 -0
  168. package/dist/topicAliases.js.map +1 -1
  169. package/dist/util/formatCliErrorMessages.js +5 -0
  170. package/dist/util/formatCliErrorMessages.js.map +1 -0
  171. package/oclif.config.js +5 -1
  172. package/oclif.manifest.json +579 -374
  173. package/package.json +7 -7
  174. package/dist/commands/tokens/add.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/documents/query.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {colorizeJson, getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst queryDocumentDebug = subdebug('documents:query')\n\nexport class QueryDocumentCommand extends SanityCommand<typeof QueryDocumentCommand> {\n static override args = {\n query: Args.string({\n description: 'GROQ query to run against the dataset',\n required: true,\n }),\n }\n\n static override description = 'Query for documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> \\'*[_type == \"movie\"][0..4]\\'',\n description: 'Fetch 5 documents of type \"movie\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_type == \"movie\"]|order(releaseDate asc)[0]{title}\\' --dataset staging',\n description: 'Fetch title of the oldest movie in the dataset named \"staging\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_id == \"header\"] { \"headerText\": pt::text(body) }\\' --api-version v2021-06-07',\n description: 'Use API version v2021-06-07 and do a query',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_type == \"post\"]\\' --project-id abc123 --dataset production',\n description: 'Query documents in a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({description: 'Project ID to query', semantics: 'override'}),\n ...getDatasetFlag({description: 'Dataset to query', semantics: 'override'}),\n anonymous: Flags.boolean({\n default: false,\n description: 'Send the query without any authorization token',\n }),\n 'api-version': Flags.string({\n description: `API version to use (defaults to ${DOCUMENTS_API_VERSION})`,\n env: 'SANITY_CLI_QUERY_API_VERSION',\n }),\n pretty: Flags.boolean({\n default: false,\n description: 'Colorize JSON output',\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to query',\n hidden: true,\n }),\n }\n\n static override hiddenAliases: string[] = ['document:query']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(QueryDocumentCommand)\n const {query} = args\n const {anonymous, 'api-version': apiVersion, dataset, pretty} = flags\n\n const cliConfig = await this.tryGetCliConfig()\n\n const projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () => promptForProject({}),\n })\n\n const requireUser = !anonymous\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag',\n {exit: 1},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n const targetApiVersion = apiVersion || DOCUMENTS_API_VERSION\n\n if (!apiVersion) {\n this.warn(`--api-version not specified, using \\`${DOCUMENTS_API_VERSION}\\``)\n }\n\n try {\n const projectClient = await getProjectCliClient({\n apiVersion: targetApiVersion,\n dataset: targetDataset,\n projectId,\n requireUser,\n })\n\n const docs = await projectClient.fetch(query)\n\n if (!docs) {\n this.error('Query returned no results', {exit: 1})\n }\n\n // Output the query results\n if (pretty) {\n this.log(colorizeJson(docs))\n } else {\n this.log(JSON.stringify(docs, null, 2))\n }\n } catch (error) {\n const err = error as Error\n\n queryDocumentDebug(`Error running query: ${query}`, err)\n\n // Provide more context in error messages\n const errorMsg = err.message.toLowerCase().includes('syntax')\n ? `Invalid GROQ query syntax: ${err.message}`\n : `Failed to run query: ${err.message}`\n\n this.error(`${errorMsg}\\nQuery: ${query}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","Flags","colorizeJson","getProjectCliClient","SanityCommand","subdebug","DOCUMENTS_API_VERSION","promptForProject","getDatasetFlag","getProjectIdFlag","queryDocumentDebug","QueryDocumentCommand","args","query","string","description","required","examples","command","flags","semantics","anonymous","boolean","default","env","pretty","project","deprecated","to","hidden","hiddenAliases","run","parse","apiVersion","dataset","cliConfig","tryGetCliConfig","projectId","getProjectId","deprecatedFlagName","fallback","requireUser","api","error","exit","targetDataset","targetApiVersion","warn","projectClient","docs","fetch","log","JSON","stringify","err","errorMsg","message","toLowerCase","includes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/documents/query.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {\n colorizeJson,\n exitCodes,\n getProjectCliClient,\n SanityCommand,\n subdebug,\n} from '@sanity/cli-core'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst queryDocumentDebug = subdebug('documents:query')\n\nexport class QueryDocumentCommand extends SanityCommand<typeof QueryDocumentCommand> {\n static override args = {\n query: Args.string({\n description: 'GROQ query to run against the dataset',\n required: true,\n }),\n }\n\n static override description = 'Query for documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> \\'*[_type == \"movie\"][0..4]\\'',\n description: 'Fetch 5 documents of type \"movie\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_type == \"movie\"]|order(releaseDate asc)[0]{title}\\' --dataset staging',\n description: 'Fetch title of the oldest movie in the dataset named \"staging\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_id == \"header\"] { \"headerText\": pt::text(body) }\\' --api-version v2021-06-07',\n description: 'Use API version v2021-06-07 and do a query',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> \\'*[_type == \"post\"]\\' --project-id abc123 --dataset production',\n description: 'Query documents in a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({description: 'Project ID to query', semantics: 'override'}),\n ...getDatasetFlag({description: 'Dataset to query', semantics: 'override'}),\n anonymous: Flags.boolean({\n default: false,\n description: 'Send the query without any authorization token',\n }),\n 'api-version': Flags.string({\n description: `API version to use (defaults to ${DOCUMENTS_API_VERSION})`,\n env: 'SANITY_CLI_QUERY_API_VERSION',\n }),\n pretty: Flags.boolean({\n default: false,\n description: 'Colorize JSON output',\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to query',\n hidden: true,\n }),\n }\n\n static override hiddenAliases: string[] = ['document:query']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(QueryDocumentCommand)\n const {query} = args\n const {anonymous, 'api-version': apiVersion, dataset, pretty} = flags\n\n const cliConfig = await this.tryGetCliConfig()\n\n const projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () => promptForProject({}),\n })\n\n const requireUser = !anonymous\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'Dataset is required. Pass it with `--dataset <name>` or configure it in `sanity.cli.ts`.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n const targetApiVersion = apiVersion || DOCUMENTS_API_VERSION\n\n if (!apiVersion) {\n this.warn(`--api-version not specified, using \\`${DOCUMENTS_API_VERSION}\\``)\n }\n\n try {\n const projectClient = await getProjectCliClient({\n apiVersion: targetApiVersion,\n dataset: targetDataset,\n projectId,\n requireUser,\n })\n\n const docs = await projectClient.fetch(query)\n\n if (!docs) {\n this.error('Query returned no results', {exit: 1})\n }\n\n // Output the query results\n if (pretty) {\n this.log(colorizeJson(docs))\n } else {\n this.log(JSON.stringify(docs, null, 2))\n }\n } catch (error) {\n const err = error as Error\n\n queryDocumentDebug(`Error running query: ${query}`, err)\n\n // Provide more context in error messages\n const errorMsg = err.message.toLowerCase().includes('syntax')\n ? `Invalid GROQ query syntax: ${err.message}`\n : `Failed to run query: ${err.message}`\n\n this.error(`${errorMsg}\\nQuery: ${query}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","Flags","colorizeJson","exitCodes","getProjectCliClient","SanityCommand","subdebug","DOCUMENTS_API_VERSION","promptForProject","getDatasetFlag","getProjectIdFlag","queryDocumentDebug","QueryDocumentCommand","args","query","string","description","required","examples","command","flags","semantics","anonymous","boolean","default","env","pretty","project","deprecated","to","hidden","hiddenAliases","run","parse","apiVersion","dataset","cliConfig","tryGetCliConfig","projectId","getProjectId","deprecatedFlagName","fallback","requireUser","api","error","exit","USAGE_ERROR","targetDataset","targetApiVersion","warn","projectClient","docs","fetch","log","JSON","stringify","err","errorMsg","message","toLowerCase","includes"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SACEC,YAAY,EACZC,SAAS,EACTC,mBAAmB,EACnBC,aAAa,EACbC,QAAQ,QACH,mBAAkB;AAEzB,SAAQC,qBAAqB,QAAO,uCAAsC;AAC1E,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,cAAc,EAAEC,gBAAgB,QAAO,4BAA2B;AAE1E,MAAMC,qBAAqBL,SAAS;AAEpC,OAAO,MAAMM,6BAA6BP;IACxC,OAAgBQ,OAAO;QACrBC,OAAOd,KAAKe,MAAM,CAAC;YACjBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,sBAAqB;IAEnD,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAACM,aAAa;YAAuBK,WAAW;QAAU,EAAE;QAChF,GAAGZ,eAAe;YAACO,aAAa;YAAoBK,WAAW;QAAU,EAAE;QAC3EC,WAAWrB,MAAMsB,OAAO,CAAC;YACvBC,SAAS;YACTR,aAAa;QACf;QACA,eAAef,MAAMc,MAAM,CAAC;YAC1BC,aAAa,CAAC,gCAAgC,EAAET,sBAAsB,CAAC,CAAC;YACxEkB,KAAK;QACP;QACAC,QAAQzB,MAAMsB,OAAO,CAAC;YACpBC,SAAS;YACTR,aAAa;QACf;QACAW,SAAS1B,MAAMc,MAAM,CAAC;YACpBa,YAAY;gBAACC,IAAI;YAAY;YAC7Bb,aAAa;YACbc,QAAQ;QACV;IACF,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAiB,CAAA;IAE5D,MAAaC,MAAqB;QAChC,MAAM,EAACnB,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACa,KAAK,CAACrB;QACvC,MAAM,EAACE,KAAK,EAAC,GAAGD;QAChB,MAAM,EAACS,SAAS,EAAE,eAAeY,UAAU,EAAEC,OAAO,EAAET,MAAM,EAAC,GAAGN;QAEhE,MAAMgB,YAAY,MAAM,IAAI,CAACC,eAAe;QAE5C,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,oBAAoB;YACpBC,UAAU,IAAMjC,iBAAiB,CAAC;QACpC;QAEA,MAAMkC,cAAc,CAACpB;QAErB,IAAI,CAACc,UAAUO,GAAG,EAAER,WAAW,CAACA,SAAS;YACvC,IAAI,CAACS,KAAK,CACR,4FACA;gBAACC,MAAM1C,UAAU2C,WAAW;YAAA;QAEhC;QAEA,MAAMC,gBAAgBZ,WAAWC,UAAUO,GAAG,EAAER;QAChD,MAAMa,mBAAmBd,cAAc3B;QAEvC,IAAI,CAAC2B,YAAY;YACf,IAAI,CAACe,IAAI,CAAC,CAAC,qCAAqC,EAAE1C,sBAAsB,EAAE,CAAC;QAC7E;QAEA,IAAI;YACF,MAAM2C,gBAAgB,MAAM9C,oBAAoB;gBAC9C8B,YAAYc;gBACZb,SAASY;gBACTT;gBACAI;YACF;YAEA,MAAMS,OAAO,MAAMD,cAAcE,KAAK,CAACtC;YAEvC,IAAI,CAACqC,MAAM;gBACT,IAAI,CAACP,KAAK,CAAC,6BAA6B;oBAACC,MAAM;gBAAC;YAClD;YAEA,2BAA2B;YAC3B,IAAInB,QAAQ;gBACV,IAAI,CAAC2B,GAAG,CAACnD,aAAaiD;YACxB,OAAO;gBACL,IAAI,CAACE,GAAG,CAACC,KAAKC,SAAS,CAACJ,MAAM,MAAM;YACtC;QACF,EAAE,OAAOP,OAAO;YACd,MAAMY,MAAMZ;YAEZjC,mBAAmB,CAAC,qBAAqB,EAAEG,OAAO,EAAE0C;YAEpD,yCAAyC;YACzC,MAAMC,WAAWD,IAAIE,OAAO,CAACC,WAAW,GAAGC,QAAQ,CAAC,YAChD,CAAC,2BAA2B,EAAEJ,IAAIE,OAAO,EAAE,GAC3C,CAAC,qBAAqB,EAAEF,IAAIE,OAAO,EAAE;YAEzC,IAAI,CAACd,KAAK,CAAC,GAAGa,SAAS,SAAS,EAAE3C,OAAO,EAAE;gBAAC+B,MAAM;YAAC;QACrD;IACF;AACF"}
@@ -2,6 +2,7 @@ import { stat } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { styleText } from 'node:util';
4
4
  import { Flags } from '@oclif/core';
5
+ import { exitCodes } from '@sanity/cli-core';
5
6
  import { ProjectRootNotFoundError } from '@sanity/cli-core/errors';
6
7
  import { SanityCommand } from '@sanity/cli-core/SanityCommand';
7
8
  import { confirm, logSymbols } from '@sanity/cli-core/ux';
@@ -42,10 +43,15 @@ export class ValidateDocumentsCommand extends SanityCommand {
42
43
  semantics: 'specify'
43
44
  }),
44
45
  file: Flags.string({
45
- description: 'Provide a path to either an .ndjson file or a tarball containing an .ndjson file'
46
+ description: 'Path to an NDJSON file or tar archive containing an NDJSON file (optionally gzip-compressed)'
46
47
  }),
47
48
  format: Flags.string({
48
- description: 'The output format used to print the found validation markers and report progress'
49
+ description: 'The output format used to print the found validation markers and report progress',
50
+ options: [
51
+ 'json',
52
+ 'ndjson',
53
+ 'pretty'
54
+ ]
49
55
  }),
50
56
  level: Flags.custom({
51
57
  default: 'warning',
@@ -79,7 +85,7 @@ export class ValidateDocumentsCommand extends SanityCommand {
79
85
  async run() {
80
86
  const { flags } = await this.parse(ValidateDocumentsCommand);
81
87
  const { dataset, file, format, level, 'max-custom-validation-concurrency': maxCustomValidationConcurrency, 'max-fetch-concurrency': maxFetchConcurrency, 'project-id': projectId, workspace } = flags;
82
- const unattendedMode = Boolean(flags.yes);
88
+ const unattendedMode = this.isUnattended();
83
89
  let workDir;
84
90
  let cliConfig;
85
91
  try {
@@ -94,6 +100,24 @@ export class ValidateDocumentsCommand extends SanityCommand {
94
100
  }
95
101
  throw err;
96
102
  }
103
+ let ndjsonFilePath;
104
+ if (file) {
105
+ const filePath = path.resolve(workDir, file);
106
+ let fileStat;
107
+ try {
108
+ fileStat = await stat(filePath);
109
+ } catch {
110
+ return this.output.error(`File not found: ${file}. Pass an existing NDJSON file or tar archive with \`--file <path>\`.`, {
111
+ exit: exitCodes.USAGE_ERROR
112
+ });
113
+ }
114
+ if (!fileStat.isFile()) {
115
+ return this.output.error(`Invalid file path: ${file} is not a file. Pass an NDJSON file or tar archive with \`--file <path>\`.`, {
116
+ exit: exitCodes.USAGE_ERROR
117
+ });
118
+ }
119
+ ndjsonFilePath = filePath;
120
+ }
97
121
  if (!unattendedMode) {
98
122
  this.output.log(`${styleText('yellow', `${logSymbols.warning} Warning:`)} This command ${file ? 'reads all documents from your input file' : 'downloads all documents from your dataset'} and processes them through your local schema within a ` + `simulated browser environment.\n`);
99
123
  this.output.log(`Potential pitfalls:\n`);
@@ -109,31 +133,10 @@ export class ValidateDocumentsCommand extends SanityCommand {
109
133
  message: `Are you sure you want to continue?`
110
134
  });
111
135
  if (!confirmed) {
112
- return this.output.error('User aborted', {
113
- exit: 1
114
- });
136
+ this.output.log('Validation cancelled');
137
+ return this.exit(exitCodes.USER_ABORT);
115
138
  }
116
139
  }
117
- if (format && !(format in reporters)) {
118
- const formatter = new Intl.ListFormat('en-US', {
119
- style: 'long',
120
- type: 'conjunction'
121
- });
122
- return this.output.error(`Did not recognize format '${format}'. Available formats are ${formatter.format(Object.keys(reporters).map((key)=>`'${key}'`))}`, {
123
- exit: 1
124
- });
125
- }
126
- let ndjsonFilePath;
127
- if (file) {
128
- const filePath = path.resolve(workDir, file);
129
- const st = await stat(filePath);
130
- if (!st.isFile()) {
131
- return this.output.error(`'--file' must point to a valid ndjson file or tarball`, {
132
- exit: 1
133
- });
134
- }
135
- ndjsonFilePath = filePath;
136
- }
137
140
  try {
138
141
  const overallLevel = await validateDocuments({
139
142
  dataset,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/documents/validate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {ProjectRootNotFoundError} from '@sanity/cli-core/errors'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type CliConfig} from '@sanity/cli-core/types'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\n\nimport {type Level} from '../../actions/documents/types.js'\nimport {validateDocuments} from '../../actions/documents/validate.js'\nimport {reporters} from '../../actions/documents/validation/reporters/index.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport class ValidateDocumentsCommand extends SanityCommand<typeof ValidateDocumentsCommand> {\n static description = 'Validate documents in a dataset against the studio schema'\n\n static examples = [\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default',\n description: 'Validates all documents in a Sanity project with more than one workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default --dataset staging',\n description: 'Override the dataset specified in the workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes > report.txt',\n description: 'Save the results of the report into a file',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --level info',\n description: 'Report out info level validation markers too',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Validate documents in a specific project and dataset',\n },\n ]\n\n static flags = {\n ...getProjectIdFlag({\n description:\n 'Override the project ID used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n ...getDatasetFlag({\n description:\n 'Override the dataset used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n file: Flags.string({\n description:\n 'Provide a path to either an .ndjson file or a tarball containing an .ndjson file',\n }),\n format: Flags.string({\n description:\n 'The output format used to print the found validation markers and report progress',\n }),\n level: Flags.custom<Level>({\n default: 'warning',\n description: 'The minimum level reported. Defaults to warning',\n options: ['error', 'warning', 'info'],\n })(),\n 'max-custom-validation-concurrency': Flags.integer({\n default: 5,\n description: 'Specify how many custom validators can run concurrently',\n }),\n 'max-fetch-concurrency': Flags.integer({\n default: 25,\n description: 'Specify how many `client.fetch` requests are allowed to run concurrently',\n }),\n workspace: Flags.string({\n description: 'The name of the workspace to use when downloading and validating all documents',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skips the first confirmation prompt',\n }),\n }\n\n static override hiddenAliases: string[] = ['document:validate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ValidateDocumentsCommand)\n const {\n dataset,\n file,\n format,\n level,\n 'max-custom-validation-concurrency': maxCustomValidationConcurrency,\n 'max-fetch-concurrency': maxFetchConcurrency,\n 'project-id': projectId,\n workspace,\n } = flags\n const unattendedMode = Boolean(flags.yes)\n\n let workDir: string\n let cliConfig: CliConfig\n try {\n const root = await this.getProjectRoot()\n workDir = root.directory\n cliConfig = await this.getCliConfig()\n } catch (err) {\n if (err instanceof ProjectRootNotFoundError) {\n return this.output.error(\n 'This command must be run from within a Sanity project directory (requires studio schema for validation)',\n {exit: 1},\n )\n }\n throw err\n }\n\n if (!unattendedMode) {\n this.output.log(\n `${styleText('yellow', `${logSymbols.warning} Warning:`)} This command ${\n file\n ? 'reads all documents from your input file'\n : 'downloads all documents from your dataset'\n } and processes them through your local schema within a ` +\n `simulated browser environment.\\n`,\n )\n this.output.log(`Potential pitfalls:\\n`)\n this.output.log(\n `- Processes all documents locally (excluding assets). Large datasets may require more resources.`,\n )\n this.output.log(\n `- Executes all custom validation functions. Some functions may need to be refactored for compatibility.`,\n )\n this.output.log(\n `- Not all standard browser features are available and may cause issues while loading your Studio.`,\n )\n this.output.log(\n `- Adheres to document permissions. Ensure this account can see all desired documents.`,\n )\n if (file) {\n this.output.log(\n `- Checks for missing document references against the live dataset if not found in your file.`,\n )\n }\n\n const confirmed = await confirm({\n default: true,\n message: `Are you sure you want to continue?`,\n })\n\n if (!confirmed) {\n return this.output.error('User aborted', {exit: 1})\n }\n }\n\n if (format && !(format in reporters)) {\n const formatter = new Intl.ListFormat('en-US', {\n style: 'long',\n type: 'conjunction',\n })\n return this.output.error(\n `Did not recognize format '${format}'. Available formats are ${formatter.format(\n Object.keys(reporters).map((key) => `'${key}'`),\n )}`,\n {exit: 1},\n )\n }\n\n let ndjsonFilePath\n if (file) {\n const filePath = path.resolve(workDir, file)\n\n const st = await stat(filePath)\n if (!st.isFile()) {\n return this.output.error(`'--file' must point to a valid ndjson file or tarball`, {exit: 1})\n }\n\n ndjsonFilePath = filePath\n }\n\n try {\n const overallLevel = await validateDocuments({\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter: (worker) => {\n const reporter =\n format && format in reporters\n ? reporters[format as keyof typeof reporters]\n : reporters.pretty\n\n return reporter({flags, output: this.output, worker})\n },\n studioHost: cliConfig.studioHost,\n workDir,\n workspace,\n })\n\n if (overallLevel === 'error') {\n return this.exit(1)\n }\n } catch (err) {\n return this.output.error(err instanceof Error ? err.message : String(err), {exit: 1})\n }\n }\n}\n"],"names":["stat","path","styleText","Flags","ProjectRootNotFoundError","SanityCommand","confirm","logSymbols","validateDocuments","reporters","getDatasetFlag","getProjectIdFlag","ValidateDocumentsCommand","description","examples","command","flags","semantics","file","string","format","level","custom","default","options","integer","workspace","yes","boolean","char","hiddenAliases","run","parse","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","projectId","unattendedMode","Boolean","workDir","cliConfig","root","getProjectRoot","directory","getCliConfig","err","output","error","exit","log","warning","confirmed","message","formatter","Intl","ListFormat","style","type","Object","keys","map","key","ndjsonFilePath","filePath","resolve","st","isFile","overallLevel","reporter","worker","pretty","studioHost","Error","String"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/documents/validate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {exitCodes} from '@sanity/cli-core'\nimport {ProjectRootNotFoundError} from '@sanity/cli-core/errors'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type CliConfig} from '@sanity/cli-core/types'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\n\nimport {type Level} from '../../actions/documents/types.js'\nimport {validateDocuments} from '../../actions/documents/validate.js'\nimport {reporters} from '../../actions/documents/validation/reporters/index.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport class ValidateDocumentsCommand extends SanityCommand<typeof ValidateDocumentsCommand> {\n static description = 'Validate documents in a dataset against the studio schema'\n\n static examples = [\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default',\n description: 'Validates all documents in a Sanity project with more than one workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default --dataset staging',\n description: 'Override the dataset specified in the workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes > report.txt',\n description: 'Save the results of the report into a file',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --level info',\n description: 'Report out info level validation markers too',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Validate documents in a specific project and dataset',\n },\n ]\n\n static flags = {\n ...getProjectIdFlag({\n description:\n 'Override the project ID used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n ...getDatasetFlag({\n description:\n 'Override the dataset used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n file: Flags.string({\n description:\n 'Path to an NDJSON file or tar archive containing an NDJSON file (optionally gzip-compressed)',\n }),\n format: Flags.string({\n description:\n 'The output format used to print the found validation markers and report progress',\n options: ['json', 'ndjson', 'pretty'],\n }),\n level: Flags.custom<Level>({\n default: 'warning',\n description: 'The minimum level reported. Defaults to warning',\n options: ['error', 'warning', 'info'],\n })(),\n 'max-custom-validation-concurrency': Flags.integer({\n default: 5,\n description: 'Specify how many custom validators can run concurrently',\n }),\n 'max-fetch-concurrency': Flags.integer({\n default: 25,\n description: 'Specify how many `client.fetch` requests are allowed to run concurrently',\n }),\n workspace: Flags.string({\n description: 'The name of the workspace to use when downloading and validating all documents',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skips the first confirmation prompt',\n }),\n }\n\n static override hiddenAliases: string[] = ['document:validate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ValidateDocumentsCommand)\n const {\n dataset,\n file,\n format,\n level,\n 'max-custom-validation-concurrency': maxCustomValidationConcurrency,\n 'max-fetch-concurrency': maxFetchConcurrency,\n 'project-id': projectId,\n workspace,\n } = flags\n const unattendedMode = this.isUnattended()\n\n let workDir: string\n let cliConfig: CliConfig\n try {\n const root = await this.getProjectRoot()\n workDir = root.directory\n cliConfig = await this.getCliConfig()\n } catch (err) {\n if (err instanceof ProjectRootNotFoundError) {\n return this.output.error(\n 'This command must be run from within a Sanity project directory (requires studio schema for validation)',\n {exit: 1},\n )\n }\n throw err\n }\n\n let ndjsonFilePath\n if (file) {\n const filePath = path.resolve(workDir, file)\n\n let fileStat\n try {\n fileStat = await stat(filePath)\n } catch {\n return this.output.error(\n `File not found: ${file}. Pass an existing NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (!fileStat.isFile()) {\n return this.output.error(\n `Invalid file path: ${file} is not a file. Pass an NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n ndjsonFilePath = filePath\n }\n\n if (!unattendedMode) {\n this.output.log(\n `${styleText('yellow', `${logSymbols.warning} Warning:`)} This command ${\n file\n ? 'reads all documents from your input file'\n : 'downloads all documents from your dataset'\n } and processes them through your local schema within a ` +\n `simulated browser environment.\\n`,\n )\n this.output.log(`Potential pitfalls:\\n`)\n this.output.log(\n `- Processes all documents locally (excluding assets). Large datasets may require more resources.`,\n )\n this.output.log(\n `- Executes all custom validation functions. Some functions may need to be refactored for compatibility.`,\n )\n this.output.log(\n `- Not all standard browser features are available and may cause issues while loading your Studio.`,\n )\n this.output.log(\n `- Adheres to document permissions. Ensure this account can see all desired documents.`,\n )\n if (file) {\n this.output.log(\n `- Checks for missing document references against the live dataset if not found in your file.`,\n )\n }\n\n const confirmed = await confirm({\n default: true,\n message: `Are you sure you want to continue?`,\n })\n\n if (!confirmed) {\n this.output.log('Validation cancelled')\n return this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n const overallLevel = await validateDocuments({\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter: (worker) => {\n const reporter =\n format && format in reporters\n ? reporters[format as keyof typeof reporters]\n : reporters.pretty\n\n return reporter({flags, output: this.output, worker})\n },\n studioHost: cliConfig.studioHost,\n workDir,\n workspace,\n })\n\n if (overallLevel === 'error') {\n return this.exit(1)\n }\n } catch (err) {\n return this.output.error(err instanceof Error ? err.message : String(err), {exit: 1})\n }\n }\n}\n"],"names":["stat","path","styleText","Flags","exitCodes","ProjectRootNotFoundError","SanityCommand","confirm","logSymbols","validateDocuments","reporters","getDatasetFlag","getProjectIdFlag","ValidateDocumentsCommand","description","examples","command","flags","semantics","file","string","format","options","level","custom","default","integer","workspace","yes","boolean","char","hiddenAliases","run","parse","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","projectId","unattendedMode","isUnattended","workDir","cliConfig","root","getProjectRoot","directory","getCliConfig","err","output","error","exit","ndjsonFilePath","filePath","resolve","fileStat","USAGE_ERROR","isFile","log","warning","confirmed","message","USER_ABORT","overallLevel","reporter","worker","pretty","studioHost","Error","String"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { isInteractive, SanityCommand } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand } from '@sanity/cli-core';
3
3
  import { confirm, spinner } from '@sanity/cli-core/ux';
4
4
  import get from 'lodash-es/get.js';
5
5
  import { extractGraphQLAPIs } from '../../actions/graphql/extractGraphQLAPIs.js';
@@ -119,15 +119,18 @@ export class GraphQLDeployCommand extends SanityCommand {
119
119
  this.warn(`This will use the specified flag(s) for ALL APIs, overriding config!`);
120
120
  if (flags.force) {
121
121
  this.warn(`--force specified, continuing...`);
122
+ } else if (this.isUnattended()) {
123
+ this.error('Flag overrides for multiple APIs require confirmation. Pass `--force` to continue.', {
124
+ exit: exitCodes.USAGE_ERROR
125
+ });
122
126
  } else {
123
127
  const confirmed = await confirm({
124
128
  default: false,
125
129
  message: 'Continue with flag overrides for all APIs?'
126
130
  });
127
131
  if (!confirmed) {
128
- this.error('Operation cancelled', {
129
- exit: 1
130
- });
132
+ this.log('GraphQL deployment cancelled');
133
+ this.exit(exitCodes.USER_ABORT);
131
134
  }
132
135
  }
133
136
  }
@@ -181,8 +184,8 @@ export class GraphQLDeployCommand extends SanityCommand {
181
184
  spin = spinner(`Generating GraphQL API: ${apiName}`).start();
182
185
  if (!dataset) {
183
186
  spin.fail();
184
- this.error(`No dataset specified for API at index ${index}`, {
185
- exit: 1
187
+ this.error(`Dataset is required for API at index ${index}. Pass it with \`--dataset <name>\` or configure a dataset for the API.`, {
188
+ exit: exitCodes.USAGE_ERROR
186
189
  });
187
190
  }
188
191
  // Handle extraction errors early (computed in worker), before network calls and prompts.
@@ -226,12 +229,13 @@ export class GraphQLDeployCommand extends SanityCommand {
226
229
  force: flags.force,
227
230
  index,
228
231
  output: this.output,
229
- specifiedGeneration
232
+ specifiedGeneration,
233
+ unattended: this.isUnattended()
230
234
  });
231
235
  if (!generation) {
232
- // User cancelled
233
- spin.fail();
234
- continue;
236
+ spin.stop();
237
+ this.log('GraphQL deployment cancelled');
238
+ this.exit(exitCodes.USER_ABORT);
235
239
  }
236
240
  if (!this.isRecognizedApiGeneration(generation)) {
237
241
  spin.fail();
@@ -289,11 +293,11 @@ export class GraphQLDeployCommand extends SanityCommand {
289
293
  hasErrors = true;
290
294
  continue;
291
295
  }
292
- if (!isInteractive()) {
296
+ if (this.isUnattended()) {
293
297
  spin.fail();
294
298
  this.renderBreakingChanges(valid);
295
- this.error('Dangerous changes found - falling back. Re-run the command with the `--force` flag to force deployment.', {
296
- exit: 1
299
+ this.error('GraphQL deployment requires confirmation because the schema contains dangerous changes. Pass `--force` to continue.', {
300
+ exit: exitCodes.USAGE_ERROR
297
301
  });
298
302
  }
299
303
  spin.stop();
@@ -303,8 +307,8 @@ export class GraphQLDeployCommand extends SanityCommand {
303
307
  message: 'Do you want to deploy a new API despite the dangerous changes?'
304
308
  });
305
309
  if (!shouldDeploy) {
306
- spin.fail();
307
- continue;
310
+ this.log('GraphQL deployment cancelled');
311
+ this.exit(exitCodes.USER_ABORT);
308
312
  }
309
313
  spin.succeed();
310
314
  } else if (dryRun) {
@@ -439,7 +443,7 @@ export class GraphQLDeployCommand extends SanityCommand {
439
443
  return playgroundCurrentlyEnabled;
440
444
  }
441
445
  // If no API is deployed, default to true if non-interactive
442
- if (!isInteractive()) {
446
+ if (this.isUnattended()) {
443
447
  return true;
444
448
  }
445
449
  // Interactive environment, so prompt the user
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/graphql/deploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {isInteractive, SanityCommand} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport get from 'lodash-es/get.js'\n\nimport {extractGraphQLAPIs} from '../../actions/graphql/extractGraphQLAPIs.js'\nimport gen1 from '../../actions/graphql/gen1/index.js'\nimport gen2 from '../../actions/graphql/gen2/index.js'\nimport gen3 from '../../actions/graphql/gen3/index.js'\nimport {graphqlDebug} from '../../actions/graphql/graphqlDebug.js'\nimport {resolveApiGeneration} from '../../actions/graphql/resolveApiGeneration.js'\nimport {SchemaError} from '../../actions/graphql/SchemaError.js'\nimport {\n type ExtractedGraphQLAPI,\n type GeneratedApiSpecification,\n type ValidationResponse,\n} from '../../actions/graphql/types.js'\nimport {\n deployGraphQLAPI,\n getClientUrl,\n getCurrentSchemaProps,\n validateGraphQLAPI,\n} from '../../services/graphql.js'\nimport {getDatasetFlag} from '../../util/sharedFlags.js'\n\ninterface DeployTask {\n dataset: string\n enablePlayground: boolean\n projectId: string\n schema: GeneratedApiSpecification\n tag: string\n}\n\nconst apiIdRegex = /^[a-z0-9_-]+$/\nconst generations = {\n gen1,\n gen2,\n gen3,\n}\n\nconst ignoredBreaking = new Set<string>(['OPTIONAL_INPUT_FIELD_ADDED'])\n// Reserved for future use to filter out specific dangerous change types\nconst ignoredWarnings = new Set<string>()\n\nconst debug = graphqlDebug.extend('deploy')\n\nexport class GraphQLDeployCommand extends SanityCommand<typeof GraphQLDeployCommand> {\n static override description = 'Deploy a GraphQL API from the current Sanity schema'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Deploy all defined GraphQL APIs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dry-run',\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api staging --api ios',\n description: 'Deploy only the GraphQL APIs with the IDs \"staging\" and \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --playground',\n description: 'Deploy all defined GraphQL APIs, overriding any playground setting',\n },\n ]\n\n static override flags = {\n api: Flags.string({\n description: 'Only deploy API with this ID (can be specified multiple times)',\n multiple: true,\n }),\n ...getDatasetFlag({description: 'Deploy API for the given dataset', semantics: 'specify'}),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n }),\n force: Flags.boolean({\n description: 'Deploy API without confirming breaking changes',\n }),\n generation: Flags.string({\n description: 'API generation to deploy (defaults to \"gen3\")',\n options: ['gen1', 'gen2', 'gen3'],\n }),\n 'non-null-document-fields': Flags.boolean({\n description: 'Use non-null document fields (_id, _type etc)',\n }),\n playground: Flags.boolean({\n allowNo: true,\n description: 'Enable GraphQL playground for easier debugging',\n }),\n tag: Flags.string({\n description: 'Deploy API(s) to given tag (defaults to \"default\")',\n }),\n 'with-union-cache': Flags.boolean({\n description: 'Cache union types (faster for schemas with many self-references)',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(GraphQLDeployCommand)\n const {\n api: onlyApis,\n dataset: datasetFlag,\n 'dry-run': dryRun,\n generation: generationFlag,\n 'non-null-document-fields': nonNullDocumentFieldsFlag,\n playground: playgroundFlag,\n tag: tagFlag,\n 'with-union-cache': withUnionCache,\n } = flags\n\n const workDir = (await this.getProjectRoot()).directory\n\n let apiDefs: ExtractedGraphQLAPI[] = []\n let spin: ReturnType<typeof spinner>\n\n try {\n apiDefs = await extractGraphQLAPIs(workDir, {\n nonNullDocumentFieldsFlag,\n withUnionCache,\n })\n } catch (error) {\n if (error instanceof SchemaError) {\n debug('Schema validation errors: %O', error.problemGroups)\n error.print(this.output)\n this.error('Fix the schema errors above and try again', {exit: 1})\n }\n debug('Failed to resolve GraphQL APIs: %O', error)\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to resolve GraphQL APIs: ${message}`, {exit: 1})\n }\n\n const hasMultipleApis = flags.api ? flags.api.length > 1 : apiDefs.length > 1\n\n const usedFlags = [\n datasetFlag && '--dataset',\n tagFlag && '--tag',\n playgroundFlag !== undefined && '--playground',\n generationFlag !== undefined && '--generation',\n nonNullDocumentFieldsFlag !== undefined && '--non-null-document-fields',\n ].filter(Boolean)\n\n if (hasMultipleApis && usedFlags.length > 0) {\n this.warn(`More than one API defined, and ${usedFlags.join('/')} is specified`)\n this.warn(`This will use the specified flag(s) for ALL APIs, overriding config!`)\n\n if (flags.force) {\n this.warn(`--force specified, continuing...`)\n } else {\n const confirmed = await confirm({\n default: false,\n message: 'Continue with flag overrides for all APIs?',\n })\n if (!confirmed) {\n this.error('Operation cancelled', {exit: 1})\n }\n }\n }\n\n const deployTasks: DeployTask[] = []\n let hasErrors = false\n\n for (const apiId of onlyApis || []) {\n if (!apiDefs.some((apiDef) => apiDef.id === apiId)) {\n this.error(`GraphQL API with id \"${apiId}\" not found`, {exit: 1})\n }\n }\n\n const apiNames = new Set<string>()\n const apiIds = new Set<string>()\n\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n const {apiName} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n if (apiNames.has(apiName)) {\n this.error(`Multiple GraphQL APIs with the same dataset and tag found (${apiName})`, {\n exit: 1,\n })\n }\n\n if (apiDef.id) {\n if (!apiIdRegex.test(apiDef.id)) {\n this.error(\n `Invalid GraphQL API id \"${apiDef.id}\" - only a-z, 0-9, underscore and dashes are allowed`,\n {exit: 1},\n )\n }\n\n if (apiIds.has(apiDef.id)) {\n this.error(`Multiple GraphQL APIs with the same ID found (${apiDef.id})`, {exit: 1})\n }\n\n apiIds.add(apiDef.id)\n }\n\n apiNames.add(apiName)\n }\n\n if (onlyApis) {\n this.warn(`Deploying only specified APIs: ${onlyApis.join(', ')}`)\n }\n\n let index = -1\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n index++\n\n const {apiName, dataset, tag} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n const {playground, projectId} = apiDef\n spin = spinner(`Generating GraphQL API: ${apiName}`).start()\n\n if (!dataset) {\n spin.fail()\n this.error(`No dataset specified for API at index ${index}`, {exit: 1})\n }\n\n // Handle extraction errors early (computed in worker), before network calls and prompts.\n // Continue the loop so all API errors are reported — don't exit on the first failure.\n if (apiDef.schemaErrors?.length) {\n spin.fail()\n new SchemaError(apiDef.schemaErrors).print(this.output, `Schema errors in ${apiName}`)\n hasErrors = true\n continue\n }\n\n if (apiDef.extractionError) {\n debug('Failed to extract schema', apiDef.extractionError)\n spin.fail()\n this.log(`Failed to extract schema for ${apiName}: ${apiDef.extractionError}`)\n hasErrors = true\n continue\n }\n\n if (!apiDef.extracted) {\n spin.fail()\n this.log(`Failed to extract schema for ${apiName}: No extraction result`)\n hasErrors = true\n continue\n }\n\n let currentGeneration: string | undefined\n let playgroundEnabled: boolean | undefined\n try {\n const schemaProps = await getCurrentSchemaProps(projectId, dataset, tag)\n currentGeneration = schemaProps.currentGeneration\n playgroundEnabled = schemaProps.playgroundEnabled\n } catch (err) {\n debug('Failed to get current GraphQL schema properties', err)\n spin.fail()\n this.error('Failed to get current GraphQL schema properties', {exit: 1})\n }\n\n // CLI flag takes precedence over configuration\n const specifiedGeneration = generationFlag === undefined ? apiDef.generation : generationFlag\n\n const generation = await resolveApiGeneration({\n currentGeneration,\n force: flags.force,\n index,\n output: this.output,\n specifiedGeneration,\n })\n\n if (!generation) {\n // User cancelled\n spin.fail()\n continue\n }\n\n if (!this.isRecognizedApiGeneration(generation)) {\n spin.fail()\n this.error(`Unknown API generation \"${generation}\" for API at index ${index}`, {exit: 1})\n }\n\n const enablePlayground = await this.shouldEnablePlayground({\n dryRun,\n playgroundCliFlag: playgroundFlag,\n playgroundConfiguration: playground,\n playgroundCurrentlyEnabled: playgroundEnabled,\n spin,\n })\n\n let apiSpec: GeneratedApiSpecification\n try {\n const generateSchema = generations[generation]\n apiSpec = generateSchema(apiDef.extracted, {filterSuffix: apiDef.filterSuffix})\n } catch (err) {\n debug('Failed to generate schema', err)\n spin.fail()\n const message = err instanceof Error ? err.message : 'Unknown error'\n this.error(`Failed to generate schema: ${message}`, {exit: 1})\n }\n\n let valid: ValidationResponse | undefined\n try {\n valid = await validateGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n } catch (err) {\n debug('validateGraphQLAPI error', err)\n const validationError = get(err, 'response.body.validationError')\n spin.fail()\n this.error(validationError ?? 'Failed to validate GraphQL API', {exit: 1})\n }\n\n // when the result is not valid and there are breaking changes afoot!\n if (!this.isResultValid(valid, {force: flags.force, spin})) {\n // not valid and a dry run? then it can exit with a error\n if (dryRun) {\n spin.fail()\n this.renderBreakingChanges(valid)\n hasErrors = true\n continue\n }\n\n if (!isInteractive()) {\n spin.fail()\n this.renderBreakingChanges(valid)\n this.error(\n 'Dangerous changes found - falling back. Re-run the command with the `--force` flag to force deployment.',\n {exit: 1},\n )\n }\n\n spin.stop()\n this.renderBreakingChanges(valid)\n const shouldDeploy = await confirm({\n default: false,\n message: 'Do you want to deploy a new API despite the dangerous changes?',\n })\n\n if (!shouldDeploy) {\n spin.fail()\n continue\n }\n\n spin.succeed()\n } else if (dryRun) {\n // isResultValid() already set the spinner state (succeed or warn).\n // Check whether changes were forced so we print the correct message.\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n if (breakingChanges.length > 0 || dangerousChanges.length > 0) {\n this.renderBreakingChanges(valid)\n this.log('Forced with `--force`, skipping deploy (dry run)')\n } else {\n this.log('GraphQL API is valid and has no breaking changes')\n }\n continue\n }\n\n deployTasks.push({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n }\n\n // Give some space for deployment tasks\n this.log('')\n\n for (const task of deployTasks) {\n const {dataset, enablePlayground, projectId, schema, tag} = task\n\n this.log(`Project: ${projectId}`)\n this.log(`Dataset: ${dataset}`)\n this.log(`Tag: ${tag}`)\n\n spin = spinner('Deploying GraphQL API').start()\n\n try {\n const response = await deployGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema,\n tag,\n })\n\n spin.stop()\n const apiUrl = await getClientUrl(\n projectId,\n response.location.replace(/^\\/(v1|v\\d{4}-\\d{2}-\\d{2})\\//, '/'),\n )\n this.log(`URL: ${apiUrl}`)\n spin.start('Deployed!').succeed()\n this.log('')\n } catch (error) {\n spin.fail()\n debug('Failed to deploy GraphQL API', error)\n this.error('Failed to deploy GraphQL API', {exit: 1})\n }\n }\n\n if (hasErrors) {\n this.exit(1)\n }\n }\n\n private filterChanges(valid: ValidationResponse) {\n const {breakingChanges: breaking, dangerousChanges: dangerous} = valid\n return {\n breakingChanges: breaking.filter((change) => !ignoredBreaking.has(change.type)),\n dangerousChanges: dangerous.filter((change) => !ignoredWarnings.has(change.type)),\n }\n }\n\n private getApiIdentifiers(apiDef: ExtractedGraphQLAPI, datasetFlag?: string, tagFlag?: string) {\n const dataset = datasetFlag || apiDef.dataset\n const tag = tagFlag || apiDef.tag || 'default'\n const apiName = [dataset, tag].join('/')\n return {apiName, dataset, tag}\n }\n\n private isRecognizedApiGeneration(generation: string): generation is 'gen1' | 'gen2' | 'gen3' {\n return ['gen1', 'gen2', 'gen3'].includes(generation)\n }\n\n private isResultValid(\n valid: ValidationResponse,\n {force, spin}: {force?: boolean; spin: ReturnType<typeof spinner>},\n ) {\n const {validationError} = valid\n if (validationError) {\n spin.fail()\n this.error(`GraphQL schema is not valid:\\n\\n${validationError}`, {exit: 1})\n }\n\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n const hasProblematicChanges = breakingChanges.length > 0 || dangerousChanges.length > 0\n\n if (!hasProblematicChanges) {\n spin.succeed()\n return true\n }\n\n if (force) {\n spin.text = 'Validating GraphQL API: Dangerous changes. Forced with `--force`.'\n spin.warn()\n return true\n }\n\n spin.warn()\n return false\n }\n\n private renderBreakingChanges(valid: ValidationResponse) {\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n if (dangerousChanges.length > 0) {\n this.log('\\nFound potentially dangerous changes from previous schema:')\n for (const change of dangerousChanges) this.log(` - ${change.description}`)\n }\n\n if (breakingChanges.length > 0) {\n this.log('\\nFound BREAKING changes from previous schema:')\n for (const change of breakingChanges) this.log(` - ${change.description}`)\n }\n\n this.output.log('')\n }\n\n private async shouldEnablePlayground({\n dryRun,\n playgroundCliFlag,\n playgroundConfiguration,\n playgroundCurrentlyEnabled,\n spin,\n }: {\n dryRun: boolean\n playgroundCliFlag?: boolean\n playgroundConfiguration?: boolean\n playgroundCurrentlyEnabled?: boolean\n spin: ReturnType<typeof spinner>\n }): Promise<boolean> {\n // On a dry run, it doesn't matter, return true 🤷‍♂️\n if (dryRun) {\n return true\n }\n\n // Prioritize CLI flag if set\n if (playgroundCliFlag !== undefined) {\n return playgroundCliFlag\n }\n\n // If explicitly set true/false in configuration, use that\n if (playgroundConfiguration !== undefined) {\n return playgroundConfiguration\n }\n\n // If API is already deployed, use the current state\n if (playgroundCurrentlyEnabled !== undefined) {\n return playgroundCurrentlyEnabled\n }\n\n // If no API is deployed, default to true if non-interactive\n if (!isInteractive()) {\n return true\n }\n\n // Interactive environment, so prompt the user\n const prevText = spin.text\n spin.warn()\n const shouldDeploy = await confirm({\n default: true,\n message: 'Do you want to enable a GraphQL playground?',\n })\n spin.clear().start(prevText)\n\n return shouldDeploy\n }\n}\n"],"names":["Flags","isInteractive","SanityCommand","confirm","spinner","get","extractGraphQLAPIs","gen1","gen2","gen3","graphqlDebug","resolveApiGeneration","SchemaError","deployGraphQLAPI","getClientUrl","getCurrentSchemaProps","validateGraphQLAPI","getDatasetFlag","apiIdRegex","generations","ignoredBreaking","Set","ignoredWarnings","debug","extend","GraphQLDeployCommand","description","examples","command","flags","api","string","multiple","semantics","boolean","default","force","generation","options","playground","allowNo","tag","run","parse","onlyApis","dataset","datasetFlag","dryRun","generationFlag","nonNullDocumentFieldsFlag","playgroundFlag","tagFlag","withUnionCache","workDir","getProjectRoot","directory","apiDefs","spin","error","problemGroups","print","output","exit","message","Error","String","hasMultipleApis","length","usedFlags","undefined","filter","Boolean","warn","join","confirmed","deployTasks","hasErrors","apiId","some","apiDef","id","apiNames","apiIds","includes","apiName","getApiIdentifiers","has","test","add","index","projectId","start","fail","schemaErrors","extractionError","log","extracted","currentGeneration","playgroundEnabled","schemaProps","err","specifiedGeneration","isRecognizedApiGeneration","enablePlayground","shouldEnablePlayground","playgroundCliFlag","playgroundConfiguration","playgroundCurrentlyEnabled","apiSpec","generateSchema","filterSuffix","valid","schema","validationError","isResultValid","renderBreakingChanges","stop","shouldDeploy","succeed","breakingChanges","dangerousChanges","filterChanges","push","task","response","apiUrl","location","replace","breaking","dangerous","change","type","hasProblematicChanges","text","prevText","clear"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/graphql/deploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport get from 'lodash-es/get.js'\n\nimport {extractGraphQLAPIs} from '../../actions/graphql/extractGraphQLAPIs.js'\nimport gen1 from '../../actions/graphql/gen1/index.js'\nimport gen2 from '../../actions/graphql/gen2/index.js'\nimport gen3 from '../../actions/graphql/gen3/index.js'\nimport {graphqlDebug} from '../../actions/graphql/graphqlDebug.js'\nimport {resolveApiGeneration} from '../../actions/graphql/resolveApiGeneration.js'\nimport {SchemaError} from '../../actions/graphql/SchemaError.js'\nimport {\n type ExtractedGraphQLAPI,\n type GeneratedApiSpecification,\n type ValidationResponse,\n} from '../../actions/graphql/types.js'\nimport {\n deployGraphQLAPI,\n getClientUrl,\n getCurrentSchemaProps,\n validateGraphQLAPI,\n} from '../../services/graphql.js'\nimport {getDatasetFlag} from '../../util/sharedFlags.js'\n\ninterface DeployTask {\n dataset: string\n enablePlayground: boolean\n projectId: string\n schema: GeneratedApiSpecification\n tag: string\n}\n\nconst apiIdRegex = /^[a-z0-9_-]+$/\nconst generations = {\n gen1,\n gen2,\n gen3,\n}\n\nconst ignoredBreaking = new Set<string>(['OPTIONAL_INPUT_FIELD_ADDED'])\n// Reserved for future use to filter out specific dangerous change types\nconst ignoredWarnings = new Set<string>()\n\nconst debug = graphqlDebug.extend('deploy')\n\nexport class GraphQLDeployCommand extends SanityCommand<typeof GraphQLDeployCommand> {\n static override description = 'Deploy a GraphQL API from the current Sanity schema'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Deploy all defined GraphQL APIs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dry-run',\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api staging --api ios',\n description: 'Deploy only the GraphQL APIs with the IDs \"staging\" and \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --playground',\n description: 'Deploy all defined GraphQL APIs, overriding any playground setting',\n },\n ]\n\n static override flags = {\n api: Flags.string({\n description: 'Only deploy API with this ID (can be specified multiple times)',\n multiple: true,\n }),\n ...getDatasetFlag({description: 'Deploy API for the given dataset', semantics: 'specify'}),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Validate defined GraphQL APIs, check for breaking changes, skip deploy',\n }),\n force: Flags.boolean({\n description: 'Deploy API without confirming breaking changes',\n }),\n generation: Flags.string({\n description: 'API generation to deploy (defaults to \"gen3\")',\n options: ['gen1', 'gen2', 'gen3'],\n }),\n 'non-null-document-fields': Flags.boolean({\n description: 'Use non-null document fields (_id, _type etc)',\n }),\n playground: Flags.boolean({\n allowNo: true,\n description: 'Enable GraphQL playground for easier debugging',\n }),\n tag: Flags.string({\n description: 'Deploy API(s) to given tag (defaults to \"default\")',\n }),\n 'with-union-cache': Flags.boolean({\n description: 'Cache union types (faster for schemas with many self-references)',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(GraphQLDeployCommand)\n const {\n api: onlyApis,\n dataset: datasetFlag,\n 'dry-run': dryRun,\n generation: generationFlag,\n 'non-null-document-fields': nonNullDocumentFieldsFlag,\n playground: playgroundFlag,\n tag: tagFlag,\n 'with-union-cache': withUnionCache,\n } = flags\n\n const workDir = (await this.getProjectRoot()).directory\n\n let apiDefs: ExtractedGraphQLAPI[] = []\n let spin: ReturnType<typeof spinner>\n\n try {\n apiDefs = await extractGraphQLAPIs(workDir, {\n nonNullDocumentFieldsFlag,\n withUnionCache,\n })\n } catch (error) {\n if (error instanceof SchemaError) {\n debug('Schema validation errors: %O', error.problemGroups)\n error.print(this.output)\n this.error('Fix the schema errors above and try again', {exit: 1})\n }\n debug('Failed to resolve GraphQL APIs: %O', error)\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to resolve GraphQL APIs: ${message}`, {exit: 1})\n }\n\n const hasMultipleApis = flags.api ? flags.api.length > 1 : apiDefs.length > 1\n\n const usedFlags = [\n datasetFlag && '--dataset',\n tagFlag && '--tag',\n playgroundFlag !== undefined && '--playground',\n generationFlag !== undefined && '--generation',\n nonNullDocumentFieldsFlag !== undefined && '--non-null-document-fields',\n ].filter(Boolean)\n\n if (hasMultipleApis && usedFlags.length > 0) {\n this.warn(`More than one API defined, and ${usedFlags.join('/')} is specified`)\n this.warn(`This will use the specified flag(s) for ALL APIs, overriding config!`)\n\n if (flags.force) {\n this.warn(`--force specified, continuing...`)\n } else if (this.isUnattended()) {\n this.error(\n 'Flag overrides for multiple APIs require confirmation. Pass `--force` to continue.',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n } else {\n const confirmed = await confirm({\n default: false,\n message: 'Continue with flag overrides for all APIs?',\n })\n if (!confirmed) {\n this.log('GraphQL deployment cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n }\n\n const deployTasks: DeployTask[] = []\n let hasErrors = false\n\n for (const apiId of onlyApis || []) {\n if (!apiDefs.some((apiDef) => apiDef.id === apiId)) {\n this.error(`GraphQL API with id \"${apiId}\" not found`, {exit: 1})\n }\n }\n\n const apiNames = new Set<string>()\n const apiIds = new Set<string>()\n\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n const {apiName} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n if (apiNames.has(apiName)) {\n this.error(`Multiple GraphQL APIs with the same dataset and tag found (${apiName})`, {\n exit: 1,\n })\n }\n\n if (apiDef.id) {\n if (!apiIdRegex.test(apiDef.id)) {\n this.error(\n `Invalid GraphQL API id \"${apiDef.id}\" - only a-z, 0-9, underscore and dashes are allowed`,\n {exit: 1},\n )\n }\n\n if (apiIds.has(apiDef.id)) {\n this.error(`Multiple GraphQL APIs with the same ID found (${apiDef.id})`, {exit: 1})\n }\n\n apiIds.add(apiDef.id)\n }\n\n apiNames.add(apiName)\n }\n\n if (onlyApis) {\n this.warn(`Deploying only specified APIs: ${onlyApis.join(', ')}`)\n }\n\n let index = -1\n for (const apiDef of apiDefs) {\n if (onlyApis && (!apiDef.id || !onlyApis.includes(apiDef.id))) {\n continue\n }\n\n index++\n\n const {apiName, dataset, tag} = this.getApiIdentifiers(apiDef, datasetFlag, tagFlag)\n const {playground, projectId} = apiDef\n spin = spinner(`Generating GraphQL API: ${apiName}`).start()\n\n if (!dataset) {\n spin.fail()\n this.error(\n `Dataset is required for API at index ${index}. Pass it with \\`--dataset <name>\\` or configure a dataset for the API.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n // Handle extraction errors early (computed in worker), before network calls and prompts.\n // Continue the loop so all API errors are reported — don't exit on the first failure.\n if (apiDef.schemaErrors?.length) {\n spin.fail()\n new SchemaError(apiDef.schemaErrors).print(this.output, `Schema errors in ${apiName}`)\n hasErrors = true\n continue\n }\n\n if (apiDef.extractionError) {\n debug('Failed to extract schema', apiDef.extractionError)\n spin.fail()\n this.log(`Failed to extract schema for ${apiName}: ${apiDef.extractionError}`)\n hasErrors = true\n continue\n }\n\n if (!apiDef.extracted) {\n spin.fail()\n this.log(`Failed to extract schema for ${apiName}: No extraction result`)\n hasErrors = true\n continue\n }\n\n let currentGeneration: string | undefined\n let playgroundEnabled: boolean | undefined\n try {\n const schemaProps = await getCurrentSchemaProps(projectId, dataset, tag)\n currentGeneration = schemaProps.currentGeneration\n playgroundEnabled = schemaProps.playgroundEnabled\n } catch (err) {\n debug('Failed to get current GraphQL schema properties', err)\n spin.fail()\n this.error('Failed to get current GraphQL schema properties', {exit: 1})\n }\n\n // CLI flag takes precedence over configuration\n const specifiedGeneration = generationFlag === undefined ? apiDef.generation : generationFlag\n\n const generation = await resolveApiGeneration({\n currentGeneration,\n force: flags.force,\n index,\n output: this.output,\n specifiedGeneration,\n unattended: this.isUnattended(),\n })\n\n if (!generation) {\n spin.stop()\n this.log('GraphQL deployment cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n\n if (!this.isRecognizedApiGeneration(generation)) {\n spin.fail()\n this.error(`Unknown API generation \"${generation}\" for API at index ${index}`, {exit: 1})\n }\n\n const enablePlayground = await this.shouldEnablePlayground({\n dryRun,\n playgroundCliFlag: playgroundFlag,\n playgroundConfiguration: playground,\n playgroundCurrentlyEnabled: playgroundEnabled,\n spin,\n })\n\n let apiSpec: GeneratedApiSpecification\n try {\n const generateSchema = generations[generation]\n apiSpec = generateSchema(apiDef.extracted, {filterSuffix: apiDef.filterSuffix})\n } catch (err) {\n debug('Failed to generate schema', err)\n spin.fail()\n const message = err instanceof Error ? err.message : 'Unknown error'\n this.error(`Failed to generate schema: ${message}`, {exit: 1})\n }\n\n let valid: ValidationResponse | undefined\n try {\n valid = await validateGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n } catch (err) {\n debug('validateGraphQLAPI error', err)\n const validationError = get(err, 'response.body.validationError')\n spin.fail()\n this.error(validationError ?? 'Failed to validate GraphQL API', {exit: 1})\n }\n\n // when the result is not valid and there are breaking changes afoot!\n if (!this.isResultValid(valid, {force: flags.force, spin})) {\n // not valid and a dry run? then it can exit with a error\n if (dryRun) {\n spin.fail()\n this.renderBreakingChanges(valid)\n hasErrors = true\n continue\n }\n\n if (this.isUnattended()) {\n spin.fail()\n this.renderBreakingChanges(valid)\n this.error(\n 'GraphQL deployment requires confirmation because the schema contains dangerous changes. Pass `--force` to continue.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n spin.stop()\n this.renderBreakingChanges(valid)\n const shouldDeploy = await confirm({\n default: false,\n message: 'Do you want to deploy a new API despite the dangerous changes?',\n })\n\n if (!shouldDeploy) {\n this.log('GraphQL deployment cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n\n spin.succeed()\n } else if (dryRun) {\n // isResultValid() already set the spinner state (succeed or warn).\n // Check whether changes were forced so we print the correct message.\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n if (breakingChanges.length > 0 || dangerousChanges.length > 0) {\n this.renderBreakingChanges(valid)\n this.log('Forced with `--force`, skipping deploy (dry run)')\n } else {\n this.log('GraphQL API is valid and has no breaking changes')\n }\n continue\n }\n\n deployTasks.push({\n dataset,\n enablePlayground,\n projectId,\n schema: apiSpec,\n tag,\n })\n }\n\n // Give some space for deployment tasks\n this.log('')\n\n for (const task of deployTasks) {\n const {dataset, enablePlayground, projectId, schema, tag} = task\n\n this.log(`Project: ${projectId}`)\n this.log(`Dataset: ${dataset}`)\n this.log(`Tag: ${tag}`)\n\n spin = spinner('Deploying GraphQL API').start()\n\n try {\n const response = await deployGraphQLAPI({\n dataset,\n enablePlayground,\n projectId,\n schema,\n tag,\n })\n\n spin.stop()\n const apiUrl = await getClientUrl(\n projectId,\n response.location.replace(/^\\/(v1|v\\d{4}-\\d{2}-\\d{2})\\//, '/'),\n )\n this.log(`URL: ${apiUrl}`)\n spin.start('Deployed!').succeed()\n this.log('')\n } catch (error) {\n spin.fail()\n debug('Failed to deploy GraphQL API', error)\n this.error('Failed to deploy GraphQL API', {exit: 1})\n }\n }\n\n if (hasErrors) {\n this.exit(1)\n }\n }\n\n private filterChanges(valid: ValidationResponse) {\n const {breakingChanges: breaking, dangerousChanges: dangerous} = valid\n return {\n breakingChanges: breaking.filter((change) => !ignoredBreaking.has(change.type)),\n dangerousChanges: dangerous.filter((change) => !ignoredWarnings.has(change.type)),\n }\n }\n\n private getApiIdentifiers(apiDef: ExtractedGraphQLAPI, datasetFlag?: string, tagFlag?: string) {\n const dataset = datasetFlag || apiDef.dataset\n const tag = tagFlag || apiDef.tag || 'default'\n const apiName = [dataset, tag].join('/')\n return {apiName, dataset, tag}\n }\n\n private isRecognizedApiGeneration(generation: string): generation is 'gen1' | 'gen2' | 'gen3' {\n return ['gen1', 'gen2', 'gen3'].includes(generation)\n }\n\n private isResultValid(\n valid: ValidationResponse,\n {force, spin}: {force?: boolean; spin: ReturnType<typeof spinner>},\n ) {\n const {validationError} = valid\n if (validationError) {\n spin.fail()\n this.error(`GraphQL schema is not valid:\\n\\n${validationError}`, {exit: 1})\n }\n\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n const hasProblematicChanges = breakingChanges.length > 0 || dangerousChanges.length > 0\n\n if (!hasProblematicChanges) {\n spin.succeed()\n return true\n }\n\n if (force) {\n spin.text = 'Validating GraphQL API: Dangerous changes. Forced with `--force`.'\n spin.warn()\n return true\n }\n\n spin.warn()\n return false\n }\n\n private renderBreakingChanges(valid: ValidationResponse) {\n const {breakingChanges, dangerousChanges} = this.filterChanges(valid)\n\n if (dangerousChanges.length > 0) {\n this.log('\\nFound potentially dangerous changes from previous schema:')\n for (const change of dangerousChanges) this.log(` - ${change.description}`)\n }\n\n if (breakingChanges.length > 0) {\n this.log('\\nFound BREAKING changes from previous schema:')\n for (const change of breakingChanges) this.log(` - ${change.description}`)\n }\n\n this.output.log('')\n }\n\n private async shouldEnablePlayground({\n dryRun,\n playgroundCliFlag,\n playgroundConfiguration,\n playgroundCurrentlyEnabled,\n spin,\n }: {\n dryRun: boolean\n playgroundCliFlag?: boolean\n playgroundConfiguration?: boolean\n playgroundCurrentlyEnabled?: boolean\n spin: ReturnType<typeof spinner>\n }): Promise<boolean> {\n // On a dry run, it doesn't matter, return true 🤷‍♂️\n if (dryRun) {\n return true\n }\n\n // Prioritize CLI flag if set\n if (playgroundCliFlag !== undefined) {\n return playgroundCliFlag\n }\n\n // If explicitly set true/false in configuration, use that\n if (playgroundConfiguration !== undefined) {\n return playgroundConfiguration\n }\n\n // If API is already deployed, use the current state\n if (playgroundCurrentlyEnabled !== undefined) {\n return playgroundCurrentlyEnabled\n }\n\n // If no API is deployed, default to true if non-interactive\n if (this.isUnattended()) {\n return true\n }\n\n // Interactive environment, so prompt the user\n const prevText = spin.text\n spin.warn()\n const shouldDeploy = await confirm({\n default: true,\n message: 'Do you want to enable a GraphQL playground?',\n })\n spin.clear().start(prevText)\n\n return shouldDeploy\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","confirm","spinner","get","extractGraphQLAPIs","gen1","gen2","gen3","graphqlDebug","resolveApiGeneration","SchemaError","deployGraphQLAPI","getClientUrl","getCurrentSchemaProps","validateGraphQLAPI","getDatasetFlag","apiIdRegex","generations","ignoredBreaking","Set","ignoredWarnings","debug","extend","GraphQLDeployCommand","description","examples","command","flags","api","string","multiple","semantics","boolean","default","force","generation","options","playground","allowNo","tag","run","parse","onlyApis","dataset","datasetFlag","dryRun","generationFlag","nonNullDocumentFieldsFlag","playgroundFlag","tagFlag","withUnionCache","workDir","getProjectRoot","directory","apiDefs","spin","error","problemGroups","print","output","exit","message","Error","String","hasMultipleApis","length","usedFlags","undefined","filter","Boolean","warn","join","isUnattended","USAGE_ERROR","confirmed","log","USER_ABORT","deployTasks","hasErrors","apiId","some","apiDef","id","apiNames","apiIds","includes","apiName","getApiIdentifiers","has","test","add","index","projectId","start","fail","schemaErrors","extractionError","extracted","currentGeneration","playgroundEnabled","schemaProps","err","specifiedGeneration","unattended","stop","isRecognizedApiGeneration","enablePlayground","shouldEnablePlayground","playgroundCliFlag","playgroundConfiguration","playgroundCurrentlyEnabled","apiSpec","generateSchema","filterSuffix","valid","schema","validationError","isResultValid","renderBreakingChanges","shouldDeploy","succeed","breakingChanges","dangerousChanges","filterChanges","push","task","response","apiUrl","location","replace","breaking","dangerous","change","type","hasProblematicChanges","text","prevText","clear"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { confirm } from '@sanity/cli-core/ux';
4
4
  import { getGraphQLAPIs } from '../../actions/graphql/getGraphQLAPIs.js';
5
5
  import { promptForProject } from '../../prompts/promptForProject.js';
@@ -117,29 +117,26 @@ export class Undeploy extends SanityCommand {
117
117
  dataset = cliConfig.api?.dataset;
118
118
  }
119
119
  if (!dataset) {
120
- this.error('Dataset is required. Specify it with --dataset or configure it in your project.', {
121
- exit: 1
120
+ this.error('Dataset is required. Pass it with `--dataset <name>` or configure it in your project.', {
121
+ exit: exitCodes.USAGE_ERROR
122
122
  });
123
123
  }
124
124
  // Confirm deletion unless --force is used
125
125
  if (!force) {
126
- const confirmMessage = tag === 'default' ? `Are you absolutely sure you want to delete the current GraphQL API connected to the "${dataset}" dataset in project ${projectId}?` : `Are you absolutely sure you want to delete the GraphQL API connected to the "${dataset}" dataset in project ${projectId}, tagged "${tag}"?`;
127
- try {
128
- const confirmed = await confirm({
129
- default: false,
130
- message: confirmMessage
131
- });
132
- if (!confirmed) {
133
- this.log('Operation cancelled');
134
- return;
135
- }
136
- } catch (error) {
137
- const err = error instanceof Error ? error : new Error(`${error}`);
138
- undeployGraphqlDebug('User cancelled', err);
139
- this.error('Operation cancelled', {
140
- exit: 1
126
+ if (this.isUnattended()) {
127
+ this.error('GraphQL API undeploy requires confirmation. Pass `--force` to continue.', {
128
+ exit: exitCodes.USAGE_ERROR
141
129
  });
142
130
  }
131
+ const confirmMessage = tag === 'default' ? `Delete the GraphQL API for dataset "${dataset}" in project ${projectId}?` : `Delete the GraphQL API for dataset "${dataset}" in project ${projectId} with tag "${tag}"?`;
132
+ const confirmed = await confirm({
133
+ default: false,
134
+ message: confirmMessage
135
+ });
136
+ if (!confirmed) {
137
+ this.log('GraphQL API undeploy cancelled');
138
+ this.exit(exitCodes.USER_ABORT);
139
+ }
143
140
  }
144
141
  try {
145
142
  await deleteGraphQLAPI({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/graphql/undeploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\n\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteGraphQLAPI} from '../../services/graphql.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst undeployGraphqlDebug = subdebug('graphql:undeploy')\n\nexport class Undeploy extends SanityCommand<typeof Undeploy> {\n static override description = 'Remove a deployed GraphQL API'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Undeploy GraphQL API for current project and dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api ios',\n description: 'Undeploy API with ID \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging',\n description: 'Undeploy GraphQL API for staging dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging --tag next',\n description: 'Undeploy GraphQL API for staging dataset with \"next\" tag',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --force',\n description: 'Undeploy GraphQL API without confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Undeploy GraphQL API for a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to undeploy GraphQL API from',\n semantics: 'override',\n }),\n api: Flags.string({\n description: 'Undeploy API with this ID',\n exclusive: ['project-id', 'project'],\n required: false,\n }),\n ...getDatasetFlag({description: 'Dataset to undeploy GraphQL API from', semantics: 'override'}),\n force: Flags.boolean({\n description: 'Skip confirmation prompt',\n required: false,\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to delete GraphQL API for',\n hidden: true,\n required: false,\n }),\n tag: Flags.string({\n default: 'default',\n description: 'Tag to undeploy GraphQL API from',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(Undeploy)\n const {api: apiFlag, dataset: datasetFlag, force, tag: tagFlag} = flags\n\n let projectId: string | undefined\n let dataset = datasetFlag\n let tag = tagFlag\n\n // If specifying --api, use it for the flags not provided\n if (apiFlag) {\n const workDir = (await this.getProjectRoot()).directory\n const apiDefs = await getGraphQLAPIs(workDir)\n const apiDef = apiDefs.find((def) => def.id === apiFlag)\n\n if (!apiDef) {\n this.error(`GraphQL API \"${apiFlag}\" not found`, {exit: 1})\n }\n\n projectId = apiDef.projectId\n\n if (dataset && dataset !== apiDef.dataset) {\n this.warn(`Both --api and --dataset specified, using --dataset ${dataset}`)\n } else {\n dataset = apiDef.dataset\n }\n\n if (tag && tag !== 'default' && apiDef.tag && tag !== apiDef.tag) {\n this.warn(`Both --api and --tag specified, using --tag ${tag}`)\n } else {\n tag = apiDef.tag || 'default'\n }\n }\n\n // Get projectId from config if not specified\n if (!projectId) {\n projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'manage', permission: 'sanity.project.graphql'}],\n }),\n })\n }\n\n // Get dataset from CLI config if not specified\n if (!dataset) {\n const cliConfig = await this.tryGetCliConfig()\n dataset = cliConfig.api?.dataset\n }\n\n if (!dataset) {\n this.error(\n 'Dataset is required. Specify it with --dataset or configure it in your project.',\n {\n exit: 1,\n },\n )\n }\n\n // Confirm deletion unless --force is used\n if (!force) {\n const confirmMessage =\n tag === 'default'\n ? `Are you absolutely sure you want to delete the current GraphQL API connected to the \"${dataset}\" dataset in project ${projectId}?`\n : `Are you absolutely sure you want to delete the GraphQL API connected to the \"${dataset}\" dataset in project ${projectId}, tagged \"${tag}\"?`\n\n try {\n const confirmed = await confirm({\n default: false,\n message: confirmMessage,\n })\n\n if (!confirmed) {\n this.log('Operation cancelled')\n return\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n undeployGraphqlDebug('User cancelled', err)\n this.error('Operation cancelled', {exit: 1})\n }\n }\n\n try {\n await deleteGraphQLAPI({\n dataset,\n projectId,\n tag,\n })\n\n this.log('GraphQL API deleted')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n undeployGraphqlDebug(`Error deleting GraphQL API for ${dataset}/${tag}`, err)\n this.error(`GraphQL API deletion failed:\\n${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["Flags","SanityCommand","subdebug","confirm","getGraphQLAPIs","promptForProject","deleteGraphQLAPI","getDatasetFlag","getProjectIdFlag","undeployGraphqlDebug","Undeploy","description","examples","command","flags","semantics","api","string","exclusive","required","force","boolean","project","deprecated","to","hidden","tag","default","run","parse","apiFlag","dataset","datasetFlag","tagFlag","projectId","workDir","getProjectRoot","directory","apiDefs","apiDef","find","def","id","error","exit","warn","getProjectId","deprecatedFlagName","fallback","requiredPermissions","grant","permission","cliConfig","tryGetCliConfig","confirmMessage","confirmed","message","log","err","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/graphql/undeploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\n\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteGraphQLAPI} from '../../services/graphql.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst undeployGraphqlDebug = subdebug('graphql:undeploy')\n\nexport class Undeploy extends SanityCommand<typeof Undeploy> {\n static override description = 'Remove a deployed GraphQL API'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Undeploy GraphQL API for current project and dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api ios',\n description: 'Undeploy API with ID \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging',\n description: 'Undeploy GraphQL API for staging dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging --tag next',\n description: 'Undeploy GraphQL API for staging dataset with \"next\" tag',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --force',\n description: 'Undeploy GraphQL API without confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Undeploy GraphQL API for a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to undeploy GraphQL API from',\n semantics: 'override',\n }),\n api: Flags.string({\n description: 'Undeploy API with this ID',\n exclusive: ['project-id', 'project'],\n required: false,\n }),\n ...getDatasetFlag({description: 'Dataset to undeploy GraphQL API from', semantics: 'override'}),\n force: Flags.boolean({\n description: 'Skip confirmation prompt',\n required: false,\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to delete GraphQL API for',\n hidden: true,\n required: false,\n }),\n tag: Flags.string({\n default: 'default',\n description: 'Tag to undeploy GraphQL API from',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(Undeploy)\n const {api: apiFlag, dataset: datasetFlag, force, tag: tagFlag} = flags\n\n let projectId: string | undefined\n let dataset = datasetFlag\n let tag = tagFlag\n\n // If specifying --api, use it for the flags not provided\n if (apiFlag) {\n const workDir = (await this.getProjectRoot()).directory\n const apiDefs = await getGraphQLAPIs(workDir)\n const apiDef = apiDefs.find((def) => def.id === apiFlag)\n\n if (!apiDef) {\n this.error(`GraphQL API \"${apiFlag}\" not found`, {exit: 1})\n }\n\n projectId = apiDef.projectId\n\n if (dataset && dataset !== apiDef.dataset) {\n this.warn(`Both --api and --dataset specified, using --dataset ${dataset}`)\n } else {\n dataset = apiDef.dataset\n }\n\n if (tag && tag !== 'default' && apiDef.tag && tag !== apiDef.tag) {\n this.warn(`Both --api and --tag specified, using --tag ${tag}`)\n } else {\n tag = apiDef.tag || 'default'\n }\n }\n\n // Get projectId from config if not specified\n if (!projectId) {\n projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'manage', permission: 'sanity.project.graphql'}],\n }),\n })\n }\n\n // Get dataset from CLI config if not specified\n if (!dataset) {\n const cliConfig = await this.tryGetCliConfig()\n dataset = cliConfig.api?.dataset\n }\n\n if (!dataset) {\n this.error(\n 'Dataset is required. Pass it with `--dataset <name>` or configure it in your project.',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n }\n\n // Confirm deletion unless --force is used\n if (!force) {\n if (this.isUnattended()) {\n this.error('GraphQL API undeploy requires confirmation. Pass `--force` to continue.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n const confirmMessage =\n tag === 'default'\n ? `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId}?`\n : `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId} with tag \"${tag}\"?`\n\n const confirmed = await confirm({\n default: false,\n message: confirmMessage,\n })\n\n if (!confirmed) {\n this.log('GraphQL API undeploy cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n await deleteGraphQLAPI({\n dataset,\n projectId,\n tag,\n })\n\n this.log('GraphQL API deleted')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n undeployGraphqlDebug(`Error deleting GraphQL API for ${dataset}/${tag}`, err)\n this.error(`GraphQL API deletion failed:\\n${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","confirm","getGraphQLAPIs","promptForProject","deleteGraphQLAPI","getDatasetFlag","getProjectIdFlag","undeployGraphqlDebug","Undeploy","description","examples","command","flags","semantics","api","string","exclusive","required","force","boolean","project","deprecated","to","hidden","tag","default","run","parse","apiFlag","dataset","datasetFlag","tagFlag","projectId","workDir","getProjectRoot","directory","apiDefs","apiDef","find","def","id","error","exit","warn","getProjectId","deprecatedFlagName","fallback","requiredPermissions","grant","permission","cliConfig","tryGetCliConfig","USAGE_ERROR","isUnattended","confirmMessage","confirmed","message","log","USER_ABORT","err","Error"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Args } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { select } from '@sanity/cli-core/ux';
4
4
  import { promptForProject } from '../../prompts/promptForProject.js';
5
5
  import { deleteHookForProject, listHooksForProject } from '../../services/hooks.js';
@@ -40,7 +40,7 @@ export class Delete extends SanityCommand {
40
40
  const { args } = await this.parse(Delete);
41
41
  if (!args.name && this.isUnattended()) {
42
42
  this.error('Webhook name is required. Pass the name as an argument.', {
43
- exit: 2
43
+ exit: exitCodes.USAGE_ERROR
44
44
  });
45
45
  }
46
46
  const projectId = await this.getProjectId({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/hooks/delete.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {type Hook} from '../../actions/hook/types'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteHookForProject, listHooksForProject} from '../../services/hooks.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst deleteHookDebug = subdebug('hook:delete')\n\nexport class Delete extends SanityCommand<typeof Delete> {\n static override args = {\n name: Args.string({\n description: 'Name of webhook to delete (will prompt if not provided)',\n required: false,\n }),\n }\n\n static override description = 'Delete a webhook from the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively select and delete a webhook',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-hook',\n description: 'Delete a specific webhook by name',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123',\n description: 'Delete a webhook from a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to delete webhook from',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['hook:delete']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(Delete)\n\n if (!args.name && this.isUnattended()) {\n this.error('Webhook name is required. Pass the name as an argument.', {exit: 2})\n }\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'delete', permission: 'sanity.project.webhooks'}],\n }),\n })\n\n // Get the hook ID to delete\n const hookId = await this.promptForHook(args.name, projectId)\n\n try {\n await deleteHookForProject(projectId, hookId)\n\n this.log('Hook deleted')\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error deleting hook ${hookId} for project ${projectId}`, err)\n this.error(`Hook deletion failed:\\n${err.message}`, {exit: 1})\n }\n }\n\n private async promptForHook(\n specifiedName: string | undefined,\n projectId: string,\n ): Promise<string> {\n let hooks: Hook[]\n try {\n hooks = await listHooksForProject(projectId)\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error fetching hooks for project ${projectId}`, err)\n this.error(`Failed to fetch hooks:\\n${err.message}`, {exit: 1})\n }\n\n if (hooks.length === 0) {\n this.error('No hooks configured for this project.', {exit: 1})\n }\n\n // If hook name is specified, find it in the list\n if (specifiedName) {\n const specifiedNameLower = specifiedName.toLowerCase()\n const selectedHook = hooks.find((hook) => hook.name.toLowerCase() === specifiedNameLower)\n\n if (!selectedHook) {\n this.error(`Hook with name \"${specifiedName}\" not found`, {exit: 1})\n }\n\n return selectedHook.id\n }\n\n // If no hook name specified, prompt user to select one\n const choices = hooks.map((hook) => ({\n name: hook.name,\n value: hook.id,\n }))\n\n const selectedId = await select({\n choices,\n message: 'Select hook to delete',\n })\n\n return selectedId\n }\n}\n"],"names":["Args","SanityCommand","subdebug","select","promptForProject","deleteHookForProject","listHooksForProject","getProjectIdFlag","deleteHookDebug","Delete","args","name","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","isUnattended","error","exit","projectId","getProjectId","fallback","requiredPermissions","grant","permission","hookId","promptForHook","log","err","message","specifiedName","hooks","length","specifiedNameLower","toLowerCase","selectedHook","find","hook","id","choices","map","value","selectedId"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/hooks/delete.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {type Hook} from '../../actions/hook/types'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteHookForProject, listHooksForProject} from '../../services/hooks.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst deleteHookDebug = subdebug('hook:delete')\n\nexport class Delete extends SanityCommand<typeof Delete> {\n static override args = {\n name: Args.string({\n description: 'Name of webhook to delete (will prompt if not provided)',\n required: false,\n }),\n }\n\n static override description = 'Delete a webhook from the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively select and delete a webhook',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-hook',\n description: 'Delete a specific webhook by name',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123',\n description: 'Delete a webhook from a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to delete webhook from',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['hook:delete']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(Delete)\n\n if (!args.name && this.isUnattended()) {\n this.error('Webhook name is required. Pass the name as an argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'delete', permission: 'sanity.project.webhooks'}],\n }),\n })\n\n // Get the hook ID to delete\n const hookId = await this.promptForHook(args.name, projectId)\n\n try {\n await deleteHookForProject(projectId, hookId)\n\n this.log('Hook deleted')\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error deleting hook ${hookId} for project ${projectId}`, err)\n this.error(`Hook deletion failed:\\n${err.message}`, {exit: 1})\n }\n }\n\n private async promptForHook(\n specifiedName: string | undefined,\n projectId: string,\n ): Promise<string> {\n let hooks: Hook[]\n try {\n hooks = await listHooksForProject(projectId)\n } catch (error) {\n const err = error as Error\n deleteHookDebug(`Error fetching hooks for project ${projectId}`, err)\n this.error(`Failed to fetch hooks:\\n${err.message}`, {exit: 1})\n }\n\n if (hooks.length === 0) {\n this.error('No hooks configured for this project.', {exit: 1})\n }\n\n // If hook name is specified, find it in the list\n if (specifiedName) {\n const specifiedNameLower = specifiedName.toLowerCase()\n const selectedHook = hooks.find((hook) => hook.name.toLowerCase() === specifiedNameLower)\n\n if (!selectedHook) {\n this.error(`Hook with name \"${specifiedName}\" not found`, {exit: 1})\n }\n\n return selectedHook.id\n }\n\n // If no hook name specified, prompt user to select one\n const choices = hooks.map((hook) => ({\n name: hook.name,\n value: hook.id,\n }))\n\n const selectedId = await select({\n choices,\n message: 'Select hook to delete',\n })\n\n return selectedId\n }\n}\n"],"names":["Args","exitCodes","SanityCommand","subdebug","select","promptForProject","deleteHookForProject","listHooksForProject","getProjectIdFlag","deleteHookDebug","Delete","args","name","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","isUnattended","error","exit","USAGE_ERROR","projectId","getProjectId","fallback","requiredPermissions","grant","permission","hookId","promptForHook","log","err","message","specifiedName","hooks","length","specifiedNameLower","toLowerCase","selectedHook","find","hook","id","choices","map","value","selectedId"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,MAAM,QAAO,sBAAqB;AAG1C,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,oBAAoB,EAAEC,mBAAmB,QAAO,0BAAyB;AACjF,SAAQC,gBAAgB,QAAO,4BAA2B;AAE1D,MAAMC,kBAAkBN,SAAS;AAEjC,OAAO,MAAMO,eAAeR;IAC1B,OAAgBS,OAAO;QACrBC,MAAMZ,KAAKa,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oCAAmC;IAEjE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAc,CAAA;IAEzD,MAAaC,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAC,GAAG,MAAM,IAAI,CAACW,KAAK,CAACZ;QAEhC,IAAI,CAACC,KAAKC,IAAI,IAAI,IAAI,CAACW,YAAY,IAAI;YACrC,IAAI,CAACC,KAAK,CAAC,2DAA2D;gBACpEC,MAAMxB,UAAUyB,WAAW;YAC7B;QACF;QAEA,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRxB,iBAAiB;oBACfyB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAUC,YAAY;wBAAyB;qBAAE;gBACjF;QACJ;QAEA,4BAA4B;QAC5B,MAAMC,SAAS,MAAM,IAAI,CAACC,aAAa,CAACvB,KAAKC,IAAI,EAAEe;QAEnD,IAAI;YACF,MAAMrB,qBAAqBqB,WAAWM;YAEtC,IAAI,CAACE,GAAG,CAAC;QACX,EAAE,OAAOX,OAAO;YACd,MAAMY,MAAMZ;YACZf,gBAAgB,CAAC,oBAAoB,EAAEwB,OAAO,aAAa,EAAEN,WAAW,EAAES;YAC1E,IAAI,CAACZ,KAAK,CAAC,CAAC,uBAAuB,EAAEY,IAAIC,OAAO,EAAE,EAAE;gBAACZ,MAAM;YAAC;QAC9D;IACF;IAEA,MAAcS,cACZI,aAAiC,EACjCX,SAAiB,EACA;QACjB,IAAIY;QACJ,IAAI;YACFA,QAAQ,MAAMhC,oBAAoBoB;QACpC,EAAE,OAAOH,OAAO;YACd,MAAMY,MAAMZ;YACZf,gBAAgB,CAAC,iCAAiC,EAAEkB,WAAW,EAAES;YACjE,IAAI,CAACZ,KAAK,CAAC,CAAC,wBAAwB,EAAEY,IAAIC,OAAO,EAAE,EAAE;gBAACZ,MAAM;YAAC;QAC/D;QAEA,IAAIc,MAAMC,MAAM,KAAK,GAAG;YACtB,IAAI,CAAChB,KAAK,CAAC,yCAAyC;gBAACC,MAAM;YAAC;QAC9D;QAEA,iDAAiD;QACjD,IAAIa,eAAe;YACjB,MAAMG,qBAAqBH,cAAcI,WAAW;YACpD,MAAMC,eAAeJ,MAAMK,IAAI,CAAC,CAACC,OAASA,KAAKjC,IAAI,CAAC8B,WAAW,OAAOD;YAEtE,IAAI,CAACE,cAAc;gBACjB,IAAI,CAACnB,KAAK,CAAC,CAAC,gBAAgB,EAAEc,cAAc,WAAW,CAAC,EAAE;oBAACb,MAAM;gBAAC;YACpE;YAEA,OAAOkB,aAAaG,EAAE;QACxB;QAEA,uDAAuD;QACvD,MAAMC,UAAUR,MAAMS,GAAG,CAAC,CAACH,OAAU,CAAA;gBACnCjC,MAAMiC,KAAKjC,IAAI;gBACfqC,OAAOJ,KAAKC,EAAE;YAChB,CAAA;QAEA,MAAMI,aAAa,MAAM9C,OAAO;YAC9B2C;YACAV,SAAS;QACX;QAEA,OAAOa;IACT;AACF"}