sanity 3.26.2-canary.52 → 3.26.2-canary.69

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 (112) hide show
  1. package/lib/_chunks/{_internal-2CJ5wSKF.js → _internal-6Pl2wJGj.js} +422 -201
  2. package/lib/_chunks/_internal-6Pl2wJGj.js.map +1 -0
  3. package/lib/_chunks/{_internal-79flWvL8.js → _internal-yQwMw2ht.js} +419 -203
  4. package/lib/_chunks/_internal-yQwMw2ht.js.map +1 -0
  5. package/lib/_chunks/{_internalBrowser-QAFz3SKp.js → _internalBrowser-HWvRXvlU.js} +22 -22
  6. package/lib/_chunks/_internalBrowser-HWvRXvlU.js.map +1 -0
  7. package/lib/_chunks/{_internalBrowser-Y0qKZ-GA.js → _internalBrowser-TWIhitgI.js} +22 -22
  8. package/lib/_chunks/_internalBrowser-TWIhitgI.js.map +1 -0
  9. package/lib/_chunks/{deployApiAction-SHteit1G.js → deployApiAction-TZcCtXan.js} +2 -2
  10. package/lib/_chunks/{deployApiAction-SHteit1G.js.map → deployApiAction-TZcCtXan.js.map} +1 -1
  11. package/lib/_chunks/{deployApiAction-bRyJpGOS.js → deployApiAction-rVL67VYW.js} +2 -2
  12. package/lib/_chunks/{deployApiAction-bRyJpGOS.js.map → deployApiAction-rVL67VYW.js.map} +1 -1
  13. package/lib/_chunks/{getStudioConfig-JSkc4GE0.js → getStudioWorkspaces-HX9o9-hl.js} +20 -4
  14. package/lib/_chunks/getStudioWorkspaces-HX9o9-hl.js.map +1 -0
  15. package/lib/_chunks/{index-EO9iRnDS.js → index-2kSxso3r.js} +2 -2
  16. package/lib/_chunks/{index-EO9iRnDS.js.map → index-2kSxso3r.js.map} +1 -1
  17. package/lib/_chunks/{index-FQCCBbuC.js → index-751ZLh3z.js} +6 -6
  18. package/lib/_chunks/{index-FQCCBbuC.js.map → index-751ZLh3z.js.map} +1 -1
  19. package/lib/_chunks/{index-VNSHvpZr.js → index-HcF369ru.js} +2 -2
  20. package/lib/_chunks/{index-VNSHvpZr.js.map → index-HcF369ru.js.map} +1 -1
  21. package/lib/_chunks/{index-Xs2xnLUV.js → index-MAAxgUnl.js} +6 -6
  22. package/lib/_chunks/{index-Xs2xnLUV.js.map → index-MAAxgUnl.js.map} +1 -1
  23. package/lib/_chunks/{index-AaK2CidU.js → index-NweJPfGb.js} +2 -2
  24. package/lib/_chunks/{index-AaK2CidU.js.map → index-NweJPfGb.js.map} +1 -1
  25. package/lib/_chunks/{index-R7R6AyHF.js → index-zobOqko7.js} +2 -2
  26. package/lib/_chunks/{index-R7R6AyHF.js.map → index-zobOqko7.js.map} +1 -1
  27. package/lib/_chunks/{listApisAction-6lGkFZrU.js → listApisAction-IvKV4iAd.js} +2 -2
  28. package/lib/_chunks/{listApisAction-6lGkFZrU.js.map → listApisAction-IvKV4iAd.js.map} +1 -1
  29. package/lib/_chunks/{listApisAction-CqCkBz-F.js → listApisAction-oca2uykY.js} +2 -2
  30. package/lib/_chunks/{listApisAction-CqCkBz-F.js.map → listApisAction-oca2uykY.js.map} +1 -1
  31. package/lib/_chunks/pane-9HEeITpx.js +5 -0
  32. package/lib/_chunks/pane-9HEeITpx.js.map +1 -0
  33. package/lib/_chunks/pane-QyVrOLqS.js +2 -0
  34. package/lib/_chunks/pane-QyVrOLqS.js.map +1 -0
  35. package/lib/_chunks/pane-TXXUUvdc.js +5 -0
  36. package/lib/_chunks/pane-TXXUUvdc.js.map +1 -0
  37. package/lib/_chunks/pane-cQxQtBcL.js +2 -0
  38. package/lib/_chunks/pane-cQxQtBcL.js.map +1 -0
  39. package/lib/_chunks/{structure-qJLnDJXq.js → structure-iqIDIH7-.js} +3 -3
  40. package/lib/_chunks/structure-iqIDIH7-.js.map +1 -0
  41. package/lib/_chunks/{structure-588eAwLd.js → structure-o_wMXC_G.js} +3 -3
  42. package/lib/_chunks/structure-o_wMXC_G.js.map +1 -0
  43. package/lib/_chunks/validateAction-4Jl_y_iB.js +154 -0
  44. package/lib/_chunks/validateAction-4Jl_y_iB.js.map +1 -0
  45. package/lib/_chunks/{validateAction-GUvMkXiN.js → validateAction-6q8Sqwaz.js} +25 -73
  46. package/lib/_chunks/validateAction-6q8Sqwaz.js.map +1 -0
  47. package/lib/_chunks/validateAction-Bz67ApRP.js +143 -0
  48. package/lib/_chunks/validateAction-Bz67ApRP.js.map +1 -0
  49. package/lib/_chunks/{validateAction-NIrqtyYJ.js → validateAction-shi462sq.js} +27 -75
  50. package/lib/_chunks/validateAction-shi462sq.js.map +1 -0
  51. package/lib/_internal/cli/threads/getGraphQLAPIs.js +2 -2
  52. package/lib/_internal/cli/threads/getGraphQLAPIs.js.map +1 -1
  53. package/lib/_internal/cli/threads/validateDocuments.js +5 -3
  54. package/lib/_internal/cli/threads/validateDocuments.js.map +1 -1
  55. package/lib/_internal/cli/threads/validateSchema.js +55 -0
  56. package/lib/_internal/cli/threads/validateSchema.js.map +1 -0
  57. package/lib/_internal.esm.js +1 -1
  58. package/lib/_internal.js +1 -1
  59. package/lib/_internalBrowser.esm.js +1 -1
  60. package/lib/_internalBrowser.js +1 -1
  61. package/lib/desk.esm.js +1 -1
  62. package/lib/desk.js +1 -1
  63. package/lib/exports/index.d.ts +25 -0
  64. package/lib/index.cjs.mjs +1 -0
  65. package/lib/index.esm.js +2 -2
  66. package/lib/index.js +2 -1
  67. package/lib/index.js.map +1 -1
  68. package/lib/structure.esm.js +1 -1
  69. package/lib/structure.js +1 -1
  70. package/package.json +15 -15
  71. package/src/_internal/cli/actions/schema/formatSchemaValidation.ts +96 -0
  72. package/src/_internal/cli/actions/schema/validateAction.ts +120 -0
  73. package/src/_internal/cli/actions/validation/reporters/prettyReporter/formatDocumentValidation.ts +17 -95
  74. package/src/_internal/cli/commands/index.ts +2 -0
  75. package/src/_internal/cli/commands/migration/createMigrationCommand.ts +18 -10
  76. package/src/_internal/cli/commands/migration/listMigrationsCommand.ts +34 -31
  77. package/src/_internal/cli/commands/migration/prettyMutationFormatter.ts +214 -0
  78. package/src/_internal/cli/commands/migration/runMigrationCommand.ts +102 -58
  79. package/src/_internal/cli/commands/migration/templates/minimalAdvanced.ts +1 -1
  80. package/src/_internal/cli/commands/migration/templates/minimalSimple.ts +1 -1
  81. package/src/_internal/cli/commands/migration/templates/renameField.ts +3 -3
  82. package/src/_internal/cli/commands/migration/templates/renameType.ts +1 -1
  83. package/src/_internal/cli/commands/migration/templates/stringToPTE.ts +1 -1
  84. package/src/_internal/cli/commands/migration/utils/mutationFormatter.ts +1 -1
  85. package/src/_internal/cli/commands/schema/validateSchemaCommand.ts +35 -0
  86. package/src/_internal/cli/threads/getGraphQLAPIs.ts +2 -2
  87. package/src/_internal/cli/threads/validateDocuments.ts +6 -3
  88. package/src/_internal/cli/threads/validateSchema.ts +73 -0
  89. package/src/_internal/cli/util/{getStudioConfig.ts → getStudioWorkspaces.ts} +30 -8
  90. package/src/_internal/cli/util/tree.ts +110 -0
  91. package/src/core/config/index.ts +1 -0
  92. package/src/core/config/prepareConfig.ts +2 -5
  93. package/src/core/config/resolveSchemaTypes.ts +29 -0
  94. package/src/core/studio/screens/schemaErrors/SchemaProblemGroups.tsx +4 -2
  95. package/src/structure/comments/src/components/pte/blocks/MentionInlineBlock.tsx +13 -6
  96. package/lib/_chunks/_internal-2CJ5wSKF.js.map +0 -1
  97. package/lib/_chunks/_internal-79flWvL8.js.map +0 -1
  98. package/lib/_chunks/_internalBrowser-QAFz3SKp.js.map +0 -1
  99. package/lib/_chunks/_internalBrowser-Y0qKZ-GA.js.map +0 -1
  100. package/lib/_chunks/getStudioConfig-JSkc4GE0.js.map +0 -1
  101. package/lib/_chunks/pane-QmJb9ZTN.js +0 -2
  102. package/lib/_chunks/pane-QmJb9ZTN.js.map +0 -1
  103. package/lib/_chunks/pane-SK7FWNTJ.js +0 -2
  104. package/lib/_chunks/pane-SK7FWNTJ.js.map +0 -1
  105. package/lib/_chunks/pane-y4hpcKe1.js +0 -5
  106. package/lib/_chunks/pane-y4hpcKe1.js.map +0 -1
  107. package/lib/_chunks/pane-yQXBQyyI.js +0 -5
  108. package/lib/_chunks/pane-yQXBQyyI.js.map +0 -1
  109. package/lib/_chunks/structure-588eAwLd.js.map +0 -1
  110. package/lib/_chunks/structure-qJLnDJXq.js.map +0 -1
  111. package/lib/_chunks/validateAction-GUvMkXiN.js.map +0 -1
  112. package/lib/_chunks/validateAction-NIrqtyYJ.js.map +0 -1
@@ -38,9 +38,10 @@ import { existsSync } from 'node:fs';
38
38
  import deburr from 'lodash/deburr';
39
39
  import mkdirp from 'mkdirp';
40
40
  import { register } from 'esbuild-register/dist/node';
41
- import { MAX_MUTATION_CONCURRENCY, runFromArchive, dryRun, run, DEFAULT_MUTATION_CONCURRENCY } from '@sanity/migrate';
42
- import { toString } from '@sanity/util/paths';
43
- const helpText$s = "\nOptions\n --source-maps Enable source maps for built bundles (increases size of bundle)\n --no-minify Skip minifying built JavaScript (speeds up build, increases size of bundle)\n -y, --yes Use unattended mode, accepting defaults and using only flags for choices\n\nExamples\n sanity build\n sanity build --no-minify --source-maps\n";
41
+ import { MAX_MUTATION_CONCURRENCY, run, runFromArchive, dryRun, DEFAULT_MUTATION_CONCURRENCY } from '@sanity/migrate';
42
+ import { isatty } from 'tty';
43
+ import { pathToString } from 'sanity';
44
+ const helpText$t = "\nOptions\n --source-maps Enable source maps for built bundles (increases size of bundle)\n --no-minify Skip minifying built JavaScript (speeds up build, increases size of bundle)\n -y, --yes Use unattended mode, accepting defaults and using only flags for choices\n\nExamples\n sanity build\n sanity build --no-minify --source-maps\n";
44
45
  const buildCommand = {
45
46
  name: "build",
46
47
  signature: "[OUTPUT_DIR]",
@@ -49,7 +50,7 @@ const buildCommand = {
49
50
  const buildAction = await getBuildAction();
50
51
  return buildAction(args, context, overrides);
51
52
  },
52
- helpText: helpText$s
53
+ helpText: helpText$t
53
54
  };
54
55
  async function getBuildAction() {
55
56
  const mod = await import('./buildAction-O9Qgxl8O.js');
@@ -86,7 +87,7 @@ var datasetGroup = {
86
87
  isGroupRoot: true,
87
88
  description: "Interact with datasets in your project"
88
89
  };
89
- const helpText$r = "\nOptions\n --source-maps Enable source maps for built bundles (increases size of bundle)\n --no-minify Skip minifying built JavaScript (speeds up build, increases size of bundle)\n --no-build Don't build the studio prior to deploy, instead deploying the version currently in `dist/`\n\nExamples\n sanity deploy\n sanity deploy --no-minify --source-maps\n";
90
+ const helpText$s = "\nOptions\n --source-maps Enable source maps for built bundles (increases size of bundle)\n --no-minify Skip minifying built JavaScript (speeds up build, increases size of bundle)\n --no-build Don't build the studio prior to deploy, instead deploying the version currently in `dist/`\n\nExamples\n sanity deploy\n sanity deploy --no-minify --source-maps\n";
90
91
  const deployCommand = {
91
92
  name: "deploy",
92
93
  signature: "[SOURCE_DIR] [--no-build] [--source-maps] [--no-minify]",
@@ -95,9 +96,9 @@ const deployCommand = {
95
96
  const mod = await import('./deployAction-ntbb8I6E.js');
96
97
  return mod.default(args, context);
97
98
  },
98
- helpText: helpText$r
99
+ helpText: helpText$s
99
100
  };
100
- const helpText$q = "\nExamples\n sanity undeploy\n";
101
+ const helpText$r = "\nExamples\n sanity undeploy\n";
101
102
  const undeployCommand = {
102
103
  name: "undeploy",
103
104
  signature: "",
@@ -106,7 +107,7 @@ const undeployCommand = {
106
107
  const mod = await import('./undeployAction-PLZBCxip.js');
107
108
  return mod.default(args, context);
108
109
  },
109
- helpText: helpText$q
110
+ helpText: helpText$r
110
111
  };
111
112
  const MAX_DATASET_NAME_LENGTH$1 = 64;
112
113
  function validateDatasetAliasName(datasetName) {
@@ -231,13 +232,13 @@ function promptForDatasetName(prompt) {
231
232
  ...options
232
233
  });
233
234
  }
234
- const helpText$p = "\nOptions\n --visibility <mode> Set visibility for this dataset (public/private)\n\nExamples\n sanity dataset create\n sanity dataset create <name>\n sanity dataset create <name> --visibility private\n";
235
+ const helpText$q = "\nOptions\n --visibility <mode> Set visibility for this dataset (public/private)\n\nExamples\n sanity dataset create\n sanity dataset create <name>\n sanity dataset create <name> --visibility private\n";
235
236
  const allowedModes = ["private", "public", "custom"];
236
237
  const createDatasetCommand = {
237
238
  name: "create",
238
239
  group: "dataset",
239
240
  signature: "[NAME]",
240
- helpText: helpText$p,
241
+ helpText: helpText$q,
241
242
  description: "Create a new dataset within your project",
242
243
  action: async (args, context) => {
243
244
  const {
@@ -347,7 +348,7 @@ const datasetVisibilityCommand = {
347
348
  output.print("Dataset visibility changed");
348
349
  }
349
350
  };
350
- const helpText$o = "\nOptions\n --force Do not prompt for delete confirmation - forcefully delete\n\nExamples\n sanity dataset delete\n sanity dataset delete my-dataset\n sanity dataset delete my-dataset --force\n";
351
+ const helpText$p = "\nOptions\n --force Do not prompt for delete confirmation - forcefully delete\n\nExamples\n sanity dataset delete\n sanity dataset delete my-dataset\n sanity dataset delete my-dataset --force\n";
351
352
  function parseCliFlags$4(args) {
352
353
  return yargs(hideBin(args.argv || process.argv).slice(2)).option("force", {
353
354
  type: "boolean"
@@ -356,7 +357,7 @@ function parseCliFlags$4(args) {
356
357
  const deleteDatasetCommand = {
357
358
  name: "delete",
358
359
  group: "dataset",
359
- helpText: helpText$o,
360
+ helpText: helpText$p,
360
361
  signature: "[datasetName]",
361
362
  description: "Delete a dataset within your project",
362
363
  action: async (args, context) => {
@@ -429,7 +430,7 @@ async function chooseDatasetPrompt(context) {
429
430
  return selected;
430
431
  }
431
432
  const noop = () => null;
432
- const helpText$n = "\nOptions\n --raw Extract only documents, without rewriting asset references\n --no-assets Export only non-asset documents and remove references to image assets\n --no-drafts Export only published versions of documents\n --no-compress Skips compressing tarball entries (still generates a gzip file)\n --types Defines which document types to export\n --overwrite Overwrite any file with the same name\n --asset-concurrency <num> Concurrent number of asset downloads\n\nExamples\n sanity dataset export moviedb localPath.tar.gz\n sanity dataset export moviedb assetless.tar.gz --no-assets\n sanity dataset export staging staging.tar.gz --raw\n sanity dataset export staging staging.tar.gz --types products,shops\n";
433
+ const helpText$o = "\nOptions\n --raw Extract only documents, without rewriting asset references\n --no-assets Export only non-asset documents and remove references to image assets\n --no-drafts Export only published versions of documents\n --no-compress Skips compressing tarball entries (still generates a gzip file)\n --types Defines which document types to export\n --overwrite Overwrite any file with the same name\n --asset-concurrency <num> Concurrent number of asset downloads\n\nExamples\n sanity dataset export moviedb localPath.tar.gz\n sanity dataset export moviedb assetless.tar.gz --no-assets\n sanity dataset export staging staging.tar.gz --raw\n sanity dataset export staging staging.tar.gz --types products,shops\n";
433
434
  function parseFlags$1(rawFlags) {
434
435
  const flags = {};
435
436
  if (rawFlags.types) {
@@ -460,7 +461,7 @@ const exportDatasetCommand = {
460
461
  group: "dataset",
461
462
  signature: "[NAME] [DESTINATION]",
462
463
  description: "Export dataset to local filesystem as a gzipped tarball",
463
- helpText: helpText$n,
464
+ helpText: helpText$o,
464
465
  action: async (args, context) => {
465
466
  const {
466
467
  apiClient,
@@ -570,7 +571,7 @@ async function getOutputPath(destination, dataset, prompt, flags) {
570
571
  return finalPath;
571
572
  }
572
573
  const yellow = str => "\x1B[33m".concat(str, "\x1B[39m");
573
- const helpText$m = '\nOptions\n --missing On duplicate document IDs, skip importing document in question\n --replace On duplicate document IDs, replace existing document with imported document\n --allow-failing-assets Skip assets that cannot be fetched/uploaded\n --replace-assets Skip reuse of existing assets\n --skip-cross-dataset-references Skips references to other datasets\n\nRarely used options (should generally not be used)\n --allow-assets-in-different-dataset Allow asset documents to reference different project/dataset\n\nExamples\n # Import "moviedb.ndjson" from the current directory to the dataset called "moviedb"\n sanity dataset import moviedb.ndjson moviedb\n\n # Import "moviedb.tar.gz" from the current directory to the dataset called "moviedb",\n # replacing any documents encountered that have the same document IDs\n sanity dataset import moviedb.tar.gz moviedb --replace\n\n # Import from a folder containing an ndjson file, such as an extracted tarball\n # retrieved through "sanity dataset export".\n sanity dataset import ~/some/folder moviedb\n\n # Import from a remote URL. Will download and extract the tarball to a temporary\n # location before importing it.\n sanity dataset import https://some.url/moviedb.tar.gz moviedb --replace\n';
574
+ const helpText$n = '\nOptions\n --missing On duplicate document IDs, skip importing document in question\n --replace On duplicate document IDs, replace existing document with imported document\n --allow-failing-assets Skip assets that cannot be fetched/uploaded\n --replace-assets Skip reuse of existing assets\n --skip-cross-dataset-references Skips references to other datasets\n\nRarely used options (should generally not be used)\n --allow-assets-in-different-dataset Allow asset documents to reference different project/dataset\n\nExamples\n # Import "moviedb.ndjson" from the current directory to the dataset called "moviedb"\n sanity dataset import moviedb.ndjson moviedb\n\n # Import "moviedb.tar.gz" from the current directory to the dataset called "moviedb",\n # replacing any documents encountered that have the same document IDs\n sanity dataset import moviedb.tar.gz moviedb --replace\n\n # Import from a folder containing an ndjson file, such as an extracted tarball\n # retrieved through "sanity dataset export".\n sanity dataset import ~/some/folder moviedb\n\n # Import from a remote URL. Will download and extract the tarball to a temporary\n # location before importing it.\n sanity dataset import https://some.url/moviedb.tar.gz moviedb --replace\n';
574
575
  function toBoolIfSet(flag) {
575
576
  return typeof flag === "undefined" ? void 0 : Boolean(flag);
576
577
  }
@@ -597,7 +598,7 @@ const importDatasetCommand = {
597
598
  group: "dataset",
598
599
  signature: "[FILE | FOLDER | URL] [TARGET_DATASET]",
599
600
  description: "Import documents to given dataset from either an ndjson file or a gzipped tarball",
600
- helpText: helpText$m,
601
+ helpText: helpText$n,
601
602
  // eslint-disable-next-line max-statements
602
603
  action: async (args, context) => {
603
604
  const {
@@ -953,7 +954,7 @@ const getClientUrl = function (client, uri) {
953
954
  const base = useCdn ? config.cdnUrl : config.url;
954
955
  return "".concat(base, "/").concat(uri.replace(/^\//, ""));
955
956
  };
956
- const helpText$l = "\nOptions\n --detach Start the copy without waiting for it to finish\n --attach <job-id> Attach to the running copy process to show progress\n --skip-history Don't preserve document history on copy\n --list Lists all dataset copy jobs corresponding to a certain criteria.\n --offset Start position in the list of jobs. Default 0. With --list.\n --limit Maximum number of jobs returned. Default 10. Maximum 1000. With --list.\n\nExamples\n sanity dataset copy\n sanity dataset copy <source-dataset>\n sanity dataset copy <source-dataset> <target-dataset>\n sanity dataset copy --skip-history <source-dataset> <target-dataset>\n sanity dataset copy --detach <source-dataset> <target-dataset>\n sanity dataset copy --attach <job-id>\n sanity dataset copy --list\n sanity dataset copy --list --offset=2\n sanity dataset copy --list --offset=2 --limit=10\n";
957
+ const helpText$m = "\nOptions\n --detach Start the copy without waiting for it to finish\n --attach <job-id> Attach to the running copy process to show progress\n --skip-history Don't preserve document history on copy\n --list Lists all dataset copy jobs corresponding to a certain criteria.\n --offset Start position in the list of jobs. Default 0. With --list.\n --limit Maximum number of jobs returned. Default 10. Maximum 1000. With --list.\n\nExamples\n sanity dataset copy\n sanity dataset copy <source-dataset>\n sanity dataset copy <source-dataset> <target-dataset>\n sanity dataset copy --skip-history <source-dataset> <target-dataset>\n sanity dataset copy --detach <source-dataset> <target-dataset>\n sanity dataset copy --attach <job-id>\n sanity dataset copy --list\n sanity dataset copy --list --offset=2\n sanity dataset copy --list --offset=2 --limit=10\n";
957
958
  function parseCliFlags$3(args) {
958
959
  return yargs(hideBin(args.argv || process.argv).slice(2)).option("attach", {
959
960
  type: "string"
@@ -1046,7 +1047,7 @@ const copyDatasetCommand = {
1046
1047
  name: "copy",
1047
1048
  group: "dataset",
1048
1049
  signature: "[SOURCE_DATASET] [TARGET_DATASET]",
1049
- helpText: helpText$l,
1050
+ helpText: helpText$m,
1050
1051
  description: "Manages dataset copying, including starting a new copy job, listing copy jobs and following the progress of a running copy job",
1051
1052
  action: async (args, context) => {
1052
1053
  const {
@@ -1341,12 +1342,12 @@ var __template$1 = (cooked, raw) => __freeze$1(__defProp$1(cooked, "raw", {
1341
1342
  value: __freeze$1(raw || cooked.slice())
1342
1343
  }));
1343
1344
  var _a$1;
1344
- const helpText$k = "\nBelow are examples of the alias subcommand\n\nCreate Alias\n sanity dataset alias create\n sanity dataset alias create <alias-name>\n sanity dataset alias create <alias-name> <target-dataset>\n\nDelete Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias delete <alias-name>\n sanity dataset alias delete <alias-name> --force\n\nLink Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias link\n sanity dataset alias link <alias-name>\n sanity dataset alias link <alias-name> <target-dataset>\n sanity dataset alias link <alias-name> <target-dataset> --force\n\nUn-link Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias unlink\n sanity dataset alias unlink <alias-name>\n sanity dataset alias unlink <alias-name> --force\n";
1345
+ const helpText$l = "\nBelow are examples of the alias subcommand\n\nCreate Alias\n sanity dataset alias create\n sanity dataset alias create <alias-name>\n sanity dataset alias create <alias-name> <target-dataset>\n\nDelete Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias delete <alias-name>\n sanity dataset alias delete <alias-name> --force\n\nLink Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias link\n sanity dataset alias link <alias-name>\n sanity dataset alias link <alias-name> <target-dataset>\n sanity dataset alias link <alias-name> <target-dataset> --force\n\nUn-link Alias\n Options\n --force Skips security prompt and forces link command\n\n Usage\n sanity dataset alias unlink\n sanity dataset alias unlink <alias-name>\n sanity dataset alias unlink <alias-name> --force\n";
1345
1346
  const aliasCommand = {
1346
1347
  name: "alias",
1347
1348
  group: "dataset",
1348
1349
  signature: "SUBCOMMAND [ALIAS_NAME, TARGET_DATASET]",
1349
- helpText: helpText$k,
1350
+ helpText: helpText$l,
1350
1351
  description: "You can manage your dataset alias using this command.",
1351
1352
  action: async (args, context) => {
1352
1353
  const [verb] = args.argsWithoutOptions;
@@ -1399,12 +1400,12 @@ function colorizeJson(input, chalk) {
1399
1400
  return formatter(token.raw);
1400
1401
  }).join("");
1401
1402
  }
1402
- const helpText$j = "\nGet and print a document from the projects configured dataset\n\nOptions\n --pretty colorized JSON output\n --dataset NAME to override dataset\n\nExamples\n # Get the document with the ID \"myDocId\"\n sanity documents get myDocId\n\n # ID wrapped in double or single quote works equally well\n sanity documents get 'myDocId'\n";
1403
+ const helpText$k = "\nGet and print a document from the projects configured dataset\n\nOptions\n --pretty colorized JSON output\n --dataset NAME to override dataset\n\nExamples\n # Get the document with the ID \"myDocId\"\n sanity documents get myDocId\n\n # ID wrapped in double or single quote works equally well\n sanity documents get 'myDocId'\n";
1403
1404
  const getDocumentsCommand = {
1404
1405
  name: "get",
1405
1406
  group: "documents",
1406
1407
  signature: "[DOCUMENT_ID]",
1407
- helpText: helpText$j,
1408
+ helpText: helpText$k,
1408
1409
  description: "Get and print a document by ID",
1409
1410
  action: async (args, context) => {
1410
1411
  const {
@@ -1435,12 +1436,12 @@ const getDocumentsCommand = {
1435
1436
  }
1436
1437
  };
1437
1438
  const defaultApiVersion = "v2022-06-01";
1438
- const helpText$i = "\nRun a query against the projects configured dataset\n\nOptions\n --pretty colorized JSON output\n --dataset NAME to override dataset\n --project PROJECT to override project ID\n --anonymous Send the query without any authorization token\n --api-version API version to use (defaults to `".concat(defaultApiVersion, '`)\n\nEnvironment variables\n `SANITY_CLI_QUERY_API_VERSION` - will use the defined API version,\n unless `--api-version` is specified.\n\nExamples\n # Fetch 5 documents of type "movie"\n sanity documents query \'*[_type == "movie"][0..4]\'\n\n # Fetch title of the oldest movie in the dataset named "staging"\n sanity documents query \'*[_type == "movie"]|order(releaseDate asc)[0]{title}\' --dataset staging\n\n # Use API version v2021-06-07 and do a query\n sanity documents query --api-version v2021-06-07 \'*[_id == "header"] { "headerText": pt::text(body) }\'\n');
1439
+ const helpText$j = "\nRun a query against the projects configured dataset\n\nOptions\n --pretty colorized JSON output\n --dataset NAME to override dataset\n --project PROJECT to override project ID\n --anonymous Send the query without any authorization token\n --api-version API version to use (defaults to `".concat(defaultApiVersion, '`)\n\nEnvironment variables\n `SANITY_CLI_QUERY_API_VERSION` - will use the defined API version,\n unless `--api-version` is specified.\n\nExamples\n # Fetch 5 documents of type "movie"\n sanity documents query \'*[_type == "movie"][0..4]\'\n\n # Fetch title of the oldest movie in the dataset named "staging"\n sanity documents query \'*[_type == "movie"]|order(releaseDate asc)[0]{title}\' --dataset staging\n\n # Use API version v2021-06-07 and do a query\n sanity documents query --api-version v2021-06-07 \'*[_id == "header"] { "headerText": pt::text(body) }\'\n');
1439
1440
  var queryDocumentsCommand = {
1440
1441
  name: "query",
1441
1442
  group: "documents",
1442
1443
  signature: "[QUERY]",
1443
- helpText: helpText$i,
1444
+ helpText: helpText$j,
1444
1445
  description: "Query for documents",
1445
1446
  action: async (args, context) => {
1446
1447
  var _a, _b;
@@ -1514,12 +1515,12 @@ function parseCliFlags(args) {
1514
1515
  default: fallbackApiVersion
1515
1516
  }).argv;
1516
1517
  }
1517
- const helpText$h = '\nDelete a document from the projects configured dataset\n\nOptions\n --dataset NAME to override dataset\n\nExample\n # Delete the document with the ID "myDocId"\n sanity documents delete myDocId\n\n # ID wrapped in double or single quote works equally well\n sanity documents delete \'myDocId\'\n\n # Delete document with ID "someDocId" from dataset "blog"\n sanity documents delete --dataset=blog someDocId\n\n # Delete the document with ID "doc1" and "doc2"\n sanity documents delete doc1 doc2\n';
1518
+ const helpText$i = '\nDelete a document from the projects configured dataset\n\nOptions\n --dataset NAME to override dataset\n\nExample\n # Delete the document with the ID "myDocId"\n sanity documents delete myDocId\n\n # ID wrapped in double or single quote works equally well\n sanity documents delete \'myDocId\'\n\n # Delete document with ID "someDocId" from dataset "blog"\n sanity documents delete --dataset=blog someDocId\n\n # Delete the document with ID "doc1" and "doc2"\n sanity documents delete doc1 doc2\n';
1518
1519
  const deleteDocumentsCommand = {
1519
1520
  name: "delete",
1520
1521
  group: "documents",
1521
1522
  signature: "[ID] [...IDS]",
1522
- helpText: helpText$h,
1523
+ helpText: helpText$i,
1523
1524
  description: "Delete a document by ID",
1524
1525
  action: async (args, context) => {
1525
1526
  const {
@@ -1555,12 +1556,12 @@ const deleteDocumentsCommand = {
1555
1556
  }
1556
1557
  }
1557
1558
  };
1558
- const helpText$g = '\nOptions\n --replace On duplicate document IDs, replace existing document with specified document(s)\n --missing On duplicate document IDs, don\'t modify the target document(s)\n --watch Write the documents whenever the target file or buffer changes\n --json5 Use JSON5 file type to allow a "simplified" version of JSON\n --id <id> Specify a document ID to use. Will fetch remote document ID and populate editor.\n --dataset NAME to override dataset\n\nExamples\n # Create the document specified in "myDocument.json".\n sanity documents create myDocument.json\n\n # Open configured $EDITOR and create the specified document(s)\n sanity documents create\n\n # Fetch document with the ID "myDocId" and open configured $EDITOR with the\n # current document content (if any). Replace document with the edited version\n # when the editor closes\n sanity documents create --id myDocId --replace\n\n # Open configured $EDITOR and replace the document with the given content\n # on each save. Use JSON5 file extension and parser for simplified syntax.\n sanity documents create --id myDocId --watch --replace --json5\n';
1559
+ const helpText$h = '\nOptions\n --replace On duplicate document IDs, replace existing document with specified document(s)\n --missing On duplicate document IDs, don\'t modify the target document(s)\n --watch Write the documents whenever the target file or buffer changes\n --json5 Use JSON5 file type to allow a "simplified" version of JSON\n --id <id> Specify a document ID to use. Will fetch remote document ID and populate editor.\n --dataset NAME to override dataset\n\nExamples\n # Create the document specified in "myDocument.json".\n sanity documents create myDocument.json\n\n # Open configured $EDITOR and create the specified document(s)\n sanity documents create\n\n # Fetch document with the ID "myDocId" and open configured $EDITOR with the\n # current document content (if any). Replace document with the edited version\n # when the editor closes\n sanity documents create --id myDocId --replace\n\n # Open configured $EDITOR and replace the document with the given content\n # on each save. Use JSON5 file extension and parser for simplified syntax.\n sanity documents create --id myDocId --watch --replace --json5\n';
1559
1560
  const createDocumentsCommand = {
1560
1561
  name: "create",
1561
1562
  group: "documents",
1562
1563
  signature: "[FILE]",
1563
- helpText: helpText$g,
1564
+ helpText: helpText$h,
1564
1565
  description: "Create one or more documents",
1565
1566
  // eslint-disable-next-line complexity
1566
1567
  action: async (args, context) => {
@@ -1744,20 +1745,20 @@ function getEditor() {
1744
1745
  args
1745
1746
  };
1746
1747
  }
1747
- const description = "Downloads and validates all document specified in a workspace";
1748
- const helpText$f = "\nOptions\n -y, --yes Skips the first confirmation prompt.\n --workspace <name> The name of the workspace to use when downloading and validating all documents.\n --dataset <name> Override the dataset used. By default, this is derived from the given workspace.\n --file <filepath> Provide a path to either an .ndjson file or a tarball containing an .ndjson file.\n --format <pretty|ndjson|json> The output format used to print the found validation markers and report progress.\n --level <error|warning|info> The minimum level reported out. Defaults to warning.\n --max-custom-validation-concurrency <number> Specify how many custom validators can run concurrently. Defaults to 5.\n\nExamples\n # Validates all documents in a Sanity project with more than one workspace\n sanity documents validate --workspace default\n\n # Override the dataset specified in the workspace\n sanity documents validate --workspace default --dataset staging\n\n # Save the results of the report into a file\n sanity documents validate > report.txt\n\n # Report out info level validation markers too\n sanity documents validate --level info\n";
1749
- const validateDocumentsCommand = {
1748
+ const description$1 = "Downloads and validates all document specified in a workspace";
1749
+ const helpText$g = "\nOptions\n -y, --yes Skips the first confirmation prompt.\n --workspace <name> The name of the workspace to use when downloading and validating all documents.\n --dataset <name> Override the dataset used. By default, this is derived from the given workspace.\n --file <filepath> Provide a path to either an .ndjson file or a tarball containing an .ndjson file.\n --format <pretty|ndjson|json> The output format used to print the found validation markers and report progress.\n --level <error|warning|info> The minimum level reported out. Defaults to warning.\n --max-custom-validation-concurrency <number> Specify how many custom validators can run concurrently. Defaults to 5.\n\nExamples\n # Validates all documents in a Sanity project with more than one workspace\n sanity documents validate --workspace default\n\n # Override the dataset specified in the workspace\n sanity documents validate --workspace default --dataset staging\n\n # Save the results of the report into a file\n sanity documents validate > report.txt\n\n # Report out info level validation markers too\n sanity documents validate --level info\n";
1750
+ const validateDocumentsCommand$1 = {
1750
1751
  name: "validate",
1751
1752
  group: "documents",
1752
1753
  signature: "",
1753
- description,
1754
- helpText: helpText$f,
1754
+ description: description$1,
1755
+ helpText: helpText$g,
1755
1756
  action: async (args, context) => {
1756
- const mod = await import('./validateAction-GUvMkXiN.js');
1757
+ const mod = await import('./validateAction-6q8Sqwaz.js');
1757
1758
  return mod.default(args, context);
1758
1759
  }
1759
1760
  };
1760
- const helpText$e = '\nNotes\n Changing the hostname or port number might require a new entry to the CORS-origins allow list.\n\nOptions\n --port <port> TCP port to start server on. [default: 3333]\n --host <host> The local network interface at which to listen. [default: "127.0.0.1"]\n\nExamples\n sanity dev --host=0.0.0.0\n sanity dev --port=1942\n';
1761
+ const helpText$f = '\nNotes\n Changing the hostname or port number might require a new entry to the CORS-origins allow list.\n\nOptions\n --port <port> TCP port to start server on. [default: 3333]\n --host <host> The local network interface at which to listen. [default: "127.0.0.1"]\n\nExamples\n sanity dev --host=0.0.0.0\n sanity dev --port=1942\n';
1761
1762
  const devCommand = {
1762
1763
  name: "dev",
1763
1764
  signature: "[--port <port>] [--host <host>]",
@@ -1766,14 +1767,14 @@ const devCommand = {
1766
1767
  const devAction = await getDevAction();
1767
1768
  return devAction(args, context);
1768
1769
  },
1769
- helpText: helpText$e
1770
+ helpText: helpText$f
1770
1771
  };
1771
1772
  async function getDevAction() {
1772
1773
  const mod = await import('./devAction-qv5vS7Y4.js');
1773
1774
  return mod.default;
1774
1775
  }
1775
1776
  const isInteractive = process.stdout.isTTY && process.env.TERM !== "dumb" && !("CI" in process.env);
1776
- const helpText$d = '\nNotes\n Changing the hostname or port number might require a new CORS-entry to be added.\n\nOptions\n --port <port> TCP port to start server on. [default: 3333]\n --host <host> The local network interface at which to listen. [default: "127.0.0.1"]\n\nExamples\n sanity start --host=0.0.0.0\n sanity start --port=1942\n sanity start some/build-output-dir\n';
1777
+ const helpText$e = '\nNotes\n Changing the hostname or port number might require a new CORS-entry to be added.\n\nOptions\n --port <port> TCP port to start server on. [default: 3333]\n --host <host> The local network interface at which to listen. [default: "127.0.0.1"]\n\nExamples\n sanity start --host=0.0.0.0\n sanity start --port=1942\n sanity start some/build-output-dir\n';
1777
1778
  const startCommand = {
1778
1779
  name: "start",
1779
1780
  signature: "[BUILD_OUTPUT_DIR] [--port <port>] [--host <host>]",
@@ -1818,12 +1819,25 @@ const startCommand = {
1818
1819
  }
1819
1820
  }
1820
1821
  },
1821
- helpText: helpText$d
1822
+ helpText: helpText$e
1822
1823
  };
1823
1824
  async function getPreviewAction$1() {
1824
1825
  const mod = await import('./previewAction-_jasPP0I.js');
1825
1826
  return mod.default;
1826
1827
  }
1828
+ const description = "Validates all schema types specified in a workspace.";
1829
+ const helpText$d = "\nOptions\n --workspace <name> The name of the workspace to use when validating all schema types.\n --format <pretty|ndjson|json> The output format used to print schema errors and warnings.\n --level <error|warning> The minimum level reported out. Defaults to warning.\n\nExamples\n # Validates all schema types in a Sanity project with more than one workspace\n sanity schema validate --workspace default\n\n # Save the results of the report into a file\n sanity schema validate > report.txt\n\n # Report out only errors\n sanity schema validate --level error\n";
1830
+ const validateDocumentsCommand = {
1831
+ name: "validate",
1832
+ group: "schema",
1833
+ signature: "",
1834
+ description,
1835
+ helpText: helpText$d,
1836
+ action: async (args, context) => {
1837
+ const mod = await import('./validateAction-Bz67ApRP.js');
1838
+ return mod.default(args, context);
1839
+ }
1840
+ };
1827
1841
  const helpText$c = '\nNotes\n Changing the hostname or port number might require a new entry to the CORS-origins allow list.\n\nOptions\n --port <port> TCP port to start server on. [default: 3333]\n --host <host> The local network interface at which to listen. [default: "127.0.0.1"]\n\nExamples\n sanity preview --host=0.0.0.0\n sanity preview --port=1942\n sanity preview some/build-output-dir\n';
1828
1842
  const previewCommand = {
1829
1843
  name: "preview",
@@ -2430,7 +2444,7 @@ const listGraphQLAPIsCommand = {
2430
2444
  group: "graphql",
2431
2445
  description: "Lists all the GraphQL endpoints deployed for this project",
2432
2446
  action: async (args, context) => {
2433
- const mod = await import('./listApisAction-CqCkBz-F.js');
2447
+ const mod = await import('./listApisAction-oca2uykY.js');
2434
2448
  return mod.default(args, context);
2435
2449
  },
2436
2450
  helpText: helpText$7
@@ -2442,7 +2456,7 @@ const deployGraphQLAPICommand = {
2442
2456
  group: "graphql",
2443
2457
  description: "Deploy a GraphQL API from the current Sanity schema",
2444
2458
  action: async (args, context) => {
2445
- const mod = await import('./deployApiAction-SHteit1G.js');
2459
+ const mod = await import('./deployApiAction-TZcCtXan.js');
2446
2460
  return mod.default(args, context);
2447
2461
  },
2448
2462
  helpText: helpText$6
@@ -2654,37 +2668,37 @@ const renameType = _ref4 => {
2654
2668
  migrationName,
2655
2669
  documentTypes
2656
2670
  } = _ref4;
2657
- return "import {defineMigration, at, set} from 'sanity/migrate'\n\nconst oldType = 'old'\nconst newType = 'new'\n\nexport default defineMigration({\n name: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n object(object, path, context) {\n if (object._type === oldType) {\n return at('_type', set(newType))\n }\n }\n }\n})\n");
2671
+ return "import {defineMigration, at, set} from 'sanity/migrate'\n\nconst oldType = 'old'\nconst newType = 'new'\n\nexport default defineMigration({\n title: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n object(object, path, context) {\n if (object._type === oldType) {\n return at('_type', set(newType))\n }\n }\n }\n})\n");
2658
2672
  };
2659
2673
  const stringToPTE = _ref5 => {
2660
2674
  let {
2661
2675
  migrationName,
2662
2676
  documentTypes
2663
2677
  } = _ref5;
2664
- return "import {pathsAreEqual, stringToPath} from 'sanity'\nimport {defineMigration, set} from 'sanity/migrate'\n\nconst targetPath = stringToPath('some.path')\n\nexport default defineMigration({\n name: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n string(node, path, ctx) {\n if (pathsAreEqual(path, targetPath)) {\n return set([\n {\n style: 'normal',\n _type: 'block',\n children: [\n {\n _type: 'span',\n marks: [],\n text: node,\n },\n ],\n markDefs: [],\n },\n ])\n }\n },\n },\n})\n");
2678
+ return "import {pathsAreEqual, stringToPath} from 'sanity'\nimport {defineMigration, set} from 'sanity/migrate'\n\nconst targetPath = stringToPath('some.path')\n\nexport default defineMigration({\n title: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n string(node, path, ctx) {\n if (pathsAreEqual(path, targetPath)) {\n return set([\n {\n style: 'normal',\n _type: 'block',\n children: [\n {\n _type: 'span',\n marks: [],\n text: node,\n },\n ],\n markDefs: [],\n },\n ])\n }\n },\n },\n})\n");
2665
2679
  };
2666
2680
  const minimalSimple = _ref6 => {
2667
2681
  let {
2668
2682
  migrationName,
2669
2683
  documentTypes
2670
2684
  } = _ref6;
2671
- return "import {defineMigration} from 'sanity/migrate'\n\nexport default defineMigration({\n name: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n document(doc, context) {\n // this will be called for every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n node(node, path, context) {\n // this will be called for every node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n object(node, path, context) {\n // this will be called for every object node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n array(node, path, context) {\n // this will be called for every array node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n string(node, path, context) {\n // this will be called for every string node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n number(node, path, context) {\n // this will be called for every number node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n boolean(node, path, context) {\n // this will be called for every boolean node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n null(node, path, context) {\n // this will be called for every null node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n },\n})\n");
2685
+ return "import {defineMigration} from 'sanity/migrate'\n\nexport default defineMigration({\n title: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n document(doc, context) {\n // this will be called for every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n node(node, path, context) {\n // this will be called for every node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n object(node, path, context) {\n // this will be called for every object node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n array(node, path, context) {\n // this will be called for every array node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n string(node, path, context) {\n // this will be called for every string node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n number(node, path, context) {\n // this will be called for every number node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n boolean(node, path, context) {\n // this will be called for every boolean node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n null(node, path, context) {\n // this will be called for every null node in every document of the matching type\n // any patch returned will be applied to the document\n // you can also return mutations that touches other documents\n },\n },\n})\n");
2672
2686
  };
2673
2687
  const minimalAdvanced = _ref7 => {
2674
2688
  let {
2675
2689
  migrationName,
2676
2690
  documentTypes
2677
2691
  } = _ref7;
2678
- return "import {defineMigration, patch, at, setIfMissing} from 'sanity/migrate'\n\n/**\n * this migration will set `Default title` on all documents that are missing a title\n * and make `true` the default value for the `enabled` field\n */\nexport default defineMigration({\n name: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n async *migrate(documents, context) {\n for await (const document of documents()) {\n yield patch(document._id, [\n at('title', setIfMissing('Default title')),\n at('enabled', setIfMissing(true)),\n ])\n }\n }\n})\n");
2692
+ return "import {defineMigration, patch, at, setIfMissing} from 'sanity/migrate'\n\n/**\n * this migration will set `Default title` on all documents that are missing a title\n * and make `true` the default value for the `enabled` field\n */\nexport default defineMigration({\n title: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n async *migrate(documents, context) {\n for await (const document of documents()) {\n yield patch(document._id, [\n at('title', setIfMissing('Default title')),\n at('enabled', setIfMissing(true)),\n ])\n }\n }\n})\n");
2679
2693
  };
2680
2694
  const renameField = _ref8 => {
2681
2695
  let {
2682
2696
  migrationName,
2683
2697
  documentTypes
2684
2698
  } = _ref8;
2685
- return "import {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'\n\nconst from = 'oldFieldName'\nconst to = 'newFieldName'\n\nexport default defineMigration({\n name: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n document(doc, path, context) {\n return [\n at(to, setIfMissing(doc[from]))\n at(from, unset())\n ]\n }\n }\n})\n");
2699
+ return "import {defineMigration, at, setIfMissing, unset} from 'sanity/migrate'\n\nconst from = 'oldFieldName'\nconst to = 'newFieldName'\n\nexport default defineMigration({\n title: '".concat(migrationName, "',\n").concat(documentTypes.length > 0 ? " documentTypes: [".concat(documentTypes.map(t => JSON.stringify(t)).join(", "), "],\n") : "", "\n migrate: {\n document(doc, context) {\n return [\n at(to, setIfMissing(doc[from])),\n at(from, unset())\n ]\n }\n }\n})\n");
2686
2700
  };
2687
- const helpText$2 = "\nCreate a new migration within your project\n";
2701
+ const helpText$2 = '\nCreate a new migration within your project\n\nExamples:\n # Create a new migration, you will be prompted to provide a type\n sanity migration create\n\n # Create a new migration, specifying the title\n sanity migration create "Rename field from location to address"\n';
2688
2702
  const TEMPLATES = [{
2689
2703
  name: "Minimalistic migration to get you started",
2690
2704
  template: minimalSimple
@@ -2701,10 +2715,10 @@ const TEMPLATES = [{
2701
2715
  name: "Advanced template using async iterators providing more fine grained control",
2702
2716
  template: minimalAdvanced
2703
2717
  }];
2704
- const createMigrationCommand$2 = {
2718
+ const createMigrationCommand$1 = {
2705
2719
  name: "create",
2706
2720
  group: "migration",
2707
- signature: "[NAME]",
2721
+ signature: "[TITLE]",
2708
2722
  helpText: helpText$2,
2709
2723
  description: "Create a new content migration within your project",
2710
2724
  action: async (args, context) => {
@@ -2714,15 +2728,15 @@ const createMigrationCommand$2 = {
2714
2728
  workDir,
2715
2729
  chalk
2716
2730
  } = context;
2717
- let name = "";
2718
- while (!name.trim()) {
2719
- name = await prompt.single({
2731
+ let [title] = args.argsWithoutOptions;
2732
+ while (!(title == null ? void 0 : title.trim())) {
2733
+ title = await prompt.single({
2720
2734
  type: "input",
2721
- suffix: " (e.g. rename field from location to address)",
2722
- message: "Name of migration"
2735
+ suffix: ' (e.g. "Rename field from location to address")',
2736
+ message: "Title of migration"
2723
2737
  });
2724
- if (!name.trim()) {
2725
- output.print(chalk.red("Name cannot be empty"));
2738
+ if (!title.trim()) {
2739
+ output.error(chalk.red("Name cannot be empty"));
2726
2740
  }
2727
2741
  }
2728
2742
  const types = await prompt.single({
@@ -2739,7 +2753,7 @@ const createMigrationCommand$2 = {
2739
2753
  value: definedTemplate.name
2740
2754
  }))
2741
2755
  });
2742
- const sluggedName = deburr(name.toLowerCase()).replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
2756
+ const sluggedName = deburr(title.toLowerCase()).replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
2743
2757
  const destDir = path.join(MIGRATIONS_DIRECTORY, sluggedName);
2744
2758
  if (existsSync(destDir)) {
2745
2759
  if (!(await prompt.single({
@@ -2752,7 +2766,7 @@ const createMigrationCommand$2 = {
2752
2766
  }
2753
2767
  mkdirp.sync(destDir);
2754
2768
  const renderedTemplate = (templatesByName[template].template || minimalSimple)({
2755
- migrationName: name,
2769
+ migrationName: title,
2756
2770
  documentTypes: types.split(",").map(t => t.trim()).filter(Boolean)
2757
2771
  });
2758
2772
  const definitionFile = path.join(destDir, "index.ts");
@@ -2768,71 +2782,302 @@ const createMigrationCommand$2 = {
2768
2782
  output.print("\u{1F449} Learn more about schema and content migrations at ".concat(chalk.bold("https://www.sanity.io/docs/schema-and-content-migrations")));
2769
2783
  }
2770
2784
  };
2785
+ function resolveMigrationScript$1(workDir, migrationName) {
2786
+ return [migrationName, path.join(migrationName, "index")].flatMap(location => MIGRATION_SCRIPT_EXTENSIONS.map(ext => {
2787
+ const relativePath = path.join(MIGRATIONS_DIRECTORY, "".concat(location, ".").concat(ext));
2788
+ const absolutePath = path.resolve(workDir, relativePath);
2789
+ let mod;
2790
+ try {
2791
+ mod = require(absolutePath);
2792
+ } catch (err) {}
2793
+ return {
2794
+ relativePath,
2795
+ absolutePath,
2796
+ mod
2797
+ };
2798
+ }));
2799
+ }
2800
+ const helpText$1 = "";
2801
+ const createMigrationCommand = {
2802
+ name: "list",
2803
+ group: "migration",
2804
+ signature: "[NAME]",
2805
+ helpText: helpText$1,
2806
+ description: "List available migrations",
2807
+ action: async (args, context) => {
2808
+ const {
2809
+ workDir,
2810
+ output
2811
+ } = context;
2812
+ const migrations = await resolveMigrations(workDir);
2813
+ const table = new Table({
2814
+ title: "Found ".concat(migrations.length, " migrations in project"),
2815
+ columns: [{
2816
+ name: "id",
2817
+ title: "ID",
2818
+ alignment: "left"
2819
+ }, {
2820
+ name: "title",
2821
+ title: "Title",
2822
+ alignment: "left"
2823
+ }]
2824
+ });
2825
+ migrations.forEach(definedMigration => {
2826
+ table.addRow({
2827
+ id: definedMigration.dirname,
2828
+ title: definedMigration.migration.title
2829
+ });
2830
+ });
2831
+ table.printTable();
2832
+ output.print("\nRun `sanity migration run <ID>` to run a migration");
2833
+ }
2834
+ };
2835
+ async function resolveMigrations(workDir) {
2836
+ {
2837
+ register({
2838
+ target: "node".concat(process.version.slice(1))
2839
+ });
2840
+ }
2841
+ const directories = (await readdir(path.join(workDir, MIGRATIONS_DIRECTORY), {
2842
+ withFileTypes: true
2843
+ })).filter(ent => ent.isDirectory());
2844
+ return directories.map(ent => {
2845
+ const candidates = resolveMigrationScript$1(workDir, ent.name);
2846
+ const found = candidates.find(candidate => {
2847
+ var _a;
2848
+ return (_a = candidate.mod) == null ? void 0 : _a.default;
2849
+ });
2850
+ if (!found) {
2851
+ return null;
2852
+ }
2853
+ return {
2854
+ dirname: ent.name,
2855
+ migration: found.mod.default
2856
+ };
2857
+ }).filter(Boolean);
2858
+ }
2859
+ const maxKeyLength = function () {
2860
+ let children = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2861
+ let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
2862
+ return Object.entries(children).map(_ref9 => {
2863
+ let [key, child] = _ref9;
2864
+ return Math.max(key.length + depth * 2, maxKeyLength(child.children, depth + 1));
2865
+ }).reduce((max, next) => next > max ? next : max, 0);
2866
+ };
2867
+ const formatTree = _ref10 => {
2868
+ let {
2869
+ node = {},
2870
+ paddingLength,
2871
+ indent = "",
2872
+ getNodes: getLeaves = _ref11 => {
2873
+ let {
2874
+ nodes
2875
+ } = _ref11;
2876
+ return nodes;
2877
+ },
2878
+ getMessage
2879
+ } = _ref10;
2880
+ const entries = Object.entries(node);
2881
+ return entries.map((_ref12, index) => {
2882
+ let [key, child] = _ref12;
2883
+ const isLast = index === entries.length - 1;
2884
+ const nextIndent = "".concat(indent).concat(isLast ? " " : "\u2502 ");
2885
+ const leaves = getLeaves(child);
2886
+ const nested = formatTree({
2887
+ node: child.children,
2888
+ paddingLength,
2889
+ indent: nextIndent,
2890
+ getNodes: getLeaves,
2891
+ getMessage
2892
+ });
2893
+ if (!(leaves == null ? void 0 : leaves.length)) {
2894
+ const current2 = "".concat(indent).concat(isLast ? "\u2514" : "\u251C", "\u2500 ").concat(key);
2895
+ return [current2, nested].filter(Boolean).join("\n");
2896
+ }
2897
+ const [first, ...rest] = leaves;
2898
+ const firstPadding = ".".repeat(paddingLength - indent.length - key.length);
2899
+ const elbow = isLast ? "\u2514" : "\u251C";
2900
+ const subsequentPadding = " ".repeat(paddingLength - indent.length + 2);
2901
+ const firstMessage = "".concat(indent).concat(elbow, "\u2500 ").concat(key, " ").concat(firstPadding, " ").concat(getMessage(first));
2902
+ const subsequentMessages = rest.map(marker => "".concat(nextIndent).concat(subsequentPadding, " ").concat(getMessage(marker))).join("\n");
2903
+ const current = [firstMessage, subsequentMessages].filter(Boolean).join("\n");
2904
+ return [current, nested].filter(Boolean).join("\n");
2905
+ }).join("\n");
2906
+ };
2907
+ function convertToTree(nodes) {
2908
+ const root = {};
2909
+ function addNode(node) {
2910
+ let tree = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : root;
2911
+ if (!node.path.length) {
2912
+ if (!tree.nodes) tree.nodes = [];
2913
+ tree.nodes.push(node);
2914
+ return;
2915
+ }
2916
+ const [current, ...rest] = node.path;
2917
+ const key = pathToString([current]);
2918
+ if (!tree.children) tree.children = {};
2919
+ if (!(key in tree.children)) tree.children[key] = {};
2920
+ addNode({
2921
+ ...node,
2922
+ path: rest
2923
+ }, tree.children[key]);
2924
+ }
2925
+ for (const node of nodes) addNode(node);
2926
+ return root;
2927
+ }
2928
+ const isTty = isatty(1);
2929
+ function prettyFormat(_ref13) {
2930
+ let {
2931
+ chalk,
2932
+ subject,
2933
+ migration,
2934
+ indentSize = 0
2935
+ } = _ref13;
2936
+ return (Array.isArray(subject) ? subject : [subject]).map(subjectEntry => {
2937
+ if (subjectEntry.type === "transaction") {
2938
+ return [[badge("transaction", "info", chalk), typeof subjectEntry.id === "undefined" ? null : chalk.underline(subjectEntry.id)].filter(Boolean).join(" "), indent(prettyFormat({
2939
+ chalk,
2940
+ subject: subjectEntry.mutations,
2941
+ migration,
2942
+ indentSize
2943
+ }))].join("\n\n");
2944
+ }
2945
+ return prettyFormatMutation({
2946
+ chalk,
2947
+ subject: subjectEntry,
2948
+ migration,
2949
+ indentSize
2950
+ });
2951
+ }).join("\n\n");
2952
+ }
2771
2953
  function encodeItemRef(ref) {
2772
2954
  return typeof ref === "number" ? ref : ref._key;
2773
2955
  }
2774
- function formatTransaction(chalk, mutation) {
2775
- var _a;
2776
- if (mutation.type === "transaction") {
2777
- return mutation.mutations.flatMap(m => formatTransaction(chalk, m)).join("\n");
2778
- }
2779
- if (mutation.type === "create" || mutation.type === "createIfNotExists" || mutation.type === "createOrReplace") {
2780
- return [chalk.bold(mutation.type), ": ", JSON.stringify(mutation.document)].join("");
2956
+ function badgeStyle(chalk, variant) {
2957
+ const styles = {
2958
+ info: chalk.bgWhite.black,
2959
+ incremental: chalk.bgGreen.black.bold,
2960
+ maybeDestructive: chalk.bgYellow.black.bold,
2961
+ destructive: chalk.bgRed.black.bold
2962
+ };
2963
+ return styles[variant];
2964
+ }
2965
+ function badge(label, variant, chalk) {
2966
+ if (!isTty) {
2967
+ return "[".concat(label, "]");
2781
2968
  }
2782
- if (mutation.type === "delete") {
2783
- return ["".concat(chalk.red.bold("delete"), " "), mutation.id].join(": ");
2969
+ return badgeStyle(chalk, variant)(" ".concat(label, " "));
2970
+ }
2971
+ const mutationImpact = {
2972
+ create: "incremental",
2973
+ createIfNotExists: "incremental",
2974
+ createOrReplace: "maybeDestructive",
2975
+ delete: "destructive",
2976
+ patch: "maybeDestructive"
2977
+ };
2978
+ function documentId(mutation) {
2979
+ if ("id" in mutation) {
2980
+ return mutation.id;
2784
2981
  }
2785
- if (mutation.type === "patch") {
2786
- const ifRevision = (_a = mutation.options) == null ? void 0 : _a.ifRevision;
2787
- return [chalk.blue.bold("patch"), "", "(".concat(mutation.id, ")"), ifRevision ? " (if revision==".concat(ifRevision, ")") : "", ":\n", mutation.patches.map(nodePatch => " ".concat(formatPatchMutation(chalk, nodePatch))).join("\n")].join("");
2982
+ if ("document" in mutation) {
2983
+ return mutation.document._id;
2788
2984
  }
2789
- throw new Error("Invalid mutation type: ".concat(mutation.type));
2985
+ return void 0;
2986
+ }
2987
+ const listFormatter = new Intl.ListFormat("en-US", {
2988
+ type: "disjunction"
2989
+ });
2990
+ function mutationHeader(chalk, mutation, migration) {
2991
+ var _a;
2992
+ const mutationType = badge(mutation.type, mutationImpact[mutation.type], chalk);
2993
+ const documentType = "document" in mutation || migration.documentTypes ? badge("document" in mutation ? mutation.document._type : listFormatter.format((_a = migration.documentTypes) != null ? _a : []), "info", chalk) : null;
2994
+ return [mutationType, documentType, chalk.underline(documentId(mutation))].filter(Boolean).join(" ");
2995
+ }
2996
+ function prettyFormatMutation(_ref14) {
2997
+ let {
2998
+ chalk,
2999
+ subject,
3000
+ migration,
3001
+ indentSize = 0
3002
+ } = _ref14;
3003
+ var _a;
3004
+ const lock = "options" in subject ? chalk.cyan("(if revision==".concat((_a = subject.options) == null ? void 0 : _a.ifRevision, ")")) : "";
3005
+ const header = [mutationHeader(chalk, subject, migration), lock].join(" ");
3006
+ const padding = " ".repeat(indentSize);
3007
+ if (subject.type === "create" || subject.type === "createIfNotExists" || subject.type === "createOrReplace") {
3008
+ return [header, "\n", indent(JSON.stringify(subject.document, null, 2), indentSize)].join("");
3009
+ }
3010
+ if (subject.type === "patch") {
3011
+ const tree = convertToTree(subject.patches.flat());
3012
+ const paddingLength = Math.max(maxKeyLength(tree.children) + 2, 30);
3013
+ return [header, "\n", formatTree({
3014
+ node: tree.children,
3015
+ paddingLength,
3016
+ indent: padding,
3017
+ getMessage: patch => formatPatchMutation(chalk, patch)
3018
+ })].join("");
3019
+ }
3020
+ return header;
2790
3021
  }
2791
3022
  function formatPatchMutation(chalk, patch) {
2792
3023
  const {
2793
3024
  op
2794
3025
  } = patch;
2795
- const path = chalk.grey(toString(patch.path));
2796
3026
  const formattedType = chalk.bold(op.type);
2797
3027
  if (op.type === "unset") {
2798
- return [path, "".concat(formattedType, "()")].join(": ");
3028
+ return "".concat(chalk.red(formattedType), "()");
2799
3029
  }
2800
3030
  if (op.type === "diffMatchPatch") {
2801
- return [path, "".concat(formattedType, "(").concat(op.value, ")")].join(": ");
3031
+ return "".concat(chalk.yellow(formattedType), "(").concat(op.value, ")");
2802
3032
  }
2803
3033
  if (op.type === "inc" || op.type === "dec") {
2804
- return [path, "".concat(formattedType, "(").concat(op.amount, ")")].join(": ");
3034
+ return "".concat(chalk.yellow(formattedType), "(").concat(op.amount, ")");
3035
+ }
3036
+ if (op.type === "set") {
3037
+ return "".concat(chalk.yellow(formattedType), "(").concat(JSON.stringify(op.value), ")");
2805
3038
  }
2806
- if (op.type === "set" || op.type === "setIfMissing") {
2807
- return [path, "".concat(formattedType, "(").concat(JSON.stringify(op.value), ")")].join(": ");
3039
+ if (op.type === "setIfMissing") {
3040
+ return "".concat(chalk.green(formattedType), "(").concat(JSON.stringify(op.value), ")");
2808
3041
  }
2809
3042
  if (op.type === "assign") {
2810
- return [path, "".concat(formattedType, "(").concat(JSON.stringify(op.value), ")")].join(": ");
3043
+ return "".concat(chalk.yellow(formattedType), "(").concat(JSON.stringify(op.value), ")");
2811
3044
  }
2812
3045
  if (op.type === "unassign") {
2813
- return [path, "".concat(formattedType, "(").concat(JSON.stringify(op.keys), ")")].join(": ");
3046
+ return "".concat(chalk.red(formattedType), "(").concat(JSON.stringify(op.keys), ")");
2814
3047
  }
2815
- if (op.type === "insert" || op.type === "upsert") {
2816
- return [path, "".concat(formattedType, "(").concat(op.position, ", ").concat(encodeItemRef(op.referenceItem), ", ").concat(JSON.stringify(op.items), ")")].join(": ");
3048
+ if (op.type === "insert") {
3049
+ return "".concat(chalk.green(formattedType), "(").concat(op.position, ", ").concat(encodeItemRef(op.referenceItem), ", ").concat(JSON.stringify(op.items), ")");
3050
+ }
3051
+ if (op.type === "upsert") {
3052
+ return "".concat(chalk.yellow(formattedType), "(").concat(op.position, ", ").concat(encodeItemRef(op.referenceItem), ", ").concat(JSON.stringify(op.items), ")");
2817
3053
  }
2818
3054
  if (op.type === "replace") {
2819
- return [path, "".concat(formattedType, "(").concat(encodeItemRef(op.referenceItem), ", ").concat(JSON.stringify(op.items), ")")].join(": ");
3055
+ return "".concat(chalk.yellow(formattedType), "(").concat(encodeItemRef(op.referenceItem), ", ").concat(JSON.stringify(op.items), ")");
2820
3056
  }
2821
3057
  if (op.type === "truncate") {
2822
- return [path, "".concat(formattedType, "(").concat(op.startIndex, ", ").concat(op.endIndex)].join(": ");
3058
+ return "".concat(chalk.red(formattedType), "(").concat(op.startIndex, ", ").concat(op.endIndex, ")");
2823
3059
  }
2824
3060
  throw new Error("Invalid operation type: ".concat(op.type));
2825
3061
  }
2826
- const helpText$1 = "\nOptions\n --dry <boolean> Whether or not to dry run the migration. Default to true, to actually run the migration, pass --no-dry\n --from-export <export.tar.gz> Use a local dataset export as source for migration instead of calling the Sanity API. Note: this is only supported for dry runs.\n --concurrency <concurrent> How many mutation requests to run in parallel. Must be between 1 and ".concat(MAX_MUTATION_CONCURRENCY, ". Default: ").concat(DEFAULT_MUTATION_CONCURRENCY, ".\n --no-progress Don't output progress. Useful if you want debug your migration script and see the output of console.log() statements.\n --dataset <dataset> Dataset to migrate. Defaults to the dataset configured in your Sanity CLI config.\n --projectId <project id> Project ID of the dataset to migrate. Defaults to the projectId configured in your Sanity CLI config.\n --no-confirm Skip the confirmation prompt before running the migration. Make sure you know what you're doing before using this flag.\n\n\nExamples\n # dry run the migration\n sanity migration run <name>\n\n # execute the migration against a dataset\n sanity migration run <name> --no-dry --projectId xyz --dataset staging\n\n # run the migration using the dataset export as the source\n sanity migration run <name> --dry false --from-export=production.tar.gz --projectId xyz --dataset staging\n");
3062
+ function indent(subject) {
3063
+ let size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
3064
+ const padding = " ".repeat(size);
3065
+ return subject.split("\n").map(line => padding + line).join("\n");
3066
+ }
3067
+ const helpText = "\nOptions\n --dry <boolean> Whether or not to dry run the migration. Default to true, to actually run the migration, pass --no-dry\n --concurrency <concurrent> How many mutation requests to run in parallel. Must be between 1 and ".concat(MAX_MUTATION_CONCURRENCY, ". Default: ").concat(DEFAULT_MUTATION_CONCURRENCY, ".\n --no-progress Don't output progress. Useful if you want debug your migration script and see the output of console.log() statements.\n --dataset <dataset> Dataset to migrate. Defaults to the dataset configured in your Sanity CLI config.\n --projectId <project id> Project ID of the dataset to migrate. Defaults to the projectId configured in your Sanity CLI config.\n --no-confirm Skip the confirmation prompt before running the migration. Make sure you know what you're doing before using this flag.\n --from-export <export.tar.gz> Use a local dataset export as source for migration instead of calling the Sanity API. Note: this is only supported for dry runs.\n\n\nExamples\n # dry run the migration\n sanity migration run <id>\n\n # execute the migration against a dataset\n sanity migration run <id> --no-dry --projectId xyz --dataset staging\n\n # run the migration using the dataset export as the source\n sanity migration run <id> --dry false --from-export=production.tar.gz --projectId xyz --dataset staging\n");
2827
3068
  const tryExtensions = ["mjs", "js", "ts", "cjs"];
2828
- function resolveMigrationScript$1(workDir, migrationName) {
2829
- return [migrationName, path.join(migrationName, "index")].flatMap(location => tryExtensions.map(ext => {
3069
+ function resolveMigrationScript(workDir, migrationId) {
3070
+ return [migrationId, path.join(migrationId, "index")].flatMap(location => tryExtensions.map(ext => {
2830
3071
  const relativePath = path.join("migrations", "".concat(location, ".").concat(ext));
2831
3072
  const absolutePath = path.resolve(workDir, relativePath);
2832
3073
  let mod;
2833
3074
  try {
2834
3075
  mod = require(absolutePath);
2835
- } catch (err) {}
3076
+ } catch (err) {
3077
+ if (err.code !== "MODULE_NOT_FOUND") {
3078
+ throw new Error("Error: ".concat(err.message, '"'));
3079
+ }
3080
+ }
2836
3081
  return {
2837
3082
  relativePath,
2838
3083
  absolutePath,
@@ -2840,11 +3085,11 @@ function resolveMigrationScript$1(workDir, migrationName) {
2840
3085
  };
2841
3086
  }));
2842
3087
  }
2843
- const createMigrationCommand$1 = {
3088
+ const runMigrationCommand = {
2844
3089
  name: "run",
2845
3090
  group: "migration",
2846
- signature: "[NAME] [MIGRATION NAME]",
2847
- helpText: helpText$1,
3091
+ signature: "ID",
3092
+ helpText,
2848
3093
  description: "Run a migration against a dataset",
2849
3094
  action: async (args, context) => {
2850
3095
  const {
@@ -2854,29 +3099,51 @@ const createMigrationCommand$1 = {
2854
3099
  chalk,
2855
3100
  workDir
2856
3101
  } = context;
2857
- const [migrationName] = args.argsWithoutOptions;
3102
+ const [id] = args.argsWithoutOptions;
2858
3103
  const [fromExport, dry, showProgress, dataset, projectId, shouldConfirm] = [args.extOptions["from-export"], args.extOptions.dry !== false, args.extOptions.progress !== false, args.extOptions.dataset, args.extOptions["project-id"], args.extOptions.confirm !== false];
2859
3104
  if (dataset && !projectId || projectId && !dataset) {
2860
3105
  throw new Error("If either --dataset or --projectId is provided, both must be provided");
2861
3106
  }
2862
- if (!migrationName) {
2863
- throw new Error("MIGRATION NAME must be provided. `sanity migration run <name>`");
3107
+ if (!id) {
3108
+ output.error(chalk.red("Error: Migration ID must be provided"));
3109
+ const migrations = await resolveMigrations(workDir);
3110
+ const table = new Table({
3111
+ title: "Migrations found in project",
3112
+ columns: [{
3113
+ name: "id",
3114
+ title: "ID",
3115
+ alignment: "left"
3116
+ }, {
3117
+ name: "title",
3118
+ title: "Title",
3119
+ alignment: "left"
3120
+ }]
3121
+ });
3122
+ migrations.forEach(definedMigration => {
3123
+ table.addRow({
3124
+ id: definedMigration.dirname,
3125
+ title: definedMigration.migration.title
3126
+ });
3127
+ });
3128
+ table.printTable();
3129
+ output.print("\nRun `sanity migration run <ID>` to run a migration");
3130
+ return;
2864
3131
  }
2865
3132
  {
2866
3133
  register({
2867
3134
  target: "node".concat(process.version.slice(1))
2868
3135
  });
2869
3136
  }
2870
- const candidates = resolveMigrationScript$1(workDir, migrationName);
3137
+ const candidates = resolveMigrationScript(workDir, id);
2871
3138
  const resolvedScripts = candidates.filter(candidate => {
2872
3139
  var _a;
2873
3140
  return (_a = candidate.mod) == null ? void 0 : _a.default;
2874
3141
  });
2875
3142
  if (resolvedScripts.length > 1) {
2876
- throw new Error('Found multiple migrations for "'.concat(migrationName, '" in current directory ').concat(candidates.map(candidate => candidate.relativePath).join(", ")));
3143
+ throw new Error('Found multiple migrations for "'.concat(id, '" in current directory ').concat(candidates.map(candidate => candidate.relativePath).join(", ")));
2877
3144
  }
2878
3145
  if (resolvedScripts.length === 0) {
2879
- throw new Error('No migration found for "'.concat(migrationName, '" in current directory. Make sure that the migration file exists and exports a valid migration as its default export.\n\n Tried the following files:\n -').concat(candidates.map(candidate => candidate.relativePath).join("\n - ")));
3146
+ throw new Error('No migration found for "'.concat(id, '" in current directory. Make sure that the migration file exists and exports a valid migration as its default export.\n\n Tried the following files:\n -').concat(candidates.map(candidate => candidate.relativePath).join("\n - ")));
2880
3147
  }
2881
3148
  const script = resolvedScripts[0];
2882
3149
  const mod = script.mod;
@@ -2908,132 +3175,81 @@ const createMigrationCommand$1 = {
2908
3175
  apiVersion: "v2024-01-29"
2909
3176
  };
2910
3177
  if (dry) {
2911
- const spinner = output.spinner('Running migration "'.concat(migrationName, '" in dry mode')).start();
2912
- if (fromExport) {
2913
- await runFromArchive(migration, fromExport, {
2914
- api: apiConfig,
2915
- concurrency,
2916
- onProgress: createProgress(spinner)
2917
- });
2918
- return;
2919
- }
2920
- dryRun({
2921
- api: apiConfig
2922
- }, migration);
2923
- spinner.stop();
2924
- } else {
2925
- const response = shouldConfirm && (await prompt.single({
2926
- message: "This migration will run on the ".concat(chalk.yellow(chalk.bold(apiConfig.dataset)), " dataset in ").concat(chalk.yellow(chalk.bold(apiConfig.projectId)), " project. Are you sure?"),
2927
- type: "confirm"
2928
- }));
2929
- if (response === false) {
2930
- debug("User aborted migration");
2931
- return;
2932
- }
2933
- const spinner = output.spinner('Running migration "'.concat(migrationName, '"')).start();
2934
- await run({
2935
- api: apiConfig,
2936
- concurrency,
2937
- onProgress: createProgress(spinner)
2938
- }, migration);
2939
- spinner.stop();
2940
- }
2941
- function createProgress(spinner) {
3178
+ dryRunHandler();
3179
+ return;
3180
+ }
3181
+ const response = shouldConfirm && (await prompt.single({
3182
+ message: "This migration will run on the ".concat(chalk.yellow(chalk.bold(apiConfig.dataset)), " dataset in ").concat(chalk.yellow(chalk.bold(apiConfig.projectId)), " project. Are you sure?"),
3183
+ type: "confirm"
3184
+ }));
3185
+ if (response === false) {
3186
+ debug("User aborted migration");
3187
+ return;
3188
+ }
3189
+ const spinner = output.spinner('Running migration "'.concat(id, '"')).start();
3190
+ await run({
3191
+ api: apiConfig,
3192
+ concurrency,
3193
+ onProgress: createProgress(spinner)
3194
+ }, migration);
3195
+ spinner.stop();
3196
+ function createProgress(progressSpinner) {
2942
3197
  return function onProgress(progress) {
2943
3198
  if (!showProgress) {
2944
- spinner.stop();
3199
+ progressSpinner.stop();
2945
3200
  return;
2946
3201
  }
2947
3202
  if (progress.done) {
2948
- spinner.text = 'Migration "'.concat(migrationName, '" completed.\n\n Project id: ').concat(chalk.bold(projectId), "\n Dataset: ").concat(chalk.bold(dataset), "\n\n ").concat(progress.documents, " documents processed.\n ").concat(progress.mutations, " mutations generated.\n ").concat(chalk.green(progress.completedTransactions.length), " transactions committed.");
2949
- spinner.stopAndPersist({
3203
+ progressSpinner.text = 'Migration "'.concat(id, '" completed.\n\n Project id: ').concat(chalk.bold(apiConfig.projectId), "\n Dataset: ").concat(chalk.bold(apiConfig.dataset), "\n\n ").concat(progress.documents, " documents processed.\n ").concat(progress.mutations, " mutations generated.\n ").concat(chalk.green(progress.completedTransactions.length), " transactions committed.");
3204
+ progressSpinner.stopAndPersist({
2950
3205
  symbol: chalk.green("\u2714")
2951
3206
  });
2952
3207
  return;
2953
3208
  }
2954
3209
  [null, ...progress.currentTransactions].forEach(transaction => {
2955
3210
  var _a;
2956
- spinner.text = 'Running migration "'.concat(migrationName, '"\u2026\n\n Project id: ').concat(chalk.bold(projectId), "\n Dataset: ").concat(chalk.bold(dataset), "\n Document type: ").concat(chalk.bold((_a = migration.documentTypes) == null ? void 0 : _a.join(",")), "\n\n ").concat(progress.documents, " documents processed\u2026\n ").concat(progress.mutations, " mutations generated\u2026\n ").concat(chalk.blue(progress.pending), " requests pending\u2026\n ").concat(chalk.green(progress.completedTransactions.length), " transactions committed.\n\n ").concat(transaction && !progress.done ? "\xBB ".concat(chalk.grey(formatTransaction(chalk, transaction))) : "");
3211
+ progressSpinner.text = 'Running migration "'.concat(id, '" ').concat(dry ? "in dry mode..." : "...", "\n\n Project id: ").concat(chalk.bold(apiConfig.projectId), "\n Dataset: ").concat(chalk.bold(apiConfig.dataset), "\n Document type: ").concat(chalk.bold((_a = migration.documentTypes) == null ? void 0 : _a.join(",")), "\n\n ").concat(progress.documents, " documents processed\u2026\n ").concat(progress.mutations, " mutations generated\u2026\n ").concat(chalk.blue(progress.pending), " requests pending\u2026\n ").concat(chalk.green(progress.completedTransactions.length), " transactions committed.\n\n ").concat(transaction && !progress.done ? "\xBB ".concat(prettyFormat({
3212
+ chalk,
3213
+ subject: transaction,
3214
+ migration,
3215
+ indentSize: 2
3216
+ })) : "");
2957
3217
  });
2958
3218
  };
2959
3219
  }
2960
- }
2961
- };
2962
- function resolveMigrationScript(workDir, migrationName) {
2963
- return [migrationName, path.join(migrationName, "index")].flatMap(location => MIGRATION_SCRIPT_EXTENSIONS.map(ext => {
2964
- const relativePath = path.join(MIGRATIONS_DIRECTORY, "".concat(location, ".").concat(ext));
2965
- const absolutePath = path.resolve(workDir, relativePath);
2966
- let mod;
2967
- try {
2968
- mod = require(absolutePath);
2969
- } catch (err) {}
2970
- return {
2971
- relativePath,
2972
- absolutePath,
2973
- mod
2974
- };
2975
- }));
2976
- }
2977
- const helpText = "";
2978
- const createMigrationCommand = {
2979
- name: "list",
2980
- group: "migration",
2981
- signature: "[NAME]",
2982
- helpText,
2983
- description: "List available migrations",
2984
- action: async (args, context) => {
2985
- const {
2986
- output,
2987
- workDir
2988
- } = context;
2989
- {
2990
- register({
2991
- target: "node".concat(process.version.slice(1))
2992
- });
2993
- }
2994
- const directories = (await readdir(path.join(workDir, MIGRATIONS_DIRECTORY), {
2995
- withFileTypes: true
2996
- })).filter(ent => ent.isDirectory());
2997
- const migrationModules = directories.map(ent => {
2998
- const candidates = resolveMigrationScript(workDir, ent.name);
2999
- const found = candidates.find(candidate => {
3000
- var _a;
3001
- return (_a = candidate.mod) == null ? void 0 : _a.default;
3002
- });
3003
- if (!found) {
3004
- return null;
3220
+ async function dryRunHandler() {
3221
+ if (fromExport) {
3222
+ const dryRunSpinner = output.spinner('Running migration "'.concat(id, '" in dry mode')).start();
3223
+ await runFromArchive(migration, fromExport, {
3224
+ api: apiConfig,
3225
+ concurrency,
3226
+ onProgress: createProgress(dryRunSpinner)
3227
+ });
3228
+ dryRunSpinner.stop();
3229
+ } else {
3230
+ output.print('Running migration "'.concat(id, '" in dry mode'));
3231
+ output.print();
3232
+ output.print("Project id: ".concat(chalk.bold(apiConfig.projectId)));
3233
+ output.print("Dataset: ".concat(chalk.bold(apiConfig.dataset)));
3234
+ for await (const mutation of dryRun({
3235
+ api: apiConfig
3236
+ }, migration)) {
3237
+ if (!mutation) continue;
3238
+ output.print();
3239
+ output.print(prettyFormat({
3240
+ chalk,
3241
+ subject: mutation,
3242
+ migration
3243
+ }));
3244
+ }
3005
3245
  }
3006
- return {
3007
- dirname: ent.name,
3008
- migration: found.mod.default
3009
- };
3010
- }).filter(Boolean);
3011
- const table = new Table({
3012
- title: "Found ".concat(migrationModules.length, " migrations in project"),
3013
- columns: [{
3014
- name: "id",
3015
- title: "ID",
3016
- alignment: "left"
3017
- }, {
3018
- name: "name",
3019
- title: "Name",
3020
- alignment: "left"
3021
- }]
3022
- });
3023
- migrationModules.forEach(definedMigration => {
3024
- table.addRow({
3025
- id: definedMigration.dirname,
3026
- name: definedMigration.migration.name
3027
- });
3028
- });
3029
- table.printTable();
3030
- output.print('\nRun "sanity migration run <MIGRATION ID>" to run a migration');
3246
+ }
3031
3247
  }
3032
3248
  };
3033
- const commands = [buildCommand, checkCommand, configCheckCommand, datasetGroup, deployCommand, undeployCommand, listDatasetsCommand, createDatasetCommand, datasetVisibilityCommand, exportDatasetCommand, importDatasetCommand, deleteDatasetCommand, copyDatasetCommand, aliasCommand, corsGroup, listCorsOriginsCommand, addCorsOriginCommand, deleteCorsOriginCommand, usersGroup, inviteUserCommand, listUsersCommand, hookGroup, listHooksCommand, createHookCommand, migrationGroup, createMigrationCommand$2, createMigrationCommand$1, createMigrationCommand, deleteHookCommand, listHookLogsCommand, printHookAttemptCommand, documentsGroup, getDocumentsCommand, queryDocumentsCommand, deleteDocumentsCommand, createDocumentsCommand, validateDocumentsCommand, graphqlGroup, listGraphQLAPIsCommand, deployGraphQLAPICommand, deleteGraphQLAPICommand, devCommand, startCommand, previewCommand, uninstallCommand, execCommand];
3249
+ const commands = [buildCommand, checkCommand, configCheckCommand, datasetGroup, deployCommand, undeployCommand, listDatasetsCommand, createDatasetCommand, datasetVisibilityCommand, exportDatasetCommand, importDatasetCommand, deleteDatasetCommand, copyDatasetCommand, aliasCommand, corsGroup, listCorsOriginsCommand, addCorsOriginCommand, deleteCorsOriginCommand, usersGroup, inviteUserCommand, listUsersCommand, hookGroup, listHooksCommand, createHookCommand, migrationGroup, createMigrationCommand$1, runMigrationCommand, createMigrationCommand, deleteHookCommand, listHookLogsCommand, printHookAttemptCommand, documentsGroup, getDocumentsCommand, queryDocumentsCommand, deleteDocumentsCommand, createDocumentsCommand, validateDocumentsCommand$1, graphqlGroup, listGraphQLAPIsCommand, deployGraphQLAPICommand, deleteGraphQLAPICommand, devCommand, startCommand, validateDocumentsCommand, previewCommand, uninstallCommand, execCommand];
3034
3250
  const cliProjectCommands = {
3035
3251
  requiredCliVersionRange: "^3.0.0",
3036
3252
  commands
3037
3253
  };
3038
- export { cliProjectCommands, debug, getClientUrl };
3039
- //# sourceMappingURL=_internal-79flWvL8.js.map
3254
+ export { cliProjectCommands, convertToTree, debug, formatTree, getClientUrl, maxKeyLength };
3255
+ //# sourceMappingURL=_internal-yQwMw2ht.js.map