@sanity/cli 3.88.3 → 3.89.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.
@@ -22,7 +22,11 @@ Examples
22
22
  sanity functions env list echo
23
23
  `
24
24
 
25
- const envFunctionsCommand: CliCommandDefinition = {
25
+ export interface FunctionsEnvFlags {
26
+ //
27
+ }
28
+
29
+ const envFunctionsCommand: CliCommandDefinition<FunctionsEnvFlags> = {
26
30
  name: 'env',
27
31
  group: 'functions',
28
32
  helpText,
@@ -31,7 +35,6 @@ const envFunctionsCommand: CliCommandDefinition = {
31
35
  'Add or remove an environment variable or list environment variables for a Sanity function',
32
36
  async action(args, context) {
33
37
  const {apiClient, output} = context
34
- const {print} = output
35
38
  const [subCommand, name, key, value] = args.argsWithoutOptions
36
39
 
37
40
  if (!subCommand || !['add', 'list', 'remove'].includes(subCommand)) {
@@ -49,71 +52,53 @@ const envFunctionsCommand: CliCommandDefinition = {
49
52
  requireProject: false,
50
53
  })
51
54
 
52
- if (name === '') {
55
+ if (!name) {
53
56
  throw new Error('You must provide a function name as the first argument')
54
57
  }
55
58
 
56
59
  const token = client.config().token
57
60
  if (!token) throw new Error('No API token found. Please run `sanity login`.')
58
61
 
59
- const {env: envAction} = await import('@sanity/runtime-cli/actions/functions')
60
- const {blueprint, getBlueprintAndStack} = await import('@sanity/runtime-cli/actions/blueprints')
61
- const {findFunction} = await import('@sanity/runtime-cli/utils')
62
-
63
- const {deployedStack} = await getBlueprintAndStack({token})
64
-
65
- if (!deployedStack) {
66
- throw new Error('Stack not found')
67
- }
62
+ const {initDeployedBlueprintConfig} = await import('@sanity/runtime-cli/cores')
63
+ const {functionEnvAddCore, functionEnvListCore, functionEnvRemoveCore} = await import(
64
+ '@sanity/runtime-cli/cores/functions'
65
+ )
68
66
 
69
- const blueprintConfig = blueprint.readConfigFile()
70
- const projectId = blueprintConfig?.projectId
67
+ const cmdConfig = await initDeployedBlueprintConfig({
68
+ bin: 'sanity',
69
+ log: (message) => output.print(message),
70
+ token,
71
+ })
71
72
 
72
- const {externalId} = findFunction.findFunctionByName(deployedStack, name)
73
+ if (!cmdConfig.ok) throw new Error(cmdConfig.error)
73
74
 
74
- if (token && projectId) {
75
- if (subCommand === 'add') {
76
- print(`Updating "${key}" environment variable in "${name}"`)
77
- const result = await envAction.update(externalId, key, value, {
78
- token,
79
- projectId,
75
+ let response
76
+ switch (subCommand) {
77
+ case 'add':
78
+ response = await functionEnvAddCore({
79
+ ...cmdConfig.value,
80
+ args: {name, key, value},
80
81
  })
81
- if (result.ok) {
82
- print(`Update of "${key}" succeeded`)
83
- } else {
84
- print(`Failed to update "${key}"`)
85
- print(`Error: ${result.error || 'Unknown error'}`)
86
- }
87
- } else if (subCommand === 'remove') {
88
- print(`Removing "${key}" environment variable in "${name}"`)
89
- const result = await envAction.remove(externalId, key, {
90
- token,
91
- projectId,
82
+ break
83
+ case 'list':
84
+ response = await functionEnvListCore({
85
+ ...cmdConfig.value,
86
+ args: {name},
92
87
  })
93
- if (result.ok) {
94
- print(`Removal of "${key}" succeeded`)
95
- } else {
96
- print(`Failed to remove "${key}"`)
97
- print(`Error: ${result.error || 'Unknown error'}`)
98
- }
99
- } else if (subCommand === 'list') {
100
- print(`Environment variables in "${name}"`)
101
- const result = await envAction.list(externalId, {
102
- token,
103
- projectId,
88
+ break
89
+ case 'remove':
90
+ response = await functionEnvRemoveCore({
91
+ ...cmdConfig.value,
92
+ args: {name, key},
104
93
  })
105
- if (result.ok && Array.isArray(result.envvars)) {
106
- for (const envVarKey of result.envvars) {
107
- print(envVarKey)
108
- }
109
- } else {
110
- print(`Failed to list environment variables in "${key}"`)
111
- print(`Error: ${result.error || 'Unknown error'}`)
112
- }
113
- }
114
- } else {
115
- print('You must run this command from a blueprints project')
94
+ break
95
+ default:
96
+ throw new Error(`Unknown subcommand: ${subCommand}`)
116
97
  }
98
+
99
+ const {success, error} = response
100
+
101
+ if (!success) throw new Error(error)
117
102
  },
118
103
  }
119
104
 
@@ -4,7 +4,7 @@ const functionsGroup: CliCommandGroupDefinition = {
4
4
  name: 'functions',
5
5
  signature: '[COMMAND]',
6
6
  isGroupRoot: true,
7
- description: 'Test Sanity Functions locally, update environment variables and retrieve logs',
7
+ description: 'Manage, test, and observe Sanity Functions',
8
8
  }
9
9
 
10
10
  export default functionsGroup
@@ -1,6 +1,3 @@
1
- import chalk from 'chalk'
2
- import inquirer from 'inquirer'
3
-
4
1
  import {type CliCommandDefinition} from '../../types'
5
2
 
6
3
  const helpText = `
@@ -11,6 +8,8 @@ Options
11
8
  --limit <limit> The number of log entries to retrieve [default 50]
12
9
  --json If set return json
13
10
  --utc Use UTC dates in logs
11
+ --delete Delete all logs for the Function
12
+ --force Force delete all logs for the Function
14
13
 
15
14
  Examples
16
15
  # Retrieve logs for Sanity Function
@@ -26,23 +25,32 @@ Examples
26
25
  sanity functions logs --name echo --delete
27
26
  `
28
27
 
28
+ export interface FunctionsLogsFlags {
29
+ limit?: number
30
+ json?: boolean
31
+ utc?: boolean
32
+ delete?: boolean
33
+ force?: boolean
34
+ watch?: boolean // undocumented for now
35
+ }
36
+
29
37
  const defaultFlags = {
30
38
  limit: 50,
31
39
  json: false,
32
40
  utc: false,
33
41
  delete: false,
34
42
  force: false,
43
+ watch: false,
35
44
  }
36
45
 
37
- const logsFunctionsCommand: CliCommandDefinition = {
46
+ const logsFunctionsCommand: CliCommandDefinition<FunctionsLogsFlags> = {
38
47
  name: 'logs',
39
48
  group: 'functions',
40
49
  helpText,
41
- signature: '<name> [--limit <number>] [--json] [--utc] [--delete [--force]]',
50
+ signature: '<name> [--limit <number>] [--json] [--utc] [--delete [--force]] [--watch]',
42
51
  description: 'Retrieve or delete logs for a Sanity Function',
43
52
  async action(args, context) {
44
53
  const {apiClient, output} = context
45
- const {print, error: printError} = output
46
54
  const [name] = args.argsWithoutOptions
47
55
  const flags = {...defaultFlags, ...args.extOptions}
48
56
 
@@ -58,106 +66,25 @@ const logsFunctionsCommand: CliCommandDefinition = {
58
66
  const token = client.config().token
59
67
  if (!token) throw new Error('No API token found. Please run `sanity login`.')
60
68
 
61
- const {getBlueprintAndStack} = await import('@sanity/runtime-cli/actions/blueprints')
62
- const {findFunction} = await import('@sanity/runtime-cli/utils')
69
+ const {initDeployedBlueprintConfig} = await import('@sanity/runtime-cli/cores')
70
+ const {functionLogsCore} = await import('@sanity/runtime-cli/cores/functions')
63
71
 
64
- const {deployedStack} = await getBlueprintAndStack({token})
72
+ const cmdConfig = await initDeployedBlueprintConfig({
73
+ bin: 'sanity',
74
+ log: (message) => output.print(message),
75
+ token,
76
+ })
65
77
 
66
- if (!deployedStack) {
67
- throw new Error('Stack not found')
68
- }
78
+ if (!cmdConfig.ok) throw new Error(cmdConfig.error)
69
79
 
70
- const {projectId} = deployedStack
71
-
72
- const {externalId} = findFunction.findFunctionByName(deployedStack, name)
73
-
74
- if (token && projectId) {
75
- const {logs: logsAction} = await import('@sanity/runtime-cli/actions/functions')
76
-
77
- if (!externalId) throw new Error('Unable to delete logs. Unable to determine function ID.')
78
-
79
- if (flags.delete) {
80
- if (!flags.force) {
81
- const {certain} = await inquirer.prompt({
82
- type: 'confirm',
83
- name: 'certain',
84
- message: `Are you sure you want to delete ${chalk.bold('all')} logs for function ${chalk.yellow(name)}?`,
85
- default: false,
86
- })
87
- if (!certain) return
88
- }
89
-
90
- print(`Deleting logs for function ${chalk.yellow(name)}`)
91
- const {ok, error} = await logsAction.deleteLogs(externalId, {token, projectId})
92
-
93
- if (!ok) {
94
- printError(`${chalk.red('Failed')} to retrieve logs`)
95
- printError(`Error: ${error || 'Unknown error'}`)
96
- return
97
- }
98
-
99
- print('Logs deleted')
100
- } else {
101
- print(`Finding logs for function "${name}"`)
102
-
103
- const {ok, error, logs, total} = await logsAction.logs(
104
- externalId,
105
- {limit: flags.limit},
106
- {token, projectId},
107
- )
108
-
109
- if (!ok) {
110
- printError(`${chalk.red('Failed')} to retrieve logs`)
111
- printError(`Error: ${error || 'Unknown error'}`)
112
- return
113
- }
114
-
115
- const filteredLogs = logs.filter(
116
- (entry: {level: string; message: string}) => entry.level && entry.message,
117
- )
118
-
119
- if (filteredLogs.length === 0) {
120
- print(`No logs found for function ${name}`)
121
- return
122
- }
123
-
124
- if (flags.json) {
125
- print(JSON.stringify(filteredLogs, null, 2))
126
- } else {
127
- print(`Found ${total} log entries for function ${name}`)
128
- if (logs.length < total) {
129
- print(`Here are the last ${filteredLogs.length} entries`)
130
- }
131
- print('\n')
132
-
133
- for (const log of filteredLogs) {
134
- const {time, level, message} = log
135
- const date = new Date(time)
136
- const [dateString, timeString] = flags.utc
137
- ? date.toISOString().slice(0, 19).split('T')
138
- : [date.toLocaleDateString(), date.toLocaleTimeString()]
139
- print(
140
- [chalk.bold(dateString), chalk.bold.blue(timeString), logLevel(level), message].join(
141
- ' ',
142
- ),
143
- )
144
- }
145
- }
146
- }
147
- } else {
148
- print('You must run this command from a blueprints project')
149
- }
150
- },
151
- }
80
+ const {success, error} = await functionLogsCore({
81
+ ...cmdConfig.value,
82
+ args: {name},
83
+ flags,
84
+ })
152
85
 
153
- function logLevel(level: string) {
154
- if (level === 'ERROR') {
155
- return chalk.red(level)
156
- }
157
- if (level === 'WARN') {
158
- return chalk.yellow(level)
159
- }
160
- return chalk.green(level)
86
+ if (!success) throw new Error(error)
87
+ },
161
88
  }
162
89
 
163
90
  export default logsFunctionsCommand
@@ -24,18 +24,20 @@ Examples
24
24
  sanity functions test echo --data '{ "id": 1 }' --timeout 60
25
25
  `
26
26
 
27
- const defaultFlags = {
28
- 'data': undefined,
29
- 'file': undefined,
30
- 'timeout': 10, // seconds
31
- 'api': undefined,
32
- 'dataset': undefined,
33
- 'project-id': undefined,
34
- 'project': undefined,
35
- 'projectId': undefined,
27
+ export interface FunctionsTestFlags {
28
+ 'data'?: string
29
+ 'file'?: string
30
+ 'timeout'?: number
31
+ 'api'?: string
32
+ 'dataset'?: string
33
+ 'project-id'?: string
36
34
  }
37
35
 
38
- const testFunctionsCommand: CliCommandDefinition = {
36
+ const defaultFlags: FunctionsTestFlags = {
37
+ timeout: 10, // seconds
38
+ }
39
+
40
+ const testFunctionsCommand: CliCommandDefinition<FunctionsTestFlags> = {
39
41
  name: 'test',
40
42
  group: 'functions',
41
43
  helpText,
@@ -43,55 +45,47 @@ const testFunctionsCommand: CliCommandDefinition = {
43
45
  '<name> [--data <json>] [--file <filename>] [--timeout <seconds>] [--api <version>] [--dataset <name>] [--project-id] <id>]',
44
46
  description: 'Invoke a local Sanity Function',
45
47
  async action(args, context) {
46
- const {output} = context
47
- const {print, error: printError} = output
48
+ const {apiClient, output} = context
48
49
  const [name] = args.argsWithoutOptions
49
50
  const flags = {...defaultFlags, ...args.extOptions}
50
51
 
52
+ const client = apiClient({
53
+ requireUser: true,
54
+ requireProject: false,
55
+ })
56
+ const {token} = client.config()
57
+
58
+ if (!token) throw new Error('No API token found. Please run `sanity login`.')
59
+
51
60
  if (!name) {
52
61
  throw new Error('You must provide a function name as the first argument')
53
62
  }
54
63
 
55
- const {test} = await import('@sanity/runtime-cli/actions/functions')
56
- const {blueprint} = await import('@sanity/runtime-cli/actions/blueprints')
57
- const {findFunction} = await import('@sanity/runtime-cli/utils')
58
-
59
- const {parsedBlueprint} = await blueprint.readLocalBlueprint()
60
-
61
- try {
62
- const fn = findFunction.findFunctionByName(parsedBlueprint, name)
63
- if (!fn) {
64
- throw new Error(`Function ${name} has no source code`)
65
- }
66
-
67
- const projectId = flags['project-id'] ?? flags.projectId ?? flags.project
68
- const {json, logs, error} = await test.testAction(
69
- fn,
70
- {
71
- data: flags.data,
72
- file: flags.file,
73
- timeout: flags.timeout,
74
- },
75
- {
76
- clientOptions: {
77
- apiVersion: flags.api,
78
- dataset: flags.dataset,
79
- projectId: projectId,
80
- },
81
- },
82
- )
83
-
84
- if (error) {
85
- print(error.toString())
86
- } else {
87
- print('Logs:')
88
- print(logs)
89
- print('Response:')
90
- print(JSON.stringify(json, null, 2))
91
- }
92
- } catch (error) {
93
- printError(`Error: ${error || 'Unknown error'}`)
94
- }
64
+ const {initBlueprintConfig} = await import('@sanity/runtime-cli/cores')
65
+ const {functionTestCore} = await import('@sanity/runtime-cli/cores/functions')
66
+
67
+ const cmdConfig = await initBlueprintConfig({
68
+ bin: 'sanity',
69
+ log: (message: string) => output.print(message),
70
+ token,
71
+ })
72
+
73
+ if (!cmdConfig.ok) throw new Error(cmdConfig.error)
74
+
75
+ const {success, error} = await functionTestCore({
76
+ ...cmdConfig.value,
77
+ args: {name},
78
+ flags: {
79
+ 'data': flags.data,
80
+ 'file': flags.file,
81
+ 'timeout': flags.timeout,
82
+ 'api': flags.api,
83
+ 'dataset': flags.dataset,
84
+ 'project-id': flags['project-id'],
85
+ },
86
+ })
87
+
88
+ if (!success) throw new Error(error)
95
89
  },
96
90
  }
97
91
 
@@ -3,7 +3,7 @@ import {SanityApp} from '@sanity/sdk-react'
3
3
  import {ExampleComponent} from './ExampleComponent'
4
4
  import './App.css'
5
5
 
6
- export function App() {
6
+ function App() {
7
7
  // apps can access many different projects or other sources of data
8
8
  const sanityConfigs: SanityConfig[] = [
9
9
  {
@@ -6,7 +6,7 @@ import {ExampleComponent} from './ExampleComponent'
6
6
 
7
7
  const theme = buildTheme()
8
8
 
9
- export function App() {
9
+ function App() {
10
10
  // apps can access many different projects or other sources of data
11
11
  const sanityConfigs: SanityConfig[] = [
12
12
  {