UNPKG

@sanity/cli

Version:

Sanity CLI tool for managing Sanity installations, managing plugins, schemas and datasets

523 lines (478 loc) • 14.6 kB
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 {}