@sanity/runtime-cli 12.3.0 → 13.0.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 (137) hide show
  1. package/README.md +190 -76
  2. package/dist/actions/blueprints/assets.d.ts +3 -1
  3. package/dist/actions/blueprints/assets.js +15 -5
  4. package/dist/actions/blueprints/blueprint.d.ts +2 -1
  5. package/dist/actions/blueprints/blueprint.js +3 -1
  6. package/dist/actions/blueprints/config.d.ts +5 -2
  7. package/dist/actions/blueprints/config.js +4 -4
  8. package/dist/actions/blueprints/logs-streaming.d.ts +4 -2
  9. package/dist/actions/blueprints/logs-streaming.js +5 -2
  10. package/dist/actions/blueprints/logs.d.ts +2 -1
  11. package/dist/actions/blueprints/logs.js +4 -2
  12. package/dist/actions/blueprints/resources.d.ts +2 -1
  13. package/dist/actions/blueprints/resources.js +2 -2
  14. package/dist/actions/blueprints/stacks.d.ts +12 -6
  15. package/dist/actions/blueprints/stacks.js +18 -11
  16. package/dist/actions/functions/dev.d.ts +2 -1
  17. package/dist/actions/functions/dev.js +2 -2
  18. package/dist/actions/functions/env/list.d.ts +2 -1
  19. package/dist/actions/functions/env/list.js +4 -2
  20. package/dist/actions/functions/env/remove.d.ts +2 -1
  21. package/dist/actions/functions/env/remove.js +4 -2
  22. package/dist/actions/functions/env/update.d.ts +2 -1
  23. package/dist/actions/functions/env/update.js +4 -2
  24. package/dist/actions/functions/logs.d.ts +4 -3
  25. package/dist/actions/functions/logs.js +10 -6
  26. package/dist/actions/node.d.ts +2 -1
  27. package/dist/actions/node.js +2 -2
  28. package/dist/actions/sanity/examples.d.ts +5 -2
  29. package/dist/actions/sanity/examples.js +6 -6
  30. package/dist/actions/sanity/projects.d.ts +7 -3
  31. package/dist/actions/sanity/projects.js +11 -7
  32. package/dist/baseCommands.d.ts +47 -7
  33. package/dist/baseCommands.js +90 -12
  34. package/dist/commands/blueprints/add.d.ts +3 -2
  35. package/dist/commands/blueprints/add.js +14 -10
  36. package/dist/commands/blueprints/config.d.ts +3 -2
  37. package/dist/commands/blueprints/config.js +12 -6
  38. package/dist/commands/blueprints/deploy.d.ts +3 -2
  39. package/dist/commands/blueprints/deploy.js +10 -4
  40. package/dist/commands/blueprints/destroy.d.ts +3 -2
  41. package/dist/commands/blueprints/destroy.js +10 -4
  42. package/dist/commands/blueprints/doctor.d.ts +6 -4
  43. package/dist/commands/blueprints/doctor.js +17 -14
  44. package/dist/commands/blueprints/info.d.ts +3 -2
  45. package/dist/commands/blueprints/info.js +11 -5
  46. package/dist/commands/blueprints/init.d.ts +3 -2
  47. package/dist/commands/blueprints/init.js +26 -20
  48. package/dist/commands/blueprints/logs.d.ts +3 -2
  49. package/dist/commands/blueprints/logs.js +10 -4
  50. package/dist/commands/blueprints/plan.d.ts +3 -2
  51. package/dist/commands/blueprints/plan.js +8 -4
  52. package/dist/commands/blueprints/stacks.d.ts +3 -2
  53. package/dist/commands/blueprints/stacks.js +10 -6
  54. package/dist/commands/functions/add.d.ts +3 -2
  55. package/dist/commands/functions/add.js +10 -4
  56. package/dist/commands/functions/dev.d.ts +3 -2
  57. package/dist/commands/functions/dev.js +16 -5
  58. package/dist/commands/functions/env/add.d.ts +4 -3
  59. package/dist/commands/functions/env/add.js +8 -4
  60. package/dist/commands/functions/env/list.d.ts +4 -3
  61. package/dist/commands/functions/env/list.js +8 -4
  62. package/dist/commands/functions/env/remove.d.ts +4 -3
  63. package/dist/commands/functions/env/remove.js +8 -4
  64. package/dist/commands/functions/logs.d.ts +5 -4
  65. package/dist/commands/functions/logs.js +11 -5
  66. package/dist/commands/functions/test.d.ts +5 -4
  67. package/dist/commands/functions/test.js +13 -6
  68. package/dist/cores/blueprints/config.d.ts +2 -5
  69. package/dist/cores/blueprints/config.js +9 -9
  70. package/dist/cores/blueprints/deploy.js +14 -17
  71. package/dist/cores/blueprints/destroy.d.ts +2 -5
  72. package/dist/cores/blueprints/destroy.js +6 -6
  73. package/dist/cores/blueprints/doctor.js +32 -29
  74. package/dist/cores/blueprints/info.js +5 -5
  75. package/dist/cores/blueprints/init.d.ts +3 -3
  76. package/dist/cores/blueprints/init.js +15 -8
  77. package/dist/cores/blueprints/logs.js +6 -7
  78. package/dist/cores/blueprints/plan.js +1 -0
  79. package/dist/cores/blueprints/stacks.d.ts +2 -5
  80. package/dist/cores/blueprints/stacks.js +4 -4
  81. package/dist/cores/functions/add.js +8 -3
  82. package/dist/cores/functions/dev.js +2 -2
  83. package/dist/cores/functions/env/add.js +3 -4
  84. package/dist/cores/functions/env/list.js +3 -4
  85. package/dist/cores/functions/env/remove.js +3 -4
  86. package/dist/cores/functions/index.d.ts +3 -9
  87. package/dist/cores/functions/logs.d.ts +3 -1
  88. package/dist/cores/functions/logs.js +19 -11
  89. package/dist/cores/functions/test.d.ts +3 -1
  90. package/dist/cores/functions/test.js +18 -10
  91. package/dist/cores/index.d.ts +4 -7
  92. package/dist/cores/index.js +3 -3
  93. package/dist/index.d.ts +1 -2
  94. package/dist/index.js +1 -2
  95. package/dist/server/app.d.ts +2 -1
  96. package/dist/server/app.js +4 -4
  97. package/dist/server/handlers/invoke.d.ts +2 -1
  98. package/dist/server/handlers/invoke.js +2 -2
  99. package/dist/server/static/components/app.css +0 -116
  100. package/dist/server/static/components/clear-button.js +1 -1
  101. package/dist/server/static/components/console-panel.js +27 -6
  102. package/dist/server/static/components/fetch-button.js +1 -1
  103. package/dist/server/static/components/filter-api-version.js +39 -3
  104. package/dist/server/static/components/filter-document-id.js +39 -3
  105. package/dist/server/static/components/filter-with-token.js +27 -4
  106. package/dist/server/static/components/filters.js +127 -62
  107. package/dist/server/static/components/function-list.js +33 -13
  108. package/dist/server/static/components/network-spinner.js +6 -4
  109. package/dist/server/static/components/payload-panel.js +46 -24
  110. package/dist/server/static/components/response-panel.js +33 -6
  111. package/dist/server/static/components/rule-panel.js +13 -4
  112. package/dist/server/static/components/run-panel.js +14 -7
  113. package/dist/server/static/components/select-dropdown.js +34 -5
  114. package/dist/server/static/components/shared-styles.js +31 -0
  115. package/dist/server/static/components/toggle-switch.js +11 -2
  116. package/dist/utils/display/blueprints-formatting.d.ts +2 -2
  117. package/dist/utils/display/blueprints-formatting.js +31 -26
  118. package/dist/utils/display/prompt.d.ts +5 -2
  119. package/dist/utils/display/prompt.js +5 -4
  120. package/dist/utils/find-function.d.ts +4 -0
  121. package/dist/utils/find-function.js +6 -0
  122. package/dist/utils/functions/fetch-document.d.ts +3 -2
  123. package/dist/utils/functions/fetch-document.js +7 -6
  124. package/dist/utils/index.d.ts +2 -0
  125. package/dist/utils/index.js +2 -0
  126. package/dist/utils/logger.d.ts +13 -0
  127. package/dist/utils/logger.js +61 -0
  128. package/dist/utils/other/github.d.ts +2 -1
  129. package/dist/utils/other/github.js +4 -2
  130. package/dist/utils/other/npmjs.d.ts +2 -1
  131. package/dist/utils/other/npmjs.js +4 -2
  132. package/dist/utils/traced-fetch.d.ts +35 -0
  133. package/dist/utils/traced-fetch.js +238 -0
  134. package/dist/utils/validated-token.d.ts +3 -2
  135. package/dist/utils/validated-token.js +6 -4
  136. package/oclif.manifest.json +455 -75
  137. package/package.json +14 -6
@@ -1,9 +1,11 @@
1
1
  import config from '../../config.js';
2
+ import { createTracedFetch } from '../../utils/traced-fetch.js';
2
3
  const { apiUrl } = config;
3
4
  export const projectsApiPath = `${apiUrl}v2021-06-07/projects`;
4
5
  export const orgsApiPath = `${apiUrl}v2021-06-07/organizations`;
5
- export async function listProjects({ token }) {
6
- const projectsFetch = await fetch(projectsApiPath, {
6
+ export async function listProjects({ token, logger, }) {
7
+ const fetchFn = createTracedFetch(logger);
8
+ const projectsFetch = await fetchFn(projectsApiPath, {
7
9
  method: 'GET',
8
10
  headers: {
9
11
  Authorization: `Bearer ${token}`,
@@ -17,8 +19,9 @@ export async function listProjects({ token }) {
17
19
  projects,
18
20
  };
19
21
  }
20
- export async function groupProjectsByOrganization({ token, }) {
21
- const projectsResponse = await listProjects({ token });
22
+ export async function groupProjectsByOrganization({ token, logger, }) {
23
+ const fetchFn = createTracedFetch(logger);
24
+ const projectsResponse = await listProjects({ token, logger });
22
25
  if (!projectsResponse.ok) {
23
26
  return {
24
27
  ok: false,
@@ -26,7 +29,7 @@ export async function groupProjectsByOrganization({ token, }) {
26
29
  organizations: [],
27
30
  };
28
31
  }
29
- const orgsFetch = await fetch(orgsApiPath, {
32
+ const orgsFetch = await fetchFn(orgsApiPath, {
30
33
  method: 'GET',
31
34
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
32
35
  });
@@ -48,11 +51,12 @@ export async function groupProjectsByOrganization({ token, }) {
48
51
  organizations: orgsWithProjects,
49
52
  };
50
53
  }
51
- export async function getProject({ token, scopeId, scopeType, }) {
54
+ export async function getProject({ token, scopeId, scopeType, logger, }) {
52
55
  if (scopeType !== 'project') {
53
56
  throw new Error('Scope type must be project');
54
57
  }
55
- const response = await fetch(`${projectsApiPath}/${scopeId}`, {
58
+ const fetchFn = createTracedFetch(logger);
59
+ const response = await fetchFn(`${projectsApiPath}/${scopeId}`, {
56
60
  method: 'GET',
57
61
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
58
62
  });
@@ -2,19 +2,56 @@ import type { Interfaces } from '@oclif/core';
2
2
  import { Command } from '@oclif/core';
3
3
  import type { ReadBlueprintResult } from './actions/blueprints/blueprint.js';
4
4
  import type { AuthParams, ScopeType, Stack } from './utils/types.js';
5
- export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BlueprintCommand)['baseFlags'] & T['flags']>;
5
+ export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof RuntimeCommand)['baseFlags'] & T['flags']>;
6
6
  export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
7
+ export declare const baseFlags: {
8
+ json: Interfaces.BooleanFlag<boolean>;
9
+ path: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
10
+ trace: Interfaces.BooleanFlag<boolean>;
11
+ verbose: Interfaces.BooleanFlag<boolean>;
12
+ };
13
+ /**
14
+ * @description Unhides a flag by setting its hidden property to false
15
+ * Also makes oclif's types happy when destructuring the flag
16
+ */
17
+ export declare function unhide<T>(flag: T): T;
18
+ /**
19
+ * @description Guarantees flags and args.
20
+ * Also centralizes baseFlags and enables oclif's built-in --json for all subclasses.
21
+ * @extends Command
22
+ */
23
+ export declare abstract class RuntimeCommand<T extends typeof Command> extends Command {
24
+ protected flags: Flags<T>;
25
+ protected args: Args<T>;
26
+ static baseFlags: {
27
+ json: Interfaces.BooleanFlag<boolean>;
28
+ path: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
29
+ trace: Interfaces.BooleanFlag<boolean>;
30
+ verbose: Interfaces.BooleanFlag<boolean>;
31
+ };
32
+ static enableJsonFlag: boolean;
33
+ /**
34
+ * Generates help text for this command class
35
+ * @param bin - The bin name to use for the help text; e.g. 'sanity', defaults to 'sanity-run'
36
+ * @param commandId - The sub-command to use for the help text; optional but recommended for better help text
37
+ * @returns The oclif-styled help text for the command
38
+ * @example const helpText = InfoCommand.getHelpText('sanity', 'blueprints info')
39
+ */
40
+ static getHelpText(bin?: string, commandId?: string): string;
41
+ init(): Promise<void>;
42
+ }
7
43
  /**
8
44
  * @description Guarantees flags, args, sanityToken, and blueprint.
9
45
  * Blueprint parser errors are logged and the command exits with an error
10
- * @extends Command
46
+ * @extends RuntimeCommand
11
47
  */
12
- export declare abstract class BlueprintCommand<T extends typeof Command> extends Command {
48
+ export declare abstract class LocalBlueprintCommand<T extends typeof Command> extends RuntimeCommand<T> {
13
49
  protected sanityToken: string;
14
50
  protected blueprint: ReadBlueprintResult;
15
- protected flags: Flags<T>;
16
- protected args: Args<T>;
17
51
  static baseFlags: {
52
+ json: Interfaces.BooleanFlag<boolean>;
53
+ path: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
54
+ trace: Interfaces.BooleanFlag<boolean>;
18
55
  verbose: Interfaces.BooleanFlag<boolean>;
19
56
  };
20
57
  init(): Promise<void>;
@@ -26,15 +63,18 @@ export declare abstract class BlueprintCommand<T extends typeof Command> extends
26
63
  /**
27
64
  * @description Guarantees flags, args, sanityToken, blueprint, scopeType, scopeId, stackId, auth, and deployedStack.
28
65
  * If scope or stack is missing, the command exits with an error
29
- * @extends BlueprintCommand
66
+ * @extends LocalBlueprintCommand
30
67
  */
31
- export declare abstract class DeployedBlueprintCommand<T extends typeof Command> extends BlueprintCommand<T> {
68
+ export declare abstract class DeployedStackCommand<T extends typeof Command> extends LocalBlueprintCommand<T> {
32
69
  protected auth: AuthParams;
33
70
  protected deployedStack: Stack;
34
71
  protected scopeType: ScopeType;
35
72
  protected scopeId: string;
36
73
  protected stackId: string;
37
74
  static baseFlags: {
75
+ json: Interfaces.BooleanFlag<boolean>;
76
+ path: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
77
+ trace: Interfaces.BooleanFlag<boolean>;
38
78
  verbose: Interfaces.BooleanFlag<boolean>;
39
79
  };
40
80
  init(): Promise<void>;
@@ -1,24 +1,89 @@
1
1
  // * https://oclif.io/docs/base_class
2
- import { Command, Flags as OclifFlags } from '@oclif/core';
2
+ import { Command, CommandHelp, Flags as OclifFlags } from '@oclif/core';
3
3
  import { initBlueprintConfig, initDeployedBlueprintConfig } from './cores/index.js';
4
- const baseFlags = {
4
+ import { Logger } from './utils/logger.js';
5
+ const hidden = true;
6
+ export const baseFlags = {
7
+ json: OclifFlags.boolean({
8
+ // override defaults from oclif's built-in --json flag
9
+ description: 'Format output as json.',
10
+ hidden,
11
+ }),
12
+ path: OclifFlags.string({
13
+ description: 'Path to the directory containing the Blueprint',
14
+ hidden,
15
+ }),
16
+ trace: OclifFlags.boolean({
17
+ description: 'Trace output',
18
+ default: false,
19
+ hidden,
20
+ }),
5
21
  verbose: OclifFlags.boolean({
6
22
  description: 'Verbose output',
7
23
  default: false,
8
- hidden: true, // prevent help output on all commands
24
+ hidden,
9
25
  }),
10
26
  };
11
27
  /**
12
- * @description Guarantees flags, args, sanityToken, and blueprint.
13
- * Blueprint parser errors are logged and the command exits with an error
28
+ * @description Unhides a flag by setting its hidden property to false
29
+ * Also makes oclif's types happy when destructuring the flag
30
+ */
31
+ export function unhide(flag) {
32
+ return { ...flag, hidden: false };
33
+ }
34
+ /**
35
+ * @description Guarantees flags and args.
36
+ * Also centralizes baseFlags and enables oclif's built-in --json for all subclasses.
14
37
  * @extends Command
15
38
  */
16
- export class BlueprintCommand extends Command {
17
- sanityToken;
18
- blueprint;
39
+ export class RuntimeCommand extends Command {
19
40
  flags;
20
41
  args;
21
42
  static baseFlags = baseFlags;
43
+ static enableJsonFlag = true; // oclif's built-in --json flag
44
+ /**
45
+ * Generates help text for this command class
46
+ * @param bin - The bin name to use for the help text; e.g. 'sanity', defaults to 'sanity-run'
47
+ * @param commandId - The sub-command to use for the help text; optional but recommended for better help text
48
+ * @returns The oclif-styled help text for the command
49
+ * @example const helpText = InfoCommand.getHelpText('sanity', 'blueprints info')
50
+ */
51
+ static getHelpText(bin = 'sanity-run', commandId) {
52
+ // biome-ignore lint/complexity/noThisInStatic: this is this command class - not confusing
53
+ const thisClass = this;
54
+ const rawArgs = thisClass.args || {};
55
+ const args = Object.entries(rawArgs).reduce((acc, [name, arg]) => {
56
+ acc[name] = { ...arg, name };
57
+ return acc;
58
+ }, {});
59
+ const commandLoadable = {
60
+ //! required properties
61
+ id: commandId || thisClass.id || '',
62
+ flags: thisClass.flags || {},
63
+ args,
64
+ aliases: thisClass.aliases || [],
65
+ hidden: thisClass.hidden || false,
66
+ hiddenAliases: thisClass.hiddenAliases || [],
67
+ load: async () => thisClass,
68
+ //* optional properties
69
+ // bin, // seems to not be used in the CommandHelp class
70
+ // thisClass, // doesn't change the help text
71
+ help: thisClass.help,
72
+ usage: thisClass.usage,
73
+ examples: thisClass.examples,
74
+ description: thisClass.description,
75
+ summary: thisClass.summary,
76
+ state: thisClass.state,
77
+ deprecateAliases: thisClass.deprecateAliases,
78
+ deprecationOptions: thisClass.deprecationOptions,
79
+ strict: thisClass.strict,
80
+ hasDynamicHelp: thisClass.hasDynamicHelp,
81
+ };
82
+ const commandHelp = new CommandHelp(commandLoadable, { bin }, {
83
+ maxWidth: 120,
84
+ });
85
+ return commandHelp.generate();
86
+ }
22
87
  async init() {
23
88
  const { args, flags } = await this.parse({
24
89
  flags: this.ctor.flags,
@@ -30,9 +95,22 @@ export class BlueprintCommand extends Command {
30
95
  this.flags = flags;
31
96
  this.args = args;
32
97
  await super.init();
98
+ }
99
+ }
100
+ /**
101
+ * @description Guarantees flags, args, sanityToken, and blueprint.
102
+ * Blueprint parser errors are logged and the command exits with an error
103
+ * @extends RuntimeCommand
104
+ */
105
+ export class LocalBlueprintCommand extends RuntimeCommand {
106
+ sanityToken;
107
+ blueprint;
108
+ static baseFlags = baseFlags;
109
+ async init() {
110
+ await super.init();
33
111
  const result = await initBlueprintConfig({
34
112
  bin: this.config.bin,
35
- log: (msg) => this.log(msg),
113
+ log: Logger(this.log.bind(this), this.flags),
36
114
  });
37
115
  if (!result.ok) {
38
116
  this.error(result.error);
@@ -53,9 +131,9 @@ export class BlueprintCommand extends Command {
53
131
  /**
54
132
  * @description Guarantees flags, args, sanityToken, blueprint, scopeType, scopeId, stackId, auth, and deployedStack.
55
133
  * If scope or stack is missing, the command exits with an error
56
- * @extends BlueprintCommand
134
+ * @extends LocalBlueprintCommand
57
135
  */
58
- export class DeployedBlueprintCommand extends BlueprintCommand {
136
+ export class DeployedStackCommand extends LocalBlueprintCommand {
59
137
  auth;
60
138
  deployedStack;
61
139
  scopeType;
@@ -67,7 +145,7 @@ export class DeployedBlueprintCommand extends BlueprintCommand {
67
145
  const result = await initDeployedBlueprintConfig({
68
146
  bin: this.config.bin,
69
147
  blueprint: this.blueprint,
70
- log: (msg) => this.log(msg),
148
+ log: Logger(this.log.bind(this), this.flags),
71
149
  token: this.sanityToken,
72
150
  validateToken: false,
73
151
  });
@@ -3,8 +3,9 @@
3
3
  * @deprecated Use `functions add` instead.
4
4
  * We're in the process of deprecating the `blueprints add` command.
5
5
  */
6
- import { BlueprintCommand } from '../../baseCommands.js';
7
- export default class AddCommand extends BlueprintCommand<typeof AddCommand> {
6
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
7
+ export default class AddCommand extends LocalBlueprintCommand<typeof AddCommand> {
8
+ static summary: string;
8
9
  static description: string;
9
10
  static examples: string[];
10
11
  static args: {
@@ -4,15 +4,19 @@
4
4
  * We're in the process of deprecating the `blueprints add` command.
5
5
  */
6
6
  import { Args, Flags } from '@oclif/core';
7
- import { BlueprintCommand } from '../../baseCommands.js';
7
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
8
8
  import { functionAddCore } from '../../cores/functions/index.js';
9
+ import { Logger } from '../../utils/logger.js';
9
10
  // import {warn} from '../../utils/display/presenters.js'
10
- export default class AddCommand extends BlueprintCommand {
11
+ export default class AddCommand extends LocalBlueprintCommand {
11
12
  // static state = 'deprecated'
12
13
  // static deprecationOptions = {
13
14
  // message: '`blueprints add` is deprecated. Use `functions add` instead.',
14
15
  // }
15
- static description = 'Add a Resource to a Blueprint';
16
+ static summary = 'Add a function resource to a Blueprint';
17
+ static description = `Scaffolds a new Sanity Function in your Blueprint. Functions are serverless handlers triggered by document events (create, update, delete, publish) or media library events.
18
+
19
+ After adding a function, use 'functions dev' to test locally, then 'blueprints deploy' to publish it.`;
16
20
  static examples = [
17
21
  '<%= config.bin %> <%= command.id %> function',
18
22
  '<%= config.bin %> <%= command.id %> function --helpers',
@@ -22,19 +26,19 @@ export default class AddCommand extends BlueprintCommand {
22
26
  ];
23
27
  static args = {
24
28
  type: Args.string({
25
- description: 'Type of Resource to add (e.g. function)',
29
+ description: 'Type of resource to add (only "function" is supported)',
26
30
  options: ['function'],
27
31
  required: true,
28
32
  }),
29
33
  };
30
34
  static flags = {
31
35
  example: Flags.string({
32
- description: 'Example to use for the Resource',
36
+ description: 'Example to use for the function resource. Discover examples at https://www.sanity.io/exchange/type=recipes/by=sanity',
33
37
  aliases: ['recipe'],
34
38
  exclusive: ['name', 'fn-type', 'language', 'javascript', 'fn-helpers', 'fn-installer'],
35
39
  }),
36
40
  name: Flags.string({
37
- description: 'Name of the Resource to add',
41
+ description: 'Name of the resource to add',
38
42
  char: 'n',
39
43
  }),
40
44
  'fn-type': Flags.string({
@@ -54,7 +58,7 @@ export default class AddCommand extends BlueprintCommand {
54
58
  dependsOn: ['name'],
55
59
  }),
56
60
  language: Flags.string({
57
- description: 'Language of the new Function',
61
+ description: 'Language of the new function',
58
62
  aliases: ['function-language', 'fn-language', 'lang'],
59
63
  options: ['ts', 'js'],
60
64
  default: 'ts',
@@ -65,12 +69,12 @@ export default class AddCommand extends BlueprintCommand {
65
69
  exclusive: ['language'],
66
70
  }),
67
71
  'fn-helpers': Flags.boolean({
68
- description: 'Add helpers to the new Function',
72
+ description: 'Add helpers to the new function',
69
73
  aliases: ['function-helpers', 'helpers'],
70
74
  allowNo: true,
71
75
  }),
72
76
  'fn-installer': Flags.string({
73
- description: 'How to install the @sanity/functions helpers',
77
+ description: 'Which package manager to use when installing the @sanity/functions helpers',
74
78
  aliases: ['function-installer', 'installer'],
75
79
  options: ['skip', 'npm', 'pnpm', 'yarn'],
76
80
  }),
@@ -92,7 +96,7 @@ export default class AddCommand extends BlueprintCommand {
92
96
  // )
93
97
  const { success, error } = await functionAddCore({
94
98
  bin,
95
- log: (msg) => this.log(msg),
99
+ log: Logger(this.log.bind(this), this.flags),
96
100
  blueprint,
97
101
  flags: {
98
102
  example: flags.example,
@@ -1,5 +1,6 @@
1
- import { BlueprintCommand } from '../../baseCommands.js';
2
- export default class ConfigCommand extends BlueprintCommand<typeof ConfigCommand> {
1
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ export default class ConfigCommand extends LocalBlueprintCommand<typeof ConfigCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: string[];
5
6
  static flags: {
@@ -1,8 +1,14 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { BlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
3
3
  import { blueprintConfigCore } from '../../cores/blueprints/config.js';
4
- export default class ConfigCommand extends BlueprintCommand {
5
- static description = 'View or edit Blueprint configuration';
4
+ import { Logger } from '../../utils/logger.js';
5
+ export default class ConfigCommand extends LocalBlueprintCommand {
6
+ static summary = 'View or edit the local Blueprint configuration';
7
+ static description = `Manages the local Blueprint configuration, which links your Blueprint to a Sanity project and Stack.
8
+
9
+ Without flags, displays the current configuration. Use --edit to interactively modify settings, or combine --edit with ID flags to update values directly (useful for scripting and automation).
10
+
11
+ If you need to switch your Blueprint to a different Stack, use --edit --stack-id.`;
6
12
  static examples = [
7
13
  '<%= config.bin %> <%= command.id %>',
8
14
  '<%= config.bin %> <%= command.id %> --edit',
@@ -16,12 +22,12 @@ export default class ConfigCommand extends BlueprintCommand {
16
22
  default: false,
17
23
  }),
18
24
  'project-id': Flags.string({
19
- description: 'Directly set the Project ID in the configuration. Requires --edit flag',
25
+ description: 'Directly set the project ID in the configuration. Requires --edit flag',
20
26
  aliases: ['project', 'projectId'],
21
27
  dependsOn: ['edit'],
22
28
  }),
23
29
  'organization-id': Flags.string({
24
- description: 'Directly set the Organization ID in the configuration. Requires --edit flag',
30
+ description: 'Directly set the organization ID in the configuration. Requires --edit flag',
25
31
  aliases: ['organization', 'organizationId', 'org'],
26
32
  dependsOn: ['edit'],
27
33
  }),
@@ -34,7 +40,7 @@ export default class ConfigCommand extends BlueprintCommand {
34
40
  async run() {
35
41
  const { success, error } = await blueprintConfigCore({
36
42
  bin: this.config.bin,
37
- log: (message) => this.log(message),
43
+ log: Logger(this.log.bind(this), this.flags),
38
44
  blueprint: this.blueprint,
39
45
  token: this.sanityToken,
40
46
  flags: this.flags,
@@ -1,5 +1,6 @@
1
- import { DeployedBlueprintCommand } from '../../baseCommands.js';
2
- export default class DeployCommand extends DeployedBlueprintCommand<typeof DeployCommand> {
1
+ import { DeployedStackCommand } from '../../baseCommands.js';
2
+ export default class DeployCommand extends DeployedStackCommand<typeof DeployCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: string[];
5
6
  static flags: {
@@ -1,8 +1,14 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { DeployedBlueprintCommand } from '../../baseCommands.js';
2
+ import { DeployedStackCommand } from '../../baseCommands.js';
3
3
  import { blueprintDeployCore } from '../../cores/blueprints/deploy.js';
4
- export default class DeployCommand extends DeployedBlueprintCommand {
5
- static description = 'Deploy a Blueprint';
4
+ import { Logger } from '../../utils/logger.js';
5
+ export default class DeployCommand extends DeployedStackCommand {
6
+ static summary = 'Deploy the local Blueprint to the remote Stack';
7
+ static description = `Pushes your local Blueprint configuration to the remote Stack; provisioning, updating, or destroying resources as needed. This is the primary command for applying infrastructure changes.
8
+
9
+ Before deploying, run 'blueprints plan' to preview changes. After deployment, use 'blueprints info' to verify Stack status or 'blueprints logs' to monitor activity.
10
+
11
+ Use --no-wait to queue the deployment and return immediately without waiting for completion.`;
6
12
  static examples = [
7
13
  '<%= config.bin %> <%= command.id %>',
8
14
  '<%= config.bin %> <%= command.id %> --no-wait',
@@ -16,7 +22,7 @@ export default class DeployCommand extends DeployedBlueprintCommand {
16
22
  async run() {
17
23
  const { success, error } = await blueprintDeployCore({
18
24
  bin: this.config.bin,
19
- log: (message) => this.log(message),
25
+ log: Logger(this.log.bind(this), this.flags),
20
26
  auth: this.auth,
21
27
  stackId: this.stackId,
22
28
  scopeType: this.scopeType,
@@ -1,5 +1,6 @@
1
- import { BlueprintCommand } from '../../baseCommands.js';
2
- export default class DestroyCommand extends BlueprintCommand<typeof DestroyCommand> {
1
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ export default class DestroyCommand extends LocalBlueprintCommand<typeof DestroyCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: string[];
5
6
  static flags: {
@@ -1,8 +1,14 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { BlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand } from '../../baseCommands.js';
3
3
  import { blueprintDestroyCore } from '../../cores/blueprints/destroy.js';
4
- export default class DestroyCommand extends BlueprintCommand {
5
- static description = 'Destroy a Blueprint Stack deployment and its resources (will not delete local files)';
4
+ import { Logger } from '../../utils/logger.js';
5
+ export default class DestroyCommand extends LocalBlueprintCommand {
6
+ static summary = 'Destroy the remote Stack deployment and its resources (will not delete local files)';
7
+ static description = `Permanently removes the remote Stack and all its provisioned resources. Your local Blueprint files remain untouched, allowing you to redeploy later with 'blueprints init' + 'blueprints deploy'.
8
+
9
+ This is a destructive operation. You will be prompted to confirm unless --force is specified.
10
+
11
+ Use this to clean up test environments or decommission a Stack you no longer need.`;
6
12
  static examples = [
7
13
  '<%= config.bin %> <%= command.id %>',
8
14
  '<%= config.bin %> <%= command.id %> --stack-id <stackId> --project-id <projectId> --force --no-wait',
@@ -37,7 +43,7 @@ export default class DestroyCommand extends BlueprintCommand {
37
43
  async run() {
38
44
  const { success, error } = await blueprintDestroyCore({
39
45
  bin: this.config.bin,
40
- log: (message) => this.log(message),
46
+ log: Logger(this.log.bind(this), this.flags),
41
47
  token: this.sanityToken,
42
48
  blueprint: this.blueprint,
43
49
  flags: this.flags,
@@ -1,11 +1,13 @@
1
- import { Command } from '@oclif/core';
2
- export default class DoctorCommand extends Command {
1
+ import { RuntimeCommand } from '../../baseCommands.js';
2
+ export default class DoctorCommand extends RuntimeCommand<typeof DoctorCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: never[];
5
6
  static flags: {
6
- verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
7
  path: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
8
  fix: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
11
  };
10
- run(): Promise<void>;
12
+ run(): Promise<Record<string, unknown> | undefined>;
11
13
  }
@@ -1,32 +1,35 @@
1
- import { Command, Flags } from '@oclif/core';
1
+ import { Flags } from '@oclif/core';
2
+ import { baseFlags, RuntimeCommand, unhide } from '../../baseCommands.js';
2
3
  import config from '../../config.js';
3
4
  import { blueprintDoctorCore } from '../../cores/blueprints/doctor.js';
4
- export default class DoctorCommand extends Command {
5
- static description = 'Diagnose potential issues with Blueprint configuration';
5
+ import { Logger } from '../../utils/logger.js';
6
+ export default class DoctorCommand extends RuntimeCommand {
7
+ static summary = 'Diagnose potential issues with local Blueprint and remote Stack configuration';
8
+ static description = `Analyzes your local Blueprint and remote Stack configuration for common issues, such as missing authentication, invalid project references, or misconfigured resources.
9
+
10
+ Run this command when encountering errors with other Blueprint commands. Use --fix to interactively resolve detected issues.`;
11
+ // TODO: add "Supports --json for programmatic consumption of diagnostic results." to help text
6
12
  static examples = [];
7
13
  static flags = {
8
- verbose: Flags.boolean({
9
- description: 'Provide detailed information about issues',
10
- default: false,
11
- }),
12
- path: Flags.string({
13
- description: 'Path to the Blueprint configuration file',
14
- }),
14
+ path: unhide(baseFlags.path),
15
15
  fix: Flags.boolean({
16
16
  description: 'Interactively fix configuration issues',
17
17
  default: false,
18
18
  }),
19
+ json: unhide(baseFlags.json),
20
+ verbose: unhide(baseFlags.verbose),
19
21
  };
20
22
  async run() {
21
- const { flags } = await this.parse(DoctorCommand);
22
23
  const { token } = config;
23
- const { success, error } = await blueprintDoctorCore({
24
+ const result = await blueprintDoctorCore({
24
25
  bin: this.config.bin,
25
- log: (message) => this.log(message),
26
+ log: Logger(this.log.bind(this), this.flags),
26
27
  token,
27
- flags,
28
+ flags: this.flags,
28
29
  });
30
+ const { success, error } = result;
29
31
  if (!success)
30
32
  this.error(error);
33
+ return result.data;
31
34
  }
32
35
  }
@@ -1,5 +1,6 @@
1
- import { DeployedBlueprintCommand } from '../../baseCommands.js';
2
- export default class InfoCommand extends DeployedBlueprintCommand<typeof InfoCommand> {
1
+ import { DeployedStackCommand } from '../../baseCommands.js';
2
+ export default class InfoCommand extends DeployedStackCommand<typeof InfoCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: string[];
5
6
  static flags: {
@@ -1,21 +1,27 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { DeployedBlueprintCommand } from '../../baseCommands.js';
2
+ import { DeployedStackCommand } from '../../baseCommands.js';
3
3
  import { blueprintInfoCore } from '../../cores/blueprints/info.js';
4
- export default class InfoCommand extends DeployedBlueprintCommand {
5
- static description = 'Show information about a Blueprint Stack deployment';
4
+ import { Logger } from '../../utils/logger.js';
5
+ export default class InfoCommand extends DeployedStackCommand {
6
+ static summary = "Show information about the local Blueprint's remote Stack deployment";
7
+ static description = `Displays the current state and metadata of your remote Stack deployment, including deployed resources, status, and configuration.
8
+
9
+ Use this command to verify a deployment succeeded, check what resources are live, or confirm which Stack your local Blueprint is connected to.
10
+
11
+ Run 'blueprints stacks' to see all available Stacks in your project or organization.`;
6
12
  static examples = [
7
13
  '<%= config.bin %> <%= command.id %>',
8
14
  '<%= config.bin %> <%= command.id %> --id <stackId>',
9
15
  ];
10
16
  static flags = {
11
17
  id: Flags.string({
12
- description: 'Stack ID to show info for (defaults to current Stack)',
18
+ description: 'Stack ID to show info for (defaults to the current Stack)',
13
19
  }),
14
20
  };
15
21
  async run() {
16
22
  const { success, error } = await blueprintInfoCore({
17
23
  bin: this.config.bin,
18
- log: (message) => this.log(message),
24
+ log: Logger(this.log.bind(this), this.flags),
19
25
  auth: this.auth,
20
26
  stackId: this.stackId,
21
27
  deployedStack: this.deployedStack,
@@ -1,5 +1,6 @@
1
- import { Command } from '@oclif/core';
2
- export default class InitCommand extends Command {
1
+ import { RuntimeCommand } from '../../baseCommands.js';
2
+ export default class InitCommand extends RuntimeCommand<typeof InitCommand> {
3
+ static summary: string;
3
4
  static description: string;
4
5
  static examples: string[];
5
6
  static args: {