@sanity/cli
Version:
Sanity CLI tool for managing Sanity installations, managing plugins, schemas and datasets
523 lines (478 loc) • 14.6 kB
text/typescript
import {Answers} from 'inquirer'
import type chalk from 'chalk'
import {ChoiceCollection} from 'inquirer'
import {ConfigEnv} from 'vite'
import {DistinctQuestion} from 'inquirer'
import {InlineConfig} from 'vite'
import {Options} from 'ora'
import {Ora} from 'ora'
import {SanityClient} from '@sanity/client'
import {Separator} from 'inquirer'
import {TelemetryLogger} from '@sanity/telemetry'
declare interface AppConfig {
/**
* The ID of your Sanity organization
*/
organizationId: string
/**
* The entrypoint for your Sanity app. Defaults to './src/App'.
*/
entry?: string
/**
* @deprecated - Moved to `deployment.appId`
*/
id?: string
}
export declare type CliApiClient = (options?: ClientRequirements) => SanityClient
export declare interface CliApiConfig {
projectId?: string
dataset?: string
}
export declare interface CliClientOptions {
cwd?: string
projectId?: string
dataset?: string
useCdn?: boolean
token?: string
apiVersion?: string
}
export declare type CliCommandAction<F = Record<string, unknown>> = (
args: CliCommandArguments<F>,
context: CliCommandContext,
) => Promise<unknown>
export declare interface CliCommandArguments<F = Record<string, unknown>> {
groupOrCommand: string
argv: string[]
extOptions: F
argsWithoutOptions: string[]
extraArguments: string[]
}
export declare interface CliCommandContext {
output: CliOutputter
prompt: CliPrompter
apiClient: CliApiClient
cliConfigPath?: string
cliRoot: string
workDir: string
corePath?: string
chalk: typeof chalk
commandRunner: CliCommandRunner
fromInitCommand?: boolean
cliConfig?: CliConfig
cliPackageManager: CliPackageManager
telemetry: TelemetryLogger<TelemetryUserProperties>
}
export declare interface CliCommandDefinition<F = Record<string, unknown>> {
name: string
group?: string
signature: string
description: string
helpText: string
action: CliCommandAction<F>
hideFromHelp?: boolean
}
export declare interface CliCommandGroupDefinition {
name: string
signature: string
isGroupRoot: boolean
description: string
hideFromHelp?: boolean
}
export declare interface CliCommandRunner {
commands: Readonly<(CliCommandDefinition | CliCommandGroupDefinition)[]>
commandGroups: Readonly<Record<string, (CliCommandDefinition | CliCommandGroupDefinition)[]>>
runCommand(
commandOrGroup: string,
args: CliCommandArguments,
options: CommandRunnerOptions,
): Promise<unknown>
resolveSubcommand(
group: (CliCommandDefinition | CliCommandGroupDefinition)[],
subCommandName: string,
parentGroupName: string,
): ResolvedCliCommand | null
}
export declare interface CliConfig {
api?: CliApiConfig
project?: {
basePath?: string
}
/**
* Wraps the Studio in `<React.StrictMode>` root to aid flagging potential problems related to concurrent features (`startTransition`, `useTransition`, `useDeferredValue`, `Suspense`)
* Can also be enabled by setting `SANITY_STUDIO_REACT_STRICT_MODE="true"|"false"`.
* It only applies to `sanity dev` in dev mode, it's ignored in `sanity build` and in production.
* Defaults to `false`
*/
reactStrictMode?: boolean
/**
* The React Compiler is currently in beta, and is disabled by default.
* @see https://react.dev/learn/react-compiler
* @beta
*/
reactCompiler?: ReactCompilerConfig
server?: {
hostname?: string
port?: number
}
graphql?: GraphQLAPIConfig[]
vite?: UserViteConfig
/**
* @deprecated - Moved to deployment.autoUpdates
*/
autoUpdates?: boolean
/**
* @deprecated - Replaced by deployment.appId
*/
studioHost?: string
/**
* Parameter used to configure other kinds of applications.
* Signals to `sanity` commands that this is not a studio.
*/
app?: AppConfig
/**
* Deployment configuration
*/
deployment?: {
/**
* The ID of your Sanity studio or app. Generated when deploying your studio or app for the first time.
* Get the appId either by
* - Checking the output of `sanity deploy`.
* - Get it from your project's Studio tab in https://sanity.io/manage
*/
appId?: string
/**
* Enable auto-updates for studios.
* {@link https://www.sanity.io/docs/cli#auto-updates}
*/
autoUpdates?: boolean
}
/**
* Configuration for Sanity media libraries.
*/
mediaLibrary?: {
/**
* The path to the Media Library aspects directory. When using the CLI to manage aspects, this
* is the directory they will be read from and written to.
*/
aspectsPath: string
}
}
declare type CliConfigResult =
| {
config: CliConfig
path: string
}
| {
config: null
path: string
}
declare interface ClientRequirements {
requireUser?: boolean
requireProject?: boolean
api?: {
projectId?: string
dataset?: string
apiHost?: string
apiVersion?: string
requestTagPrefix?: string
}
}
export declare interface CliOutputter {
print: (...args: unknown[]) => void
success: (...args: unknown[]) => void
warn: (...args: unknown[]) => void
error: (...args: unknown[]) => void
clear: () => void
spinner(options: Options | string): Ora
}
/**
* @internal
*/
declare type CliPackageManager = typeof cliPackageManager
/**
* @internal
*/
declare const cliPackageManager: {
getInstallCommand: typeof getInstallCommand
getPackageManagerChoice: typeof getPackageManagerChoice
installNewPackages: typeof installNewPackages
}
export declare type CliPrompter = (<T extends Answers = Answers>(
questions: DistinctQuestion<T>[],
) => Promise<T>) & {
Separator: typeof Separator
single: <T = string>(question: SinglePrompt) => Promise<T>
}
export declare type CliStubbedYarn = (args: string[], options?: CliYarnOptions) => Promise<void>
export declare interface CliUserConfig {
cliLastUpdateCheck?: number
cliLastUpdateNag?: number
authToken?: string
authType?: string
}
export declare interface CliYarnOptions {
print?: CliOutputter['print']
error?: CliOutputter['error']
rootDir?: string
}
export declare interface CommandRunnerOptions {
cliConfig: CliConfigResult | null
cliRoot: string
workDir: string
corePath: string | undefined
telemetry: TelemetryLogger<TelemetryUserProperties>
}
/**
* @deprecated Use `defineCliConfig` instead
* @beta
*/
export declare function createCliConfig(config: CliConfig): CliConfig
/** @beta */
export declare function defineCliConfig(config: CliConfig): CliConfig
declare interface GetCliClient {
(options?: CliClientOptions): SanityClient
/**
* @internal
* @deprecated This is only for INTERNAL use, and should not be relied upon outside of official Sanity modules
* @returns A token to use when constructing a client without a `token` explicitly defined, or undefined
*/
__internal__getToken: () => string | undefined
}
/** @internal */
export declare const getCliClient: GetCliClient
declare function getInstallCommand(options: {
workDir: string
pkgNames?: string[]
depType?: 'dev' | 'prod' | 'peer'
}): Promise<string>
/**
* Attempts to resolve the most optimal package manager to use to install/upgrade
* packages/dependencies at a given path. It does so by looking for package manager
* specific lockfiles. If it finds a lockfile belonging to a certain package manager,
* it prioritizes this one. However, if that package manager is not installed, it will
* prompt the user for which one they want to use and hint at the most optimal one
* not being installed.
*
* Note that this function also takes local npm binary paths into account - for instance,
* `yarn` can be installed as a dependency of the project instead of globally, and it
* will use that is available.
*
* The user can also select 'manual' to skip the process and run their preferred package
* manager manually. Commands using this function must take this `manual` choice into
* account and act accordingly if chosen.
*
* @param workDir - The working directory where a lockfile is most likely to be present
* @param options - Pass `interactive: false` to fall back to npm if most optimal is
* not available, instead of prompting
* @returns Object of `chosen` and, if a lockfile is found, the `mostOptimal` choice
*/
declare function getPackageManagerChoice(
workDir: string,
options:
| {
interactive: false
}
| {
interactive?: true
prompt: CliPrompter
},
): Promise<{
chosen: PackageManager
mostOptimal?: PackageManager
}>
export declare interface GraphQLAPIConfig {
/**
* ID of GraphQL API. Only (currently) required when using the `--api` flag
* for `sanity graphql deploy`, in order to only deploy a specific API.
*/
id?: string
/**
* Name of workspace containing the schema to deploy
*
* Optional, defaults to `default` (eg the one used if no `name` is defined)
*/
workspace?: string
/**
* Name of source containing the schema to deploy, within the configured workspace
*
* Optional, defaults to `default` (eg the one used if no `name` is defined)
*/
source?: string
/**
* API tag for this API - allows deploying multiple different APIs to a single dataset
*
* Optional, defaults to `default`
*/
tag?: string
/**
* Whether or not to deploy a "GraphQL Playground" to the API url - an HTML interface that allows
* running queries and introspecting the schema from the browser. Note that this interface is not
* secured in any way, but as the schema definition and API route is generally open, this does not
* expose any more information than is otherwise available - it only makes it more discoverable.
*
* Optional, defaults to `true`
*/
playground?: boolean
/**
* Generation of API to auto-generate from schema. New APIs should use the latest (`gen3`).
*
* Optional, defaults to `gen3`
*/
generation?: 'gen3' | 'gen2' | 'gen1'
/**
* Define document interface fields (`_id`, `_type` etc) as non-nullable.
* If you never use a document type as an object (within other documents) in your schema types,
* you can (and probably should) set this to `true`. Because a document type _could_ be used
* inside other documents, it is by default set to `false`, as in these cases these fields
* _can_ be null.
*
* Optional, defaults to `false`
*/
nonNullDocumentFields?: boolean
/**
* Suffix to use for generated filter types.
*
* Optional, Defaults to `Filter`.
*
*/
filterSuffix?: string
}
declare function installNewPackages(
options: InstallOptions,
context: Pick<CliCommandContext, 'output' | 'workDir'>,
): Promise<void>
declare interface InstallOptions {
packageManager: PackageManager
packages: string[]
}
/**
* This is an "inlined" version of Vite's `loadEnv` function,
* simplified somewhat to only support our use case.
*
* Ideally we'd just use `loadEnv` from Vite, but importing it
* causes bundling issues due to node APIs and downstream dependencies.
*
* Vite is MIT licensed, copyright (c) Yuxi (Evan) You and Vite contributors.
*/
export declare function loadEnv(
mode: string,
envDir: string,
prefixes?: string[],
): Record<string, string>
export declare interface PackageJson {
name: string
version: string
scripts?: Record<string, string>
description?: string
author?: string
license?: string
private?: boolean
dependencies?: Record<string, string>
devDependencies?: Record<string, string>
peerDependencies?: Record<string, string>
repository?: {
type: string
url: string
}
engines?: Record<string, string>
}
declare type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'manual'
/**
* Until these types are on npm: https://github.com/facebook/react/blob/0bc30748730063e561d87a24a4617526fdd38349/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts#L39-L122
* @beta
*/
export declare interface ReactCompilerConfig {
/**
* @see https://react.dev/learn/react-compiler#existing-projects
*/
sources?: Array<string> | ((filename: string) => boolean) | null
/**
* The minimum major version of React that the compiler should emit code for. If the target is 19
* or higher, the compiler emits direct imports of React runtime APIs needed by the compiler. On
* versions prior to 19, an extra runtime package react-compiler-runtime is necessary to provide
* a userspace approximation of runtime APIs.
* @see https://react.dev/learn/react-compiler#using-react-compiler-with-react-17-or-18
*/
target: '18' | '19'
panicThreshold?: 'ALL_ERRORS' | 'CRITICAL_ERRORS' | 'NONE'
compilationMode?: 'infer' | 'syntax' | 'annotation' | 'all'
}
export declare interface ResolvedCliCommand {
command: CliCommandDefinition | CliCommandGroupDefinition
commandName: string
parentName?: string
isGroup: boolean
isCommand: boolean
}
export {SanityClient}
export declare interface SanityCore {
requiredCliVersionRange: string
commands: (CliCommandDefinition | CliCommandGroupDefinition)[]
}
export declare interface SanityJson {
root?: boolean
project?: {
name?: string
basePath?: string
}
api?: CliApiConfig
__experimental_spaces?: {
name: string
title: string
default?: true
api: {
projectId?: string
dataset?: string
}
}[]
plugins?: string[]
parts?: {
name?: string
path?: string
implements?: string
description?: string
}[]
env?: {
production?: SanityJson
staging?: SanityJson
development?: SanityJson
}
}
export declare interface SanityModuleInternal {
cliProjectCommands: {
requiredCliVersionRange: string
commands: (CliCommandDefinition | CliCommandGroupDefinition)[]
}
}
export declare type SanityUser = {
id: string
name: string
email: string
profileImage?: string
tosAcceptedAt?: string
provider: 'google' | 'github' | 'sanity' | `saml-${string}`
}
export declare type SinglePrompt =
| (Omit<DistinctQuestion, 'name'> & {
type: 'list'
choices: ChoiceCollection
})
| (Omit<DistinctQuestion, 'name'> & {
type: 'confirm'
})
| (Omit<DistinctQuestion, 'name'> & {
type: 'input'
})
export declare interface TelemetryUserProperties {
runtime: string
runtimeVersion: string
cliVersion: string
machinePlatform: string
cpuArchitecture: string
projectId?: string
dataset?: string
}
export declare type UserViteConfig =
| InlineConfig
| ((config: InlineConfig, env: ConfigEnv) => InlineConfig | Promise<InlineConfig>)
export {}