diff --git a/src/commands/init.ts b/src/commands/init.ts index faf8c992..5bdda5db 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -20,7 +20,11 @@ import { removePreview, setSimulatorUrl, } from "../lib/prismic/clients/core"; -import { getRepository, type Repository } from "../lib/prismic/clients/repository"; +import { + enableTypeBuilder, + getRepository, + type Repository, +} from "../lib/prismic/clients/repository"; import { getProfile } from "../lib/prismic/clients/user"; import { diffModels, getLegacySlices, getRemoteModels } from "../lib/prismic/models"; import { completeOnboardingSteps } from "../lib/prismic/onboarding"; @@ -36,7 +40,6 @@ import { MissingPrismicConfigError, readConfig, readLegacySliceMachineConfig, - TypeBuilderRequiredError, UnknownProjectRootError, updateConfig, } from "../project"; @@ -155,12 +158,6 @@ export default createCommand(config, async ({ values }) => { `Repository "${repo}" not found in your account. Check the name or request access to the repository.`, ); }); - - const isTypeBuilderEnabled = - env.PRISMIC_TYPE_BUILDER_ENABLED ?? connectedRepository.quotas?.sliceMachineEnabled === true; - if (!isTypeBuilderEnabled) { - throw new TypeBuilderRequiredError(repo); - } } let adapter: Adapter; @@ -181,6 +178,31 @@ export default createCommand(config, async ({ values }) => { `); } + // The editor shows code snippets for the repository's framework. + const isTypeBuilderEnabled = + env.PRISMIC_TYPE_BUILDER_ENABLED ?? connectedRepository?.quotas?.sliceMachineEnabled; + if ( + repo && + connectedRepository && + (!isTypeBuilderEnabled || connectedRepository.framework !== adapter.id) + ) { + try { + await enableTypeBuilder(adapter.id, { repo, token, host }); + if (!isTypeBuilderEnabled) + console.info(`Turned on the Type Builder for repository "${repo}".`); + } catch (error) { + if (!(error instanceof ForbiddenRequestError)) throw error; + if (!isTypeBuilderEnabled) { + throw new CommandError( + `Repository "${repo}" uses the Legacy Builder. Only a repository administrator can turn on the Type Builder. Ask an administrator to run \`prismic init\`.`, + ); + } + console.warn( + `Could not set the repository's framework to ${adapter.id}. Ask a repository administrator to run \`prismic init\`.`, + ); + } + } + if (!repo) { repo = await createRepo({ name: values["repo-name"], diff --git a/src/index.ts b/src/index.ts index 98218c85..8f2fdb93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,7 +45,6 @@ import { InvalidPrismicConfigError, MissingPrismicConfigError, getRepositoryName, - TypeBuilderRequiredError, UnknownProjectRootError, } from "./project"; import { @@ -74,7 +73,6 @@ const KNOWN_ERRORS = [ InvalidLegacySliceMachineConfigError, MissingPackageJson, UnknownProjectRootError, - TypeBuilderRequiredError, NotFoundRequestError, UnauthorizedRequestError, ForbiddenRequestError, @@ -82,7 +80,7 @@ const KNOWN_ERRORS = [ UnknownRequestError, ]; -const REPORTED_KNOWN_ERRORS = [BadRequestError, UnknownRequestError, TypeBuilderRequiredError]; +const REPORTED_KNOWN_ERRORS = [BadRequestError, UnknownRequestError]; await main(); diff --git a/src/lib/prismic/clients/repository.ts b/src/lib/prismic/clients/repository.ts index 78fa2c89..302b2165 100644 --- a/src/lib/prismic/clients/repository.ts +++ b/src/lib/prismic/clients/repository.ts @@ -18,6 +18,7 @@ const RepositoryStarterSchema = z.object({ const RepositorySchema = z.object({ name: z.optional(z.string()), starter: z.nullish(RepositoryStarterSchema), + framework: z.optional(z.string()), quotas: z.optional( z.object({ sliceMachineEnabled: z.boolean(), @@ -32,6 +33,14 @@ export function getRepository(config: RepositoryConfig): Promise { return repositoryServiceRequest(url, config, { schema: RepositorySchema }); } +export async function enableTypeBuilder( + framework: string, + config: RepositoryConfig, +): Promise { + const url = new URL("type-builder", getRepositoryServiceUrl(config.host)); + await repositoryServiceRequest(url, config, { method: "PATCH", json: { framework } }); +} + const OnboardingStateSchema = z.object({ completedSteps: z.array(z.string()), }); diff --git a/src/project.ts b/src/project.ts index c8181752..1213ee6a 100644 --- a/src/project.ts +++ b/src/project.ts @@ -7,7 +7,6 @@ import * as z from "zod/mini"; import { exists, findUpward, readJsonFile } from "./lib/file"; import { stringify } from "./lib/json"; import { findPackageJson, MissingPackageJson } from "./lib/packageJson"; -import { dedent } from "./lib/string"; import { appendTrailingSlash } from "./lib/url"; const CONFIG_FILENAME = "prismic.config.json"; @@ -216,16 +215,3 @@ export async function checkIsTypeScriptProject(): Promise { const projectRoot = await findProjectRoot(); return exists(new URL("tsconfig.json", projectRoot)); } - -export class TypeBuilderRequiredError extends Error { - name = "TypeBuilderRequired"; - constructor(repo: string) { - super(dedent` - This command requires the Type Builder, but repository "${repo}" uses the Legacy Builder. - - Contact Prismic support to enable the Type Builder: https://prismic.io/docs/help-center - - Learn more at https://prismic.io/docs/type-builder - `); - } -} diff --git a/test/init.test.ts b/test/init.test.ts index 9e33eb2d..b9e1de7c 100644 --- a/test/init.test.ts +++ b/test/init.test.ts @@ -314,13 +314,18 @@ it("fails with next steps when no supported framework is found", async ({ expect(stderr).toContain("prismic repo create --framework"); }); -it("fails when Type Builder is not enabled", async ({ expect, project, prismic, repo }) => { +it("turns on the Type Builder when it is not enabled", async ({ + expect, + project, + prismic, + repo, +}) => { await rm(new URL("prismic.config.json", project)); - const { exitCode, stderr } = await prismic("init", ["--repo", repo], { + const { exitCode, stdout, stderr } = await prismic("init", ["--repo", repo, "--no-setup"], { nodeOptions: { env: { PRISMIC_TYPE_BUILDER_ENABLED: "false" } }, }); - expect(exitCode).toBe(1); - expect(stderr).toContain("Type Builder"); + expect(exitCode, stderr).toBe(0); + expect(stdout).toContain(`Turned on the Type Builder for repository "${repo}".`); }); it("installs dependencies", { timeout: 30_000 }, async ({ expect, project, prismic, repo }) => {