Skip to content

Commit

Permalink
feat(cli): add support for remote templates with --template (#7867)
Browse files Browse the repository at this point in the history
  • Loading branch information
RostiMelk authored Dec 3, 2024
1 parent 079824e commit 1f59825
Show file tree
Hide file tree
Showing 11 changed files with 1,017 additions and 207 deletions.
3 changes: 2 additions & 1 deletion packages/@sanity/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
"prettier": "^3.3.0",
"semver": "^7.3.5",
"silver-fleece": "1.1.0",
"validate-npm-package-name": "^3.0.0"
"validate-npm-package-name": "^3.0.0",
"yaml": "^2.6.1"
},
"devDependencies": {
"@repo/package.config": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import {createPackageManifest} from './createPackageManifest'
import {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig'
import {type ProjectTemplate} from './initProject'
import templates from './templates'
import {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata'

export interface BootstrapOptions {
export interface BootstrapLocalOptions {
packageName: string
templateName: string
/**
Expand All @@ -28,8 +29,8 @@ export interface BootstrapOptions {
variables: GenerateConfigOptions['variables']
}

export async function bootstrapTemplate(
opts: BootstrapOptions,
export async function bootstrapLocalTemplate(
opts: BootstrapLocalOptions,
context: CliCommandContext,
): Promise<ProjectTemplate> {
const {apiClient, cliRoot, output} = context
Expand Down Expand Up @@ -142,22 +143,8 @@ export async function bootstrapTemplate(
),
])

// Store template name metadata on project
try {
await apiClient({api: {projectId}}).request({
method: 'PATCH',
uri: `/projects/${projectId}`,
body: {metadata: {initialTemplate: `cli-${templateName}`}},
})
} catch (err: unknown) {
// Non-critical that we update this metadata, and user does not need to be aware
let message = typeof err === 'string' ? err : '<unknown error>'
if (err instanceof Error) {
message = err.message
}

debug('Failed to update initial template metadata for project: %s', message)
}
debug('Updating initial template metadata')
await updateInitialTemplateMetadata(apiClient, variables.projectId, `cli-${templateName}`)

// Finish up by providing init process with template-specific info
spinner.succeed()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {mkdir} from 'node:fs/promises'
import {join} from 'node:path'

import {debug} from '../../debug'
import {type CliCommandContext} from '../../types'
import {
applyEnvVariables,
downloadAndExtractRepo,
generateSanityApiReadToken,
getMonoRepo,
isNextJsTemplate,
type RepoInfo,
tryApplyPackageName,
validateRemoteTemplate,
} from '../../util/remoteTemplate'
import {type GenerateConfigOptions} from './createStudioConfig'
import {tryGitInit} from './git'
import {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata'

export interface BootstrapRemoteOptions {
outputPath: string
repoInfo: RepoInfo
bearerToken?: string
packageName: string
variables: GenerateConfigOptions['variables']
}

const INITIAL_COMMIT_MESSAGE = 'Initial commit from Sanity CLI'

export async function bootstrapRemoteTemplate(
opts: BootstrapRemoteOptions,
context: CliCommandContext,
): Promise<void> {
const {outputPath, repoInfo, bearerToken, variables, packageName} = opts
const {output, apiClient} = context
const name = [repoInfo.username, repoInfo.name, repoInfo.filePath].filter(Boolean).join('/')
const spinner = output.spinner(`Bootstrapping files from template "${name}"`).start()

debug('Validating remote template')
const packages = await getMonoRepo(repoInfo, bearerToken)
await validateRemoteTemplate(repoInfo, packages, bearerToken)

debug('Create new directory "%s"', outputPath)
await mkdir(outputPath, {recursive: true})

debug('Downloading and extracting repo to %s', outputPath)
await downloadAndExtractRepo(outputPath, repoInfo, bearerToken)

debug('Applying environment variables')
const readToken = await generateSanityApiReadToken(variables.projectId, apiClient)
const isNext = await isNextJsTemplate(outputPath)
const envName = isNext ? '.env.local' : '.env'

for (const folder of packages ?? ['']) {
const path = join(outputPath, folder)
await applyEnvVariables(path, {...variables, readToken}, envName)
}

debug('Setting package name to %s', packageName)
await tryApplyPackageName(outputPath, packageName)

debug('Initializing git repository')
tryGitInit(outputPath, INITIAL_COMMIT_MESSAGE)

debug('Updating initial template metadata')
await updateInitialTemplateMetadata(apiClient, variables.projectId, `external-${name}`)

spinner.succeed()
}
Loading

0 comments on commit 1f59825

Please sign in to comment.