@sanity/cli 3.74.1 → 3.74.2-canary.89

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.
@@ -10,8 +10,10 @@ import {copy} from '../../util/copy'
10
10
  import {getAndWriteJourneySchemaWorker} from '../../util/journeyConfig'
11
11
  import {resolveLatestVersions} from '../../util/resolveLatestVersions'
12
12
  import {createCliConfig} from './createCliConfig'
13
+ import {createCoreAppCliConfig} from './createCoreAppCliConfig'
13
14
  import {createPackageManifest} from './createPackageManifest'
14
15
  import {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig'
16
+ import {determineCoreAppTemplate} from './determineCoreAppTemplate'
15
17
  import {type ProjectTemplate} from './initProject'
16
18
  import templates from './templates'
17
19
  import {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata'
@@ -36,9 +38,9 @@ export async function bootstrapLocalTemplate(
36
38
  const {apiClient, cliRoot, output} = context
37
39
  const templatesDir = path.join(cliRoot, 'templates')
38
40
  const {outputPath, templateName, useTypeScript, packageName, variables} = opts
39
- const {projectId} = variables
40
41
  const sourceDir = path.join(templatesDir, templateName)
41
42
  const sharedDir = path.join(templatesDir, 'shared')
43
+ const isCoreAppTemplate = determineCoreAppTemplate(templateName)
42
44
 
43
45
  // Check that we have a template info file (dependencies, plugins etc)
44
46
  const template = templates[templateName]
@@ -81,15 +83,16 @@ export async function bootstrapLocalTemplate(
81
83
  // Resolve latest versions of Sanity-dependencies
82
84
  spinner = output.spinner('Resolving latest module versions').start()
83
85
  const dependencyVersions = await resolveLatestVersions({
84
- ...studioDependencies.dependencies,
85
- ...studioDependencies.devDependencies,
86
+ ...(isCoreAppTemplate ? {} : studioDependencies.dependencies),
87
+ ...(isCoreAppTemplate ? {} : studioDependencies.devDependencies),
86
88
  ...(template.dependencies || {}),
89
+ ...(template.devDependencies || {}),
87
90
  })
88
91
  spinner.succeed()
89
92
 
90
93
  // Use the resolved version for the given dependency
91
94
  const dependencies = Object.keys({
92
- ...studioDependencies.dependencies,
95
+ ...(isCoreAppTemplate ? {} : studioDependencies.dependencies),
93
96
  ...template.dependencies,
94
97
  }).reduce(
95
98
  (deps, dependency) => {
@@ -100,7 +103,7 @@ export async function bootstrapLocalTemplate(
100
103
  )
101
104
 
102
105
  const devDependencies = Object.keys({
103
- ...studioDependencies.devDependencies,
106
+ ...(isCoreAppTemplate ? {} : studioDependencies.devDependencies),
104
107
  ...template.devDependencies,
105
108
  }).reduce(
106
109
  (deps, dependency) => {
@@ -116,32 +119,41 @@ export async function bootstrapLocalTemplate(
116
119
  name: packageName,
117
120
  dependencies,
118
121
  devDependencies,
122
+ scripts: template.scripts,
119
123
  })
120
124
 
121
125
  // ...and a studio config (`sanity.config.[ts|js]`)
122
- const studioConfig = await createStudioConfig({
126
+ const studioConfig = createStudioConfig({
123
127
  template: template.configTemplate,
124
128
  variables,
125
129
  })
126
130
 
127
131
  // ...and a CLI config (`sanity.cli.[ts|js]`)
128
- const cliConfig = await createCliConfig({
129
- projectId: variables.projectId,
130
- dataset: variables.dataset,
131
- autoUpdates: variables.autoUpdates,
132
- })
132
+ const cliConfig = isCoreAppTemplate
133
+ ? createCoreAppCliConfig({appLocation: template.appLocation!})
134
+ : createCliConfig({
135
+ projectId: variables.projectId,
136
+ dataset: variables.dataset,
137
+ autoUpdates: variables.autoUpdates,
138
+ })
133
139
 
134
140
  // Write non-template files to disc
135
141
  const codeExt = useTypeScript ? 'ts' : 'js'
136
- await Promise.all([
137
- writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),
138
- writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),
139
- writeFileIfNotExists('package.json', packageManifest),
140
- writeFileIfNotExists(
141
- 'eslint.config.mjs',
142
- `import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n`,
143
- ),
144
- ])
142
+ await Promise.all(
143
+ [
144
+ ...[
145
+ isCoreAppTemplate
146
+ ? Promise.resolve(null)
147
+ : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),
148
+ ],
149
+ writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),
150
+ writeFileIfNotExists('package.json', packageManifest),
151
+ writeFileIfNotExists(
152
+ 'eslint.config.mjs',
153
+ `import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n`,
154
+ ),
155
+ ].filter(Boolean),
156
+ )
145
157
 
146
158
  debug('Updating initial template metadata')
147
159
  await updateInitialTemplateMetadata(apiClient, variables.projectId, `cli-${templateName}`)
@@ -1,6 +1,4 @@
1
- import traverse from '@babel/traverse'
2
- import {parse, print} from 'recast'
3
- import * as parser from 'recast/parsers/typescript'
1
+ import {processTemplate} from './processTemplate'
4
2
 
5
3
  const defaultTemplate = `
6
4
  import {defineCliConfig} from 'sanity/cli'
@@ -25,49 +23,9 @@ export interface GenerateCliConfigOptions {
25
23
  }
26
24
 
27
25
  export function createCliConfig(options: GenerateCliConfigOptions): string {
28
- const variables = options
29
- const template = defaultTemplate.trimStart()
30
- const ast = parse(template, {parser})
31
-
32
- traverse(ast, {
33
- StringLiteral: {
34
- enter({node}) {
35
- const value = node.value
36
- if (!value.startsWith('%') || !value.endsWith('%')) {
37
- return
38
- }
39
- const variableName = value.slice(1, -1) as keyof GenerateCliConfigOptions
40
- if (!(variableName in variables)) {
41
- throw new Error(`Template variable '${value}' not defined`)
42
- }
43
- const newValue = variables[variableName]
44
- /*
45
- * although there are valid non-strings in our config,
46
- * they're not in StringLiteral nodes, so assume undefined
47
- */
48
- node.value = typeof newValue === 'string' ? newValue : ''
49
- },
50
- },
51
- Identifier: {
52
- enter(path) {
53
- if (!path.node.name.startsWith('__BOOL__')) {
54
- return
55
- }
56
- const variableName = path.node.name.replace(
57
- /^__BOOL__(.+?)__$/,
58
- '$1',
59
- ) as keyof GenerateCliConfigOptions
60
- if (!(variableName in variables)) {
61
- throw new Error(`Template variable '${variableName}' not defined`)
62
- }
63
- const value = variables[variableName]
64
- if (typeof value !== 'boolean') {
65
- throw new Error(`Expected boolean value for '${variableName}'`)
66
- }
67
- path.replaceWith({type: 'BooleanLiteral', value})
68
- },
69
- },
26
+ return processTemplate({
27
+ template: defaultTemplate,
28
+ variables: options,
29
+ includeBooleanTransform: true,
70
30
  })
71
-
72
- return print(ast, {quote: 'single'}).code
73
31
  }
@@ -0,0 +1,23 @@
1
+ import {processTemplate} from './processTemplate'
2
+
3
+ const defaultCoreAppTemplate = `
4
+ import {defineCliConfig} from 'sanity/cli'
5
+
6
+ export default defineCliConfig({
7
+ __experimental_coreAppConfiguration: {
8
+ appLocation: '%appLocation%'
9
+ },
10
+ })
11
+ `
12
+
13
+ export interface GenerateCliConfigOptions {
14
+ organizationId?: string
15
+ appLocation: string
16
+ }
17
+
18
+ export function createCoreAppCliConfig(options: GenerateCliConfigOptions): string {
19
+ return processTemplate({
20
+ template: defaultCoreAppTemplate,
21
+ variables: options,
22
+ })
23
+ }
@@ -29,7 +29,7 @@ export function createPackageManifest(
29
29
 
30
30
  main: 'package.json',
31
31
  keywords: ['sanity'],
32
- scripts: {
32
+ scripts: data.scripts || {
33
33
  'dev': 'sanity dev',
34
34
  'start': 'sanity start',
35
35
  'build': 'sanity build',
@@ -1,6 +1,4 @@
1
- import traverse from '@babel/traverse'
2
- import {parse, print} from 'recast'
3
- import * as parser from 'recast/parsers/typescript'
1
+ import {processTemplate} from './processTemplate'
4
2
 
5
3
  const defaultTemplate = `
6
4
  import {defineConfig} from 'sanity'
@@ -47,29 +45,8 @@ export function createStudioConfig(options: GenerateConfigOptions): string {
47
45
  return options.template(variables).trimStart()
48
46
  }
49
47
 
50
- const template = (options.template || defaultTemplate).trimStart()
51
- const ast = parse(template, {parser})
52
- traverse(ast, {
53
- StringLiteral: {
54
- enter({node}) {
55
- const value = node.value
56
- if (!value.startsWith('%') || !value.endsWith('%')) {
57
- return
58
- }
59
-
60
- const variableName = value.slice(1, -1) as keyof GenerateConfigOptions['variables']
61
- if (!(variableName in variables)) {
62
- throw new Error(`Template variable '${value}' not defined`)
63
- }
64
- const newValue = variables[variableName]
65
- /*
66
- * although there are valid non-strings in our config,
67
- * they're not in this template, so assume undefined
68
- */
69
- node.value = typeof newValue === 'string' ? newValue : ''
70
- },
71
- },
48
+ return processTemplate({
49
+ template: options.template || defaultTemplate,
50
+ variables,
72
51
  })
73
-
74
- return print(ast, {quote: 'single'}).code
75
52
  }
@@ -0,0 +1,13 @@
1
+ const coreAppTemplates = ['core-app']
2
+
3
+ /**
4
+ * Determine if a given template is a studio template.
5
+ * This function may need to be more robust once we
6
+ * introduce remote templates, for example.
7
+ *
8
+ * @param templateName - Name of the template
9
+ * @returns boolean indicating if the template is a studio template
10
+ */
11
+ export function determineCoreAppTemplate(templateName: string): boolean {
12
+ return coreAppTemplates.includes(templateName)
13
+ }
@@ -49,6 +49,7 @@ import {createProject} from '../project/createProject'
49
49
  import {bootstrapLocalTemplate} from './bootstrapLocalTemplate'
50
50
  import {bootstrapRemoteTemplate} from './bootstrapRemoteTemplate'
51
51
  import {type GenerateConfigOptions} from './createStudioConfig'
52
+ import {determineCoreAppTemplate} from './determineCoreAppTemplate'
52
53
  import {absolutify, validateEmptyPath} from './fsUtils'
53
54
  import {tryGitInit} from './git'
54
55
  import {promptForDatasetName} from './promptForDatasetName'
@@ -97,6 +98,8 @@ export interface ProjectTemplate {
97
98
  importPrompt?: string
98
99
  configTemplate?: string | ((variables: GenerateConfigOptions['variables']) => string)
99
100
  typescriptOnly?: boolean
101
+ appLocation?: string
102
+ scripts?: Record<string, string>
100
103
  }
101
104
 
102
105
  export interface ProjectOrganization {
@@ -263,14 +266,21 @@ export default async function initSanity(
263
266
  await getOrCreateUser()
264
267
  }
265
268
 
269
+ // skip project / dataset prompting
270
+ const isCoreAppTemplate = cliFlags.template ? determineCoreAppTemplate(cliFlags.template) : false // Default to false
271
+
266
272
  let introMessage = 'Fetching existing projects'
267
273
  if (cliFlags.quickstart) {
268
274
  introMessage = "Eject your existing project's Sanity configuration"
269
275
  }
270
- success(introMessage)
271
- print('')
276
+
277
+ if (!isCoreAppTemplate) {
278
+ success(introMessage)
279
+ print('')
280
+ }
272
281
 
273
282
  const flags = await prepareFlags()
283
+
274
284
  // We're authenticated, now lets select or create a project
275
285
  const {projectId, displayName, isFirstProject, datasetName, schemaUrl} = await getProjectDetails()
276
286
 
@@ -655,11 +665,15 @@ export default async function initSanity(
655
665
  const isCurrentDir = outputPath === process.cwd()
656
666
  if (isCurrentDir) {
657
667
  print(`\n${chalk.green('Success!')} Now, use this command to continue:\n`)
658
- print(`${chalk.cyan(devCommand)} - to run Sanity Studio\n`)
668
+ print(
669
+ `${chalk.cyan(devCommand)} - to run ${isCoreAppTemplate ? 'your Sanity application' : 'Sanity Studio'}\n`,
670
+ )
659
671
  } else {
660
672
  print(`\n${chalk.green('Success!')} Now, use these commands to continue:\n`)
661
673
  print(`First: ${chalk.cyan(`cd ${outputPath}`)} - to enter project’s directory`)
662
- print(`Then: ${chalk.cyan(devCommand)} - to run Sanity Studio\n`)
674
+ print(
675
+ `Then: ${chalk.cyan(devCommand)} -to run ${isCoreAppTemplate ? 'your Sanity application' : 'Sanity Studio'}\n`,
676
+ )
663
677
  }
664
678
 
665
679
  print(`Other helpful commands`)
@@ -720,6 +734,15 @@ export default async function initSanity(
720
734
  return data
721
735
  }
722
736
 
737
+ if (isCoreAppTemplate) {
738
+ return {
739
+ projectId: '',
740
+ displayName: '',
741
+ isFirstProject: false,
742
+ datasetName: '',
743
+ }
744
+ }
745
+
723
746
  debug('Prompting user to select or create a project')
724
747
  const project = await getOrCreateProject()
725
748
  debug(`Project with name ${project.displayName} selected`)
@@ -0,0 +1,55 @@
1
+ import traverse from '@babel/traverse'
2
+ import {parse, print} from 'recast'
3
+ import * as parser from 'recast/parsers/typescript'
4
+
5
+ interface TemplateOptions<T> {
6
+ template: string
7
+ variables: T
8
+ includeBooleanTransform?: boolean
9
+ }
10
+
11
+ export function processTemplate<T extends object>(options: TemplateOptions<T>): string {
12
+ const {template, variables, includeBooleanTransform = false} = options
13
+ const ast = parse(template.trimStart(), {parser})
14
+
15
+ traverse(ast, {
16
+ StringLiteral: {
17
+ enter({node}) {
18
+ const value = node.value
19
+ if (!value.startsWith('%') || !value.endsWith('%')) {
20
+ return
21
+ }
22
+ const variableName = value.slice(1, -1) as keyof T
23
+ if (!(variableName in variables)) {
24
+ throw new Error(`Template variable '${value}' not defined`)
25
+ }
26
+ const newValue = variables[variableName]
27
+ /*
28
+ * although there are valid non-strings in our config,
29
+ * they're not in StringLiteral nodes, so assume undefined
30
+ */
31
+ node.value = typeof newValue === 'string' ? newValue : ''
32
+ },
33
+ },
34
+ ...(includeBooleanTransform && {
35
+ Identifier: {
36
+ enter(path) {
37
+ if (!path.node.name.startsWith('__BOOL__')) {
38
+ return
39
+ }
40
+ const variableName = path.node.name.replace(/^__BOOL__(.+?)__$/, '$1') as keyof T
41
+ if (!(variableName in variables)) {
42
+ throw new Error(`Template variable '${variableName.toString()}' not defined`)
43
+ }
44
+ const value = variables[variableName]
45
+ if (typeof value !== 'boolean') {
46
+ throw new Error(`Expected boolean value for '${variableName.toString()}'`)
47
+ }
48
+ path.replaceWith({type: 'BooleanLiteral', value})
49
+ },
50
+ },
51
+ }),
52
+ })
53
+
54
+ return print(ast, {quote: 'single'}).code
55
+ }
@@ -0,0 +1,31 @@
1
+ import {type ProjectTemplate} from '../initProject'
2
+
3
+ const coreAppTemplate: ProjectTemplate = {
4
+ dependencies: {
5
+ '@sanity/sdk': '^0.0.0-alpha',
6
+ '@sanity/sdk-react': '^0.0.0-alpha',
7
+ 'react': '^19',
8
+ 'react-dom': '^19',
9
+ },
10
+ devDependencies: {
11
+ /*
12
+ * this will be changed to eslint-config sanity,
13
+ * eslint.config generation will be a fast follow
14
+ */
15
+ '@sanity/eslint-config-studio': '^5.0.1',
16
+ '@types/react': '^18.0.25',
17
+ 'eslint': '^9.9.0',
18
+ 'prettier': '^3.0.2',
19
+ 'sanity': '^3',
20
+ 'typescript': '^5.1.6',
21
+ },
22
+ appLocation: './src/App.tsx',
23
+ scripts: {
24
+ // this will eventually run a concurrently process with another in-flight utility
25
+ dev: 'sanity app dev',
26
+ build: 'sanity app build',
27
+ start: 'sanity app start',
28
+ },
29
+ }
30
+
31
+ export default coreAppTemplate
@@ -1,6 +1,7 @@
1
1
  import {type ProjectTemplate} from '../initProject'
2
2
  import blog from './blog'
3
3
  import clean from './clean'
4
+ import coreAppTemplate from './coreApp'
4
5
  import getStartedTemplate from './getStarted'
5
6
  import moviedb from './moviedb'
6
7
  import quickstart from './quickstart'
@@ -10,6 +11,7 @@ import shopifyOnline from './shopifyOnline'
10
11
  const templates: Record<string, ProjectTemplate | undefined> = {
11
12
  blog,
12
13
  clean,
14
+ 'core-app': coreAppTemplate,
13
15
  'get-started': getStartedTemplate,
14
16
  moviedb,
15
17
  shopify,
package/src/cli.ts CHANGED
@@ -47,16 +47,17 @@ export async function runCli(cliRoot: string, {cliVersion}: {cliVersion: string}
47
47
 
48
48
  const args = parseArguments()
49
49
  const isInit = args.groupOrCommand === 'init' && args.argsWithoutOptions[0] !== 'plugin'
50
+ const isCoreApp = args.groupOrCommand === 'app'
50
51
  const cwd = getCurrentWorkingDirectory()
51
52
  let workDir: string | undefined
52
53
  try {
53
- workDir = isInit ? process.cwd() : resolveRootDir(cwd)
54
+ workDir = isInit ? process.cwd() : resolveRootDir(cwd, isCoreApp)
54
55
  } catch (err) {
55
56
  console.error(chalk.red(err.message))
56
57
  process.exit(1)
57
58
  }
58
59
 
59
- loadAndSetEnvFromDotEnvFiles({workDir, cmd: args.groupOrCommand})
60
+ loadAndSetEnvFromDotEnvFiles({workDir, cmd: args.groupOrCommand, isCoreApp})
60
61
  maybeFixMissingWindowsEnvVar()
61
62
 
62
63
  // Check if there are updates available for the CLI, and notify if there is
@@ -99,6 +100,7 @@ export async function runCli(cliRoot: string, {cliVersion}: {cliVersion: string}
99
100
  corePath: await getCoreModulePath(workDir, cliConfig),
100
101
  cliConfig,
101
102
  telemetry,
103
+ isCoreApp,
102
104
  }
103
105
 
104
106
  warnOnNonProductionEnvironment()
@@ -274,14 +276,22 @@ function warnOnNonProductionEnvironment(): void {
274
276
  )
275
277
  }
276
278
 
277
- function loadAndSetEnvFromDotEnvFiles({workDir, cmd}: {workDir: string; cmd: string}) {
279
+ function loadAndSetEnvFromDotEnvFiles({
280
+ workDir,
281
+ cmd,
282
+ isCoreApp,
283
+ }: {
284
+ workDir: string
285
+ cmd: string
286
+ isCoreApp: boolean
287
+ }) {
278
288
  /* eslint-disable no-process-env */
279
289
 
280
290
  // Do a cheap lookup for a sanity.json file. If there is one, assume it is a v2 project,
281
291
  // and apply the old behavior for environment variables. Otherwise, use the Vite-style
282
292
  // behavior. We need to do this "cheap" lookup because when loading the v3 config, env vars
283
293
  // may be used in the configuration file, meaning we'd have to load the config twice.
284
- if (existsSync(path.join(workDir, 'sanity.json'))) {
294
+ if (existsSync(path.join(workDir, 'sanity.json')) && !isCoreApp) {
285
295
  // v2
286
296
  debug('sanity.json exists, assuming v2 project and loading .env files using old behavior')
287
297
  const env = process.env.SANITY_ACTIVE_ENV || process.env.NODE_ENV || 'development'
@@ -309,7 +319,7 @@ function loadAndSetEnvFromDotEnvFiles({workDir, cmd}: {workDir: string; cmd: str
309
319
 
310
320
  debug('Loading environment files using %s mode', mode)
311
321
 
312
- const studioEnv = loadEnv(mode, workDir, ['SANITY_STUDIO_'])
322
+ const studioEnv = loadEnv(mode, workDir, isCoreApp ? ['VITE_'] : ['SANITY_STUDIO_'])
313
323
  process.env = {...process.env, ...studioEnv}
314
324
  /* eslint-disable no-process-env */
315
325
  }
package/src/types.ts CHANGED
@@ -24,6 +24,7 @@ export interface SanityModuleInternal {
24
24
  export interface PackageJson {
25
25
  name: string
26
26
  version: string
27
+ scripts?: Record<string, string>
27
28
 
28
29
  description?: string
29
30
  author?: string
@@ -146,6 +147,7 @@ export interface CommandRunnerOptions {
146
147
  workDir: string
147
148
  corePath: string | undefined
148
149
  telemetry: TelemetryLogger<TelemetryUserProperties>
150
+ isCoreApp: boolean
149
151
  }
150
152
 
151
153
  export interface CliOutputter {
@@ -182,6 +184,7 @@ export type CliStubbedYarn = (args: string[], options?: CliYarnOptions) => Promi
182
184
  export interface CliApiConfig {
183
185
  projectId?: string
184
186
  dataset?: string
187
+ organizationId?: string
185
188
  }
186
189
 
187
190
  export interface SanityJson {
@@ -344,6 +347,16 @@ export interface CliConfig {
344
347
  autoUpdates?: boolean
345
348
 
346
349
  studioHost?: string
350
+
351
+ /**
352
+ * Parameter used to configure other kinds of applications.
353
+ * Signals to `sanity` commands that this is not a studio.
354
+ * @internal
355
+ */
356
+ __experimental_coreAppConfiguration?: {
357
+ appLocation?: string
358
+ appHost?: string
359
+ }
347
360
  }
348
361
 
349
362
  export type UserViteConfig =
@@ -7,26 +7,27 @@ import {debug} from '../debug'
7
7
  /**
8
8
  * Resolve project root directory, falling back to cwd if it cannot be found
9
9
  */
10
- export function resolveRootDir(cwd: string): string {
10
+ export function resolveRootDir(cwd: string, isCoreApp = false): string {
11
11
  try {
12
- return resolveProjectRoot(cwd) || cwd
12
+ return resolveProjectRoot(cwd, 0, isCoreApp) || cwd
13
13
  } catch (err) {
14
14
  throw new Error(`Error occurred trying to resolve project root:\n${err.message}`)
15
15
  }
16
16
  }
17
17
 
18
- function hasStudioConfig(basePath: string): boolean {
18
+ function hasSanityConfig(basePath: string, configName: string): boolean {
19
19
  const buildConfigs = [
20
- fileExists(path.join(basePath, 'sanity.config.js')),
21
- fileExists(path.join(basePath, 'sanity.config.ts')),
20
+ fileExists(path.join(basePath, `${configName}.js`)),
21
+ fileExists(path.join(basePath, `${configName}.ts`)),
22
22
  isSanityV2StudioRoot(basePath),
23
23
  ]
24
24
 
25
25
  return buildConfigs.some(Boolean)
26
26
  }
27
27
 
28
- function resolveProjectRoot(basePath: string, iterations = 0): string | false {
29
- if (hasStudioConfig(basePath)) {
28
+ function resolveProjectRoot(basePath: string, iterations = 0, isCoreApp = false): string | false {
29
+ const configName = isCoreApp ? 'sanity.cli' : 'sanity.config'
30
+ if (hasSanityConfig(basePath, configName)) {
30
31
  return basePath
31
32
  }
32
33
 
@@ -36,7 +37,7 @@ function resolveProjectRoot(basePath: string, iterations = 0): string | false {
36
37
  return false
37
38
  }
38
39
 
39
- return resolveProjectRoot(parentDir, iterations + 1)
40
+ return resolveProjectRoot(parentDir, iterations + 1, isCoreApp)
40
41
  }
41
42
 
42
43
  function isSanityV2StudioRoot(basePath: string): boolean {
@@ -0,0 +1,26 @@
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {SanityProvider} from '@sanity/sdk-react/context'
3
+
4
+ export function App() {
5
+
6
+ const sanityConfig = {
7
+ auth: {
8
+ authScope: 'global'
9
+ }
10
+ /*
11
+ * Apps can access several different projects!
12
+ * Add the below configuration if you want to connect to a specific project.
13
+ */
14
+ // projectId: 'my-project-id',
15
+ // dataset: 'my-dataset',
16
+ }
17
+
18
+ const sanityInstance = createSanityInstance(sanityConfig)
19
+ return (
20
+ <SanityProvider sanityInstance={sanityInstance}>
21
+ Hello world!
22
+ </SanityProvider>
23
+ )
24
+ }
25
+
26
+ export default App