@sanity/cli 3.86.1 → 3.87.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/cli",
3
- "version": "3.86.1",
3
+ "version": "3.87.0",
4
4
  "description": "Sanity CLI tool for managing Sanity installations, managing plugins, schemas and datasets",
5
5
  "keywords": [
6
6
  "sanity",
@@ -58,12 +58,12 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@babel/traverse": "^7.23.5",
61
- "@sanity/client": "^6.29.0",
62
- "@sanity/codegen": "3.86.1",
61
+ "@sanity/client": "^6.29.1",
62
+ "@sanity/codegen": "3.87.0",
63
63
  "@sanity/runtime-cli": "^3.0.0",
64
64
  "@sanity/telemetry": "^0.8.0",
65
65
  "@sanity/template-validator": "^2.4.3",
66
- "@sanity/util": "3.86.1",
66
+ "@sanity/util": "3.87.0",
67
67
  "chalk": "^4.1.2",
68
68
  "debug": "^4.3.4",
69
69
  "decompress": "^4.2.0",
@@ -77,13 +77,13 @@
77
77
  "validate-npm-package-name": "^3.0.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@repo/package.config": "0.0.0",
81
- "@repo/test-config": "0.0.0",
80
+ "@repo/package.config": "3.87.0",
81
+ "@repo/test-config": "3.87.0",
82
82
  "@rexxars/gitconfiglocal": "^3.0.1",
83
83
  "@rollup/plugin-node-resolve": "^15.2.3",
84
84
  "@sanity/eslint-config-studio": "^4.0.0",
85
85
  "@sanity/generate-help-url": "^3.0.0",
86
- "@sanity/types": "3.86.1",
86
+ "@sanity/types": "3.87.0",
87
87
  "@types/babel__traverse": "^7.20.5",
88
88
  "@types/configstore": "^5.0.1",
89
89
  "@types/cpx": "^1.5.2",
@@ -135,5 +135,5 @@
135
135
  "engines": {
136
136
  "node": ">=18"
137
137
  },
138
- "gitHead": "9b19a1ca740b0a62231d80d6e9daaa8651478d39"
138
+ "gitHead": "97c3b32940f2324a9f0fc25097c33f1813374644"
139
139
  }
@@ -290,6 +290,8 @@ export default async function initSanity(
290
290
  print('')
291
291
  }
292
292
 
293
+ const isNextJs = detectedFramework?.slug === 'nextjs'
294
+
293
295
  const flags = await prepareFlags()
294
296
 
295
297
  // We're authenticated, now lets select or create a project (for studios) or org (for core apps)
@@ -313,14 +315,16 @@ export default async function initSanity(
313
315
  }
314
316
 
315
317
  let initNext = false
316
- const isNextJs = detectedFramework?.slug === 'nextjs'
317
318
  if (isNextJs) {
318
- initNext = await prompt.single({
319
- type: 'confirm',
320
- message:
321
- 'Would you like to add configuration files for a Sanity project in this Next.js folder?',
322
- default: true,
323
- })
319
+ initNext =
320
+ unattended ||
321
+ (await prompt.single({
322
+ type: 'confirm',
323
+ message:
324
+ 'Would you like to add configuration files for a Sanity project in this Next.js folder?',
325
+ default: true,
326
+ }))
327
+
324
328
  trace.log({
325
329
  step: 'useDetectedFramework',
326
330
  selectedOption: initNext ? 'yes' : 'no',
@@ -750,9 +754,15 @@ export default async function initSanity(
750
754
 
751
755
  if (isAppTemplate) {
752
756
  const client = apiClient({requireUser: true, requireProject: false})
753
- const organizations = await client.request({uri: '/organizations'})
757
+ const organizations = await client.request({
758
+ uri: '/organizations',
759
+ query: {
760
+ includeMembers: 'true',
761
+ includeImplicitMemberships: 'true',
762
+ },
763
+ })
754
764
 
755
- const appOrganizationId = await getOrganizationId(organizations)
765
+ const appOrganizationId = await getOrganizationIdForAppTemplate(organizations)
756
766
 
757
767
  return {
758
768
  projectId: '',
@@ -1223,12 +1233,15 @@ export default async function initSanity(
1223
1233
 
1224
1234
  if (unattended) {
1225
1235
  debug('Unattended mode, validating required options')
1226
- const requiredForUnattended = ['dataset', 'output-path'] as const
1227
- requiredForUnattended.forEach((flag) => {
1228
- if (!cliFlags[flag]) {
1229
- throw new Error(`\`--${flag}\` must be specified in unattended mode`)
1230
- }
1231
- })
1236
+
1237
+ if (!cliFlags['dataset' as const]) {
1238
+ throw new Error(`\`--dataset\` must be specified in unattended mode`)
1239
+ }
1240
+
1241
+ // output-path is not used in unattended mode within nextjs
1242
+ if (!isNextJs && !cliFlags['output-path' as const]) {
1243
+ throw new Error(`\`--output-path\` must be specified in unattended mode`)
1244
+ }
1232
1245
 
1233
1246
  if (!cliFlags.project && !createProjectName) {
1234
1247
  throw new Error(
@@ -1300,6 +1313,38 @@ export default async function initSanity(
1300
1313
  return organization
1301
1314
  }
1302
1315
 
1316
+ async function getOrganizationIdForAppTemplate(organizations: ProjectOrganization[]) {
1317
+ // If the user is using an app template, we don't need to check for attach access
1318
+ const organizationChoices = [
1319
+ ...organizations.map((organization) => ({
1320
+ value: organization.id,
1321
+ name: `${organization.name} [${organization.id}]`,
1322
+ })),
1323
+ new prompt.Separator(),
1324
+ {value: '-new-', name: 'Create new organization'},
1325
+ new prompt.Separator(),
1326
+ ]
1327
+
1328
+ // If the user only has a single organization, we'll default to that one.
1329
+ const defaultOrganizationId =
1330
+ organizations.length === 1
1331
+ ? organizations[0].id
1332
+ : organizations.find((org) => org.name === user?.name)?.id
1333
+
1334
+ const chosenOrg = await prompt.single({
1335
+ message: 'Select organization:',
1336
+ type: 'list',
1337
+ default: defaultOrganizationId || undefined,
1338
+ choices: organizationChoices,
1339
+ })
1340
+
1341
+ if (chosenOrg === '-new-') {
1342
+ return createOrganization().then((org) => org.id)
1343
+ }
1344
+
1345
+ return chosenOrg || undefined
1346
+ }
1347
+
1303
1348
  async function getOrganizationId(organizations: ProjectOrganization[]) {
1304
1349
  // In unattended mode, if the user hasn't specified an organization, sending null as
1305
1350
  // organization ID to the API will create a new organization for the user with their
package/src/cli.ts CHANGED
@@ -56,9 +56,6 @@ export async function runCli(cliRoot: string, {cliVersion}: {cliVersion: string}
56
56
  process.exit(1)
57
57
  }
58
58
 
59
- loadAndSetEnvFromDotEnvFiles({workDir, cmd: args.groupOrCommand})
60
- maybeFixMissingWindowsEnvVar()
61
-
62
59
  // Check if there are updates available for the CLI, and notify if there is
63
60
  await runUpdateCheck({pkg, cwd, workDir}).notify()
64
61
 
@@ -67,11 +64,20 @@ export async function runCli(cliRoot: string, {cliVersion}: {cliVersion: string}
67
64
 
68
65
  // Try to figure out if we're in a v2 or v3 context by finding a config
69
66
  debug(`Reading CLI config from "${workDir}"`)
70
- const cliConfig = await getCliConfig(workDir, {forked: true})
67
+ let cliConfig = await getCliConfig(workDir, {forked: true})
71
68
  if (!cliConfig) {
72
69
  debug('No CLI config found')
73
70
  }
74
71
 
72
+ // Figure out if the app is a studio or an app from the CLI config
73
+ const isApp = Boolean(cliConfig && 'app' in cliConfig)
74
+ // Load the environment variables from
75
+ loadAndSetEnvFromDotEnvFiles({workDir, cmd: args.groupOrCommand, isApp})
76
+ maybeFixMissingWindowsEnvVar()
77
+
78
+ // Reload the the cli config so env vars can work.
79
+ cliConfig = await getCliConfig(workDir, {forked: true})
80
+
75
81
  const {logger: telemetry, flush: flushTelemetry} = createTelemetryStore<TelemetryUserProperties>({
76
82
  projectId: cliConfig?.config?.api?.projectId,
77
83
  env: process.env,
@@ -274,7 +280,15 @@ function warnOnNonProductionEnvironment(): void {
274
280
  )
275
281
  }
276
282
 
277
- function loadAndSetEnvFromDotEnvFiles({workDir, cmd}: {workDir: string; cmd: string}) {
283
+ function loadAndSetEnvFromDotEnvFiles({
284
+ workDir,
285
+ cmd,
286
+ isApp,
287
+ }: {
288
+ workDir: string
289
+ cmd: string
290
+ isApp: boolean
291
+ }) {
278
292
  /* eslint-disable no-process-env */
279
293
 
280
294
  // Do a cheap lookup for a sanity.json file. If there is one, assume it is a v2 project,
@@ -309,7 +323,7 @@ function loadAndSetEnvFromDotEnvFiles({workDir, cmd}: {workDir: string; cmd: str
309
323
 
310
324
  debug('Loading environment files using %s mode', mode)
311
325
 
312
- const studioEnv = loadEnv(mode, workDir, ['SANITY_STUDIO_'])
326
+ const studioEnv = loadEnv(mode, workDir, [isApp ? 'SANITY_APP_' : 'SANITY_STUDIO_'])
313
327
  process.env = {...process.env, ...studioEnv}
314
328
  /* eslint-disable no-process-env */
315
329
  }
@@ -24,13 +24,13 @@ export function App() {
24
24
  }
25
25
 
26
26
  return (
27
- <SanityApp config={sanityConfigs} fallback={<Loading />}>
28
- <ThemeProvider theme={theme}>
27
+ <ThemeProvider theme={theme}>
28
+ <SanityApp config={sanityConfigs} fallback={<Loading />}>
29
29
  {/* add your own components here! */}
30
30
  <ExampleComponent />
31
- </ThemeProvider>
32
- </SanityApp>
33
- )
31
+ </SanityApp>
32
+ </ThemeProvider>
33
+ );
34
34
  }
35
35
 
36
36
  export default App