UNPKG

@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.

191 lines (177 loc) 8.33 kB
import type { ContentTypeModels, TaxonomyModels, WorkflowModels } from "@kontent-ai/management-sdk"; import { match } from "ts-pattern"; import type { ObjectWithCodename } from "../../core/core.models.js"; import { type FilenameResolver, mapFilename, mapName, type NameResolver, resolveCase } from "../../core/resolvers.js"; import type { DeliveryGeneratorConfig } from "./delivery.generator.js"; import type { DeliveryEntity, DeliveryEntityType } from "./delivery-entity.generator.js"; import { deliveryEntityUtils } from "./utils/delivery-entity.utils.js"; export type DeliveryEntityNames<T extends DeliveryEntityType> = { readonly codenamesValuePropertyName: string; readonly codenamesTypeName: string; readonly codenamesTypeguardFunctionName: string; readonly overviewFilename: string; readonly folderName: string; readonly getEntityName: (entity: Readonly<DeliveryEntity>) => string; readonly getEntityFilename: (entity: Readonly<DeliveryEntity>, addExtension: boolean) => string; readonly getCodenameTypeName: (entity: Readonly<DeliveryEntity>) => string; readonly getTypeguardFunctionName: (entity: Readonly<DeliveryEntity>) => string; } & AdditionalEntityNames<T>; export type AdditionalEntityNames<T> = T extends "Taxonomy" ? { readonly termsNames: { readonly valuesPropertyName: (taxonomy: Readonly<TaxonomyModels.Taxonomy>) => string; readonly codenamesTypeName: (taxonomy: Readonly<TaxonomyModels.Taxonomy>) => string; readonly typeguardFunctionName: (taxonomy: Readonly<TaxonomyModels.Taxonomy>) => string; }; } : T extends "Workflow" ? { readonly allStepsNames: { readonly valuesPropertyName: string; readonly codenamesTypeName: string; readonly typeguardFunctionName: string; }; readonly stepsNames: { readonly valuesPropertyName: (workflow: Readonly<WorkflowModels.Workflow>) => string; readonly codenamesTypeName: (workflow: Readonly<WorkflowModels.Workflow>) => string; readonly typeguardFunctionName: (workflow: Readonly<WorkflowModels.Workflow>) => string; }; } : T extends "Type" ? { readonly typeNames: { readonly contentItemTypeguardFunctionName: (type: Readonly<ContentTypeModels.ContentType>) => string; }; } : NonNullable<unknown>; export function getDeliveryEntityNamesGenerator<T extends DeliveryEntityType>(config: { readonly nameResolvers: Pick<DeliveryGeneratorConfig, "nameResolvers">["nameResolvers"]; readonly fileResolvers: Pick<DeliveryGeneratorConfig, "fileResolvers">["fileResolvers"]; readonly entityType: T; }) { const deliveryUtils = deliveryEntityUtils(); return { getEntityNames: (): DeliveryEntityNames<T> => { const { filenameResolver, nameResolver } = getNameAndFilenameResolver(config); const entityTypeName = { camelCase: resolveCase(config.entityType, "camelCase"), pascalCase: resolveCase(config.entityType, "pascalCase"), pluralCamelCase: resolveCase(deliveryUtils.getPluralName(config.entityType), "camelCase"), }; const entityNames: DeliveryEntityNames<DeliveryEntityType> = { codenamesTypeName: `${entityTypeName.pascalCase}Codenames`, codenamesValuePropertyName: `${entityTypeName.camelCase}Codenames`, codenamesTypeguardFunctionName: `is${entityTypeName.pascalCase}Codename`, overviewFilename: mapFilename<ObjectWithCodename>((c) => c.codename)({ codename: entityTypeName.pluralCamelCase }, true), folderName: entityTypeName.pluralCamelCase, getEntityName: mapName(nameResolver, "pascalCase"), getCodenameTypeName: mapName(nameResolver, "pascalCase", { suffix: "Codename" }), getTypeguardFunctionName: mapName(nameResolver, "pascalCase", { prefix: "is", suffix: "Codename", }), getEntityFilename: mapFilename(filenameResolver, {}), termsNames: config.entityType === "Taxonomy" ? { valuesPropertyName: mapName(nameResolver, "camelCase", { suffix: "TermCodenames" }), codenamesTypeName: mapName(nameResolver, "pascalCase", { suffix: "TermCodenames" }), typeguardFunctionName: mapName(nameResolver, "pascalCase", { prefix: "is", suffix: "TermCodename" }), } : undefined, stepsNames: config.entityType === "Workflow" ? { valuesPropertyName: mapName(nameResolver, "camelCase", { suffix: "StepCodenames" }), codenamesTypeName: mapName(nameResolver, "pascalCase", { suffix: "StepCodenames" }), typeguardFunctionName: mapName(nameResolver, "pascalCase", { prefix: "is", suffix: "StepCodename" }), } : undefined, allStepsNames: config.entityType === "Workflow" ? { valuesPropertyName: resolveCase("workflowStepCodenames", "camelCase"), codenamesTypeName: resolveCase("workflowStepCodenames", "pascalCase"), typeguardFunctionName: resolveCase("isWorkflowStepCodename", "camelCase"), } : undefined, typeNames: config.entityType === "Type" ? { contentItemTypeguardFunctionName: mapName(nameResolver, "pascalCase", { prefix: "is" }), } : undefined, }; return entityNames as DeliveryEntityNames<T>; }, }; } function getNameAndFilenameResolver<T extends DeliveryEntityType>(config: { readonly nameResolvers: Pick<DeliveryGeneratorConfig, "nameResolvers">["nameResolvers"]; readonly fileResolvers: Pick<DeliveryGeneratorConfig, "fileResolvers">["fileResolvers"]; readonly entityType: T; }): { readonly nameResolver: NonNullable<NameResolver<DeliveryEntity>>; readonly filenameResolver: NonNullable<FilenameResolver<DeliveryEntity>>; } { const defaultNameResolver = (item: DeliveryEntity) => `${item.name}${config.entityType}`; const defaultFilenameResolver = (item: DeliveryEntity) => `${item.name}.${config.entityType}`; return match<DeliveryEntityType>(config.entityType) .returnType<{ readonly nameResolver: NonNullable<NameResolver<DeliveryEntity>>; readonly filenameResolver: NonNullable<FilenameResolver<DeliveryEntity>>; }>() .with("Type", () => ({ nameResolver: config.nameResolvers?.contentType ? (config.nameResolvers.contentType as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.contentType ? (config.fileResolvers.contentType as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Snippet", () => ({ nameResolver: config.nameResolvers?.snippet ? (config.nameResolvers.snippet as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.snippet ? (config.fileResolvers.snippet as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Taxonomy", () => ({ nameResolver: config.nameResolvers?.taxonomy ? (config.nameResolvers.taxonomy as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.taxonomy ? (config.fileResolvers.taxonomy as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Language", () => ({ nameResolver: config.nameResolvers?.language ? (config.nameResolvers.language as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.language ? (config.fileResolvers.language as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Workflow", () => ({ nameResolver: config.nameResolvers?.workflow ? (config.nameResolvers.workflow as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.workflow ? (config.fileResolvers.workflow as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Collection", () => ({ nameResolver: config.nameResolvers?.collection ? (config.nameResolvers.collection as NonNullable<NameResolver<DeliveryEntity>>) : defaultNameResolver, filenameResolver: config.fileResolvers?.collection ? (config.fileResolvers.collection as NonNullable<FilenameResolver<DeliveryEntity>>) : defaultFilenameResolver, })) .with("Element", () => ({ nameResolver: (item) => item.codename, filenameResolver: (item) => item.codename, })) .exhaustive(); }