Skip to content

Commit

Permalink
feat: add option for default modifier for v10 types
Browse files Browse the repository at this point in the history
  • Loading branch information
Johannes Sjoberg committed May 29, 2024
1 parent 6fd778c commit dbd9ddd
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ OPTIONS
-p, --preserve preserve output folder
-X --v10 create contentful.js v10 types
-r, --response add response types (only for v10 types)
-m, --modifier add default modifier (only for v10 types)
-l, --localized add localized types
-d, --jsdoc add JSDoc comments
-g, --typeguard add type guards
Expand Down
22 changes: 21 additions & 1 deletion src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ContentfulMdg extends Command {
jsdoc: Flags.boolean({ char: 'd', description: 'add JSDoc comments' }),
typeguard: Flags.boolean({ char: 'g', description: 'add type guards' }),
response: Flags.boolean({ char: 'r', description: 'add response types' }),
modifier: Flags.string({ char: 'm', description: 'add default modifier (v10 only)' }),

// remote access
spaceId: Flags.string({ char: 's', description: 'space id' }),
Expand Down Expand Up @@ -75,8 +76,27 @@ class ContentfulMdg extends Command {
});
}

const v10Options: ConstructorParameters<typeof V10ContentTypeRenderer>[0] = {};

if (flags.modifier) {
if (!flags.v10) {
this.error('"--modifier" option is only available for contentful.js v10 types.');
}

if (
flags.modifier !== 'WITHOUT_UNRESOLVABLE_LINKS' &&
flags.modifier !== 'WITHOUT_LINK_RESOLUTION'
) {
this.error(
`--modifier" option only allows values: WITHOUT_UNRESOLVABLE_LINKS | WITHOUT_LINK_RESOLUTION.`,
);
}

v10Options.defaultModifier = flags.modifier;
}

const renderers: ContentTypeRenderer[] = flags.v10
? [new V10ContentTypeRenderer()]
? [new V10ContentTypeRenderer(v10Options)]
: [new DefaultContentTypeRenderer()];
if (flags.localized) {
if (flags.v10) {
Expand Down
15 changes: 14 additions & 1 deletion src/renderer/type/v10-content-type-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ import { RenderContext } from './create-default-context';
import { createV10Context } from './create-v10-context';

export class V10ContentTypeRenderer extends BaseContentTypeRenderer {
defaultModifier: 'WITHOUT_LINK_RESOLUTION' | 'WITHOUT_UNRESOLVABLE_LINKS' | undefined;

constructor(
options: {
defaultModifier?: 'WITHOUT_LINK_RESOLUTION' | 'WITHOUT_UNRESOLVABLE_LINKS';
} = {},
) {
super();
if (options.defaultModifier) this.defaultModifier = options.defaultModifier;
}

public render(contentType: CFContentType, file: SourceFile): void {
const context = this.createContext();

Expand Down Expand Up @@ -101,7 +112,9 @@ export class V10ContentTypeRenderer extends BaseContentTypeRenderer {
return {
name: renderTypeGeneric(
context.moduleName(contentType.sys.id),
'Modifiers extends ChainModifiers',
`Modifiers extends ChainModifiers${
this.defaultModifier ? ` = '${this.defaultModifier}'` : ''
}`,
'Locales extends LocaleCode = LocaleCode',
),
isExported: true,
Expand Down
61 changes: 53 additions & 8 deletions test/renderer/type/v10-content-type-renderer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,61 @@ describe('The v10 content type renderer', () => {
stripIndent(`
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from "contentful";
import type { TypeLinkedTypeSkeleton } from "./TypeLinkedType";
export interface TypeTestFields {
linkFieldId: EntryFieldTypes.EntryLink<TypeLinkedTypeSkeleton>;
}
export type TypeTestSkeleton = EntrySkeletonType<TypeTestFields, "test">;
export type TypeTest<Modifiers extends ChainModifiers, Locales extends LocaleCode = LocaleCode> = Entry<TypeTestSkeleton, Modifiers, Locales>;
`),
);
});

it('adds default modifier', () => {
const renderer = new V10ContentTypeRenderer({ defaultModifier: 'WITHOUT_UNRESOLVABLE_LINKS' });

const contentType: CFContentType = {
name: 'unused-name',
sys: {
id: 'test',
type: 'Symbol',
},
fields: [
{
id: 'linkFieldId',
name: 'Linked entry Field',
type: 'Link',
localized: false,
required: true,
validations: [
{
linkContentType: ['linkedType'],
},
],
disabled: false,
omitted: false,
linkType: 'Entry',
},
],
};

renderer.render(contentType, testFile);

expect('\n' + testFile.getFullText()).toEqual(
stripIndent(`
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from "contentful";
import type { TypeLinkedTypeSkeleton } from "./TypeLinkedType";
export interface TypeTestFields {
linkFieldId: EntryFieldTypes.EntryLink<TypeLinkedTypeSkeleton>;
}
export type TypeTestSkeleton = EntrySkeletonType<TypeTestFields, "test">;
export type TypeTest<Modifiers extends ChainModifiers = 'WITHOUT_UNRESOLVABLE_LINKS', Locales extends LocaleCode = LocaleCode> = Entry<TypeTestSkeleton, Modifiers, Locales>;
`),
);
});
});

const symbolTypeRenderer = () => {
Expand Down Expand Up @@ -141,11 +186,11 @@ describe('A derived content type renderer class', () => {
expect('\n' + testFile.getFullText()).toEqual(
stripIndent(`
import type { ChainModifiers, Entry, EntrySkeletonType, LocaleCode } from "contentful";
export interface TypeTestFields {
field_id: Test.Symbol;
}
export type TypeTestSkeleton = EntrySkeletonType<TypeTestFields, "test">;
export type TypeTest<Modifiers extends ChainModifiers, Locales extends LocaleCode = LocaleCode> = Entry<TypeTestSkeleton, Modifiers, Locales>;
`),
Expand Down Expand Up @@ -204,12 +249,12 @@ describe('A derived content type renderer class', () => {
expect('\n' + testFile.getFullText()).toEqual(
stripIndent(`
import type { Entry, EntryFieldTypes, EntrySkeletonType } from "contentful";
export interface TypeTestFields {
/** Field of type "Symbol" */
field_id: EntryFieldTypes.Symbol;
}
export type TypeTestSkeleton = EntrySkeletonType<TypeTestFields, "test">;
/** content type "display name" with id: test */
export type TypeTest = Entry<TypeTestSkeleton, Modifiers, Locales>;
Expand Down Expand Up @@ -262,11 +307,11 @@ describe('A derived content type renderer class', () => {
stripIndent(`
import type { CustomEntry } from "@custom";
import type { EntryFieldTypes, EntrySkeletonType } from "contentful";
export interface TypeTestFields {
field_id: EntryFieldTypes.Symbol;
}
export type TypeTestSkeleton = EntrySkeletonType<TypeTestFields, "test">;
export type TypeTest<Modifiers extends ChainModifiers, Locales extends LocaleCode = LocaleCode> = CustomEntry<TypeTestSkeleton, Modifiers, Locales>;
`),
Expand Down

0 comments on commit dbd9ddd

Please sign in to comment.