-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add prismic init --new to create a repository and push local models
#222
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
Open
angeloashmore
wants to merge
1
commit into
main
Choose a base branch
from
aa/init-new
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,12 @@ import type { Profile } from "../clients/user"; | |
|
|
||
| import { getAdapter } from "../adapters"; | ||
| import { createLoginSession, getHost, getToken } from "../auth"; | ||
| import { getCustomTypes, getSlices } from "../clients/custom-types"; | ||
| import { | ||
| getCustomTypes, | ||
| getSlices, | ||
| insertCustomType, | ||
| insertSlice, | ||
| } from "../clients/custom-types"; | ||
| import { getProfile } from "../clients/user"; | ||
| import { DEFAULT_PRISMIC_HOST, env } from "../env"; | ||
| import { openBrowser } from "../lib/browser"; | ||
|
|
@@ -18,6 +23,7 @@ import { | |
| readConfig, | ||
| readLegacySliceMachineConfig, | ||
| UnknownProjectRootError, | ||
| updateConfig, | ||
| } from "../project"; | ||
| import { checkIsTypeBuilderEnabled, TypeBuilderRequiredError } from "../project"; | ||
| import { createRepo } from "./repo-create"; | ||
|
|
@@ -32,9 +38,16 @@ const config = { | |
| Use --repo to connect to an existing repository instead. If a | ||
| slicemachine.config.json exists, its repository and settings will be | ||
| migrated. | ||
|
|
||
| Use --new to create an empty repository and push the project's local | ||
| models to it, instead of pulling. Useful for starting from a template. | ||
| `, | ||
| options: { | ||
| repo: { type: "string", short: "r", description: "Repository name" }, | ||
| new: { | ||
| type: "boolean", | ||
| description: "Create a new repository and push local models to it", | ||
| }, | ||
| lang: { | ||
| type: "string", | ||
| short: "l", | ||
|
|
@@ -57,31 +70,32 @@ export default createCommand(config, async ({ values }) => { | |
| lang, | ||
| "no-browser": noBrowser, | ||
| "no-setup": noSetup, | ||
| new: isNew, | ||
| } = values; | ||
|
|
||
| // Check for existing prismic.config.json | ||
| try { | ||
| await readConfig(); | ||
| if (isNew && explicitRepo) { | ||
| throw new CommandError( | ||
| "A prismic.config.json file exists. This project is already initialized.", | ||
| "`--new` creates a new repository and cannot be combined with `--repo`.", | ||
| ); | ||
| } catch (error) { | ||
| if (error instanceof MissingPrismicConfigError) { | ||
| // No config found — proceed with initialization. | ||
| } else { | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| // Load legacy slicemachine.config.json | ||
| let legacySliceMachineConfig; | ||
| // `--new` repoints an existing config (e.g. a starter's) at a new | ||
| // repository, so a config is allowed with `--new`. Otherwise, a config | ||
| // means the project is already initialized. | ||
| let hasConfig = false; | ||
| try { | ||
| legacySliceMachineConfig = await readLegacySliceMachineConfig(); | ||
| await readConfig(); | ||
| hasConfig = true; | ||
| } catch (error) { | ||
| if (error instanceof InvalidLegacySliceMachineConfigError) { | ||
| console.warn("Could not read slicemachine.config.json, ignoring."); | ||
| if (!(error instanceof MissingPrismicConfigError)) { | ||
| throw error; | ||
| } | ||
| } | ||
| if (hasConfig && !isNew) { | ||
| throw new CommandError( | ||
| "A prismic.config.json file exists. This project is already initialized.", | ||
| ); | ||
| } | ||
|
|
||
| let token = await getToken(); | ||
| const host = await getHost(); | ||
|
|
@@ -115,6 +129,91 @@ export default createCommand(config, async ({ values }) => { | |
| } | ||
| } | ||
|
|
||
| const adapter = await getAdapter(); | ||
|
|
||
| // `prismic init --new`: create a new empty repository and push the project's | ||
| // local models to it. `--new` always creates a new repository and pushes — | ||
| // it never connects to an existing repository or pulls, so it can't delete | ||
| // local models. An existing config (a starter's) is repointed at the new | ||
| // repository; otherwise a fresh config is created. | ||
| if (isNew) { | ||
| const repo = await createRepo({ lang, token, host }); | ||
| console.info(`Created repository: ${repo}`); | ||
|
|
||
| const documentAPIEndpoint = | ||
| host !== DEFAULT_PRISMIC_HOST ? `https://${repo}.cdn.${host}/api/v2/` : undefined; | ||
|
|
||
| // Without a config, create one first so the adapter and project setup can | ||
| // resolve the project. With a config (a starter), it is repointed after | ||
| // the push so a failed push doesn't leave the config switched. | ||
| if (!hasConfig) { | ||
| try { | ||
| await createConfig({ repositoryName: repo, documentAPIEndpoint, routes: [] }); | ||
| } catch (error) { | ||
| if (error instanceof UnknownProjectRootError) { | ||
| throw new CommandError( | ||
| "Could not find a package.json file. Run this command from a project directory.", | ||
| ); | ||
| } | ||
| throw new CommandError("Failed to create prismic.config.json."); | ||
| } | ||
| } | ||
|
|
||
| const [localCustomTypes, localSlices] = await Promise.all([ | ||
| adapter.getCustomTypes(), | ||
| adapter.getSlices(), | ||
| ]); | ||
| for (const slice of localSlices) { | ||
| await insertSlice(slice.model, { repo, token, host }); | ||
| } | ||
| for (const customType of localCustomTypes) { | ||
| await insertCustomType(customType.model, { repo, token, host }); | ||
|
Comment on lines
+167
to
+170
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❓ What happens if an insert fails halfway? The config would point at the half-populated repo, so re-running |
||
| } | ||
|
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| if (hasConfig) { | ||
| await updateConfig( | ||
| documentAPIEndpoint | ||
| ? { repositoryName: repo, documentAPIEndpoint } | ||
| : { repositoryName: repo }, | ||
| ); | ||
| } | ||
|
|
||
| // Configure the project: regenerate the slice index and set the slice | ||
| // simulator and a preview on the new repository. Scaffold framework files | ||
| // only when the project doesn't already have them (i.e. there was no | ||
| // config). | ||
| await adapter.initProject({ setup: !noSetup && !hasConfig }); | ||
| if (!noSetup) { | ||
| try { | ||
| console.info("Installing dependencies..."); | ||
| await installDependencies(); | ||
| } catch { | ||
| console.warn( | ||
| "Could not install dependencies automatically. Please install them manually (i.e. `npm install`).", | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| await adapter.generateTypes(); | ||
|
|
||
| console.info(`\nInitialized Prismic for new repository "${repo}".`); | ||
| console.info(`Pushed ${localCustomTypes.length} type(s), ${localSlices.length} slice(s).`); | ||
| return; | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // Default flow: create a new repository (or connect to one with --repo) and | ||
| // pull its models. | ||
|
|
||
| // Load legacy slicemachine.config.json | ||
| let legacySliceMachineConfig; | ||
| try { | ||
| legacySliceMachineConfig = await readLegacySliceMachineConfig(); | ||
| } catch (error) { | ||
| if (error instanceof InvalidLegacySliceMachineConfigError) { | ||
| console.warn("Could not read slicemachine.config.json, ignoring."); | ||
| } | ||
| } | ||
|
|
||
|
cursor[bot] marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
|
||
| let repo = (explicitRepo ?? legacySliceMachineConfig?.repositoryName)?.toLowerCase(); | ||
| if (repo) { | ||
| const hasRepoAccess = profile.repositories.some((repository) => repository.domain === repo); | ||
|
|
@@ -130,8 +229,6 @@ export default createCommand(config, async ({ values }) => { | |
| } | ||
| } | ||
|
|
||
| const adapter = await getAdapter(); | ||
|
|
||
| if (!repo) { | ||
| repo = await createRepo({ lang, token, host }); | ||
| console.info(`Created repository: ${repo}`); | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ If I have a fully-initialized project pointing at a real repo and run
init --newby accident, this would repoint my config at a fresh empty repo without asking, yeah? Is this low risk or should we guard against it?