@sanity/runtime-cli 3.2.0 → 4.1.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.
@@ -1,10 +1,11 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import highlight from 'color-json';
3
3
  import inquirer from 'inquirer';
4
- import { readConfigFile, writeConfigFile } from '../../actions/blueprints/blueprint.js';
4
+ import { readBlueprintOnDisk, writeConfigFile } from '../../actions/blueprints/blueprint.js';
5
5
  import { listProjects } from '../../actions/blueprints/projects.js';
6
6
  import { listStacks } from '../../actions/blueprints/stacks.js';
7
7
  import config from '../../config.js';
8
+ import { bold, dim, niceId } from '../../utils/display/colors.js';
8
9
  const { token } = config;
9
10
  export default class Config extends Command {
10
11
  static description = 'View or edit Blueprint configuration';
@@ -20,12 +21,15 @@ export default class Config extends Command {
20
21
  };
21
22
  async run() {
22
23
  const { flags } = await this.parse(Config);
23
- const config = readConfigFile();
24
- if (!config) {
25
- this.error('No configuration found. Run `sanity blueprints init` first.');
24
+ const blueprint = await readBlueprintOnDisk();
25
+ const { stackId: configStackId, projectId: configProjectId, configPath, fileInfo } = blueprint;
26
+ const { extension: blueprintExtension, blueprintFilePath } = fileInfo;
27
+ if (!configStackId && !configProjectId) {
28
+ this.log('Project and Stack configuration is missing.');
26
29
  }
27
- this.log('\nCurrent configuration:');
28
- this.log(highlight(JSON.stringify(config, null, 2)));
30
+ this.log(bold('Current configuration:'));
31
+ this.log(`Sanity Project: ${niceId(configProjectId)}`);
32
+ this.log(`Blueprint Stack: ${niceId(configStackId)}`);
29
33
  if (!flags.edit)
30
34
  return;
31
35
  const { ok, projects, error } = await listProjects({ token });
@@ -34,9 +38,9 @@ export default class Config extends Command {
34
38
  if (projects.length === 0) {
35
39
  this.error('No projects found. Please create a project in Sanity.io first.');
36
40
  }
37
- const projectChoices = projects.map(({ displayName, id }) => ({
38
- name: `${displayName} <${id}>`,
39
- value: id,
41
+ const projectChoices = projects.map(({ displayName, id: projectId }) => ({
42
+ name: `"${displayName}" ${niceId(projectId)}`,
43
+ value: projectId,
40
44
  }));
41
45
  const { projectId } = await inquirer.prompt([
42
46
  {
@@ -44,7 +48,7 @@ export default class Config extends Command {
44
48
  name: 'projectId',
45
49
  message: 'Select your Sanity project:',
46
50
  choices: projectChoices,
47
- default: config.projectId,
51
+ default: configProjectId,
48
52
  },
49
53
  ]);
50
54
  const auth = { token, projectId };
@@ -54,22 +58,30 @@ export default class Config extends Command {
54
58
  this.error(stacksError ?? 'Unknown error listing stacks');
55
59
  let stackId;
56
60
  if (stacks.length > 0) {
57
- const stackChoices = stacks.map(({ name, id }) => ({
58
- name: `${name} <${id}>`,
59
- value: id,
61
+ const stackChoices = stacks.map((s) => ({
62
+ name: `"${s.name}" ${niceId(s.id)} ${dim(`(${s.resources.length} res)`)}`,
63
+ value: s.id,
60
64
  }));
65
+ stackChoices.push({ name: 'Unset Stack association', value: 'unset' });
61
66
  const { stackId: selectedStackId } = await inquirer.prompt([
62
67
  {
63
68
  type: 'list',
64
69
  name: 'stackId',
65
70
  message: 'Select a stack:',
66
71
  choices: stackChoices,
67
- default: config.stackId,
72
+ default: configStackId,
68
73
  },
69
74
  ]);
70
- stackId = selectedStackId;
75
+ stackId = selectedStackId === 'unset' ? undefined : selectedStackId;
76
+ }
77
+ try {
78
+ // update or create .blueprint/config.json
79
+ writeConfigFile({ projectId, stackId });
80
+ this.log('Configuration updated successfully.');
81
+ }
82
+ catch (error) {
83
+ this.log('Unable to dynamically update config. Use these values in your blueprint:');
84
+ this.log(highlight(JSON.stringify({ metadata: { projectId, stackId } }, null, 2)));
71
85
  }
72
- writeConfigFile({ projectId, stackId });
73
- this.log('\nConfiguration updated successfully.');
74
86
  }
75
87
  }
@@ -2,5 +2,8 @@ import { Command } from '@oclif/core';
2
2
  export default class Deploy extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
+ static flags: {
6
+ 'no-wait': import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
5
8
  run(): Promise<void>;
6
9
  }
@@ -1,55 +1,37 @@
1
- import { Command } from '@oclif/core';
2
- import inquirer from 'inquirer';
1
+ import { setTimeout } from 'node:timers/promises';
2
+ import { Command, Flags } from '@oclif/core';
3
3
  import Spinner from 'yocto-spinner';
4
4
  import { stashAsset } from '../../actions/blueprints/assets.js';
5
- import { readBlueprintOnDisk, writeConfigFile } from '../../actions/blueprints/blueprint.js';
6
- import { createStack, updateStack } from '../../actions/blueprints/stacks.js';
5
+ import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
6
+ import { getStack, updateStack } from '../../actions/blueprints/stacks.js';
7
7
  import config from '../../config.js';
8
- import { bold, green, red, yellow } from '../../utils/display/colors.js';
8
+ import { bold, niceId, red } from '../../utils/display/colors.js';
9
9
  import { isLocalFunctionResource } from '../../utils/types.js';
10
10
  const { token } = config;
11
11
  export default class Deploy extends Command {
12
12
  static description = 'Deploy a Blueprint';
13
13
  static examples = ['<%= config.bin %> <%= command.id %>'];
14
+ static flags = {
15
+ 'no-wait': Flags.boolean({
16
+ description: 'Do not wait for deployment to complete',
17
+ default: false,
18
+ }),
19
+ };
14
20
  async run() {
15
- const { errors, projectId: configuredProjectId, stackId, parsedBlueprint: { resources }, deployedStack, } = await readBlueprintOnDisk({ getStack: true, token });
21
+ const { flags } = await this.parse(Deploy);
22
+ const { errors, projectId, stackId, parsedBlueprint: { resources }, deployedStack, } = await readBlueprintOnDisk({ getStack: true, token });
16
23
  if (errors.length > 0) {
17
24
  // printErrors(errors) // TODO: error printer in formatting
18
25
  this.log('Blueprint parse errors:');
19
26
  console.dir(errors, { depth: null });
20
27
  return;
21
28
  }
22
- if (stackId && !deployedStack)
23
- this.error('Stack ID defined but deployed stack not found');
24
- let projectId = configuredProjectId;
25
- if (!projectId) {
26
- this.log('No Sanity Project context found in Blueprint configuration.');
27
- const { maybeProjectId } = await inquirer.prompt([
28
- {
29
- type: 'input',
30
- name: 'maybeProjectId',
31
- message: 'Enter Sanity Project ID:',
32
- },
33
- ]);
34
- projectId = maybeProjectId;
29
+ if (!deployedStack || !stackId || !projectId) {
30
+ this.error('Before deploying, run `sanity blueprints init`');
35
31
  }
36
- if (!projectId)
37
- this.error('Sanity Project context is required');
32
+ if (stackId !== deployedStack.id)
33
+ this.error('Stack ID mismatch');
38
34
  const auth = { token, projectId };
39
- let name = deployedStack?.name;
40
- if (!name) {
41
- const { stackName } = await inquirer.prompt([
42
- {
43
- type: 'input',
44
- name: 'stackName',
45
- message: 'Enter stack name:',
46
- validate: (input) => input.length > 0 || 'Stack name is required',
47
- },
48
- ]);
49
- name = stackName;
50
- }
51
- if (!name)
52
- this.error('Stack name is required');
53
35
  const validResources = resources?.filter((r) => r.type);
54
36
  const functionResources = validResources?.filter(isLocalFunctionResource);
55
37
  // First stash all function assets
@@ -60,7 +42,7 @@ export default class Deploy extends Command {
60
42
  if (result.success && result.assetId) {
61
43
  const src = resource.src;
62
44
  resource.src = result.assetId; // TODO: properly reference asset - for now, the API expects the assetId
63
- fnSpinner.success(`${resource.name} <${yellow(result.assetId)}>`);
45
+ fnSpinner.success(`${resource.name} ${niceId(result.assetId)}`);
64
46
  this.log(` Source: ${src}`);
65
47
  }
66
48
  else {
@@ -71,23 +53,44 @@ export default class Deploy extends Command {
71
53
  }
72
54
  }
73
55
  const stackPayload = {
74
- name,
75
56
  projectId,
57
+ name: deployedStack.name,
76
58
  document: { resources: validResources },
77
59
  };
78
60
  this.debug('BLUEPRINT DOCUMENT:', stackPayload);
79
61
  const spinner = Spinner({ text: 'Deploying stack...' }).start();
80
- const { ok: deployOk, stack, error: deployError, } = deployedStack
81
- ? await updateStack({ stackId: deployedStack.id, stackPayload, auth })
82
- : await createStack({ stackPayload, auth });
62
+ const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId: deployedStack.id, stackPayload, auth });
83
63
  this.debug('STACK RESPONSE:', stack);
84
64
  if (deployOk) {
85
- spinner.success(`${green('Success!')} Stack "${bold(stack.name)}" ${deployedStack ? 'updated' : 'created'} <${yellow(stack.id)}>`);
86
- writeConfigFile({
87
- projectId,
88
- stackId: stack.id,
89
- });
90
- this.log('\nUse `sanity blueprints info` to check deployment status');
65
+ spinner.success(`Stack "${bold(stack.name)}" ${niceId(stack.id)} deployment started!`);
66
+ if (!flags['no-wait']) {
67
+ const waitSpinner = Spinner({ text: 'Waiting for deployment to complete...' }).start();
68
+ while (true) {
69
+ // TODO: watch logs and print those while polling
70
+ const { ok, stack: currentStack } = await getStack({ stackId: stack.id, auth });
71
+ if (!ok) {
72
+ waitSpinner.error('Failed to check deployment status');
73
+ break;
74
+ }
75
+ const operation = currentStack.recentOperation;
76
+ if (!operation) {
77
+ waitSpinner.error('No operation found');
78
+ break;
79
+ }
80
+ if (operation.status === 'COMPLETED') {
81
+ waitSpinner.success('Deployment completed successfully');
82
+ break;
83
+ }
84
+ if (operation.status === 'FAILED') {
85
+ waitSpinner.error('Deployment failed');
86
+ break;
87
+ }
88
+ await setTimeout(1000);
89
+ }
90
+ }
91
+ else {
92
+ this.log('Use `sanity blueprints info` to check deployment status');
93
+ }
91
94
  }
92
95
  else {
93
96
  this.debug('STACK ERROR RESPONSE:', stack);
@@ -3,12 +3,13 @@ import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
3
  import { getStack } from '../../actions/blueprints/stacks.js';
4
4
  import config from '../../config.js';
5
5
  import { formatResourceTree, formatStackInfo } from '../../utils/display/blueprints-formatting.js';
6
+ import { niceId } from '../../utils/display/colors.js';
6
7
  const { token } = config;
7
8
  export default class Info extends Command {
8
- static description = 'Show information about a Blueprint';
9
+ static description = 'Show information about a deployed Blueprint Stack';
9
10
  static examples = [
10
11
  '<%= config.bin %> <%= command.id %>',
11
- '<%= config.bin %> <%= command.id %> --id abc123',
12
+ '<%= config.bin %> <%= command.id %> --id ST-a1b2c3',
12
13
  ];
13
14
  static flags = {
14
15
  id: Flags.string({
@@ -18,25 +19,30 @@ export default class Info extends Command {
18
19
  };
19
20
  async run() {
20
21
  const { flags } = await this.parse(Info);
21
- const { errors, deployedStack, projectId } = await readBlueprintOnDisk({ getStack: true, token });
22
+ const { errors, deployedStack, projectId, stackId } = await readBlueprintOnDisk({
23
+ getStack: true,
24
+ token,
25
+ });
22
26
  if (errors.length > 0) {
23
27
  // printErrors(errors)
24
28
  this.warn('Blueprint parse errors:');
25
29
  console.dir(errors, { depth: null });
26
30
  return;
27
31
  }
32
+ if (!stackId && !flags.id)
33
+ this.error('No Stack ID provided');
28
34
  if (!projectId)
29
- this.error('Project resource not found in blueprint');
35
+ this.error('Missing Project ID for Blueprint');
30
36
  const auth = { token, projectId };
31
37
  let stack = deployedStack;
32
38
  if (flags.id) {
33
39
  const { ok, stack: foundStack, error } = await getStack({ stackId: flags.id, auth });
34
40
  if (!ok)
35
- this.error(error || 'Failed to get stack');
41
+ this.error(`Failed to get Stack ${niceId(flags.id)}: ${error}`);
36
42
  stack = foundStack;
37
43
  }
38
44
  else if (!stack) {
39
- this.error('No stack found');
45
+ this.error(`Stack ${niceId(stackId)} not found`);
40
46
  }
41
47
  if (!stack)
42
48
  this.error('Stack not found. Is it deployed?');
@@ -4,13 +4,15 @@ import { Command } from '@oclif/core';
4
4
  import inquirer from 'inquirer';
5
5
  import { findBlueprintFile, writeBlueprintToDisk, writeConfigFile, } from '../../actions/blueprints/blueprint.js';
6
6
  import { listProjects } from '../../actions/blueprints/projects.js';
7
+ import { createStack, listStacks } from '../../actions/blueprints/stacks.js';
7
8
  import config from '../../config.js';
9
+ import { bold, dim, niceId, underline } from '../../utils/display/colors.js';
8
10
  const { token } = config;
9
11
  export default class Init extends Command {
10
12
  static description = 'Initialize a new Blueprint';
11
13
  static examples = ['<%= config.bin %> <%= command.id %>'];
12
14
  async run() {
13
- const existingBlueprint = findBlueprintFile(undefined);
15
+ const existingBlueprint = findBlueprintFile();
14
16
  if (existingBlueprint) {
15
17
  this.error(`A blueprint file already exists: ${existingBlueprint.fileName}`);
16
18
  }
@@ -21,21 +23,21 @@ export default class Init extends Command {
21
23
  message: 'Choose a blueprint type:',
22
24
  choices: [
23
25
  { name: 'JSON (Recommended)', value: 'json' },
24
- { name: 'JavaScript (Beta)', value: 'js' },
25
- { name: 'TypeScript (Alpha)', value: 'ts' },
26
+ { name: 'JavaScript', value: 'js', disabled: true },
27
+ { name: 'TypeScript', value: 'ts', disabled: true },
26
28
  ],
27
29
  default: 'json',
28
30
  },
29
31
  ]);
30
- const { ok, projects, error } = await listProjects({ token });
31
- if (!ok)
32
- this.error(error ?? 'Unknown error listing projects');
32
+ const { ok: projectsOk, error: projectsErr, projects } = await listProjects({ token });
33
+ if (!projectsOk)
34
+ this.error(projectsErr ?? 'Unknown error listing projects');
33
35
  if (projects.length === 0) {
34
36
  this.error('No projects found. Please create a project in Sanity.io first.');
35
37
  }
36
- const projectChoices = projects.map(({ displayName, id }) => ({
37
- name: `${displayName} <${id}>`,
38
- value: id,
38
+ const projectChoices = projects.map(({ displayName, id: projectId }) => ({
39
+ name: `"${displayName}" ${niceId(projectId)}`,
40
+ value: projectId,
39
41
  }));
40
42
  const { projectId } = await inquirer.prompt([
41
43
  {
@@ -45,11 +47,52 @@ export default class Init extends Command {
45
47
  choices: projectChoices,
46
48
  },
47
49
  ]);
50
+ const { ok: stacksOk, error: stacksErr, stacks } = await listStacks({ token, projectId });
51
+ if (!stacksOk)
52
+ this.error(stacksErr || 'Failed to list Stacks');
53
+ const stackChoices = [{ name: bold('✨ Create a new Stack'), value: 'new' }];
54
+ if (stacks.length > 0) {
55
+ stackChoices.push(new inquirer.Separator(underline('Use an existing Stack:')));
56
+ stackChoices.push(...stacks.map((s) => ({
57
+ name: `"${s.name}" ${niceId(s.id)} ${dim(`(${s.resources.length} res)`)}`,
58
+ value: s.id,
59
+ })));
60
+ }
61
+ let stackId;
62
+ const { stackId: stackIdChoice } = await inquirer.prompt([
63
+ {
64
+ type: 'list',
65
+ name: 'stackId',
66
+ message: 'Select your Blueprint Stack:',
67
+ choices: stackChoices,
68
+ },
69
+ ]);
70
+ if (stackIdChoice === 'new') {
71
+ const { stackName } = await inquirer.prompt([
72
+ {
73
+ type: 'input',
74
+ name: 'stackName',
75
+ message: 'Enter a name for your Stack:',
76
+ validate: (input) => input.length > 0 || 'Stack name is required',
77
+ },
78
+ ]);
79
+ const { ok: stackOk, error: stackErr, stack, } = await createStack({
80
+ stackPayload: { name: stackName, projectId, document: { resources: [] } },
81
+ auth: { token, projectId },
82
+ });
83
+ if (!stackOk)
84
+ this.error(stackErr || 'Failed to create Stack');
85
+ stackId = stack.id;
86
+ }
87
+ else {
88
+ stackId = stackIdChoice;
89
+ }
48
90
  const fileName = `blueprint.${blueprintExtension}`;
49
91
  const filePath = join(cwd(), fileName);
50
- writeBlueprintToDisk({ path: filePath, fileType: blueprintExtension });
51
- writeConfigFile({ projectId });
92
+ writeBlueprintToDisk({ blueprintFilePath: filePath });
52
93
  this.log(`Created new blueprint: ./${fileName}`);
94
+ writeConfigFile({ blueprintFilePath: filePath, projectId, stackId });
95
+ this.log(`Created new config file: ./${fileName}.config.json`);
53
96
  if (blueprintExtension === 'ts') {
54
97
  this.log('\nNote: TypeScript support requires "tsx" to be installed. Run: npm install -D tsx');
55
98
  }
@@ -4,7 +4,7 @@ import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
4
4
  import { findNewestLogTimestamp, getLogs, getRecentLogs, isNewerLog, streamLogs, } from '../../actions/blueprints/logs.js';
5
5
  import config from '../../config.js';
6
6
  import { formatTitle } from '../../utils/display/blueprints-formatting.js';
7
- import { bold, red, yellow } from '../../utils/display/colors.js';
7
+ import { bold, niceId, red } from '../../utils/display/colors.js';
8
8
  import { formatLogEntry, formatLogsByDay, organizeLogsByDay, } from '../../utils/display/logs-formatting.js';
9
9
  const { token } = config;
10
10
  export default class Logs extends Command {
@@ -35,7 +35,7 @@ export default class Logs extends Command {
35
35
  this.error('Stack not found'); // returns
36
36
  const { id: stackId, projectId, name } = deployedStack;
37
37
  const auth = { token, projectId };
38
- const spinner = Spinner({ text: `Fetching logs for stack ${yellow(`<${stackId}>`)}` }).start();
38
+ const spinner = Spinner({ text: `Fetching logs for stack ${niceId(stackId)}` }).start();
39
39
  if (watchMode) {
40
40
  const { ok, logs, error } = await getLogs(stackId, auth);
41
41
  if (!ok) {
@@ -44,7 +44,7 @@ export default class Logs extends Command {
44
44
  return;
45
45
  }
46
46
  spinner.stop().clear(); // stop and remove the spinner
47
- this.log(`${formatTitle('Blueprint', name)} <${yellow(stackId)}> logs`);
47
+ this.log(`${formatTitle('Blueprint', name)} ${niceId(stackId)} logs`);
48
48
  if (logs.length > 0) {
49
49
  this.log('\nMost recent logs:');
50
50
  const recentLogs = getRecentLogs(logs);
@@ -53,7 +53,7 @@ export default class Logs extends Command {
53
53
  }
54
54
  }
55
55
  else {
56
- this.log(`No recent logs found for stack <${yellow(stackId)}>`);
56
+ this.log(`No recent logs found for stack ${niceId(stackId)}`);
57
57
  }
58
58
  const onOpen = () => {
59
59
  this.log(`Watching for new logs... ${bold('ctrl+c')} to stop`);
@@ -65,7 +65,7 @@ export default class Logs extends Command {
65
65
  newestTimestamp = new Date(log.timestamp).getTime();
66
66
  this.log(formatLogEntry(log, true));
67
67
  };
68
- this.debug(`${yellow('Debug:')} Connecting to streaming endpoint for stack ${stackId}...`);
68
+ this.debug(`Connecting to streaming endpoint for Stack ${niceId(stackId)}...`);
69
69
  streamLogs(stackId, auth, renderLog, onOpen, (error) => this.log(`${red('Error:')} ${error}`));
70
70
  return new Promise(() => {
71
71
  // hold the line until the user terminates with Ctrl+C
@@ -82,7 +82,7 @@ export default class Logs extends Command {
82
82
  return;
83
83
  }
84
84
  spinner.success(`${formatTitle('Blueprint', name)} Logs`);
85
- this.log(`Found ${bold(logs.length.toString())} log entries for stack ${yellow(stackId)}\n`);
85
+ this.log(`Found ${bold(logs.length.toString())} log entries for Stack ${niceId(stackId)}\n`);
86
86
  // Organize and format logs by day
87
87
  const logsByDay = organizeLogsByDay(logs);
88
88
  this.log(formatLogsByDay(logsByDay));
@@ -2,5 +2,8 @@ import { Command } from '@oclif/core';
2
2
  export default class Stacks extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
+ static flags: {
6
+ projectId: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ };
5
8
  run(): Promise<void>;
6
9
  }
@@ -1,22 +1,46 @@
1
- import { Command } from '@oclif/core';
1
+ import { Command, Flags } from '@oclif/core';
2
2
  import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
3
  import { listStacks } from '../../actions/blueprints/stacks.js';
4
4
  import config from '../../config.js';
5
5
  import { formatStacksListing } from '../../utils/display/blueprints-formatting.js';
6
- import { bold, yellow } from '../../utils/display/colors.js';
6
+ import { bold, niceId } from '../../utils/display/colors.js';
7
7
  const { token } = config;
8
8
  export default class Stacks extends Command {
9
9
  static description = 'List all Blueprint stacks';
10
- static examples = ['<%= config.bin %> <%= command.id %>'];
10
+ static examples = [
11
+ '<%= config.bin %> <%= command.id %>',
12
+ '<%= config.bin %> <%= command.id %> --projectId a1b2c3',
13
+ ];
14
+ static flags = {
15
+ projectId: Flags.string({
16
+ description: 'Project ID to show stacks for',
17
+ required: false,
18
+ }),
19
+ };
11
20
  async run() {
12
- const { errors, projectId, stackId } = await readBlueprintOnDisk();
13
- if (errors.length > 0) {
14
- this.log('Blueprint parse errors:');
15
- console.dir(errors, { depth: null });
21
+ const { flags } = await this.parse(Stacks);
22
+ let { projectId } = flags;
23
+ let stackId;
24
+ if (!projectId) {
25
+ try {
26
+ const { errors, projectId: projectIdFromBlueprint, stackId: stackIdFromBlueprint, } = await readBlueprintOnDisk();
27
+ if (errors.length > 0) {
28
+ this.log('Blueprint parse errors:');
29
+ console.dir(errors, { depth: null });
30
+ return;
31
+ }
32
+ projectId = projectIdFromBlueprint;
33
+ stackId = stackIdFromBlueprint;
34
+ }
35
+ catch {
36
+ // continue to print error
37
+ }
38
+ }
39
+ if (!projectId) {
40
+ this.log('Unable to determine Project ID. Provide one with --projectId');
41
+ this.log('Or create a Blueprint with `sanity blueprints init`');
16
42
  return;
17
43
  }
18
- if (!projectId)
19
- this.error('Project resource not found in blueprint');
20
44
  const auth = { token, projectId };
21
45
  const { ok, stacks, error } = await listStacks(auth);
22
46
  if (!ok)
@@ -25,7 +49,7 @@ export default class Stacks extends Command {
25
49
  this.warn('No stacks found');
26
50
  return;
27
51
  }
28
- this.log(`${bold('Project')} <${yellow(projectId)}> ${bold('Stacks')}:\n`);
52
+ this.log(`${bold('Project')} ${niceId(projectId)} ${bold('Stacks')}:\n`);
29
53
  this.log(formatStacksListing(stacks, stackId));
30
54
  }
31
55
  }
@@ -51,9 +51,11 @@ export default class Test extends Command {
51
51
  file: flags.file,
52
52
  timeout: flags.timeout,
53
53
  }, {
54
- apiVersion: flags.api,
55
- dataset: flags.dataset,
56
- projectId: flags.project,
54
+ clientOptions: {
55
+ apiVersion: flags.api,
56
+ dataset: flags.dataset,
57
+ projectId: flags.project,
58
+ },
57
59
  });
58
60
  if (!error) {
59
61
  this.log('Logs:');
@@ -21,9 +21,11 @@ class PayloadPanel extends ApiBaseElement {
21
21
  const payloadText = this.api.store.payload.state.doc.text.join('') || '{}'
22
22
  const event = JSON.parse(payloadText)
23
23
  const context = {
24
- apiVersion: this.apiVersion.value,
25
- dataset: this.api.store.selectedDataset,
26
- projectId: this.api.store.selectedProject,
24
+ clientOptions: {
25
+ apiVersion: this.apiVersion.value,
26
+ dataset: this.api.store.selectedDataset,
27
+ projectId: this.api.store.selectedProject,
28
+ },
27
29
  }
28
30
  this.api.invoke({context, event})
29
31
  }
@@ -13,30 +13,6 @@ export function getFunctionSource(src) {
13
13
  return src
14
14
  }
15
15
 
16
- async function enhanceContext(context = {}) {
17
- const {apiHost, apiVersion, dataset, projectId, token} = context
18
- const enhancedContext = {...context}
19
-
20
- try {
21
- if (apiHost && apiVersion && dataset && projectId && token) {
22
- // @ts-ignore
23
- const {createClient} = await import('@sanity/client')
24
- const client = createClient({
25
- projectId,
26
- dataset,
27
- useCdn: true,
28
- apiHost,
29
- apiVersion,
30
- token,
31
- })
32
- enhancedContext.client = client
33
- }
34
- } catch {
35
- // ignore as user hasn't provided the @sanity/client
36
- }
37
- return enhancedContext
38
- }
39
-
40
16
  // Start when payload data arrives from parent process
41
17
  process.on('message', async (data) => {
42
18
  let jsonData = null
@@ -48,7 +24,6 @@ process.on('message', async (data) => {
48
24
  }
49
25
  const {srcPath, payload} = jsonData
50
26
  const {context, ...event} = payload
51
- const enhancedContext = await enhanceContext(context)
52
27
  let logs = ''
53
28
  let json = null
54
29
 
@@ -67,7 +42,7 @@ process.on('message', async (data) => {
67
42
  }
68
43
 
69
44
  if (handler && typeof handler === 'function') {
70
- json = await handler({context: enhancedContext, event})
45
+ json = await handler({context, event})
71
46
  }
72
47
 
73
48
  // revert changes to stdout