@sanity/cli 3.93.0 → 3.93.1-bump-pkg-utils.34.5d0c0b3d22

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.
Files changed (160) hide show
  1. package/lib/_chunks-cjs/cli.js +5 -5
  2. package/lib/_chunks-cjs/cli.js.map +1 -1
  3. package/lib/_chunks-cjs/cliWorker.js.map +1 -1
  4. package/lib/_chunks-cjs/generateAction.js.map +1 -1
  5. package/lib/_chunks-cjs/getCliConfig.js.map +1 -1
  6. package/lib/_chunks-cjs/journeyConfig.js.map +1 -1
  7. package/lib/_chunks-cjs/loadEnv.js.map +1 -1
  8. package/lib/index.js.map +1 -1
  9. package/lib/index.mjs.map +1 -1
  10. package/lib/run.js.map +1 -1
  11. package/lib/workers/getAndWriteJourneySchema.js.map +1 -1
  12. package/lib/workers/getCliConfig.js.map +1 -1
  13. package/lib/workers/typegenGenerate.js.map +1 -1
  14. package/package.json +6 -7
  15. package/templates/blog/README.md +1 -1
  16. package/templates/clean/README.md +1 -1
  17. package/templates/ecommerce/README.md +1 -1
  18. package/templates/get-started/README.md +1 -1
  19. package/templates/moviedb/README.md +1 -1
  20. package/templates/quickstart/README.md +1 -1
  21. package/src/CommandRunner.ts +0 -219
  22. package/src/__telemetry__/cli.telemetry.ts +0 -29
  23. package/src/__telemetry__/init.telemetry.ts +0 -95
  24. package/src/actions/codemod/codemodAction.ts +0 -109
  25. package/src/actions/codemod/mods/deskRename.ts +0 -19
  26. package/src/actions/codemod/mods/index.ts +0 -9
  27. package/src/actions/codemod/mods/partsTypeDirective.ts +0 -28
  28. package/src/actions/codemod/mods/reactIconsV3.ts +0 -54
  29. package/src/actions/codemod/types.ts +0 -10
  30. package/src/actions/init-plugin/bootstrapFromTemplate.ts +0 -196
  31. package/src/actions/init-project/bootstrapLocalTemplate.ts +0 -201
  32. package/src/actions/init-project/bootstrapRemoteTemplate.ts +0 -118
  33. package/src/actions/init-project/createAppCliConfig.ts +0 -24
  34. package/src/actions/init-project/createCliConfig.ts +0 -31
  35. package/src/actions/init-project/createPackageManifest.ts +0 -102
  36. package/src/actions/init-project/createStudioConfig.ts +0 -53
  37. package/src/actions/init-project/determineAppTemplate.ts +0 -13
  38. package/src/actions/init-project/fsUtils.ts +0 -40
  39. package/src/actions/init-project/git.ts +0 -59
  40. package/src/actions/init-project/initProject.ts +0 -1708
  41. package/src/actions/init-project/processTemplate.ts +0 -55
  42. package/src/actions/init-project/promptForDatasetName.ts +0 -68
  43. package/src/actions/init-project/prompts/index.ts +0 -51
  44. package/src/actions/init-project/prompts/nextjs.ts +0 -59
  45. package/src/actions/init-project/readPackageJson.ts +0 -17
  46. package/src/actions/init-project/templates/appQuickstart.ts +0 -23
  47. package/src/actions/init-project/templates/appSanityUi.ts +0 -25
  48. package/src/actions/init-project/templates/blog.ts +0 -5
  49. package/src/actions/init-project/templates/clean.ts +0 -5
  50. package/src/actions/init-project/templates/getStarted.ts +0 -37
  51. package/src/actions/init-project/templates/index.ts +0 -24
  52. package/src/actions/init-project/templates/moviedb.ts +0 -35
  53. package/src/actions/init-project/templates/nextjs/index.ts +0 -238
  54. package/src/actions/init-project/templates/nextjs/schemaTypes/blog.ts +0 -252
  55. package/src/actions/init-project/templates/quickstart.ts +0 -5
  56. package/src/actions/init-project/templates/shopify.ts +0 -78
  57. package/src/actions/init-project/templates/shopifyOnline.ts +0 -50
  58. package/src/actions/init-project/updateInitialTemplateMetadata.ts +0 -24
  59. package/src/actions/login/login.telemetry.ts +0 -18
  60. package/src/actions/login/login.ts +0 -350
  61. package/src/actions/login/types.ts +0 -19
  62. package/src/actions/project/createProject.ts +0 -36
  63. package/src/actions/telemetry/setTelemetryConsent.ts +0 -101
  64. package/src/actions/typegen/generate.telemetry.ts +0 -20
  65. package/src/actions/typegen/generateAction.ts +0 -210
  66. package/src/actions/versions/findSanityModuleVersions.ts +0 -185
  67. package/src/actions/yarn/events.ts +0 -73
  68. package/src/cli.ts +0 -350
  69. package/src/cliClient.ts +0 -62
  70. package/src/commands/blueprints/addBlueprintsCommand.ts +0 -155
  71. package/src/commands/blueprints/blueprintsGroup.ts +0 -10
  72. package/src/commands/blueprints/configBlueprintsCommand.ts +0 -86
  73. package/src/commands/blueprints/deployBlueprintsCommand.ts +0 -63
  74. package/src/commands/blueprints/destroyBlueprintsCommand.ts +0 -78
  75. package/src/commands/blueprints/infoBlueprintsCommand.ts +0 -55
  76. package/src/commands/blueprints/initBlueprintsCommand.ts +0 -99
  77. package/src/commands/blueprints/logsBlueprintsCommand.ts +0 -66
  78. package/src/commands/blueprints/planBlueprintsCommand.ts +0 -51
  79. package/src/commands/blueprints/stacksBlueprintsCommand.ts +0 -66
  80. package/src/commands/codemod/codemodCommand.ts +0 -32
  81. package/src/commands/debug/debugCommand.ts +0 -26
  82. package/src/commands/debug/printDebugInfo.ts +0 -243
  83. package/src/commands/docs/docsCommand.ts +0 -20
  84. package/src/commands/functions/devFunctionsCommand.ts +0 -73
  85. package/src/commands/functions/envFunctionsCommand.ts +0 -105
  86. package/src/commands/functions/functionsGroup.ts +0 -10
  87. package/src/commands/functions/logsFunctionsCommand.ts +0 -94
  88. package/src/commands/functions/testFunctionsCommand.ts +0 -93
  89. package/src/commands/help/helpCommand.ts +0 -21
  90. package/src/commands/help/showHelp.ts +0 -58
  91. package/src/commands/index.ts +0 -72
  92. package/src/commands/init/initCommand.ts +0 -123
  93. package/src/commands/install/installCommand.ts +0 -38
  94. package/src/commands/learn/learnCommand.ts +0 -20
  95. package/src/commands/login/loginCommand.ts +0 -29
  96. package/src/commands/logout/logoutCommand.ts +0 -52
  97. package/src/commands/manage/manageCommand.ts +0 -24
  98. package/src/commands/projects/listProjectsCommand.ts +0 -62
  99. package/src/commands/projects/projectsGroup.ts +0 -10
  100. package/src/commands/telemetry/disableTelemetryCommand.ts +0 -19
  101. package/src/commands/telemetry/enableTelemetryCommand.ts +0 -19
  102. package/src/commands/telemetry/telemetryGroup.ts +0 -10
  103. package/src/commands/telemetry/telemetryStatusCommand.ts +0 -89
  104. package/src/commands/typegen/generateTypesCommand.ts +0 -56
  105. package/src/commands/typegen/typegenGroup.ts +0 -10
  106. package/src/commands/versions/printVersionResult.ts +0 -51
  107. package/src/commands/versions/versionsCommand.ts +0 -13
  108. package/src/config.ts +0 -14
  109. package/src/debug.ts +0 -3
  110. package/src/index.ts +0 -6
  111. package/src/outputters/cliOutputter.ts +0 -47
  112. package/src/packageManager/getInstallCommand.ts +0 -26
  113. package/src/packageManager/getUpgradeCommand.ts +0 -52
  114. package/src/packageManager/index.ts +0 -33
  115. package/src/packageManager/installPackages.ts +0 -99
  116. package/src/packageManager/packageManagerChoice.ts +0 -204
  117. package/src/packageManager/uninstallPackages.ts +0 -44
  118. package/src/packageManager/yarnStub.ts +0 -22
  119. package/src/prompters/cliPrompter.ts +0 -9
  120. package/src/run.ts +0 -8
  121. package/src/studioDependencies.ts +0 -25
  122. package/src/types.ts +0 -387
  123. package/src/util/canLaunchBrowser.ts +0 -12
  124. package/src/util/cliWorker.ts +0 -34
  125. package/src/util/clientWrapper.ts +0 -119
  126. package/src/util/copy.ts +0 -50
  127. package/src/util/createExpiringConfig.ts +0 -80
  128. package/src/util/createTelemetryStore.ts +0 -204
  129. package/src/util/detectRuntime.ts +0 -12
  130. package/src/util/dynamicRequire.ts +0 -17
  131. package/src/util/frameworkPort.ts +0 -63
  132. package/src/util/generateCommandsDocumentation.ts +0 -62
  133. package/src/util/getCliConfig.ts +0 -172
  134. package/src/util/getCliVersion.ts +0 -22
  135. package/src/util/getLocalVersion.ts +0 -35
  136. package/src/util/getProjectDefaults.ts +0 -103
  137. package/src/util/getProviderName.ts +0 -9
  138. package/src/util/getUserConfig.ts +0 -15
  139. package/src/util/isCi.ts +0 -7
  140. package/src/util/isCommandGroup.ts +0 -7
  141. package/src/util/isInteractive.ts +0 -3
  142. package/src/util/isTrueish.ts +0 -8
  143. package/src/util/journeyConfig.ts +0 -280
  144. package/src/util/loadEnv.ts +0 -110
  145. package/src/util/mergeCommands.ts +0 -78
  146. package/src/util/neatStack.ts +0 -30
  147. package/src/util/noSuchCommandText.ts +0 -91
  148. package/src/util/parseArguments.ts +0 -76
  149. package/src/util/pathExists.ts +0 -14
  150. package/src/util/readJson.ts +0 -6
  151. package/src/util/readdirRecursive.ts +0 -26
  152. package/src/util/remoteTemplate.ts +0 -320
  153. package/src/util/resolveLatestVersions.ts +0 -24
  154. package/src/util/resolveRootDir.ts +0 -59
  155. package/src/util/telemetryDisclosure.ts +0 -45
  156. package/src/util/updateNotifier.ts +0 -158
  157. package/src/util/writeJson.ts +0 -6
  158. package/src/workers/getAndWriteJourneySchema.ts +0 -7
  159. package/src/workers/getCliConfig.ts +0 -14
  160. package/src/workers/typegenGenerate.ts +0 -228
@@ -1,91 +0,0 @@
1
- import chalk from 'chalk'
2
- import leven from 'leven'
3
-
4
- import {type CliCommandDefinition, type CliCommandGroupDefinition} from '../types'
5
-
6
- const commonMistakes: Record<string, string | undefined> = {get: 'list'}
7
- const levenThreshold = 3
8
- const coreCommands = [
9
- 'build',
10
- 'check',
11
- 'configcheck',
12
- 'cors',
13
- 'dataset',
14
- 'deploy',
15
- 'dev',
16
- 'documents',
17
- 'exec',
18
- 'graphql',
19
- 'hook',
20
- 'migration',
21
- 'manifest',
22
- 'preview',
23
- 'schema',
24
- 'start',
25
- 'undeploy',
26
- 'uninstall',
27
- 'users',
28
- ]
29
-
30
- // These are disabled in v3, but still present because of v2.
31
- // We don't want to suggest them anymore, though.
32
- const discouragedCommands = ['upgrade', 'check', 'configcheck', 'uninstall']
33
-
34
- const helpText = `
35
- Run the command again within a Sanity project directory, where "sanity"
36
- is installed as a dependency.`
37
-
38
- export function getNoSuchCommandText(
39
- cmdName: string,
40
- parentGroupName?: string | null,
41
- groups?: Record<string, (CliCommandDefinition | CliCommandGroupDefinition)[]>,
42
- ): string {
43
- if (parentGroupName && groups && groups[parentGroupName]) {
44
- return suggestCommand(cmdName, groups[parentGroupName], parentGroupName)
45
- }
46
-
47
- const isCoreCommand = coreCommands.includes(cmdName)
48
- if (isCoreCommand) {
49
- return `Command "${cmdName}" is not available outside of a Sanity project context.${helpText}`
50
- }
51
-
52
- return suggestCommand(cmdName, groups ? groups.default : [])
53
- }
54
-
55
- function suggestCommand(
56
- cmdName: string,
57
- group: (CliCommandDefinition | CliCommandGroupDefinition)[],
58
- parentGroupName: string | null = null,
59
- ) {
60
- // Try to find something similar
61
- const closest = group
62
- .filter((command) => !discouragedCommands.includes(command.name))
63
- .map((command) => leven(command.name, cmdName))
64
- .reduce(
65
- (current: {index: number; distance: number}, distance: number, index: number) =>
66
- distance < current.distance ? {index, distance} : current,
67
- {index: 0, distance: +Infinity},
68
- )
69
-
70
- // Given we are within our target threshold, suggest the command
71
- let suggestCmd = ''
72
- if (closest.distance <= levenThreshold) {
73
- const cmdCandidate = group[closest.index]
74
- suggestCmd = cmdCandidate.name
75
- }
76
-
77
- // Is this a common mistake that we can suggest an alias for?
78
- const alternative = commonMistakes[cmdName]
79
- if (!suggestCmd && alternative) {
80
- suggestCmd = alternative
81
- }
82
-
83
- const input = chalk.cyan(`"${cmdName}"`)
84
- const suggest = chalk.green(`"${suggestCmd}"`)
85
- const help = chalk.cyan('"sanity --help"')
86
-
87
- const didYouMean = suggestCmd ? `Did you mean ${suggest}? ` : ' '
88
- return parentGroupName
89
- ? `${input} is not a subcommand of "sanity ${parentGroupName}". ${didYouMean}See ${help}`
90
- : `${input} is not a sanity command. ${didYouMean}See ${help}`
91
- }
@@ -1,76 +0,0 @@
1
- import minimist from 'minimist'
2
-
3
- export interface ParsedArguments<F = Record<string, string>> {
4
- /**
5
- * Group or command name, eg `dataset` (`sanity dataset`) or `import` (`sanity dataset import`)
6
- */
7
- groupOrCommand: string
8
-
9
- // Raw, forwarded arguments, for commands that want to be more explicit about parsing
10
- argv: string[]
11
-
12
- /**
13
- * Command flags, without the core options (help, debug, version etc)
14
- */
15
- extOptions: F
16
-
17
- /**
18
- * Command arguments, eg any arguments after `sanity <command>` (no flags)
19
- */
20
- argsWithoutOptions: string[]
21
-
22
- /**
23
- * Arguments after the ended argument list (--)
24
- */
25
- extraArguments: string[]
26
-
27
- /**
28
- * Options mostly relevant for the core CLI runner
29
- */
30
- coreOptions: {
31
- h: boolean
32
- help: boolean
33
-
34
- d: boolean
35
- debug: boolean
36
-
37
- v: boolean
38
- version: boolean
39
- }
40
- }
41
-
42
- export function parseArguments(argv = process.argv): ParsedArguments {
43
- /* eslint-disable id-length */
44
- // prettier-ignore
45
- const {
46
- _,
47
- h, help,
48
- d, debug,
49
- v, version,
50
- '--': extraArguments,
51
- ...extOptions
52
- } = minimist(argv.slice(2), {
53
- '--': true,
54
- boolean: ['h', 'help', 'd', 'debug', 'v', 'version'],
55
- string: ['_']
56
- })
57
-
58
- const [groupOrCommand, ...argsWithoutOptions] = _
59
-
60
- return {
61
- groupOrCommand,
62
-
63
- argv,
64
- extOptions,
65
- argsWithoutOptions,
66
- extraArguments: extraArguments || [],
67
-
68
- // prettier-ignore
69
- coreOptions: {
70
- h, help,
71
- d, debug,
72
- v, version,
73
- },
74
- }
75
- /* eslint-enable id-length */
76
- }
@@ -1,14 +0,0 @@
1
- import fs from 'node:fs/promises'
2
-
3
- export async function pathExists(filePath: string): Promise<boolean> {
4
- try {
5
- await fs.access(filePath)
6
- return true
7
- } catch (err) {
8
- if (err.code === 'ENOENT') {
9
- return false
10
- }
11
-
12
- throw err
13
- }
14
- }
@@ -1,6 +0,0 @@
1
- import {readFile} from 'node:fs/promises'
2
-
3
- export async function readJson<T>(filePath: string): Promise<T> {
4
- const content = await readFile(filePath, 'utf8')
5
- return JSON.parse(content)
6
- }
@@ -1,26 +0,0 @@
1
- import fs from 'node:fs/promises'
2
- import path from 'node:path'
3
-
4
- export interface ReaddirItem {
5
- path: string
6
- isDir: boolean
7
- }
8
-
9
- export async function readdirRecursive(dir: string): Promise<ReaddirItem[]> {
10
- let content: ReaddirItem[] = []
11
-
12
- const currentPath = path.resolve(dir)
13
- const dirContent = (await fs.readdir(currentPath)).map((item) => path.join(currentPath, item))
14
-
15
- for (const subPath of dirContent) {
16
- const stat = await fs.stat(subPath)
17
- const isDir = stat.isDirectory()
18
- content.push({path: subPath, isDir})
19
-
20
- if (isDir) {
21
- content = content.concat(await readdirRecursive(subPath))
22
- }
23
- }
24
-
25
- return content
26
- }
@@ -1,320 +0,0 @@
1
- import {access, readFile, writeFile} from 'node:fs/promises'
2
- import {join, posix, sep} from 'node:path'
3
- import {Readable} from 'node:stream'
4
- import {pipeline} from 'node:stream/promises'
5
- import {type ReadableStream} from 'node:stream/web'
6
-
7
- import {ENV_TEMPLATE_FILES, REQUIRED_ENV_VAR} from '@sanity/template-validator'
8
- import {x} from 'tar'
9
-
10
- import {debug} from '../debug'
11
- import {type CliApiClient, type PackageJson} from '../types'
12
-
13
- const DISALLOWED_PATHS = [
14
- // Prevent security risks from unknown GitHub Actions
15
- '/.github/',
16
- ]
17
-
18
- const ENV_VAR = {
19
- ...REQUIRED_ENV_VAR,
20
- READ_TOKEN: 'SANITY_API_READ_TOKEN',
21
- WRITE_TOKEN: 'SANITY_API_WRITE_TOKEN',
22
- } as const
23
-
24
- const API_READ_TOKEN_ROLE = 'viewer'
25
- const API_WRITE_TOKEN_ROLE = 'editor'
26
-
27
- type EnvData = {
28
- projectId: string
29
- dataset: string
30
- readToken?: string
31
- writeToken?: string
32
- }
33
-
34
- type GithubUrlString =
35
- | `https://github.com/${string}/${string}`
36
- | `https://www.github.com/${string}/${string}`
37
-
38
- export type RepoInfo = {
39
- username: string
40
- name: string
41
- branch: string
42
- filePath: string
43
- }
44
-
45
- export function getGitHubRawContentUrl(repoInfo: RepoInfo): string {
46
- const {username, name, branch, filePath} = repoInfo
47
- return `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`
48
- }
49
-
50
- function isGithubRepoShorthand(value: string): boolean {
51
- if (URL.canParse(value)) {
52
- return false
53
- }
54
- // This supports :owner/:repo and :owner/:repo/nested/path, e.g.
55
- // sanity-io/sanity
56
- // sanity-io/sanity/templates/next-js
57
- // sanity-io/templates/live-content-api
58
- // sanity-io/sanity/packages/@sanity/cli/test/test-template
59
- return /^[\w-]+\/[\w-.]+(\/[@\w-.]+)*$/.test(value)
60
- }
61
-
62
- function isGithubRepoUrl(value: string | URL): value is URL | GithubUrlString {
63
- if (URL.canParse(value) === false) {
64
- return false
65
- }
66
- const url = new URL(value)
67
- const pathSegments = url.pathname.slice(1).split('/')
68
-
69
- return (
70
- url.protocol === 'https:' &&
71
- url.hostname === 'github.com' &&
72
- // The pathname must have at least 2 segments. If it has more than 2, the
73
- // third must be "tree" and it must have at least 4 segments.
74
- // https://github.com/:owner/:repo
75
- // https://github.com/:owner/:repo/tree/:ref
76
- pathSegments.length >= 2 &&
77
- (pathSegments.length > 2 ? pathSegments[2] === 'tree' && pathSegments.length >= 4 : true)
78
- )
79
- }
80
-
81
- async function downloadTarStream(url: string, bearerToken?: string): Promise<Readable> {
82
- const headers: Record<string, string> = {}
83
- if (bearerToken) {
84
- headers.Authorization = `Bearer ${bearerToken}`
85
- }
86
-
87
- const res = await fetch(url, {headers})
88
-
89
- if (!res.body) {
90
- throw new Error(`Failed to download: ${url}`)
91
- }
92
-
93
- return Readable.fromWeb(res.body as ReadableStream)
94
- }
95
-
96
- export function checkIsRemoteTemplate(templateName?: string): boolean {
97
- return templateName?.includes('/') ?? false
98
- }
99
-
100
- export async function getGitHubRepoInfo(value: string, bearerToken?: string): Promise<RepoInfo> {
101
- let username = ''
102
- let name = ''
103
- let branch = ''
104
- let filePath = ''
105
-
106
- if (isGithubRepoShorthand(value)) {
107
- const parts = value.split('/')
108
- username = parts[0]
109
- name = parts[1]
110
- // If there are more segments after owner/repo, they form the file path
111
- if (parts.length > 2) {
112
- filePath = parts.slice(2).join('/')
113
- }
114
- }
115
-
116
- if (isGithubRepoUrl(value)) {
117
- const url = new URL(value)
118
- const pathSegments = url.pathname.slice(1).split('/')
119
- username = pathSegments[0]
120
- name = pathSegments[1]
121
-
122
- // If we have a "tree" segment, everything after branch is the file path
123
- if (pathSegments[2] === 'tree') {
124
- branch = pathSegments[3]
125
- if (pathSegments.length > 4) {
126
- filePath = pathSegments.slice(4).join('/')
127
- }
128
- }
129
- }
130
-
131
- if (!username || !name) {
132
- throw new Error('Invalid GitHub repository format')
133
- }
134
-
135
- const tokenMessage =
136
- 'GitHub repository not found. For private repositories, use --template-token to provide an access token.\n\n' +
137
- 'You can generate a new token at https://github.com/settings/personal-access-tokens/new\n' +
138
- 'Set the token to "read-only" with repository access and a short expiry (e.g. 7 days) for security.'
139
-
140
- try {
141
- const headers: Record<string, string> = {}
142
- if (bearerToken) {
143
- headers.Authorization = `Bearer ${bearerToken}`
144
- }
145
-
146
- const infoResponse = await fetch(`https://api.github.com/repos/${username}/${name}`, {
147
- headers,
148
- })
149
-
150
- if (infoResponse.status !== 200) {
151
- if (infoResponse.status === 404) {
152
- throw new Error(tokenMessage)
153
- }
154
- throw new Error('GitHub repository not found')
155
- }
156
-
157
- const info = await infoResponse.json()
158
-
159
- return {
160
- username,
161
- name,
162
- branch: branch || info.default_branch,
163
- filePath,
164
- }
165
- } catch {
166
- throw new Error(tokenMessage)
167
- }
168
- }
169
-
170
- export async function downloadAndExtractRepo(
171
- root: string,
172
- {username, name, branch, filePath}: RepoInfo,
173
- bearerToken?: string,
174
- ): Promise<void> {
175
- let rootPath: string | null = null
176
- await pipeline(
177
- await downloadTarStream(
178
- `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`,
179
- bearerToken,
180
- ),
181
- x({
182
- cwd: root,
183
- strip: filePath ? filePath.split('/').length + 1 : 1,
184
- filter: (p: string) => {
185
- const posixPath = p.split(sep).join(posix.sep)
186
- if (rootPath === null) {
187
- const pathSegments = posixPath.split(posix.sep)
188
- rootPath = pathSegments.length ? pathSegments[0] : null
189
- }
190
- for (const disallowedPath of DISALLOWED_PATHS) {
191
- if (posixPath.includes(disallowedPath)) return false
192
- }
193
- return posixPath.startsWith(`${rootPath}${filePath ? `/${filePath}/` : '/'}`)
194
- },
195
- }),
196
- )
197
- }
198
-
199
- export async function checkIfNeedsApiToken(root: string, type: 'read' | 'write'): Promise<boolean> {
200
- try {
201
- const templatePath = await Promise.any(
202
- ENV_TEMPLATE_FILES.map(async (file) => {
203
- await access(join(root, file))
204
- return file
205
- }),
206
- )
207
- const templateContent = await readFile(join(root, templatePath), 'utf8')
208
- return templateContent.includes(type === 'read' ? ENV_VAR.READ_TOKEN : ENV_VAR.WRITE_TOKEN)
209
- } catch {
210
- return false
211
- }
212
- }
213
-
214
- export async function applyEnvVariables(
215
- root: string,
216
- envData: EnvData,
217
- targetName = '.env',
218
- ): Promise<void> {
219
- const templatePath = await Promise.any(
220
- ENV_TEMPLATE_FILES.map(async (file) => {
221
- await access(join(root, file))
222
- return file
223
- }),
224
- ).catch(() => undefined)
225
-
226
- if (!templatePath) {
227
- return // No template .env file found, skip
228
- }
229
-
230
- try {
231
- const templateContent = await readFile(join(root, templatePath), 'utf8')
232
- const {projectId, dataset, readToken = '', writeToken = ''} = envData
233
-
234
- const findAndReplaceVariable = (
235
- content: string,
236
- varRegex: RegExp | string,
237
- value: string,
238
- useQuotes: boolean,
239
- ) => {
240
- const varPattern = typeof varRegex === 'string' ? varRegex : varRegex.source
241
- const pattern = new RegExp(`.*${varPattern}=.*$`, 'gm')
242
- const matches = content.matchAll(pattern)
243
- return Array.from(matches).reduce((updatedContent, match) => {
244
- if (!match[0]) return updatedContent
245
- const varName = match[0].split('=')[0].trim()
246
- return updatedContent.replace(
247
- new RegExp(`${varName}=.*$`, 'gm'),
248
- `${varName}=${useQuotes ? `"${value}"` : value}`,
249
- )
250
- }, content)
251
- }
252
-
253
- let envContent = templateContent
254
- const vars = [
255
- {pattern: ENV_VAR.PROJECT_ID, value: projectId},
256
- {pattern: ENV_VAR.DATASET, value: dataset},
257
- {pattern: ENV_VAR.READ_TOKEN, value: readToken},
258
- {pattern: ENV_VAR.WRITE_TOKEN, value: writeToken},
259
- ]
260
- const useQuotes = templateContent.includes('="')
261
-
262
- for (const {pattern, value} of vars) {
263
- envContent = findAndReplaceVariable(envContent, pattern, value, useQuotes)
264
- }
265
-
266
- await writeFile(join(root, targetName), envContent)
267
- } catch {
268
- throw new Error(
269
- 'Failed to set environment variables. This could be due to file permissions or the .env file format. See https://www.sanity.io/docs/environment-variables for details on environment variable setup.',
270
- )
271
- }
272
- }
273
-
274
- export async function tryApplyPackageName(root: string, name: string): Promise<void> {
275
- try {
276
- const packageJson = await readFile(join(root, 'package.json'), 'utf8')
277
- const pkg: PackageJson = JSON.parse(packageJson)
278
- pkg.name = name
279
-
280
- await writeFile(join(root, 'package.json'), JSON.stringify(pkg, null, 2))
281
- } catch {
282
- // noop
283
- }
284
- }
285
-
286
- export async function generateSanityApiToken(
287
- label: string,
288
- type: 'read' | 'write',
289
- projectId: string,
290
- apiClient: CliApiClient,
291
- ): Promise<string> {
292
- const response = await apiClient({requireProject: false, requireUser: true})
293
- .config({apiVersion: 'v2021-06-07'})
294
- .request<{key: string}>({
295
- uri: `/projects/${projectId}/tokens`,
296
- method: 'POST',
297
- body: {
298
- label: `${label} (${Date.now()})`,
299
- roleName: type === 'read' ? API_READ_TOKEN_ROLE : API_WRITE_TOKEN_ROLE,
300
- },
301
- })
302
- return response.key
303
- }
304
-
305
- export async function setCorsOrigin(
306
- origin: string,
307
- projectId: string,
308
- apiClient: CliApiClient,
309
- ): Promise<void> {
310
- try {
311
- await apiClient({api: {projectId}}).request({
312
- method: 'POST',
313
- url: '/cors',
314
- body: {origin: origin, allowCredentials: true}, // allowCredentials is true to allow for embedded studios if needed
315
- })
316
- } catch (error) {
317
- // Silent fail, it most likely means that the origin is already set
318
- debug('Failed to set CORS origin', error)
319
- }
320
- }
@@ -1,24 +0,0 @@
1
- import latestVersion from 'get-latest-version'
2
- import promiseProps from 'promise-props-recursive'
3
-
4
- /**
5
- * Resolve the latest versions of given packages within their defined ranges
6
- *
7
- * @param pkgs - `{packageName: rangeOrTag}`
8
- * @returns Object of resolved version numbers
9
- */
10
- export function resolveLatestVersions(
11
- pkgs: Record<string, string>,
12
- ): Promise<Record<string, string>> {
13
- const lookups: Record<string, Promise<string> | string> = {}
14
- for (const [packageName, range] of Object.entries(pkgs)) {
15
- lookups[packageName] =
16
- range === 'latest' ? latestVersion(packageName, {range}).then(caretify) : range
17
- }
18
-
19
- return promiseProps(lookups)
20
- }
21
-
22
- function caretify(version: string | undefined) {
23
- return version ? `^${version}` : 'latest'
24
- }
@@ -1,59 +0,0 @@
1
- /* eslint-disable no-sync */
2
- import fs from 'node:fs'
3
- import path from 'node:path'
4
-
5
- import {debug} from '../debug'
6
-
7
- /**
8
- * Resolve project root directory, falling back to cwd if it cannot be found
9
- */
10
- export function resolveRootDir(cwd: string): string {
11
- try {
12
- return resolveProjectRoot(cwd) || cwd
13
- } catch (err) {
14
- throw new Error(`Error occurred trying to resolve project root:\n${err.message}`)
15
- }
16
- }
17
-
18
- function hasSanityConfig(basePath: string, configName: string): boolean {
19
- const buildConfigs = [
20
- fileExists(path.join(basePath, `${configName}.js`)),
21
- fileExists(path.join(basePath, `${configName}.ts`)),
22
- isSanityV2StudioRoot(basePath),
23
- ]
24
-
25
- return buildConfigs.some(Boolean)
26
- }
27
-
28
- function resolveProjectRoot(basePath: string, iterations = 0): string | false {
29
- const configName = 'sanity.config'
30
- if (hasSanityConfig(basePath, configName)) {
31
- return basePath
32
- }
33
-
34
- const parentDir = path.resolve(basePath, '..')
35
- if (parentDir === basePath || iterations > 30) {
36
- // Reached root (or max depth), give up
37
- return false
38
- }
39
-
40
- return resolveProjectRoot(parentDir, iterations + 1)
41
- }
42
-
43
- function isSanityV2StudioRoot(basePath: string): boolean {
44
- try {
45
- const content = fs.readFileSync(path.join(basePath, 'sanity.json'), 'utf8')
46
- const sanityJson = JSON.parse(content)
47
- const isRoot = Boolean(sanityJson?.root)
48
- if (isRoot) {
49
- debug('Found Sanity v2 studio root at %s', basePath)
50
- }
51
- return isRoot
52
- } catch (err) {
53
- return false
54
- }
55
- }
56
-
57
- function fileExists(filePath: string): boolean {
58
- return fs.existsSync(filePath)
59
- }
@@ -1,45 +0,0 @@
1
- import boxen from 'boxen'
2
- import chalk from 'chalk'
3
-
4
- import {telemetryLearnMoreMessage} from '../commands/telemetry/telemetryStatusCommand'
5
- import {debug} from '../debug'
6
- import {getUserConfig} from './getUserConfig'
7
- import {isCi} from './isCi'
8
-
9
- const TELEMETRY_DISCLOSED_CONFIG_KEY = 'telemetryDisclosed'
10
-
11
- export function telemetryDisclosure(): void {
12
- const userConfig = getUserConfig()
13
-
14
- if (isCi) {
15
- debug('CI environment detected, skipping telemetry disclosure')
16
- return
17
- }
18
-
19
- if (userConfig.get(TELEMETRY_DISCLOSED_CONFIG_KEY)) {
20
- debug('Telemetry disclosure has already been shown')
21
- return
22
- }
23
-
24
- // Print to stderr to prevent garbling command output
25
- console.error(
26
- boxen(
27
- `The Sanity CLI now collects telemetry data on general usage and errors.
28
- This helps us improve Sanity and prioritize features.
29
-
30
- To opt in/out, run ${chalk.cyan('npx sanity telemetry enable/disable')}.
31
-
32
- ${telemetryLearnMoreMessage('unset')}`,
33
- {
34
- padding: 1,
35
- margin: 1,
36
- borderColor: 'yellow',
37
-
38
- // Typescript issues forcing these to any
39
- borderStyle: 'round' as any,
40
- },
41
- ),
42
- )
43
-
44
- userConfig.set(TELEMETRY_DISCLOSED_CONFIG_KEY, Date.now())
45
- }