Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): add support for remote templates with --template #7867

Open
wants to merge 34 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f7c47a3
fix: remove trailing commas when sanitizing
RostiMelk Jun 21, 2024
da20886
feat: add support for React Compiler beta (#7702)
stipsan Nov 19, 2024
48035a1
feat: initial branch commit
RostiMelk Nov 22, 2024
b4fe4ad
feat: bad rebase
RostiMelk Nov 22, 2024
2b1c1cb
feat: wip tests
RostiMelk Nov 25, 2024
5bac6af
feat: token, package name, git init
RostiMelk Nov 25, 2024
3e420e2
feat: more debugs
RostiMelk Nov 25, 2024
df17185
feat: reorder intro msg
RostiMelk Nov 25, 2024
e544df3
feat: remove unused var
RostiMelk Nov 25, 2024
610e3a9
feat: lints
RostiMelk Nov 25, 2024
29aa52d
feat: remove console log
RostiMelk Nov 25, 2024
a8dec47
feat: framework name on error
RostiMelk Nov 25, 2024
7734959
feat: allow slug sanity
RostiMelk Nov 25, 2024
6dd40b9
feat: allow slug sanity
RostiMelk Nov 25, 2024
fede57b
feat: pass bearer to fetcher
RostiMelk Nov 25, 2024
6cd69c7
feat: cleanup env func
RostiMelk Nov 25, 2024
bd69dff
feat: update tests to match template
RostiMelk Nov 25, 2024
05da0d6
feat: update throw
RostiMelk Nov 25, 2024
acd2846
feat: check repo info earlier
RostiMelk Nov 25, 2024
a8526e3
feat: lint
RostiMelk Nov 25, 2024
c8b88d1
feat: check for .env.local.template
RostiMelk Nov 25, 2024
735850f
feat: support for applying to env.local.example
RostiMelk Nov 25, 2024
f422fd9
feat: remove console logs
RostiMelk Nov 25, 2024
cc9ff7c
feat: official template
RostiMelk Nov 25, 2024
611a268
feat: patch metadata
RostiMelk Nov 25, 2024
ccb02a3
feat: pass context + clean up a bit
RostiMelk Nov 25, 2024
42a1614
feat: add suport for monorepos
RostiMelk Nov 26, 2024
578e50b
fix: return
RostiMelk Nov 26, 2024
ce43f61
feat: handle envs
RostiMelk Nov 26, 2024
7b065c4
feat: support for studio alt
RostiMelk Nov 26, 2024
21493b9
feat: generate token
RostiMelk Nov 26, 2024
c36e5df
feat: cleanup
RostiMelk Nov 26, 2024
511a6b5
feat: cleanup
RostiMelk Nov 27, 2024
a5f2dde
feat: filter empty filepaths and update type path
RostiMelk Nov 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
applyPackageName,
downloadAndExtractRepo,
generateSanityApiReadToken,
getMonoRepo,
isNextJsTemplate,
type RepoInfo,
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 applyPackageName(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