Git Product home page Git Product logo

model-generator-js's Introduction

npm version Build GitHub license

Kontent.ai Model Generator

The purpose of this project is to help you generate Typescript models based on Kontent.ai item types. These models can be used with the Delivery SDK and enhances your experience by providing strongly typed models.

Installation

Install package globally so you can use it anywhere:

npm i @kontent-ai/model-generator -g

Generate models with CLI

Go to folder where you want to create models and run:

kontent-generate --environmentId=xxx --apiKey=yyy

You may specify other options like:

kontent-generate --environmentId=xxx --apiKey=yyy --addTimestamp=false --elementResolver=camelCase

Generate models in code

Apart from generating models via CLI, you may also generate models in code which also gives you some additional configuration options (such as using custom name resolver).

import { generateModelsAsync } from '@kontent-ai/model-generator';

await generateModelsAsync({
    sdkType: 'delivery',
    environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9',
    isEnterpriseSubscription: true,
    apiKey: 'yyy',
    addTimestamp: true,
    addEnvironmentInfo: true,
    elementResolver: 'camelCase',
    sortConfig: {
      sortTaxonomyTerms: true
    }
})

Customizing generated file names

You may customize the way filenames are stored on file system using the contentTypeFileResolver and / or taxonomyTypeFileResolver configuration option:

await generateModelsAsync({
  sdkType: 'delivery',
  environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9',
  isEnterpriseSubscription: true,
  addEnvironmentInfo: true,
  apiKey: 'yyy',
  addTimestamp: true,
  elementResolver: 'camelCase',
  contentTypeFileResolver: (type) => `content_type_${type.codename}`,
  taxonomyTypeFileResolver: (taxonomy) => `taxonomy_${taxonomy.codename}`,
});

Customizing generated content type names

You may customize name of content types using the contentTypeResolver configuration option and taxonomy types with the taxonomyTypeResolver option:

await generateModelsAsync({
  sdkType: 'delivery',
  environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9',
  isEnterpriseSubscription: true,
  apiKey: 'yyy',
  addTimestamp: true,
  addEnvironmentInfo: true,
  elementResolver: 'camelCase',
  contentTypeResolver: (type) => `${textHelper.toPascalCase(type.codename)}Model`,
  taxonomyTypeResolver: (taxonomy) => `${textHelper.toPascalCase(taxonomy.codename)}Taxonomy`,
});

FAQ

  • If you are getting the The Subscription API is not supported in your plan error, set the isEnterpriseSubscription option to false

CLI Configuration

  • environmentId - Id of the Kontent.ai environment
  • apiKey- Management API Key
  • outputDir- Directory where files will be created. Defaults to current directory - --outputDir=./. Some other examples: --outputDir=./sample
  • isEnterpriseSubscription - Indicates if enterprise subscription endpoint can be used to export data.
  • addTimestamp- Indicates if timestamp is added to generated models
  • addEnvironmentInfo- Indicates if environment info stamp is added to generated models
  • elementResolver- Name resolver for elements. Available options are: camelCase, pascalCase, snakeCase
  • contentTypeFileResolver- Name resolver for content type filenames. Available options are: camelCase, pascalCase, snakeCase
  • contentTypeSnippetFileResolver- Name resolver for content type snippet filenames. Available options are: camelCase, pascalCase, snakeCase
  • taxonomyTypeFileResolver- Name resolver for taxonomy filenames. Available options are: camelCase, pascalCase, snakeCase
  • contentTypeResolver- Name resolver for content type names. Available options are: camelCase, pascalCase, snakeCase
  • contentTypeSnippetResolver- Name resolver for content type snippet names. Available options are: camelCase, pascalCase, snakeCase
  • taxonomyTypeResolver- Name resolver for taxonomy type names. Available options are: camelCase, pascalCase, snakeCase
  • sdkType- Type of sdk for which models are generated. Available options are: delivery
  • exportWebhooks - Indicates if webhooks are exported
  • exportWorkflows - Indicates if workflows are exported
  • exportAssetFolders - Indicates if asset folders are exported
  • exportCollections - Indicates if collections are exported
  • exportLanguages - Indicates if languages are exported
  • exportRoles - Indicates if roles are exported. * Only available for Enterprise subscription plans
  • managementApiUrl - Sets the url of Management API.

Example models

Generator creates file for each content type in your project. For example:

movie.ts

import { IContentItem, Elements } from '@kontent-ai/delivery-sdk';
import { Actor } from './actor';
import { ReleaseCategory } from '../taxonomies/releasecategory';

/**
 * Generated by '@kontent-ai/[email protected]' at 'Thu, 14 Jul 2022 13:58:53 GMT'
 *
 * Movie
 * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c
 * Codename: movie
 */
export type Movie = IContentItem<{
  /**
   * Title (text)
   * Required: true
   * Id: 3473187e-dc78-eff2-7099-f690f7042d4a
   * Codename: title
   */
  title: Elements.TextElement;

  /**
   * Plot (rich_text)
   * Required: false
   * Id: f7ee4f27-27fd-a19b-3c5c-102aae1c50ce
   * Codename: plot
   */
  plot: Elements.RichTextElement;

  /**
   * Released (date_time)
   * Required: false
   * Id: 5ccf4644-0d65-5d96-9a32-f4ea21974d51
   * Codename: released
   */
  released: Elements.DateTimeElement;

  /**
   * Length (number)
   * Required: false
   * Id: 7e8ecfab-a419-27ee-d8ec-8adb76fd007c
   * Codename: length
   */
  length: Elements.NumberElement;

  /**
   * Poster (asset)
   * Required: false
   * Id: a39a7237-9503-a1ae-8431-5b6cdb85ae9d
   * Codename: poster
   */
  poster: Elements.AssetsElement;

  /**
   * Category (multiple_choice)
   * Required: false
   * Id: 9821c252-6414-f549-c17f-cc171dd87713
   * Codename: category
   */
  category: Elements.MultipleChoiceElement;

  /**
   * Stars (modular_content)
   * Required: false
   * Id: aa26a55d-19f8-7501-fea3-b0d9b1eeac71
   * Codename: stars
   */
  stars: Elements.LinkedItemsElement<Actor | Movie>;

  /**
   * SeoName (url_slug)
   * Required: false
   * Id: 756cc91a-a090-60f9-a7f0-f505bfbe046c
   * Codename: seoname
   */
  seoname: Elements.UrlSlugElement;

  /**
   * ReleaseCategory (taxonomy)
   * Required: false
   * Id: 65f2fd44-1856-bc2b-17c2-decb0635e3d2
   * Codename: releasecategory
   */
  releasecategory: Elements.TaxonomyElement<ReleaseCategory>;
}>;

movietype.ts

/**
 * Generated by '@kontent-ai/[email protected]' at 'Mon, 28 Mar 2022 14:36:32 GMT'
 *
 * MovieType
 * Id: 365a17e6-1929-27ab-9f67-a9273c846717
 * Codename: movietype
 */
export type MovieType =
  | 'student'
  | 'film'
  | 'tv'
  | 'blockbuster'
  | 'cinema_only';

To learn the complete generator output, see the following folder: https://github.com/kontent-ai/model-generator-js/tree/master/sample

Contribution & Feedback

Contributions are welcomed. Simply make a pull request.

model-generator-js's People

Stargazers

 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

model-generator-js's Issues

Importing Elements namespace even when not used

Brief bug description

When generating models for content types without any fields, Elements namespace is being exported without being used leading to build fails when using Typescript.

What went wrong?

Repro steps

  1. Create a new content type without any fields
  2. Regenerate models
  3. Run npm run build
  4. See error

Expected behavior

Only making the Elements namespace available, when actually being used

Test environment

  • Platform/OS: Javascript (Next.js) / macOS

Screenshots

Screen Shot 2022-09-13 at 12 06 15

Screen Shot 2022-09-13 at 12 11 21

Syntax error when parsing single apostrophe in element value

Brief bug description

Created './content-types/cmp.ts'
Created './content-types/tag.ts'
Created './taxonomies/regulator_categories.ts'
Created './project/languages.ts'
Created './project/collections.ts'
Created './project/contentTypes.ts'
Created './project/contentTypeSnippets.ts'
Created './project/taxonomies.ts'
Created './project/workflows.ts'
Created './project/roles.ts'
Failed with error:
SyntaxError: ',' expected. (69:34)
67 | alzheimerSSociety: {
68 | id: '8139bc72-1ed7-51d9-b74d-245841a93cf1',

69 | name: 'Alzheimer's Society',
| ^
70 | externalId: 'b7c0b5ac-c444-4614-8626-29c06dfcce61',
71 | folders: {}},

Repro steps

  1. Run model generator against a project which contains a text element that contains a single apostrophe

Expected behavior

Runs to completion and parses the data correctly

Test environment

  • Platform/OS: macOS Ventura M1
  • "@kontent-ai/model-generator": "^5.9.0" installed using npm

Screenshots

screenshot_242

Add an option to hide timestamp

Motivation

Why is this feature required? What problems does it solve?

Hi! We'd like to check in the generated models into our repo. When generating, the cli prints a line with the generation time, e.g.: Timestamp: Wed Feb 12 2020 08:55:07 GMT+0100 (Central European Standard Time). This causes merge conflicts between different pr's, eventhough the actual model hasn't change.

Proposed solution

We would like to add a flag to to the cli, something like --skipTimestamp, which would simply skip printing the line with the time. I'd be happy to send a PR for that sometime next week if it's something you would see merged.

Allow generating content item codenames

Motivation

To increase type-safety and minimize errors when querying for content items by their codename.

Adding an option to output some, or all, content item codenames would allow us to further constrain the codenames of content items by letting us specify that content item codenames can't be just any string, but instead one of many very specific strings.

Proposed solution

One solution may be to add a property to the existing IExportProjectSettings interface so that users can choose to generate types for their content item codenames, like so:

const config: IGenerateModelsConfig = {
  sdkType: 'delivery',
  projectId: '<project id>',
  apiKey: '<api key>',

  exportProjectSettings: {
    /** set to true to generate a `contentItems.ts` file alongside the existing `contentTypes.ts` file. */
    exportContentItemCodenames: true, 

   /** or perhaps a function to allow the user to specify only certain content types / items ? */
   exportContentItemCodenames: ( content_type, content_item ) => true, 
  },

Then, given a project with a content type called Hyperlink, having 3 content items whose codenames are: contact_us, warranty_and_repair, and returns, the output file could look something like:

// contentTypes.ts

export type HyperlinkCodenames = 'contact_us' | 'warranty_and_repair' | 'returns';

We could then use these types to constrain a function like this:

async function getHyperlinks(codename: HyperlinkCodenames) {
  const hyperlinks = await KontentDeliveryClient.items<Hyperlink>()
    .type(contentTypes.hyperlink.codename)
    .equalsFilter('system.codename', codename)
    .toPromise()
    .then((response) => response.data.items);

  return hyperlinks;
}

Additional considerations

If a content type has more than a certain number of content items, the proposed solution may not be ideal; as it could lead to very large file(s) that are difficult to navigate and may slow the performance of the IDE.

It might be good to allow additional configuration in the IGenerateModelsConfig to adjust the limit on the number of generated codenames.

Fix workflow test job

Brief bug description

It seems that the github actions are not testing anything, but it still passes
image

Repro steps

  1. Check any run that logs has not expired in Github
  2. Click on test:all step
  3. See error

Expected behavior

The steps should be deleted or changed to the actual steps that tests something - right now it gives a fake impression that everything is working fine.

Names of content model that contain chars like emojis or em dash results in error

Brief bug description

Getting started project contains content types with em dash (—). Similar case is sample-project for fictohealthtech. generating models for this project results in error

Expected behavior

It should generate the model with changed invalid characters

Test environment

  • Platform/OS: [e.g. .NET Core 2.1, iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Additional context

Add any other context about the problem here.

Screenshots

Add links to screenshots, if possible.

Unable to generate models - Cannot read properties of undefined (reading 'sortTaxonomyTerms')

Brief bug description

Unable to generate models when calling generateModelsAsync - the error "Cannot read properties of undefined (reading 'sortTaxonomyTerms')" is thrown. v6.2.0 works with the same call to generateModelsAsync.

Repro steps

  1. Call generateModelsAsync with the following parameters (API keys have been removed)
function generateModels() {
  const models = generateModelsAsync({
    sdkType: 'delivery',
    environmentId: ,
    apiKey: ,
    isEnterpriseSubscription: false,
    elementResolver: 'snakeCase',
    contentTypeResolver: (type) => `${upperFirst(camelCase(type.codename))}Model`,
    taxonomyTypeResolver: (taxonomy) => `${upperFirst(camelCase(taxonomy.codename))}Taxonomy`,
    contentTypeFileResolver:"pascalCase",
    exportProjectSettings : {
      exportWorkflows:false,
      exportCollections:false,
      exportAssetFolders:false,
      exportLanguages:false,
      exportRoles:false,
      exportWebhooks:false
    }
  });
  1. The following error is generated
/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generators/project/project.generator.js:467
        const sortedTerms = sortConfig.sortTaxonomyTerms
                                       ^

TypeError: Cannot read properties of undefined (reading 'sortTaxonomyTerms')
    at ProjectGenerator.getProjectTaxonomiesTerms (/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generators/project/project.generator.js:467:40)
    at ProjectGenerator.getProjectTaxonomies (/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generators/project/project.generator.js:413:24)
    at ProjectGenerator.getProjectModelCode (/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generators/project/project.generator.js:166:28)
    at ProjectGenerator.generateProjectModel (/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generators/project/project.generator.js:9:35)
    at /Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generator.js:138:74
    at Generator.next (<anonymous>)
    at fulfilled (/Users/ged/project/node_modules/@kontent-ai/model-generator/dist/cjs/lib/generator.js:5:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)`

Expected behavior

Models are generated

Test environment

  • Platform/OS: macOS 13.4.1
  • Browser N/A
  • Version v6.3.0 of @kontent-ai/model-generator library

Additional context

Add any other context about the problem here.

Screenshots

Add links to screenshots, if possible.

Generating models fails - Type 'IContentItem' is not generic.ts

Brief bug description

I have generated the models and they looks as described in readme.

import { IContentItem, Elements } from '@kentico/kontent-delivery';

/**
 * Generated by '@kentico/[email protected]' at 'Tue, 23 Nov 2021 17:18:24 GMT'
 */
export type Stat = IContentItem<{
  link_text: Elements.TextElement;
  metric: Elements.TextElement;
  link_url: Elements.TextElement;
  description: Elements.TextElement;
  note: Elements.TextElement;
}>;

But my compiler is complaining:

Type 'IContentItem' is not generic.ts(2315)
(alias) interface IContentItem
import IContentItem

Repro steps

  1. Generate any model
  2. Run TS compilation/lint

Expected behavior

No error should be raised.

Screenshots

image

Make Elements.RichTextElement generic

Motivation

Much like the LinkedItemsElement, I would like to propose to add a type parameter to RichTextElement as well.

Proposed solution

export type RichTextElement<TContentItem extends IContentItem = IContentItem> = ElementModels.IElement<string> & {
    linkedItems: TContentItem[];
    ...
};

Model Generation fails with `SyntaxError: Invalid character.`

Brief bug description

Model Generation fails with SyntaxError: Invalid character.
No more specific error message than that, but I've attached the full stack trace
generator_stack_trace.txt

Repro steps

Run kontent-generate --environmentId=xxx --apiKey=xxx (I can provide these values for testing via direct message)

Expected behavior

The models are successfully generated or if there is an issue a descriptive error message is displayed in the console.

Test environment

Node v18.16.0
model-generator v 6.5.1

Additional context

Intercom Conversation
We've checked the type that the process fails on for invalid characters in its name or elements but haven't found any. We also checked the MAPI validation endpoint but all of the returned issues are with variants rather than types.

Screenshots

image

custom nameResolver could ends as error

Brief bug description

When I run the model generator with codename _3_section_items and using nameResolver as asny value camelCase, pascalCase, snakeCase I get an error.

camelCase or pascalCase

SyntaxError: An identifier or keyword cannot immediately follow a numeric literal. (8:6)
   6 | */
   7 | export type MainMenu = IContentItem<{
>  8 |     3SectionItems: Elements.LinkedItemsElement<IContentItem>;

snakeCase

SyntaxError: Numeric separators are not allowed here. (8:6)
     7 | export type MainMenu = IContentItem<{
>  8 |     3_section_items: Elements.LinkedItemsElement<IContentItem>;

Usage:

    await generateModelsAsync({
        sdkType: 'delivery',
        projectId: process.env.KONTENT_PROJECT_ID,
        addTimestamp: true,
        nameResolver: 'camelCase',
    })

Expected behavior

The model generator does not fail and generates the codename with some prefix.

Additional context

Generation could also fail with a more polished error.

Update structure of contentTypes to support tree shaking

Motivation

Why is this feature required? What problems does it solve?

We use the smart link SDK where we can (this allows for tagging elements and linking them to kentico). The information from contentTypes.ts is used as a type safe way of providing property names for the smart link data attributes. This has been incredibly nice/convenient. It seems to have one significant downside however, and that is that contentTypes.ts is actually pretty big for our project and the entire thing ends up in our final bundle even if we only use a fraction of it. It's almost the size of angular.

Proposed solution

Right now, contentTypes ends up being a massive single object. If you want metadata about the button content model for instance, you have to pull in the entire object. What would help is if each model object was exported from a single file that contentTypes could then merge together for backwards compatibility. This would allow consumers to import only the model metadata they need and the rest could be tree shaken.

Additional context

Add any other context, screenshots, or reference links about the feature request here.

Abstract Content Type Snippets

Motivation

At the moment, content type snippets are just flattened into the model types. This defeats the purpose of the single point of truth provided by the snippet functionality, and it would make obvious sense to generate separate types for the content snippets, and have the model types extend from them.

Proposed solution

See above.

P.S. perhaps I've missed this functionality?

Types for Linked Elements

Is there any way to generate types for linked elements? (when the linked elements are restricted to a certain type or types).
Currently we are doing:

Movie.elements.stars.linkedItems as Actor[]

I think maybe what we would like is for the generated model to look like:

export type Movie = IContentItem<{
  stars: Elements.LinkedItemsElement<Actor>;
}>;

Introduce unit and integration tests

Motivation

The repository consists of a lot of helper methods that could be tested. The unit and integration tests would give the developers the confidence to bring new changes without the fear of breaking something

Proposed solution

Write tests

Additional context

Add any other context, screenshots, or reference links about the feature request here.

Ability to add prefix to generated classes

Motivation

I'd like to be able to use the generated classes as base classes that I extend from rather than modify the generated files. This way it's easier to regenerate at any time with changes.

Proposed solution

It would be nice to be able to specify a prefix or suffix for the generated classes. For example: BaseActor or ActorGenerated so that I can create a calls Actor that extends the generated one. It would also be useful for avoiding clashes with things that already exist in a framework (e.g. Page could become KontentPage)

Update node version

Motivation

Currently, the supported node is according to the package.json >=. which is not correct as there is already used for example replaceAll in the codebase that is only supported in node 18. Let's get back to 2024 change supported engine to >= 18

Proposed solution

Change engine to >= 18.

Additional context

Add any other context, screenshots, or reference links about the feature request here.

Support for Content type snippets

Motivation

In version 5.0.0-1, types are no longer generated for the Content type snippets.

Proposed solution

Generate type for Content type snippets.

Additional context

image

The yellow marked properties are missing in type generation.

Output dir option

Motivation

At the moment, the generator simply outputs the files around the CWD. This is probably not as much of a problem for CLI users (although in any automated workflow, this is going to make everyone's life a bit harder), but it's not so great for programatic use. At the moment, I have a workspace project which generates the types programatically. The generator outputs the files around the root of this workspace, which muddies the project. I have to run a script to move the files to where I actually want them to be, which is in my main project.

Proposed solution

Provide an outputDir option.

Add option to skip file preamble generation

Motivation

For developing purposes, or testing ones, we ofte cline the project/create new environment.

Then we intrduce the new feature, but then you don'T get the full list of changed models, but a list of all models, where the preabmle is changed.

image

disregard the older version, we have tweaked a thing or two to be able to run against the QA.

Proposed solution

Add the new configuration next to addTimestamp that would allow to dissable generating the preable.

Additional context

Stumble upon this issue - DEVREL-930

Cache Issue

Brief bug description

What went wrong?
When using the code generated Model process it appears that API is trying to fetch a model that was removed earlier in the day.

Created './content-types/bio.ts' Created './content-types/image__video_cover.ts' Created './content-types/icon_block_item.ts' Failed with error: Error: Could not find content type with id 'bdc395af-d19c-473c-b8c1-094a74e69b34'

Repro steps

  1. Create a few content types in kontent.ai.
  2. Generate those models (content types) or consume them with API
  3. Remove one of the content types.
  4. See if it trys to still pull in the deleted content type by its id.

Expected behavior

Should not build deleted models.

Additional context

Full Error:

Failed with error: Error: Could not find content type with id 'bdc395af-d19c-473c-b8c1-094a74e69b34' at C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-mappers.js:29:19 at C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:471:43 at Array.map (<anonymous>) at DeliveryContentTypeGenerator.extractLinkedItemsAllowedTypes (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:471:31) at DeliveryContentTypeGenerator.getLinkedItemsAllowedTypes (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:445:35) at DeliveryContentTypeGenerator.mapElementType (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:378:53) at DeliveryContentTypeGenerator.getExtendedElements (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:425:40) at DeliveryContentTypeGenerator.getContentTypeImports (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:111:39) at DeliveryContentTypeGenerator.getModelCode (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:170:35) at DeliveryContentTypeGenerator.createContentTypeModel (C:\source\repos\corp-web-www-venafi\node_modules\@kontent-ai\model-generator\dist\cjs\lib\generators\delivery\delivery-content-type.generator.js:244:27)

Add links to screenshots, if possible.

Mac Error: Parse Error: Expected HTTP/

Brief bug description

I attempt to generate models on a Mac yet receive and error. When I try the same command on a PC, it works.

Repro steps

  1. Use a Mac
  2. Attempt to generate typescript models
  3. Observe error

Expected behavior

Models generate without error

Test environment

  • Platform/OS: Mac OS 12 or 13 (retried after upgrade, still failed)

Additional context

The same command works on Windows. Here are the parameters I use:

npx @kontent-ai/model-generator --projectId=xxx --moduleResolution=ES2015 --codeType=TypeScript --strictPropertyInitialization=true --environmentId=xxx --apiKey=xxx

[Brackets] in content type's name are causing the model generator to fail

Brief bug description

What went wrong?

When running the model generator while having content type with brackets in its name, the error gets thrown:

Repro steps

  1. Prepare content type with brackets in its name such as [Buggy] brackets
  2. Run content generator
  3. See error

SyntaxError: '=' expected. (9:18)
7 | * Codename: buggy_brackets_
8 | */

9 | export type Buggy[brackets] = IContentItem<{
| ^
10 | /**
11 | * Test (text)
12 | * Required: false

...

throw Error(Failed to process content type '${type.codename}' (${type.name}));
^

Error: Failed to process content type 'buggy_brackets_' (Buggy[brackets])

Expected behavior

The error does not get thrown and the content type with brackets gets generated.

Test environment

return promise/observable from startModelGenerator for better node api usage

Motivation

To be able to generate the models programmatically via a script.

Proposed solution

This is already possible (to a degree) through code like below, however because startModelGenerator does not return this.deliveryClient there is no way to await/subscribe to the generation of models.

const generator = require('@kentico/kontent-model-generator/_commonjs/src/generator');
const utilities = require('@kentico/kontent-model-generator/_commonjs/src/utilities');
const generator = new generator.Generator({
  projectId: 'xxx',
  type: 'CommonJs',
  codeType: utilities.utilities.getCodeType('JavaScript'),
  moduleResolution: utilities.utilities.getModuleResolution('CommonJs')
});
generator.startModelGenerator();

Additional context

  • This would be really useful for CI/CD pipelines for example.
  • An option to set output directory of models would also be useful

Cannot run - /usr/bin/env: ‘node\r’: Permission denied

Brief bug description

When trying to run kontent-generate, the binary crashes and fails to run with the error message:

/usr/bin/env: ‘node\r’: Permission denied

Repro steps

  1. Install with yarn global add @kentico/kontent-model-generator or npm i @kentico/kontent-model-generator -g
  2. In a terminal, run:
kontent-generate --projectId=XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX --moduleResolution=ES2015 --codeType=TypeScript
  1. Observe error

Expected behavior

Script should work

Test environment

  • Platform/OS: Ubuntu
  • Node: 15.14.0
  • NVM: 0.37.2

Additional context

running the following command works as a workaround:

node $(which kontent-generate) --projectId=XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX --moduleResolution=ES2015 --codeType=TypeScript

Support Optional Elements

Motivation

Currently, all content element properties are generated like they are required, i.e. that they will always have a value, yet kontent.ai allows you to mark whether a content element is required or not. Non required properties should be optional in the model.

Proposed solution

myElement: Type for required elements and myElement?: Type for optional elements.

Additional Comments

This is likely a breaking change for consumers, especially those running strict Typescript because they will now have to write code to handle checking whether optional properties have a value or not.

This could potentially be offset by adding a CLI flag for supporting optional elements so this feature is opt in.

Add Subpages to generated page and homepage models

Motivation

Generated models for pages and the homepage do not explicitly reference subpages

Proposed solution

Subpages of a model can be accessed via model.subpages

Additional context

I know that subpages can currently be accessed via linkedItems, but explicitly separating out subpages helps when trying to build a hierarchical structure in a site generator

Ability to turn off timestamps/metadata in Models

Motivation

In our day-to-day workflow, we need to regenerate our models quite often. What is a bit annoying though is that we get a lot of unwanted diffs in our version control due to Last modified: time differences. For our purposes, we'd love to have the ability to turn this off so that our PRs are cleaner and we don't have to manually filter them as much.

Proposed solution

Make the Last modified model property (or maybe even all metadata) optional

Additional context

This is what we want to get rid of:
model_generator_diff

ContentTypeSnippets with LinkedItems wrongly import ContentTypes

Brief bug description

Since splitting the ContentTypeSnippets in #25, the ContentTypes are imported incorrectly inside ContentTypeSnippets.

Repro steps

  1. Generate models
  2. have a look into folder GENERATED/content-type-snippets/ANY-SNIPPET.ts
  3. Wrong relative import of ContentType

Expected behavior

Should correctly import ContentTypes if needed.

Test environment

  • Platform/OS: [e.g. .NET Core 2.1, iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Additional context

Example of generated ContentTypeSnippet, relative import should look as follows:

import { IContentItem, Elements } from '@kontent-ai/delivery-sdk';

--import { SectionContent } from './section_content';
++import { SectionContent } from '../content-types/section_content';

/**
 * Generated by '@kontent-ai/[email protected]' at 'Tue, 16 Aug 2022 13:27:01 GMT'
 *
 * Snippet - Section
 * Id: 70987e02-1761-4957-814d-4bf3d93109da
 * Codename: snippet_section
 */
export type SnippetSection = IContentItem<{
  /**
   * Section (modular_content)
   * Required: false
   * Id: 72dc987c-0b17-4873-85d9-ad1fb2bbb6f3
   * Codename: snippet_section__section
   */
  snippet_section__section: Elements.LinkedItemsElement<SectionContent>;
}>;

Screenshots

Add links to screenshots, if possible.

Use a string literal for type codename in the types for items generated in the content-types folder

Motivation

Imagine you have content types Product and Page. The model generator generates types Product and Page in their respective files in the content-types folder. The types are of shape IContentItem<...> so they have specific elements defined based on their type.
However, the type of the type property is a simple string while it is obvious that the type Product can only have the value product in the type field. It would make working with the types safer and easier if the types would have the precise string literal assigned to the type property. For example:

const renderPageOrProduct = (item: Product | Page) => {
  switch (item.system.type) {
    case contentTypes.product.codename:
      // with the current model generator, TS doesn't know that in this case the type of item is Product instead of the general Product | Page
      // if the codename property would have an exact type, TS would be able to infer that and we would not be forced to unsafely cast it to the expected type
    case contentTypes.page.codename:
      // ...
  }
};

Proposed solution

Assign the exact string literal to the type property. It would require to either extend the IContentItem type to accept another generic parameter or you can modify the type in the generated file. (e.g. IContentType<...> & { system: { type: "product" } })

Add const assertion to objects generated in the 'project' folder ( assetFolders.ts, collections.ts, contentTypes.ts, etc )

Motivation

To increase type-safety and minimize errors when querying for content items by their codename.

Adding the const assertion will allow us to further constrain the codenames of content items by letting us know that the codename property is not just any string, but instead a very specific string.

Proposed solution

The most simple solution would be to add as const to the end of the generated contentTypes object. For example:

export const contentTypes = {
  /**
   * Homepage
   */
  homepage: {
    codename: 'homepage',
    id: '<guid>',
    externalId: undefined,
    name: 'Homepage',
    elements: {
      // ... elements here
    },
  },
} as const; // added

A quick example of how this changes type safety:

BEFORE:
image

AFTER:
image

Additional context

TypeScript docs:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions

Latest version doesn't allow emoticons in Content Type names

Brief bug description

In previous versions, the generator allows for emoticons in Content Type names. It replaced these icons with an underscore in the filename and ignores it completely in the type definition.

In v5.8.0, the attached "SyntaxError: Declaration or statement expected." and "UnhandledPromiseRejectionWarning: SyntaxError: Declaration or statement expected." are thrown.

Repro steps

  1. Create a content type with an emoji as the first character (similar to some of our sample sites)
  2. Install v5.8 of the Model Generator
  3. Run kontent-generate against the project with the newly created content type
  4. See the error

Expected behavior

The model generation will complete and substitute "_" for the emoticons or ignore them completely, as they serve a UI-focused purpose.

Test environment

  • v5.8.0 of the generator
  • VSCode info:
    Version: 1.70.2 (user setup)
    Electron: 18.3.5
    Chromium: 100.0.4896.160
    Node.js: 16.13.2

Additional context

Relates to an open support conversation.

Screenshots

Add links to screenshots, if possible.
emoticon_content_type_error.txt

Cannot generate a model for new subscription

Brief bug description

Cannot finish model generation due to invalid path /v2/projects/78a0b91a-c94a-009e-cc2b-f7d99eefa397/webhooks

Repro steps

  1. Create new subsription
  2. Run this tool
  3.   request: {
    
    ...
    path: '/v2/projects/78a0b91a-c94a-009e-cc2b-f7d99eefa397/webhooks',
    ...
    }data: {
    message: 'No HTTP resource was found that matches the request. See valid routes in API documentation at https://kontent.ai/learn/reference.'
    }

Expected behavior

What is the correct behavior?

Test environment

  • Platform/OS: [e.g. .NET Core 2.1, iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Additional context

Add any other context about the problem here.

Screenshots

Add links to screenshots, if possible.

Add content model type codenames and type guards

Motivation

Including type constants and type guards would allow consumers of the models to infer the correct model type from a generic IContentItem.

Proposed solution

Include a static member on the generated class with the type codename.

export class Article extends ContentItem {
  public static readonly TYPE_NAME: string = 'article';

  // Rest of generated class...
}

And also export a type guard.

/**
 * Check if the content item is of type `article`.
 * @param item 
 */
export function isArticle(item?: IContentItem): item is Article {
  return item?.system.type === Article.TYPE_NAME;
}

This will then enable the usage in this example.

export function parseItem<TItem extends IContentItem>(item?: TItem): Record<string, unknown> | null {
  if (isArticle(item)) {
    return parseArticle(item);
  }

  if (isEvent(item)) {
    return parseEvent(item);
  }

  return null;
}

Additional context

https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

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.