Skip to content

Commit

Permalink
Generates type guards for delivery models
Browse files Browse the repository at this point in the history
  • Loading branch information
Enngage committed Nov 11, 2024
1 parent 8bffb3d commit c601a00
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 49 deletions.
1 change: 1 addition & 0 deletions lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const deliveryConfig = {
contentTypesFolderName: `content-types`,
contentTypeSnippetsFolderName: `content-type-snippets`,
taxonomiesFolderName: `taxonomies`,
typeGuardsFileName: 'delivery.type-guards',
systemTypesFolderName: 'system',
coreCodenamesFilename: 'delivery.codenames',
coreTypeFilename: 'core.type',
Expand Down
21 changes: 15 additions & 6 deletions lib/core/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,22 @@ export function mapFilename<T extends ObjectWithCodename>(resolver: FilenameReso
};
}

export function mapName<T extends ObjectWithName>(resolver: NameResolver<T>, defaultCase: CaseType): MapObjectToName<T> {
export function mapName<T extends ObjectWithName>(
resolver: NameResolver<T>,
defaultCase: CaseType,
options?: {
prefix?: string;
}
): MapObjectToName<T> {
return (item) => {
return match(resolver)
.returnType<string>()
.with(P.instanceOf(Function), (resolver) => resolver(item))
.with(undefined, () => resolveCase(item.name, defaultCase))
.otherwise((resolverType) => resolveCase(item.name, resolverType));
return (
`${options?.prefix ? options.prefix : ''}` +
match(resolver)
.returnType<string>()
.with(P.instanceOf(Function), (resolver) => resolver(item))
.with(undefined, () => resolveCase(item.name, defaultCase))
.otherwise((resolverType) => resolveCase(item.name, resolverType))
);
};
}

Expand Down
28 changes: 17 additions & 11 deletions lib/generators/delivery/delivery-content-type.generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
getWorkflowCodenamesType,
getWorkflowStepCodenamesType
} from '../shared/type-codename.generator.js';
import { deliveryTypeGuardGenerator } from './delivery-type-guard.generator.js';

interface ExtractImportsResult {
readonly typeName: string;
Expand Down Expand Up @@ -268,11 +269,6 @@ ${importer.importType({
})}
${importsResult.imports.join('\n')}
${wrapComment(`
* Type representing all available element codenames for ${snippet.name}
`)}
${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)}
${wrapComment(`
* ${snippet.name}
*
Expand All @@ -281,6 +277,11 @@ ${wrapComment(`
`)}
export type ${importsResult.typeName} = ${deliveryConfig.sdkTypes.snippet}<${nameOfTypeRepresentingAllElementCodenames},
${getElementsCode(flattenedElements)}>;
${wrapComment(`
* Type representing all available element codenames for ${snippet.name}
`)}
${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)}
`;
};

Expand All @@ -306,11 +307,6 @@ ${importer.importType({
})}
${importsResult.imports.join('\n')}
${wrapComment(`
* Type representing all available element codenames for ${contentType.name}
`)}
${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)}
${wrapComment(`
* ${contentType.name}
*
Expand All @@ -319,7 +315,17 @@ ${wrapComment(`
`)}
export type ${importsResult.typeName} = ${deliveryConfig.coreContentTypeName}<
${getElementsCode(flattenedElements)}${importsResult.contentTypeExtends ? ` ${importsResult.contentTypeExtends}` : ''},
'${contentType.codename}'>;
'${contentType.codename}'>
${wrapComment(`
* Type representing all available element codenames for ${contentType.name}
`)}
${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)};
${wrapComment(`
* Type guard for ${contentType.name}
`)}
${deliveryTypeGuardGenerator(config).getTypeGuardFunction(contentType)};
`;
};

Expand Down
28 changes: 28 additions & 0 deletions lib/generators/delivery/delivery-type-guard.generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ContentTypeModels } from '@kontent-ai/management-sdk';
import { deliveryConfig } from '../../config.js';
import { ContentTypeNameResolver, mapName } from '../../core/resolvers.js';

export interface DeliveryTypeGuardGeneratorConfig {
readonly nameResolvers?: {
readonly contentType?: ContentTypeNameResolver;
};
}

export function deliveryTypeGuardGenerator(config: DeliveryTypeGuardGeneratorConfig) {
const nameResolvers = {
typeGuardFunctionName: mapName(config.nameResolvers?.contentType, 'pascalCase', {
prefix: 'is'
}),
typeName: mapName(config.nameResolvers?.contentType, 'pascalCase')
};

const getTypeGuardFunction = (contentType: Readonly<ContentTypeModels.ContentType>): string => {
return `export function ${nameResolvers.typeGuardFunctionName(contentType)}(item: ${deliveryConfig.coreContentTypeName}): item is ${nameResolvers.typeName(contentType)} {
return item.system.type === '${contentType.codename}';
}`;
};

return {
getTypeGuardFunction
};
}
17 changes: 12 additions & 5 deletions sample/delivery/content-types/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
import type { Elements } from '@kontent-ai/delivery-sdk';
import type { CoreContentType } from '../system/index.js';

/**
* Type representing all available element codenames for Actor
*/
export type ActorElementCodenames = 'url' | 'first_name' | 'last_name' | 'photo';

/**
* Actor
*
Expand Down Expand Up @@ -69,3 +64,15 @@ export type Actor = CoreContentType<
},
'actor'
>;

/**
* Type representing all available element codenames for Actor
*/
export type ActorElementCodenames = 'url' | 'first_name' | 'last_name' | 'photo';

/**
* Type guard for Actor
*/
export function isActor(item: CoreContentType): item is Actor {
return item.system.type === 'actor';
}
35 changes: 21 additions & 14 deletions sample/delivery/content-types/movie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,6 @@ import type { Actor } from './index.js';
import type { CoreContentType } from '../system/index.js';
import type { Releasecategory } from '../taxonomies/index.js';

/**
* Type representing all available element codenames for Movie
*/
export type MovieElementCodenames =
| 'title'
| 'plot'
| 'released'
| 'length'
| 'poster'
| 'category'
| 'stars'
| 'seoname'
| 'releasecategory';

/**
* Movie
*
Expand Down Expand Up @@ -126,3 +112,24 @@ export type Movie = CoreContentType<
},
'movie'
>;

/**
* Type representing all available element codenames for Movie
*/
export type MovieElementCodenames =
| 'title'
| 'plot'
| 'released'
| 'length'
| 'poster'
| 'category'
| 'stars'
| 'seoname'
| 'releasecategory';

/**
* Type guard for Movie
*/
export function isMovie(item: CoreContentType): item is Movie {
return item.system.type === 'movie';
}
27 changes: 14 additions & 13 deletions sample/delivery/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/**
* This file has been auto-generated by '@kontent-ai/[email protected]'.
*
* (c) Kontent.ai
*
* -------------------------------------------------------------------------------
*
* Project: Movie Database
* Environment: Production
* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9
*
* -------------------------------------------------------------------------------
**/

/**
* This file has been auto-generated by '@kontent-ai/[email protected]'.
*
* (c) Kontent.ai
*
* -------------------------------------------------------------------------------
*
* Project: Movie Database
* Environment: Production
* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9
*
* -------------------------------------------------------------------------------
**/

export * from './content-type-snippets/index.js';
export * from './content-types/index.js';
Expand Down

0 comments on commit c601a00

Please sign in to comment.