intercom / contentful-typescript-codegen

Generate TypeScript interfaces from a Contentful environment
MIT License
282 stars 54 forks source link

Update to work with Contentful v10 #143

Open prichey opened 1 year ago

prichey commented 1 year ago

Just wanted to report that the types as generated do not appear to work with contentful.js@^10.

It looks like this is due to (among other things) the type of Entry changing significantly internally. For now I'm going to hold off on migrating but eventual support for v10 would be great. Or if v10 will not be supported it might be good to update docs to give folks that information.

Thanks!

thejessewinton commented 1 year ago

Bumping this

joecf commented 1 year ago

bump!!!

1Ghasthunter1 commented 1 year ago

bump!!!

sean415 commented 1 year ago

Just curious if there's any movement on this or future plans. This package is really valueable and I really appreciate everyone that's put the work in here. But this issue is definitely blocking us from moving to Contentful v10

kadencartwright commented 1 year ago

I use this project at work and am interested at giving the v10 compat a go. I'm hoping to have a first draft to review here sometime in the next several days

dylanwrightCO commented 1 year ago

Any movement on this?

kadencartwright commented 1 year ago

Any movement on this?

No, I've not had the free time recently to keep pushing on this. If anyone is interested in taking over go right ahead.

I'm trying to get away from using contentful at work anyways. It's unacceptable that they don't build typegen themselves imo

lancegliser commented 9 months ago

The current documentation for typescript suggests you could do manual:

type BlogPostSkeleton =
{
  contentTypeId: "blogPost",
  fields: {
    productName: Contentful.EntryFieldTypes.Text,
    image: Contentful.EntryFieldTypes.Asset,
    price: Contentful.EntryFieldTypes.Number,
    categories: Contentful.EntryFieldTypes.Array<Contentful.EntryFieldTypes.EntryLink<CategorySkeleton>>,
  }
}

client.getEntries<BlogPostSkeleton>()

Preceded by:

NOTE: We recommend to automate this step instead of doing it manually. To learn how to automatically generate types for your Contentful content models, refer to Generating type definitions for content types.

That file:

It is recommended to define field types for all your content types. This helps the type system to infer all possible query keys/value types for you. Doing this manually is cumbersome, but do not worry! There are several OSS projects out there to generate type definitions for Contentful content types:

Suggests: cf-content-types-generator in the https://github.com/contentful-userland which has a v10 argument.

I've spent a couple hours and have it working with v10, though it does break your break and code a bit. Examples:

CLI:

cf-content-types-generator --v10 -o src/lib/contentful/generated -s CF_SPACE_ID -t CF_MANAGEMENT_API_ACCESS_TOKEN

Client: src/lib/contentful.copy.ts

import client from "./client";
import { TypeCopySkeleton } from "./generated";
import type { Entry } from "contentful";

enum Slugs {
  GenericContentThankYou = "generic-contact-thank-you",
}

// https://app.contentful.com/spaces/****/content_types/copy/fields
const content_type = "copy";

export type CopyTypeWithoutUnresolvableLinksAndASingleLocale = Entry<
  TypeCopySkeleton,
  "WITHOUT_UNRESOLVABLE_LINKS"
>;

type GetParams = {};

export const getCopyGenericContentThankYouWithoutLocales = async (
  params?: GetParams,
): Promise<CopyTypeWithoutUnresolvableLinksAndASingleLocale> =>
  getCopy({
    ...params,
    slug: Slugs.GenericContentThankYou,
  });

type GetParamsWithSlug = GetParams & {
  slug: string;
};
const getCopy = async (
  params: GetParamsWithSlug,
): Promise<CopyTypeWithoutUnresolvableLinksAndASingleLocale> => {
  const query = {
    limit: 1,
    include: 10,
    // locale: params.locale,
    "fields.slug": params.slug,
    content_type,
  };
  const {
    items: [copy],
  } = await client.withoutUnresolvableLinks.getEntries(query);
  if (!copy) {
    throw new Error(`Contentful copy ${params.slug} undefined`);
  }
  return copy as CopyTypeWithoutUnresolvableLinksAndASingleLocale;
};

Component: src/components/Copy/index.tsx

import { ReactNode } from "react";
import RichText from "../RichText";
import { CopyTypeWithoutUnresolvableLinksAndASingleLocale } from "../../../lib/contentful/contentful.copy";

export type CopyProps = {
  fields: CopyTypeWithoutUnresolvableLinksAndASingleLocale["fields"];
};
export default function Copy({ fields }: CopyProps): ReactNode {
  return (
    <div>
      <RichText document={fields.body} />
    </div>
  );
}

Story: src/components/Copy/index.stories.tsx

import { Meta, StoryObj } from "@storybook/react";
import Component from "./index";
import { CopyTypeWithoutUnresolvableLinksAndASingleLocale } from "../../../lib/contentful/contentful.copy";
import { BLOCKS } from "@contentful/rich-text-types";

const copy: CopyTypeWithoutUnresolvableLinksAndASingleLocale["fields"] = {
  title: "Generic contact thank you",
  slug: "generic-contact-thank-you",
  apiIntegrated: true,
  body: {
    data: {},
    content: [
      {
        data: {},
        content: [
          {
            data: {},
            marks: [],
            value: "Thank you for your message.",
            nodeType: "text",
          },
        ],
        nodeType: BLOCKS.PARAGRAPH,
      },
      {
        data: {},
        content: [
          {
            data: {},
            marks: [],
            value: "Someone will get back to you shortly.",
            nodeType: "text",
          },
        ],
        nodeType: BLOCKS.PARAGRAPH,
      },
    ],
    nodeType: BLOCKS.DOCUMENT,
  },
};

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta: Meta<typeof Component> = {
  component: Component,
  // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/7.0/react/writing-docs/docs-page
  tags: ["autodocs"],
  parameters: {
    // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
    layout: "centered",
  },
  // More on argTypes: https://storybook.js.org/docs/react/api/argtypes
  argTypes: {},
  args: {
    fields: copy,
  },
};

export default meta;
type Story = StoryObj<typeof Component>;

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
export const Default: Story = {
  // More on args: https://storybook.js.org/docs/react/writing-stories/args
  args: {},
};

Hope that helps if anyone needs to migrate due to v10 requirements.