@kontent-ai/model-generator
Version:
This utility generates strongly-typed models for Delivery JS SDK, Migration toolkit or just general scripting to improve the experience when referencing Kontent.ai related objects.
119 lines (106 loc) • 3.99 kB
text/typescript
import type { IContentItem } from "@kontent-ai/delivery-sdk";
import type { ContentTypeModels } from "@kontent-ai/management-sdk";
import Chalk from "chalk";
import { itemsConfig } from "../../config.js";
import { wrapComment } from "../../core/comment.utils.js";
import type { GeneratedSet } from "../../core/core.models.js";
import { resolveCase } from "../../core/resolvers.js";
export interface ItemGeneratorConfig {
readonly disableComments: boolean;
readonly environmentData: {
readonly items: readonly Readonly<IContentItem>[];
readonly types: readonly Readonly<ContentTypeModels.ContentType>[];
};
}
export function getItemsGenerator(config: ItemGeneratorConfig) {
const getItemCodenameType = (typeCodename: string, items: readonly Readonly<IContentItem>[]): string => {
return `export type ${resolveCase(typeCodename, "pascalCase")}Codenames = ${items.map((item) => `'${item.system.codename}'`).join(" | ")};`;
};
const getItemCodenamesProp = (typeCodename: string, items: readonly Readonly<IContentItem>[]): string => {
const values = items.reduce((code, item, index) => {
const isLast = index === items.length - 1;
return `${code}\n
${wrapComment(item.system.name, { disableComments: config.disableComments })}
${item.system.codename}: {
codename: '${item.system.codename}',
id: '${item.system.id}'
}${!isLast ? ",\n" : ""}`;
}, "");
return `export const ${typeCodename}Items = {
${values}
} as const;`;
};
const groupItemsByType = (items: readonly Readonly<IContentItem>[]): Map<string, readonly Readonly<IContentItem>[]> => {
return items.reduce<Map<string, readonly Readonly<IContentItem>[]>>((itemsByType, item) => {
const existingGroupItems = itemsByType.get(item.system.type);
if (existingGroupItems) {
itemsByType.set(item.system.type, [...existingGroupItems, item]);
} else {
itemsByType.set(item.system.type, [item]);
}
return itemsByType;
}, new Map<string, readonly Readonly<IContentItem>[]>());
};
return {
getItemFiles(): GeneratedSet {
return {
folderName: itemsConfig.itemsFolderName,
files: Array.from(groupItemsByType(config.environmentData.items)).map(([typeCodename, items]) => {
const type = config.environmentData.types.find((t) => t.codename.toLowerCase() === typeCodename.toLowerCase());
if (!type) {
throw new Error(`Type with codename '${Chalk.red(typeCodename)}' not found`);
}
return {
filename: `${typeCodename}.items.ts`,
text: `${wrapComment("Object representing identifiers of available items", {
disableComments: config.disableComments,
lines: [
{
name: "Type name",
value: type.name,
},
{
name: "Codename",
value: type.codename,
},
{
name: "Id",
value: type.id,
},
],
})}
${getItemCodenamesProp(typeCodename, items)}`,
};
}),
};
},
getCodenameFiles(): GeneratedSet {
return {
folderName: itemsConfig.codenamesFolderName,
files: Array.from(groupItemsByType(config.environmentData.items)).map(([typeCodename, items]) => {
const type = config.environmentData.types.find((t) => t.codename.toLowerCase() === typeCodename.toLowerCase());
if (!type) {
throw new Error(`Type with codename '${Chalk.red(typeCodename)}' not found`);
}
return {
filename: `${typeCodename}.codenames.ts`,
text: `${wrapComment("Type representing available item codenames", {
disableComments: config.disableComments,
lines: [
{
name: "Type name",
value: type.name,
},
{
name: "Type codename",
value: type.codename,
},
],
})}
${getItemCodenameType(typeCodename, items)}`,
};
}),
};
},
};
}