diff --git a/src/commands/init.ts b/src/commands/init.ts index 6e0aa24..3efaa57 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -14,6 +14,7 @@ import { } from "../config"; import { getFramework } from "../frameworks"; import { openBrowser } from "../lib/browser"; +import { generateAndWriteTypes } from "../lib/codegen"; import { ForbiddenRequestError, UnauthorizedRequestError } from "../lib/request"; import { syncCustomTypes, syncSlices } from "./sync"; @@ -154,6 +155,16 @@ export async function init(): Promise { await syncSlices(repo, framework); await syncCustomTypes(repo, framework); + // Generate TypeScript types from synced models + const slices = await framework.getSlices(); + const customTypes = await framework.getCustomTypes(); + const projectRoot = await framework.getProjectRoot(); + await generateAndWriteTypes({ + customTypes: customTypes.map((customType) => customType.model), + slices: slices.map((slice) => slice.model), + projectRoot, + }); + console.info( `Initialized Prismic for repository "${repo}". Run \`npm install\` to install new dependencies.`, ); diff --git a/src/commands/sync.ts b/src/commands/sync.ts index b4c41b4..8eb4437 100644 --- a/src/commands/sync.ts +++ b/src/commands/sync.ts @@ -6,6 +6,7 @@ import { getHost, getToken } from "../auth"; import { getCustomTypes, getSlices } from "../clients/custom-types"; import { safeGetRepositoryFromConfig } from "../config"; import { type FrameworkAdapter, NoSupportedFrameworkError, requireFramework } from "../frameworks"; +import { generateAndWriteTypes } from "../lib/codegen"; import { segmentSetRepository, segmentTrackEnd, segmentTrackStart } from "../lib/segment"; import { sentrySetContext, sentrySetTag } from "../lib/sentry"; import { dedent } from "../lib/string"; @@ -80,6 +81,7 @@ export async function sync(): Promise { } else { await syncSlices(repo, framework); await syncCustomTypes(repo, framework); + await regenerateTypes(framework); segmentTrackEnd("sync", true, undefined, { watch: false }); console.info("Sync complete"); @@ -95,6 +97,7 @@ async function watchForChanges(repo: string, framework: FrameworkAdapter) { await syncSlices(repo, framework); await syncCustomTypes(repo, framework); + await regenerateTypes(framework); console.info(dedent` Initial sync completed! @@ -143,6 +146,8 @@ async function watchForChanges(repo: string, framework: FrameworkAdapter) { changed.push("custom types"); } + await regenerateTypes(framework); + const timestamp = new Date().toLocaleTimeString(); console.info(`[${timestamp}] Changes detected in ${changed.join(" and ")}`); } @@ -254,3 +259,14 @@ function exponentialMs(base: number): number { function hash(data: unknown): string { return createHash("sha256").update(JSON.stringify(data)).digest("hex"); } + +async function regenerateTypes(framework: FrameworkAdapter): Promise { + const slices = await framework.getSlices(); + const customTypes = await framework.getCustomTypes(); + const projectRoot = await framework.getProjectRoot(); + await generateAndWriteTypes({ + customTypes: customTypes.map((customType) => customType.model), + slices: slices.map((slice) => slice.model), + projectRoot, + }); +} diff --git a/src/lib/codegen.ts b/src/lib/codegen.ts new file mode 100644 index 0000000..b21fc5e --- /dev/null +++ b/src/lib/codegen.ts @@ -0,0 +1,23 @@ +import type { CustomType, SharedSlice } from "@prismicio/types-internal/lib/customtypes"; + +import { writeFile } from "node:fs/promises"; +import { generateTypes } from "prismic-ts-codegen"; + +export async function generateAndWriteTypes(args: { + customTypes: CustomType[]; + slices: SharedSlice[]; + projectRoot: URL; +}): Promise { + const types = generateTypes({ + customTypeModels: args.customTypes, + sharedSliceModels: args.slices, + clientIntegration: { + includeContentNamespace: true, + includeCreateClientInterface: true, + }, + cache: true, + typesProvider: "@prismicio/client", + }); + const outputPath = new URL("prismicio-types.d.ts", args.projectRoot); + await writeFile(outputPath, types); +}