@sanity/cli-core 0.0.0-20260410130107
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.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/SanityCommand.js +196 -0
- package/dist/SanityCommand.js.map +1 -0
- package/dist/_exports/index.d.ts +1391 -0
- package/dist/_exports/index.js +39 -0
- package/dist/_exports/index.js.map +1 -0
- package/dist/_exports/package-manager.d.ts +33 -0
- package/dist/_exports/package-manager.js +3 -0
- package/dist/_exports/package-manager.js.map +1 -0
- package/dist/_exports/request.d.ts +79 -0
- package/dist/_exports/request.js +7 -0
- package/dist/_exports/request.js.map +1 -0
- package/dist/_exports/ux.d.ts +75 -0
- package/dist/_exports/ux.js +7 -0
- package/dist/_exports/ux.js.map +1 -0
- package/dist/config/cli/getCliConfig.js +68 -0
- package/dist/config/cli/getCliConfig.js.map +1 -0
- package/dist/config/cli/getCliConfigSync.js +51 -0
- package/dist/config/cli/getCliConfigSync.js.map +1 -0
- package/dist/config/cli/schemas.js +62 -0
- package/dist/config/cli/schemas.js.map +1 -0
- package/dist/config/cli/types/cliConfig.js +5 -0
- package/dist/config/cli/types/cliConfig.js.map +1 -0
- package/dist/config/cli/types/userViteConfig.js +5 -0
- package/dist/config/cli/types/userViteConfig.js.map +1 -0
- package/dist/config/findProjectRoot.js +62 -0
- package/dist/config/findProjectRoot.js.map +1 -0
- package/dist/config/findProjectRootSync.js +88 -0
- package/dist/config/findProjectRootSync.js.map +1 -0
- package/dist/config/studio/getStudioConfig.js +13 -0
- package/dist/config/studio/getStudioConfig.js.map +1 -0
- package/dist/config/studio/getStudioWorkspaces.js +63 -0
- package/dist/config/studio/getStudioWorkspaces.js.map +1 -0
- package/dist/config/studio/isStudioConfig.js +19 -0
- package/dist/config/studio/isStudioConfig.js.map +1 -0
- package/dist/config/studio/readStudioConfig.js +82 -0
- package/dist/config/studio/readStudioConfig.js.map +1 -0
- package/dist/config/studio/readStudioConfig.worker.js +25 -0
- package/dist/config/studio/readStudioConfig.worker.js.map +1 -0
- package/dist/config/util/configPathsSync.js +85 -0
- package/dist/config/util/configPathsSync.js.map +1 -0
- package/dist/config/util/findAppConfigPath.js +22 -0
- package/dist/config/util/findAppConfigPath.js.map +1 -0
- package/dist/config/util/findConfigsPaths.js +21 -0
- package/dist/config/util/findConfigsPaths.js.map +1 -0
- package/dist/config/util/findStudioConfigPath.js +52 -0
- package/dist/config/util/findStudioConfigPath.js.map +1 -0
- package/dist/config/util/isSanityV2StudioRoot.js +22 -0
- package/dist/config/util/isSanityV2StudioRoot.js.map +1 -0
- package/dist/config/util/recursivelyResolveProjectRoot.js +28 -0
- package/dist/config/util/recursivelyResolveProjectRoot.js.map +1 -0
- package/dist/debug.js +15 -0
- package/dist/debug.js.map +1 -0
- package/dist/errors/NonInteractiveError.js +18 -0
- package/dist/errors/NonInteractiveError.js.map +1 -0
- package/dist/errors/NotFoundError.js +27 -0
- package/dist/errors/NotFoundError.js.map +1 -0
- package/dist/errors/ProjectRootNotFoundError.js +35 -0
- package/dist/errors/ProjectRootNotFoundError.js.map +1 -0
- package/dist/exitCodes.js +17 -0
- package/dist/exitCodes.js.map +1 -0
- package/dist/loaders/studio/studioWorkerLoader.worker.js +205 -0
- package/dist/loaders/studio/studioWorkerLoader.worker.js.map +1 -0
- package/dist/loaders/studio/studioWorkerTask.js +90 -0
- package/dist/loaders/studio/studioWorkerTask.js.map +1 -0
- package/dist/loaders/tsx/tsxWorkerLoader.worker.js +11 -0
- package/dist/loaders/tsx/tsxWorkerLoader.worker.js.map +1 -0
- package/dist/loaders/tsx/tsxWorkerTask.js +34 -0
- package/dist/loaders/tsx/tsxWorkerTask.js.map +1 -0
- package/dist/request/createRequester.js +83 -0
- package/dist/request/createRequester.js.map +1 -0
- package/dist/services/apiClient.js +97 -0
- package/dist/services/apiClient.js.map +1 -0
- package/dist/services/cliTokenCache.js +25 -0
- package/dist/services/cliTokenCache.js.map +1 -0
- package/dist/services/cliUserConfig.js +144 -0
- package/dist/services/cliUserConfig.js.map +1 -0
- package/dist/services/getCliToken.js +26 -0
- package/dist/services/getCliToken.js.map +1 -0
- package/dist/telemetry/getCliTelemetry.js +47 -0
- package/dist/telemetry/getCliTelemetry.js.map +1 -0
- package/dist/telemetry/getTelemetryBaseInfo.js +33 -0
- package/dist/telemetry/getTelemetryBaseInfo.js.map +1 -0
- package/dist/telemetry/readNDJSON.js +18 -0
- package/dist/telemetry/readNDJSON.js.map +1 -0
- package/dist/telemetry/types.js +5 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/util/doImport.js +17 -0
- package/dist/util/doImport.js.map +1 -0
- package/dist/util/environment/getStudioEnvironmentVariables.js +36 -0
- package/dist/util/environment/getStudioEnvironmentVariables.js.map +1 -0
- package/dist/util/environment/mockBrowserEnvironment.js +47 -0
- package/dist/util/environment/mockBrowserEnvironment.js.map +1 -0
- package/dist/util/environment/setupBrowserStubs.js +42 -0
- package/dist/util/environment/setupBrowserStubs.js.map +1 -0
- package/dist/util/environment/stubs.js +142 -0
- package/dist/util/environment/stubs.js.map +1 -0
- package/dist/util/fileExists.js +13 -0
- package/dist/util/fileExists.js.map +1 -0
- package/dist/util/generateHelpUrl.js +11 -0
- package/dist/util/generateHelpUrl.js.map +1 -0
- package/dist/util/getEmptyAuth.js +16 -0
- package/dist/util/getEmptyAuth.js.map +1 -0
- package/dist/util/getSanityEnvVar.js +24 -0
- package/dist/util/getSanityEnvVar.js.map +1 -0
- package/dist/util/getSanityUrl.js +9 -0
- package/dist/util/getSanityUrl.js.map +1 -0
- package/dist/util/importModule.js +32 -0
- package/dist/util/importModule.js.map +1 -0
- package/dist/util/isCi.js +7 -0
- package/dist/util/isCi.js.map +1 -0
- package/dist/util/isInteractive.js +5 -0
- package/dist/util/isInteractive.js.map +1 -0
- package/dist/util/isRecord.js +11 -0
- package/dist/util/isRecord.js.map +1 -0
- package/dist/util/isStaging.js +10 -0
- package/dist/util/isStaging.js.map +1 -0
- package/dist/util/isTrueish.js +10 -0
- package/dist/util/isTrueish.js.map +1 -0
- package/dist/util/normalizePath.js +12 -0
- package/dist/util/normalizePath.js.map +1 -0
- package/dist/util/packageManager.js +55 -0
- package/dist/util/packageManager.js.map +1 -0
- package/dist/util/promisifyWorker.js +72 -0
- package/dist/util/promisifyWorker.js.map +1 -0
- package/dist/util/readJsonFile.js +26 -0
- package/dist/util/readJsonFile.js.map +1 -0
- package/dist/util/readJsonFileSync.js +26 -0
- package/dist/util/readJsonFileSync.js.map +1 -0
- package/dist/util/readPackageJson.js +74 -0
- package/dist/util/readPackageJson.js.map +1 -0
- package/dist/util/resolveLocalPackage.js +82 -0
- package/dist/util/resolveLocalPackage.js.map +1 -0
- package/dist/util/safeStructuredClone.js +43 -0
- package/dist/util/safeStructuredClone.js.map +1 -0
- package/dist/util/tryGetDefaultExport.js +18 -0
- package/dist/util/tryGetDefaultExport.js.map +1 -0
- package/dist/util/writeJsonFileSync.js +19 -0
- package/dist/util/writeJsonFileSync.js.map +1 -0
- package/dist/ux/boxen.js +3 -0
- package/dist/ux/boxen.js.map +1 -0
- package/dist/ux/colorizeJson.js +32 -0
- package/dist/ux/colorizeJson.js.map +1 -0
- package/dist/ux/logSymbols.js +3 -0
- package/dist/ux/logSymbols.js.map +1 -0
- package/dist/ux/prompts.js +51 -0
- package/dist/ux/prompts.js.map +1 -0
- package/dist/ux/spinner.js +3 -0
- package/dist/ux/spinner.js.map +1 -0
- package/dist/ux/timer.js +29 -0
- package/dist/ux/timer.js.map +1 -0
- package/package.json +111 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sanity.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { styleText } from 'node:util';
|
|
2
|
+
import { Command } from '@oclif/core';
|
|
3
|
+
import { getCliConfig } from './config/cli/getCliConfig.js';
|
|
4
|
+
import { findProjectRoot } from './config/findProjectRoot.js';
|
|
5
|
+
import { subdebug } from './debug.js';
|
|
6
|
+
import { NonInteractiveError } from './errors/NonInteractiveError.js';
|
|
7
|
+
import { ProjectRootNotFoundError } from './errors/ProjectRootNotFoundError.js';
|
|
8
|
+
import { exitCodes } from './exitCodes.js';
|
|
9
|
+
import { getGlobalCliClient, getProjectCliClient } from './services/apiClient.js';
|
|
10
|
+
import { getCliTelemetry, reportCliTraceError } from './telemetry/getCliTelemetry.js';
|
|
11
|
+
import { isInteractive } from './util/isInteractive.js';
|
|
12
|
+
const debug = subdebug('sanityCommand');
|
|
13
|
+
export class SanityCommand extends Command {
|
|
14
|
+
args;
|
|
15
|
+
flags;
|
|
16
|
+
/**
|
|
17
|
+
* Get the global API client.
|
|
18
|
+
*
|
|
19
|
+
* @param args - The global API client options.
|
|
20
|
+
* @returns The global API client.
|
|
21
|
+
*
|
|
22
|
+
* @deprecated use `getGlobalCliClient` function directly instead.
|
|
23
|
+
*/ getGlobalApiClient = (args)=>getGlobalCliClient(args);
|
|
24
|
+
/**
|
|
25
|
+
* Get the project API client.
|
|
26
|
+
*
|
|
27
|
+
* @param args - The project API client options.
|
|
28
|
+
* @returns The project API client.
|
|
29
|
+
*
|
|
30
|
+
* @deprecated use `getProjectCliClient` function directly instead.
|
|
31
|
+
*/ getProjectApiClient = (args)=>getProjectCliClient(args);
|
|
32
|
+
/**
|
|
33
|
+
* Helper for outputting to the console.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* this.output.log('Hello')
|
|
38
|
+
* this.output.warn('Warning')
|
|
39
|
+
* this.output.error('Error')
|
|
40
|
+
* ```
|
|
41
|
+
*/ output = {
|
|
42
|
+
error: this.error.bind(this),
|
|
43
|
+
log: this.log.bind(this),
|
|
44
|
+
warn: this.warn.bind(this)
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The telemetry store.
|
|
48
|
+
*
|
|
49
|
+
* @returns The telemetry store.
|
|
50
|
+
*/ telemetry;
|
|
51
|
+
/**
|
|
52
|
+
* Report real command errors to the CLI command trace.
|
|
53
|
+
* User aborts (SIGINT, ExitPromptError) are not reported — the trace is left
|
|
54
|
+
* incomplete, which accurately represents that the command was interrupted.
|
|
55
|
+
*/ async catch(err) {
|
|
56
|
+
// ExitPromptError is thrown by `@inquirer/prompts` when the user cancels a prompt
|
|
57
|
+
// The `message === 'SIGINT'` check matches oclif's own convention (see handle.js in @oclif/core)
|
|
58
|
+
if (err.name === 'ExitPromptError' || err.message === 'SIGINT') {
|
|
59
|
+
this.logToStderr(styleText('yellow', '\u{203A}') + ' Aborted by user');
|
|
60
|
+
return this.exit(exitCodes.SIGINT);
|
|
61
|
+
}
|
|
62
|
+
// In other cases, we _do_ want to report the error
|
|
63
|
+
reportCliTraceError(err);
|
|
64
|
+
return super.catch(err);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get the CLI config.
|
|
68
|
+
*
|
|
69
|
+
* @returns The CLI config.
|
|
70
|
+
*/ async getCliConfig() {
|
|
71
|
+
const root = await this.getProjectRoot();
|
|
72
|
+
debug(`Using project root`, root);
|
|
73
|
+
return getCliConfig(root.directory);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the project ID from passed flags or (if not provided) the CLI config.
|
|
77
|
+
*
|
|
78
|
+
* Optionally accepts a `fallback` function that is called when no project ID
|
|
79
|
+
* can be determined from flags or config. This allows commands to provide
|
|
80
|
+
* interactive project selection while keeping the prompt logic in the CLI package.
|
|
81
|
+
*
|
|
82
|
+
* If the fallback throws a `NonInteractiveError` (e.g. because the terminal is
|
|
83
|
+
* not interactive), it falls through to the standard error with suggestions.
|
|
84
|
+
*
|
|
85
|
+
* Optionally accepts a `deprecatedFlagName` for commands that have a deprecated
|
|
86
|
+
* flag (e.g. `--project`) that should be checked after `--project-id` but before
|
|
87
|
+
* the CLI config.
|
|
88
|
+
*
|
|
89
|
+
* @returns The project ID.
|
|
90
|
+
*/ async getProjectId(options) {
|
|
91
|
+
const hasProjectFlag = this.ctor.flags != null && 'project-id' in this.ctor.flags;
|
|
92
|
+
// Check --project-id flag first
|
|
93
|
+
if (hasProjectFlag) {
|
|
94
|
+
const flagProjectId = 'project-id' in this.flags && typeof this.flags['project-id'] === 'string' ? this.flags['project-id'] : undefined;
|
|
95
|
+
if (flagProjectId) return flagProjectId;
|
|
96
|
+
}
|
|
97
|
+
// Check deprecated flag (e.g. --project) before CLI config
|
|
98
|
+
if (options?.deprecatedFlagName) {
|
|
99
|
+
const deprecatedValue = options.deprecatedFlagName in this.flags && typeof this.flags[options.deprecatedFlagName] === 'string' ? this.flags[options.deprecatedFlagName] : undefined;
|
|
100
|
+
if (deprecatedValue) return deprecatedValue;
|
|
101
|
+
}
|
|
102
|
+
// Fall back to CLI config
|
|
103
|
+
try {
|
|
104
|
+
const config = await this.getCliConfig();
|
|
105
|
+
const configProjectId = config.api?.projectId;
|
|
106
|
+
if (configProjectId) return configProjectId;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
if (!(err instanceof ProjectRootNotFoundError)) throw err;
|
|
109
|
+
// No project root — fall through to fallback/error
|
|
110
|
+
}
|
|
111
|
+
// Offer interactive selection if a fallback was provided
|
|
112
|
+
if (options?.fallback) {
|
|
113
|
+
try {
|
|
114
|
+
return await options.fallback();
|
|
115
|
+
} catch (err) {
|
|
116
|
+
if (!(err instanceof NonInteractiveError)) throw err;
|
|
117
|
+
// Non-interactive: throw with actionable suggestions
|
|
118
|
+
throw new ProjectRootNotFoundError('Unable to determine project ID', {
|
|
119
|
+
cause: err,
|
|
120
|
+
suggestions: [
|
|
121
|
+
...hasProjectFlag ? [
|
|
122
|
+
'Providing a project ID: --project-id <project-id>'
|
|
123
|
+
] : [],
|
|
124
|
+
'Running this command from within a Sanity project directory',
|
|
125
|
+
'Running in an interactive terminal to get a project selection prompt'
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
throw new ProjectRootNotFoundError('Unable to determine project ID', {
|
|
131
|
+
suggestions: [
|
|
132
|
+
...hasProjectFlag ? [
|
|
133
|
+
'Providing a project ID: --project-id <project-id>'
|
|
134
|
+
] : [],
|
|
135
|
+
'Running this command from within a Sanity project directory'
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the project's root directory by resolving the config
|
|
141
|
+
*
|
|
142
|
+
* @returns The project root result.
|
|
143
|
+
*/ getProjectRoot() {
|
|
144
|
+
return findProjectRoot(process.cwd());
|
|
145
|
+
}
|
|
146
|
+
async init() {
|
|
147
|
+
const { args, flags } = await this.parse({
|
|
148
|
+
args: this.ctor.args,
|
|
149
|
+
baseFlags: super.ctor.baseFlags,
|
|
150
|
+
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
151
|
+
flags: this.ctor.flags,
|
|
152
|
+
strict: this.ctor.strict
|
|
153
|
+
});
|
|
154
|
+
this.args = args;
|
|
155
|
+
this.flags = flags;
|
|
156
|
+
this.telemetry = getCliTelemetry();
|
|
157
|
+
await super.init();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Check if the command is running in unattended mode.
|
|
161
|
+
*
|
|
162
|
+
* This means the command should not ask for user input, instead using defaults where
|
|
163
|
+
* possible, and if that does not make sense (eg there's missing information), then we
|
|
164
|
+
* should error out (remember to exit with a non-zero code).
|
|
165
|
+
*
|
|
166
|
+
* Most commands should take an explicit `--yes` flag to enable unattended mode, but
|
|
167
|
+
* some commands may also be run in unattended mode if `process.stdin` is not a TTY
|
|
168
|
+
* (eg when running in a CI environment).
|
|
169
|
+
*/ isUnattended() {
|
|
170
|
+
return this.flags.yes || !this.resolveIsInteractive();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Resolver for checking if the terminal is interactive. Override in tests to provide mock values.
|
|
174
|
+
*
|
|
175
|
+
* @returns Whether the terminal is interactive.
|
|
176
|
+
*/ resolveIsInteractive() {
|
|
177
|
+
return isInteractive();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get the CLI config, returning an empty config if no project root is found.
|
|
181
|
+
*
|
|
182
|
+
* Use this instead of `getCliConfig()` in commands that can operate without a
|
|
183
|
+
* project directory (e.g. when `--project-id` and `--dataset` flags are provided).
|
|
184
|
+
*
|
|
185
|
+
* @returns The CLI config, or an empty config object if no project root is found.
|
|
186
|
+
*/ async tryGetCliConfig() {
|
|
187
|
+
try {
|
|
188
|
+
return await this.getCliConfig();
|
|
189
|
+
} catch (err) {
|
|
190
|
+
if (!(err instanceof ProjectRootNotFoundError)) throw err;
|
|
191
|
+
return {};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
//# sourceMappingURL=SanityCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SanityCommand.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Command, Interfaces} from '@oclif/core'\nimport {type CommandError} from '@oclif/core/interfaces'\n\nimport {getCliConfig} from './config/cli/getCliConfig.js'\nimport {type CliConfig} from './config/cli/types/cliConfig.js'\nimport {findProjectRoot} from './config/findProjectRoot.js'\nimport {type ProjectRootResult} from './config/util/recursivelyResolveProjectRoot.js'\nimport {subdebug} from './debug.js'\nimport {NonInteractiveError} from './errors/NonInteractiveError.js'\nimport {ProjectRootNotFoundError} from './errors/ProjectRootNotFoundError.js'\nimport {exitCodes} from './exitCodes.js'\nimport {\n getGlobalCliClient,\n getProjectCliClient,\n type GlobalCliClientOptions,\n type ProjectCliClientOptions,\n} from './services/apiClient.js'\nimport {getCliTelemetry, reportCliTraceError} from './telemetry/getCliTelemetry.js'\nimport {type CLITelemetryStore} from './telemetry/types.js'\nimport {type Output} from './types.js'\nimport {isInteractive} from './util/isInteractive.js'\n\ntype Flags<T extends typeof Command> = Interfaces.InferredFlags<\n (typeof SanityCommand)['baseFlags'] & T['flags']\n>\n\ntype Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>\n\nconst debug = subdebug('sanityCommand')\n\nexport abstract class SanityCommand<T extends typeof Command> extends Command {\n protected args!: Args<T>\n protected flags!: Flags<T>\n\n /**\n * Get the global API client.\n *\n * @param args - The global API client options.\n * @returns The global API client.\n *\n * @deprecated use `getGlobalCliClient` function directly instead.\n */\n protected getGlobalApiClient = (args: GlobalCliClientOptions) => getGlobalCliClient(args)\n\n /**\n * Get the project API client.\n *\n * @param args - The project API client options.\n * @returns The project API client.\n *\n * @deprecated use `getProjectCliClient` function directly instead.\n */\n protected getProjectApiClient = (args: ProjectCliClientOptions) => getProjectCliClient(args)\n\n /**\n * Helper for outputting to the console.\n *\n * @example\n * ```ts\n * this.output.log('Hello')\n * this.output.warn('Warning')\n * this.output.error('Error')\n * ```\n */\n protected output: Output = {\n error: this.error.bind(this),\n log: this.log.bind(this),\n warn: this.warn.bind(this),\n }\n\n /**\n * The telemetry store.\n *\n * @returns The telemetry store.\n */\n protected telemetry!: CLITelemetryStore\n\n /**\n * Report real command errors to the CLI command trace.\n * User aborts (SIGINT, ExitPromptError) are not reported — the trace is left\n * incomplete, which accurately represents that the command was interrupted.\n */\n protected override async catch(err: CommandError): Promise<void> {\n // ExitPromptError is thrown by `@inquirer/prompts` when the user cancels a prompt\n // The `message === 'SIGINT'` check matches oclif's own convention (see handle.js in @oclif/core)\n if (err.name === 'ExitPromptError' || err.message === 'SIGINT') {\n this.logToStderr(styleText('yellow', '\\u{203A}') + ' Aborted by user')\n return this.exit(exitCodes.SIGINT)\n }\n\n // In other cases, we _do_ want to report the error\n reportCliTraceError(err)\n return super.catch(err)\n }\n\n /**\n * Get the CLI config.\n *\n * @returns The CLI config.\n */\n protected async getCliConfig(): Promise<CliConfig> {\n const root = await this.getProjectRoot()\n\n debug(`Using project root`, root)\n return getCliConfig(root.directory)\n }\n\n /**\n * Get the project ID from passed flags or (if not provided) the CLI config.\n *\n * Optionally accepts a `fallback` function that is called when no project ID\n * can be determined from flags or config. This allows commands to provide\n * interactive project selection while keeping the prompt logic in the CLI package.\n *\n * If the fallback throws a `NonInteractiveError` (e.g. because the terminal is\n * not interactive), it falls through to the standard error with suggestions.\n *\n * Optionally accepts a `deprecatedFlagName` for commands that have a deprecated\n * flag (e.g. `--project`) that should be checked after `--project-id` but before\n * the CLI config.\n *\n * @returns The project ID.\n */\n protected async getProjectId(options?: {\n deprecatedFlagName?: string\n fallback?: () => Promise<string>\n }): Promise<string> {\n const hasProjectFlag = this.ctor.flags != null && 'project-id' in this.ctor.flags\n\n // Check --project-id flag first\n if (hasProjectFlag) {\n const flagProjectId =\n 'project-id' in this.flags && typeof this.flags['project-id'] === 'string'\n ? this.flags['project-id']\n : undefined\n\n if (flagProjectId) return flagProjectId\n }\n\n // Check deprecated flag (e.g. --project) before CLI config\n if (options?.deprecatedFlagName) {\n const deprecatedValue =\n options.deprecatedFlagName in this.flags &&\n typeof this.flags[options.deprecatedFlagName] === 'string'\n ? (this.flags[options.deprecatedFlagName] as string)\n : undefined\n\n if (deprecatedValue) return deprecatedValue\n }\n\n // Fall back to CLI config\n try {\n const config = await this.getCliConfig()\n const configProjectId = config.api?.projectId\n if (configProjectId) return configProjectId\n } catch (err) {\n if (!(err instanceof ProjectRootNotFoundError)) throw err\n // No project root — fall through to fallback/error\n }\n\n // Offer interactive selection if a fallback was provided\n if (options?.fallback) {\n try {\n return await options.fallback()\n } catch (err) {\n if (!(err instanceof NonInteractiveError)) throw err\n // Non-interactive: throw with actionable suggestions\n throw new ProjectRootNotFoundError('Unable to determine project ID', {\n cause: err,\n suggestions: [\n ...(hasProjectFlag ? ['Providing a project ID: --project-id <project-id>'] : []),\n 'Running this command from within a Sanity project directory',\n 'Running in an interactive terminal to get a project selection prompt',\n ],\n })\n }\n }\n\n throw new ProjectRootNotFoundError('Unable to determine project ID', {\n suggestions: [\n ...(hasProjectFlag ? ['Providing a project ID: --project-id <project-id>'] : []),\n 'Running this command from within a Sanity project directory',\n ],\n })\n }\n\n /**\n * Get the project's root directory by resolving the config\n *\n * @returns The project root result.\n */\n protected getProjectRoot(): Promise<ProjectRootResult> {\n return findProjectRoot(process.cwd())\n }\n\n public async init(): Promise<void> {\n const {args, flags} = await this.parse({\n args: this.ctor.args,\n baseFlags: (super.ctor as typeof SanityCommand).baseFlags,\n enableJsonFlag: this.ctor.enableJsonFlag,\n flags: this.ctor.flags,\n strict: this.ctor.strict,\n })\n\n this.args = args as Args<T>\n this.flags = flags as Flags<T>\n this.telemetry = getCliTelemetry()\n\n await super.init()\n }\n\n /**\n * Check if the command is running in unattended mode.\n *\n * This means the command should not ask for user input, instead using defaults where\n * possible, and if that does not make sense (eg there's missing information), then we\n * should error out (remember to exit with a non-zero code).\n *\n * Most commands should take an explicit `--yes` flag to enable unattended mode, but\n * some commands may also be run in unattended mode if `process.stdin` is not a TTY\n * (eg when running in a CI environment).\n */\n protected isUnattended(): boolean {\n return this.flags.yes || !this.resolveIsInteractive()\n }\n\n /**\n * Resolver for checking if the terminal is interactive. Override in tests to provide mock values.\n *\n * @returns Whether the terminal is interactive.\n */\n protected resolveIsInteractive(): boolean {\n return isInteractive()\n }\n\n /**\n * Get the CLI config, returning an empty config if no project root is found.\n *\n * Use this instead of `getCliConfig()` in commands that can operate without a\n * project directory (e.g. when `--project-id` and `--dataset` flags are provided).\n *\n * @returns The CLI config, or an empty config object if no project root is found.\n */\n protected async tryGetCliConfig(): Promise<CliConfig> {\n try {\n return await this.getCliConfig()\n } catch (err) {\n if (!(err instanceof ProjectRootNotFoundError)) throw err\n return {}\n }\n }\n}\n"],"names":["styleText","Command","getCliConfig","findProjectRoot","subdebug","NonInteractiveError","ProjectRootNotFoundError","exitCodes","getGlobalCliClient","getProjectCliClient","getCliTelemetry","reportCliTraceError","isInteractive","debug","SanityCommand","args","flags","getGlobalApiClient","getProjectApiClient","output","error","bind","log","warn","telemetry","catch","err","name","message","logToStderr","exit","SIGINT","root","getProjectRoot","directory","getProjectId","options","hasProjectFlag","ctor","flagProjectId","undefined","deprecatedFlagName","deprecatedValue","config","configProjectId","api","projectId","fallback","cause","suggestions","process","cwd","init","parse","baseFlags","enableJsonFlag","strict","isUnattended","yes","resolveIsInteractive","tryGetCliConfig"],"mappings":"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"}
|