From 6d79b044187d0cd5a96954eaf74e2858920cdcf4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 00:38:23 +0000 Subject: [PATCH] feat: turn on the Type Builder in `prismic init` `prismic init` no longer stops on a Legacy Builder repository. It turns on the Type Builder and saves the project's framework, so the editor shows code snippets for that framework. Only repository administrators can turn on the Type Builder. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01H4jg7fmGVLhLJjo27eC7Mj --- src/commands/init.ts | 38 +++++++++++++++++++++------ src/index.ts | 4 +-- src/lib/prismic/clients/repository.ts | 9 +++++++ src/project.ts | 14 ---------- test/init.test.ts | 13 ++++++--- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 20856975..48b77dee 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, 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 }) => {