diff --git a/packages/@sanity/cli/src/actions/init-project/bootstrapTemplate.ts b/packages/@sanity/cli/src/actions/init-project/bootstrapTemplate.ts index 186d5a19ef07..1c14b8f0614e 100644 --- a/packages/@sanity/cli/src/actions/init-project/bootstrapTemplate.ts +++ b/packages/@sanity/cli/src/actions/init-project/bootstrapTemplate.ts @@ -127,6 +127,7 @@ export async function bootstrapTemplate( const cliConfig = await createCliConfig({ projectId: variables.projectId, dataset: variables.dataset, + autoUpdates: variables.autoUpdates, }) // Write non-template files to disc diff --git a/packages/@sanity/cli/src/actions/init-project/createCliConfig.ts b/packages/@sanity/cli/src/actions/init-project/createCliConfig.ts index 4a6f524ad275..14e6b9facd20 100644 --- a/packages/@sanity/cli/src/actions/init-project/createCliConfig.ts +++ b/packages/@sanity/cli/src/actions/init-project/createCliConfig.ts @@ -14,13 +14,14 @@ export default defineCliConfig({ * Enable auto-updates for studios. * Learn more at https://www.sanity.io/docs/cli#auto-updates */ - autoUpdates: true, + autoUpdates: %autoUpdates%, }) ` export interface GenerateCliConfigOptions { projectId: string dataset: string + autoUpdates: boolean } export function createCliConfig(options: GenerateCliConfigOptions): string { @@ -28,20 +29,27 @@ export function createCliConfig(options: GenerateCliConfigOptions): string { const template = defaultTemplate.trimStart() const ast = parse(template, {parser}) traverse(ast, { - StringLiteral: { - enter({node}) { - const value = node.value + enter(path) { + if (path.node.type === 'StringLiteral') { + const value = path.node.value if (!value.startsWith('%') || !value.endsWith('%')) { return } - const variableName = value.slice(1, -1) as keyof GenerateCliConfigOptions if (!(variableName in variables)) { throw new Error(`Template variable '${value}' not defined`) } - - node.value = variables[variableName] || '' - }, + const variableValue = variables[variableName] + if (typeof variableValue === 'boolean') { + // For boolean values, replace the entire string with a raw boolean + path.replaceWithSourceString(variableValue.toString()) + } else if (typeof variableValue === 'string') { + // For strings, just update the value + path.node.value = variableValue + } else { + throw new Error(`Unsupported variable type for '${variableName}'`) + } + } }, }) diff --git a/packages/@sanity/cli/src/actions/init-project/createStudioConfig.ts b/packages/@sanity/cli/src/actions/init-project/createStudioConfig.ts index 6aa2b8f8ecbe..761ad5c04dbf 100644 --- a/packages/@sanity/cli/src/actions/init-project/createStudioConfig.ts +++ b/packages/@sanity/cli/src/actions/init-project/createStudioConfig.ts @@ -34,6 +34,7 @@ export interface GenerateConfigOptions { variables: { projectId: string dataset: string + autoUpdates: boolean projectName?: string sourceName?: string sourceTitle?: string @@ -49,20 +50,27 @@ export function createStudioConfig(options: GenerateConfigOptions): string { const template = (options.template || defaultTemplate).trimStart() const ast = parse(template, {parser}) traverse(ast, { - StringLiteral: { - enter({node}) { - const value = node.value + enter(path) { + if (path.node.type === 'StringLiteral') { + const value = path.node.value if (!value.startsWith('%') || !value.endsWith('%')) { return } - const variableName = value.slice(1, -1) as keyof GenerateConfigOptions['variables'] if (!(variableName in variables)) { throw new Error(`Template variable '${value}' not defined`) } - - node.value = variables[variableName] || '' - }, + const variableValue = variables[variableName] + if (typeof variableValue === 'boolean') { + // For boolean values, replace the entire string with a raw boolean + path.replaceWithSourceString(variableValue.toString()) + } else if (typeof variableValue === 'string') { + // For strings, just update the value + path.node.value = variableValue + } else { + throw new Error(`Unsupported variable type for '${variableName}'`) + } + } }, }) diff --git a/packages/@sanity/cli/src/actions/init-project/initProject.ts b/packages/@sanity/cli/src/actions/init-project/initProject.ts index 9ca2f92b1811..48e779a89db0 100644 --- a/packages/@sanity/cli/src/actions/init-project/initProject.ts +++ b/packages/@sanity/cli/src/actions/init-project/initProject.ts @@ -439,10 +439,14 @@ export default async function initSanity( } const {chosen} = await getPackageManagerChoice(workDir, {interactive: false}) trace.log({step: 'selectPackageManager', selectedOption: chosen}) + const packages = ['@sanity/vision@3', 'sanity@3', '@sanity/image-url@1', 'styled-components@6'] + if (templateToUse === 'blog') { + packages.push('@sanity/icons') + } await installNewPackages( { packageManager: chosen, - packages: ['@sanity/vision@3', 'sanity@3', '@sanity/image-url@1', 'styled-components@6'], + packages, }, { output: context.output, @@ -530,6 +534,12 @@ export default async function initSanity( trace.log({step: 'useTypeScript', selectedOption: useTypeScript ? 'yes' : 'no'}) } + // we enable auto-updates by default, but allow users to specify otherwise + let autoUpdates = true + if (typeof cliFlags['auto-updates'] === 'boolean') { + autoUpdates = cliFlags['auto-updates'] + } + // Build a full set of resolved options const templateOptions: BootstrapOptions = { outputPath, @@ -540,6 +550,7 @@ export default async function initSanity( variables: { dataset: datasetName, projectId, + autoUpdates, projectName: displayName || answers.projectName, }, } @@ -1277,8 +1288,7 @@ export default async function initSanity( '# Warning: Do not add secrets (API keys and similar) to this file, as it source controlled!', '# Use `.env.local` for any secrets, and ensure it is not added to source control', ].join('\n') - const shouldPrependWarning = !existingEnv.includes(warningComment) - // prepend warning comment to the env vars if one does not exist + const shouldPrependWarning = filename !== '.env.local' && !existingEnv.includes(warningComment) if (shouldPrependWarning) { await fs.writeFile(fileOutputPath, `${warningComment}\n\n${updatedEnv}`, { encoding: 'utf8', diff --git a/packages/@sanity/cli/src/commands/init/initCommand.ts b/packages/@sanity/cli/src/commands/init/initCommand.ts index 2863f626b383..b0592632cf30 100644 --- a/packages/@sanity/cli/src/commands/init/initCommand.ts +++ b/packages/@sanity/cli/src/commands/init/initCommand.ts @@ -27,6 +27,7 @@ Options --coupon Optionally select a coupon for a new project (cannot be used with --project-plan) --no-typescript Do not use TypeScript for template files --package-manager Specify which package manager to use [allowed: ${allowedPackageManagersString}] + --no-auto-updates Disable import maps that keep your studio up-to-date with the latest Sanity versions Examples # Initialize a new project, prompt for required information along the way @@ -60,6 +61,7 @@ export interface InitFlags { 'visibility'?: string 'typescript'?: boolean + 'auto-updates'?: boolean /** * Used for initializing a project from a server schema that is saved in the Journey API * Overrides `project` option. diff --git a/packages/@sanity/cli/test/init.test.ts b/packages/@sanity/cli/test/init.test.ts index c1ee94fe028a..5d4734b92a35 100644 --- a/packages/@sanity/cli/test/init.test.ts +++ b/packages/@sanity/cli/test/init.test.ts @@ -34,6 +34,8 @@ describeCliTest('CLI: `sanity init v3`', () => { 'utf-8', ) + console.log(cliConfig) + expect(cliConfig).toContain(`projectId: '${cliProjectId}'`) expect(cliConfig).toContain(`dataset: '${testRunArgs.dataset}'`) expect(cliConfig).toContain(`autoUpdates: true`) @@ -60,6 +62,7 @@ describeCliTest('CLI: `sanity init v3`', () => { ]) const cliConfig = await fs.readFile(path.join(baseTestPath, outpath, 'sanity.cli.js'), 'utf-8') + console.log(cliConfig) expect(cliConfig).toContain(`projectId: '${cliProjectId}'`) expect(cliConfig).toContain(`dataset: '${testRunArgs.dataset}'`)