prismicio / prismic-ts-codegen

A Prismic model-to-TypeScript-type generator.
Apache License 2.0
18 stars 6 forks source link

feat: integrate generated types into `@prismicio/client` automatically #14

Closed angeloashmore closed 2 years ago

angeloashmore commented 2 years ago

Types of changes

Description

This PR adds the ability to generate a @prismicio/client module augmentation that automatically types a Prismic client. It does this by generating a CreateClient interface that uses the Prismic repository's generated document types. For more details on CreateClient, see the "Client type augmentation" section of prismicio/prismic-client#238.

The generated CreateClient interface overrides all calls to @prismicio/client's createClient() function to be typed with the generated AllDocumentTypes type. The output looks like this:

declare module "@prismicio/client" {
  interface CreateClient {
    (
      repositoryNameOrEndpoint: string,
      options?: prismic.ClientConfig
    ): prismic.Client<AllDocumentTypes>;
  }
}

Projects using multiple Prismic repositories: If a project queries content from multiple Prismic repositories, the automatic integration should be disabled and AllDocumentTypes should be passed to createClient() manually.

See the below sections for details on new CLI and library behaviors.

prismic-ts-codegen CLI

When using the prismic-ts-codegen CLI, this new functionality is enabled by default. The integration can be disabled using the clientIntegration.includeCreateClientInterface.

// prismicCodegen.config.ts

import type { Config } from "prismic-ts-codegen";

const config: Config = {
  repositoryName: "nextjs-starter-prismic-blog",
  output: "./types.generated.ts",
  models: ["./customtypes/**/index.json", "./slices/**/model.json"],

  clientIntegration: {
    // `true` by default
    includeCreateClientInterface: false,
  },
};

export default config;

generateTypes() API

When using the generateTypes() API, this new functionality is disabled by default. To enable it, pass clientIntegration.includeCreateClientInterface: true as an option.

generateTypes({
  repositoryName: config.repositoryName,
  customTypeModels,
  sharedSliceModels,
  localeIDs,
  clientIntegration: {
    includeCreateClientInterface: false,
  },
});

Checklist:

github-actions[bot] commented 2 years ago

size-limit report 📦

Path Size
dist/index.js 1.05 MB (+0.03% 🔺)
dist/index.cjs 1.06 MB (+0.03% 🔺)
codecov-commenter commented 2 years ago

Codecov Report

Merging #14 (2b005c0) into main (cf52d58) will decrease coverage by 0.18%. The diff coverage is 90.00%.

@@            Coverage Diff             @@
##             main      #14      +/-   ##
==========================================
- Coverage   95.49%   95.31%   -0.19%     
==========================================
  Files          20       20              
  Lines         311      320       +9     
  Branches       64       67       +3     
==========================================
+ Hits          297      305       +8     
  Misses          2        2              
- Partials       12       13       +1     
Impacted Files Coverage Δ
src/generateTypes.ts 96.66% <90.00%> (-3.34%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update cf52d58...2b005c0. Read the comment docs.

angeloashmore commented 2 years ago

@lihbr I just tested the current implementation and confirmed that document types are overridable per client via the type parameter.

const client1 = prismic.createClient("foo") // Automatic generated types
const client2 = prismic.createClient<AllDocumentTypes1>("bar") // Uses AllDocumentTypes1
const client3 = prismic.createClient<AllDocumentTypes2>("baz") // Uses AllDocumentTypes2

This means consumers don't need to disable the CreateClient interface generation in order to manually provides types. I think we should still recommend disabling it since it results in cleaner and more predictable createClient() calls, but it won't be harmful to leave the default behavior.

Side note: I made the clientIntegration option an object to set us up to support other integration options in the future. Originally, the option was called includeClientInterface (not nested in an object), but that would make it awkward in the future if we need to accept options, such as automatic sm.json reading.

I think we're good to merge. 👍