Giter Club home page Giter Club logo

contentful-typescript-codegen's Introduction

contentful-typescript-codegen

Generate typings from your Contentful environment.

  • Content Types become interfaces.
  • Locales (and your default locale) become string types.
  • Assets and Rich Text link to Contentful's types.

At Intercom, we use this in our website to increase developer confidence and productivity, ensure that breaking changes to our Content Types don't cause an outage, and because it's neat.

Usage

yarn add --dev contentful-typescript-codegen

Then, add the following to your package.json:

{
  // ...
  "scripts": {
    "contentful-typescript-codegen": "contentful-typescript-codegen --output @types/generated/contentful.d.ts"
  }
}

Feel free to change the output path to whatever you like.

Next, the codegen will expect you to have created a file called either getContentfulEnvironment.js or getContentfulEnvironment.ts in the root of your project directory, which should export a promise that resolves with your Contentful environment.

The reason for this is that you can do whatever you like to set up your Contentful Management Client. Here's an example of a JavaScript config:

const contentfulManagement = require("contentful-management")

module.exports = function() {
  const contentfulClient = contentfulManagement.createClient({
    accessToken: process.env.CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN,
  })

  return contentfulClient
    .getSpace(process.env.CONTENTFUL_SPACE_ID)
    .then(space => space.getEnvironment(process.env.CONTENTFUL_ENVIRONMENT))
}

And the same example in TypeScript:

import { strict as assert } from "assert"
import contentfulManagement from "contentful-management"
import { EnvironmentGetter } from "contentful-typescript-codegen"

const { CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN, CONTENTFUL_SPACE_ID, CONTENTFUL_ENVIRONMENT } = process.env

assert(CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN)
assert(CONTENTFUL_SPACE_ID)
assert(CONTENTFUL_ENVIRONMENT)

const getContentfulEnvironment: EnvironmentGetter = () => {
  const contentfulClient = contentfulManagement.createClient({
    accessToken: CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN,
  })

  return contentfulClient
    .getSpace(CONTENTFUL_SPACE_ID)
    .then(space => space.getEnvironment(CONTENTFUL_ENVIRONMENT))
}

module.exports = getContentfulEnvironment

Note

ts-node must be installed to use a TypeScript config

Command line options

Usage
  $ contentful-typescript-codegen --output <file> <options>

Options
  --output,      -o  Where to write to
  --poll,        -p  Continuously refresh types
  --interval N,  -i  The interval in seconds at which to poll (defaults to 15)

Example output

Here's an idea of what the output will look like for a Content Type:

interface IBlogPostFields {
  /** Title */
  title: string

  /** Body */
  body: Document

  /** Author link */
  author: IAuthor

  /** Image */
  image: Asset

  /** Published? */
  published: boolean | null

  /** Tags */
  tags: string[]

  /** Blog CTA variant */
  ctaVariant: "new-cta" | "old-cta"
}

/**
 * A blog post.
 */
export interface IBlogPost extends Entry<IBlogPostFields> {}

You can see that a few things are handled for you:

  • Documentation comments are automatically generated from Contentful descriptions.
  • Links, like author, are resolved to other TypeScript interfaces.
  • Assets are handled properly.
  • Validations on symbols and text fields are expanded to unions.
  • Non-required attributes automatically have | null appended to their type.
  • The output is formatted using your Prettier config.

contentful-typescript-codegen's People

Contributors

danielhusar avatar dependabot[bot] avatar g-ginzunza avatar g-rath avatar gabrielanca avatar garyjzhao avatar greym0uth avatar horiaa avatar kouhei avatar kylemh avatar lorcan avatar zernie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contentful-typescript-codegen's Issues

Should prettier be a hard requirement?

Hello !

I have been trying your script and I have gotten an error saying that I needed to install prettier. Can you state that as a dependency or in the documentation?

I will probably do it afterwards if I get time.

Thanks :)

Prettier config not resolved correctly

The resolveConfig method is invoked with process.cwd() as first argument.

const prettierConfig = await resolveConfig(process.cwd())

Using process.cwd() as argument the config returns null on Node v18.17.0.
Without it, the config is resolved correctly.

.prettierrc

{
  trailingComma': 'es5',
  tabWidth: 2,
  semi: true,
  singleQuote: true,
  printWidth: 80,
  proseWrap: 'never'
}

index.js

const prettier = require("prettier");
const prettierConfig = await resolveConfig(process.cwd()) // null
const prettier = require("prettier");
const prettierConfig = await resolveConfig() // resolved correctly

Fields are incorrectly extending Entry

My generated type looks something like this:

export interface Link
  extends Entry<LinkFields> {
  sys: {--snip--};
}

LinkFields looks something like this:

export interface LinkFields {
  /** Link Text */
  linkText: string;

  /** Link */
  link: string;
}

and for reference, Entry's type signature is this:

export interface Entry<T> {
    sys: Sys;
    fields: T;
    metadata: Metadata;
    toPlainObject(): object;
    update(): Promise<Entry<T>>;
}

Entry includes toPlainObject and update neither of which are present on fields of an Entry (to the best of my understanding).

My understanding of the "resolved" type signature looks like this:

interface Link {
    sys: {--snip--};
    fields: {
      /** Link Text */
      linkText: string;

      /** Link */
      link: string;
    };
    metadata: Metadata;
    toPlainObject(): object;
    update(): Promise<Entry<T>>;
}

This is incorrect, it should be something like this:

interface Link {
    sys: {--snip--};
    fields: {
      /** Link Text */
      linkText: string;

      /** Link */
      link: string;
    };
    metadata: Metadata;
}

[feat] Pulling multiple locales

Generated typings don't support pulling multiple locales for content types with the Enable localization of this field field option.

For example:

/spaces/space/environments/master/entries?locale=*&content_type=test&access_token=access_token

will return the following json:

{
  "sys": {
    "type": "Array"
  },
  "total": 1,
  "skip": 0,
  "limit": 100,
  "items": [
    {
      "sys": {
        "space": {
          "sys": {
            "type": "Link",
            "linkType": "Space",
            "id": "123"
          }
        },
        "type": "Entry",
        "id": "id",
        "contentType": {
          "sys": {
            "type": "Link",
            "linkType": "ContentType",
            "id": "test"
          }
        },
        "revision": 1,
        "createdAt": "2016-09-13T20:29:10.193Z",
        "updatedAt": "2019-05-09T18:25:51.873Z",
        "environment": {
          "sys": {
            "id": "master",
            "type": "Link",
            "linkType": "Environment"
          }
        }
      },
      "fields": {
        "id": {
          "en-US": "1", // NOT SUPPORTED
          "fr-FR": "2",
        },
      }
    }
  ]
}

Syntax error from code generation

I'm having a problem with various apps that are using the cf-content-types-generator, specifically this app which I'm using in Contentful. The same thing is happening from contentful-typescript-codegen.

What is happening is when I try to generate types, a clear syntax error is happening which comes from an extra semicolon and backslash at the end of the colorPalette line:

export interface TypeComponentTextBlockFields {
    internalName?: Contentful.EntryFields.Symbol;
    headline?: Contentful.EntryFields.Symbol;
    subline?: Contentful.EntryFields.Symbol;
    body?: CFRichTextTypes.Block | CFRichTextTypes.Inline;
    colorPalette?: "1. White (#FFFFFF)" | "2. White Smoke (#FCFCFC)" | "3. Light Gray (#F4F4F4)" | "4. Gray (#EAEAEA)" | "5. Steel Gray (#BBBBBB)" | "6. Dark Gray (#797979)" | "7. Black (#000000)\";;
}

I don't know why this is happening, but it means that I can't usefully use the package/script as a single command or as part of CI/CD, since linting stops it. Currently I have to use the Contentful app and then manually edit the file to allow the project to use the types correctly.

What could be causing this error? Let me know if I can provide more information.

Error in the renderSymbol function

Hello I get the following error when letting your script run.

TypeError: Cannot read property 'find' of undefined
    at Object.renderSymbol (/Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:124:42)
    at /Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:218:58
    at Array.map (<anonymous>)
    at renderContentTypeFields (/Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:204:10)
    at renderContentType (/Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:191:18)
    at /Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:262:61
    at Array.map (<anonymous>)
    at renderAllContentTypes (/Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:262:25)
    at /Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:248:25
    at step (/Users/anagenrauft/dev/carfax-web/carfax-web-frontend-website-nextjs/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:68:23)
error Command failed with exit code 1.

Header imports are duplicated

After a fresh run of master, I see this in the generated files:

// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY IT.

import { Asset, Entry } from 'contentful'
import { Document } from '@contentful/rich-text-types'

// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY IT.

import { Asset, Entry } from 'contentful'
import { Document } from '@contentful/rich-text-types'

Worth fixing before the next release.

Feature Request: Export union of all entries

Would it be possible to export a union of all generated Entries/Content Types?

Use cases:

  • When I call ContentfulClientApi.getEntries<T> I know I should be passing one of these types in as the generic, so it would be useful for me to apply this guard before the getEntries call to ensure a valid generic type has been passed.
  • If I have a renderer function intended to handle all entry types, I could also utilise this generated union to ensure I have handled all possible entry types, potentially using union type subtraction for cases I know I'm not handling.
  • Once the property type guard is available, I can use entry.sys.contentType.sys.id to infer the type of entry.sys

Update to work with Contentful v10

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!

have option to add namespace and own commenting to generated types

Hi, i now do post processing with your generated file. But it would be nice to have a namespace option with this tooling itself. There are multiple routes to it, so im giving two examples:

With a prefix and suffix option i would be able to add my own comments, and wrap it all in a namespace :)

Rationale: i export directly into a .d.ts file and i just like to be able to use: ContentfullRaw.IComponentBanner with no need to import anything in my application. Also when not in a 'd.ts' file a namespace would still be nice!

/* eslint-disable */
/* AUTO GENERATED DO NOT TOUCH, see tooling/xx/xx */
declare namespace ContentfullRaw {
  export interface IComponentBanner {
    sys: {
      id: string;

Don't include Document if not needed

The codegen'd file included

import {Document} from '@contentful/rich-text-types'

even though none of my types needed it. In order to avoid TS errors without manual intervention (or a hack-y script to modify the file), I have to include the package @contentful/rich-text-types. Ideally, it would not automatically assume our schema includes RichText.

Support usage with GraphQL query responses

When using this library to add type information to the anticipated structure of GraphQL queries to Contentful, I found that this library doesn't quite support my use case.

There are two exported interfaces for each of the Contentful models. The IModelNameFields and IModelName interfaces. When I query with GraphQL, the model of the data is comprised entirely of interfaces matching the IModelNameFields signatures, rather than the IModelName interfaces. For modes that don't have any references, this is fine because I can simply declare that the GraphQL query structure will contain interfaces using IModelNameFields. However, if there is a relation where one model references another, the reference points to an IModelName interface.

For example, say you have a model Blog with a relation to a Comment model. If I do a GraphQL query for all Comments, then I'm okay because I can use the ICommentFields interface. However, if I do a GraphQL query for Blogs, and I provide the IBlogFields interface, the interface will have a relation to IComment, which won't match the structure of the object I get back from GraphQL.

Might it be possible for this library to support my use case? As it stands now, I will need to override all of the relations for my models in the generated interfaces. This is significantly less work than maintaining entire interfaces myself, but I'd prefer for the interfaces generated to match 1:1.

Thanks!

Type import confusion: how should I import the types generated by this package?

Thank you for publishing this, it's very helpful!

As a TypeScript novice, I am a little confused about the best way to import these types. The research I've done suggests that importing from @types packages is discouraged as TypeScript would prefer for the types to be imported along with the JS itself.

However, since I'm using these types to add typing to the Contentful Graphql responses that my React components expect, I'm not actually importing any JavaScript. The only thing I need to import is the type, and the TypeScript linter complains about this....

When I try:

import { ILinkFields } from '@types/generated/contentful'

The error I get is:

Cannot import type declaration files. Consider importing 'generated/contentful' instead of '@types/generated/contentful'.ts(6137)

I've written the generated types to my project root at @types/generated/contentful and configured my TypeScript compiler to view my project root as the basePath.

{
  "compilerOptions": {
    "noEmit": true,
    "baseUrl": ".",
    "jsx": "react",
    "allowJs": true,
    "esModuleInterop": true
  },
  "exclude": ["node_modules", "**/*.spec.ts"]
}

I'd really appreciate some guidance here!

Non-required attributes are not automatically generated to have `| null` appended to type

The documentation states:

Non-required attributes automatically have | null appended to their type.

However after generating types, there is not a single instance of null in the generated files, despite dozens of attributes being non-required.

Node version: 16.17.0
Package version: 3.4.0

Yarn script:

yarn contentful-typescript-codegen --output src/types/contentful/types.generated.ts --fieldsOnly && contentful-typescript-codegen --output server/types/contentful/types.generated.ts --fieldsOnly

Expected output:

      /** Add To Bag Text */
    addToBagText?: string | null;

    /** Bag Text */
    bagText?: string | null;

    /** Added To Bag Text */
    addedToBagText?: string | null;

Actual output:

      /** Add To Bag Text */
    addToBagText?: string | undefined;

    /** Bag Text */
    bagText?: string | undefined;

    /** Added To Bag Text */
    addedToBagText?: string | undefined;

Any debugging guidance would be greatly appreciated! Thank you!

export enums

For large projects sometimes I need to use string values from fields. But it is not always type safe if I declare enums manually.

So for example I have following generated model:

export interface IReactComponentFields {
  /** _entryTitle */
  entryTitle?: string | undefined

  /** Component */
  component:
    | 'red'
    | 'blue'
    | 'orange'
}

But sometimes I need to get this fields as Enum for exhaustiveCheck or some other needs.

But I can't generate Enum out of generated model. I can create Object iwth properties. But exhaustive check doesn't work with object properties.

So I would suggest to generate code like that:

export enum IReactComponentEnumComponent {
  red = 'red',
  blue = 'blue',
  orange = 'orange'
}

export interface IReactComponentFields {
  /** _entryTitle */
  entryTitle?: string | undefined

  /** Component */
  component: IReactComponentEnumComponent
}

That would be awesome to have

Property 'json' does not exist on type 'Document'.

I'm querying Contentful with GraphQL and it returns me content?: Document | undefined.

In order to render the file I need to access content.json, using @contentful/rich-text-html-renderer, and it works. The issue is that Typescript keeps warning me that Property 'json' does not exist on type 'Document'. even though it surely does.

Is the typing wrong? Is something to do with the typings this library provides or something else?

ERR_REQUIRE_ESM in Node 16.6

I've got "ERR_REQUIRE_ESM" in Node v16.6.

$ npm run contentful-typescript-codegen

> [email protected] contentful-typescript-codegen
> contentful-typescript-codegen --output @types/generated/contentful.d.ts

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/getContentfulEnvironment.js from /Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js not supported.
Instead change the require of getContentfulEnvironment.js in /Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_
modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js to a dynamic import() which is available in all CommonJS modules.
    at /Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:425:38
    at step (/Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:68:23)
    at Object.next (/Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:49:53)
    at /Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:42:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:38:12)
    at runCodegen (/Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:419:12)
    at Object.<anonymous> (/Users/tnzk/dev/repo/ORGNAME/PROD_NAME/sveltekit/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:455:1) {
  code: 'ERR_REQUIRE_ESM'
}

One cannot require an EJS module, which Node v16 determines it by the extension being .js.

This filename with .js is hard-coded in node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js. I can monkey-patch this, but it would also be helpful if we can specify the path for this in command line.

TypeError: functionMap[field.type] is not a function

When trying to create schema for a Contentful space which has pointer to content in another space(latest multi-space feature from Contentful), the script fails with the error: TypeError: functionMap[field.type] is not a function

Not using prettierrc.json

I have a prettierrc.json in my root directory that specifies single quotes, but the generated output using double quotes.

{
  "trailingComma": "all",
  "tabWidth": 2,
  "semi": false,
  "singleQuote": true
}

Add option to disable interface "I" prefix.

Issue

As described here, it can often be concidered bad to name interfaces with a prefix of "I".

Solution

Therefore, it may be good to add a prefix option to the CLI to let the user select this prefix. For example, contentful-typescript-codegen --prefix I or contentful-typescript-codegen --no-prefix. It could default to "I".

`sys.contentType.sys.id` string is not assignable to string literal

Hello πŸ˜„ first of all, amazing package, thank you for releasing and maintaining it.

I've noticed that when I try and define the return type of the getStaticProps() function (Next.js), if I use an interface that defines the contentType I get a typescript error on the contentType.sys.id property, complaining that type string is incompatible with the string literal (in my example, "city").

Here's the code snippet:

interface Props {
  cities: ICity[];
}

export const getStaticProps: GetStaticProps<Props> = async context => {
  const client = createClient({
    space: process.env.CONTENTFUL_SPACE,
    accessToken: process.env.CONTENTFUL_TOKEN
  });

  const cities = await client.getEntries<ICityFields>({
    content_type: 'city'
  });

  return {
    props: {
      cities: cities.items
    }
  }
}

And a snapshot of the error:

Screen Shot 2021-02-04 at 11 38 01

For now, I'm asserting the type in the return statement to make the error go away - which isn't much of an inconvenience tbh. Is this the correct solution?

  return {
    props: {
      cities: cities.items as ICity[]
    }
  }

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


No npm token specified.

An npm token must be created and set in the NPM_TOKEN environment variable on your CI environment.

Please make sure to create an npm token and to set it in the NPM_TOKEN environment variable on your CI environment. The token must allow to publish to the registry https://registry.npmjs.org/.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Smooth integration with next.js , env.local and alternative to getContentfulEnvironment

Hello!
First of all, would like to say that your app is a game changer for contentful.

I'm using Next.js (Commerce variant) and would like to have a smooth way to adopt your package.

First, of all, for the sake of security we aim to store environment variables in env.local file which is out of git control. It's a common approach and also is adoped in next.js ecosystem.

So, it's not automatically works with env.local, which should be fixed on the library level.

And the second, I would like to have an alternative to a commonjs syntax of getContentfulEnvironment and the file itself. The problem is I have to duplicate client setup logic in typescript and then in javascript only for your library.

Thanks!

Enum of content type ids

Hi,

First of all, thank you very much for your work on this project it has been saving us a lot of time!

I am opening this issue to suggest/ask if there is interest on having this codegen generate an enum containing all content type ids, similar to what we have today on CONTENT_TYPE union, but as an enum. We need to reference ids on our code base and it would be of great help to have something like this.

The only downside I can think of of having this would be that enums generate run time code, so if this is a problem we could put this feature behind a flag.

Please let me know what you think and if there is interest I would be happy to submit a PR.

Type narrowing not working with current setup

Using the generated types I assume that type narrowing would work fine.

const embeddedEntry = (entry: IEntry) => {
  switch (entry.sys.contentType.sys.id) {
    case 'article':
      entry.fields // Should be known as IArticleFields here
      break
    case 'page':
      entry.fields  // Should be known as IPageFields here
}

Weirdly this does not seem to work, even though IArticleEntry should be the only one to have sys.contentType.sys.id as "article".
Is it because of the generic typing?

Imports { Document } when it is not used

When we generate our types we are seeing import { Document } from '@contentful/rich-text-types'; when that type isnt used anywhere. The result is that our type checks and thus builds fail.

I believe this is being imported because we have a string value in one of our union types in contentful that is 'Document'.

Add apostrophe support

image

Ran into a small bump in the road attempting to pull when using apostrophes in Contentful schemas.

Could we use backticks as opposed to apostrophes in auto generated .d.ts file? This would allow for apostrophes in the schema.

generating typescript models fails for specific space with TypeError: contentTypeValidation.linkContentType.map is not a function

It seems there's an issue with our contentful space that causes the codegen to break. We tried running the codegen in a new organization and it worked perfectly. However trying to generate models on our existing environment throws the following error:

yarn run v1.22.19
$ contentful-typescript-codegen --output types/generated/contentful.d.ts
TypeError: contentTypeValidation.linkContentType.map is not a function
    at renderLink (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:154:76)
    at Object.renderArray [as Array] (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:177:34)
    at (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:232:58
    at Array.map (<anonymous>)
    at renderContentTypeFields (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:218:10)
    at renderContentType (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:205:18)
    at /node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:291:61
    at Array.map (<anonymous>)
    at renderAllContentTypes (/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:291:25)
    at /node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:271:25
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I assume the problem is with one of our content models but as we have a lot we're not sure how to find out which content type is causing this exactly.

Is there any way we can investigate this or find out where the problem comes from?

Top level id, contentType and type on Entry

Hi,
Thank you for the amazing work done here, Really appreciate it.

Currently if I want to know the content type of an entry I have to do it like: entry.sys.contentType.id and it's similar to other properties like id and type as well

Is there a way to get this info in a simpler way? for example:
entry.id
entry.contentType
entry.type

If not then is this something the team could consider?

Thank you!

add 'sys' or 'id' to generated types

Adding 'sys' to the generated typings (as its something returned in the response) would be useful , mainly to retrieving the 'id' of the entry.

Getting the content type, when targeting multiple content types, (Similar to #4) would be very useful too. Ideally we wouldn't have to extend the generated typings to achieve this.

Check if validations field is an array to fix error

This script was not working for me originally because it was assuming that field.validations was a defined array, but when hooked up to my contentful client, the field was undefined. Here is a PR that should fix this error - #88.

Feature request: Node.js API

I like what this tool does very much, but I don't care for the API. The magic getContentfulEnvironment.js file is sort of weird, and I also don't like exposing an entire Contentful client instance.

It would be super nice to be able to call this from Node, with the locales and content types as plain objects as opposed to a live client. Something like this:

const codegen = require('contentful-typescript-codegen');

const contentTypes = {}; // get from somewhere
const locales = []; // get from somewhere

const options = { output: "./some-file.ts" }; // same options as CLI flags

codegen({ contentTypes, locales }, options);

Just to be clear, I'm not talking about replacing the existing interface, just adding another one.

If you'd accept a PR that does this I'm happy to do the work!

TypeError: Cannot read property 'getContentTypes' of undefined

Hello ! First of all thanks for this package, It will be really useful to me πŸ‘

I have this issue while trying to generate types. I created the getContentfulEnvironment in the root of the project like that :

const contentfulManagement = require("contentful-management");

module.exports = function () {
  const contentfulClient = contentfulManagement.createClient({
    accessToken: "myaccesstoken",
    host: "cdn.contentful.com",
  });

  return contentfulClient.getSpace("myspaceid").then((space) => {
    space.getEnvironment("master");
  });
};

then I just ran npm run contentful-typescript-codegen and I get this error :

TypeError: Cannot read property 'getContentTypes' of undefined

Thanks and have a great day !

getContenfulEnvironment.ts

For the current contentfulManagement version (11.6.1) the correct import string in the getContentfulEnvironment.ts must be:

import * as contentfulManagement from 'contentful-management';

Please update the Readme.md

contentful^8.1.9 is required

The latest contentful package is version 10.2.4 which is not compatible with this helpful script. People need to install 8.1.9.

output file, object error

When I run the script as per your example, yarn contentful-typescript-codegen --output @types/generated/contentful.d.ts, I get the error:

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type object
    at validateString (internal/validators.js:125:11)
    at Object.resolve (path.js:1080:7)
    at /Users/wvgg/projects/prior/web/node_modules/contentful-typescript-codegen/dist/contentful-typescript-codegen.js:389:39
...

This also happens with yarn contentful-typescript-codegen --output '@types/generated/contentful.d.ts' or yarn contentful-typescript-codegen --output 'contentful.d.ts'

Running the script with no arguments, yarn contentful-typescript-codegen seems to work perfectly, putting the file in /@types/generated/contentful.d.ts

Am I overlooking something?

Support for possible deleted/archived/draft entries

When using the Contentful API, and the include is being used in the request, linked content has the possibility to not have field data if that linked content is in draft/deleted/archived status.

For instance, if there was a Page entry that linked to a Content entry, and the Content entry was in draft and the Page was not, there would be an undefined error for the following: page.fields.content.fields.title. Generated interfaces should enforce type by making fields and content a union type with undefined, where the following is now written: page.fields.content?.fields?.title

Bug: field-types are not correct when calling getEntries with locale = '*'

A call to: getEntries({content_type: 'example', locale: 'en'}) matches the following generated types

export interface IExampleFields {
    /** Title */
    title: string;

    /** Slug */
    slug: string;
}

However, if requesting all languages with getEntries({content_type: 'example', locale: '*'}), the return type is instead (assuming title is not localised and slug is):

export interface IExampleFields {
    /** Title */
    title: string;

    /** Slug */
    slug: {string: string}[];
}

where the types in slug corresponds to {locale: slug}

I suggest extending the codegen to create IExampleFieldsWithLocalisation. This way it is possible to extend getEntries to return different types based on the locale.

I suspect contentful has designed it like this to avoid returning the sys object multiple times.

Bug? Cannot read property 'find' of undefined

I'm just trying out this tool because it looks cool and we might need something like this. The script fails for me with TypeError: Cannot read property 'find' of undefined at Object.renderSymbol.

This seems to be caused by the below line:

const inValidation = field.validations.find(validation => !!validation.in)

field.validations can be undefined (I don't know how, but in our space this occurs). It might be the case that the Contentful Field type incorrectly asserts that field.validations always exists. Anyway I was able to get it running locally by editing the javascript for that line to be (field.validations || []).find.

Clear unavailable validations

I found bug at the contentful models.
Many models have incorrect validation references.

How its happens:

  1. create model A
  2. create model B
  3. create references field (e.g. category) at the model A
  4. go to settings of category field and add validation Accept only specified entry type to model B
  5. save and check json preview
  6. go to model B and delete this model
  7. go back to model A and check json preview.
  8. validation continues to refer to model B, but model B already deleted
  9. run codegen

In results we will have links to non-existent interfaces and generated code will be broken.

I think this problem on the contentful side.... But maybe need fix it on codegen side?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.