Skip to content

Commit

Permalink
add transformers for content type snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanKiral committed Mar 18, 2024
1 parent 2bdd88e commit 5cfd4ac
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 13 deletions.
45 changes: 32 additions & 13 deletions src/modules/sync/modelTransfomers/contentTypeSnippets.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,54 @@
import { ContentTypeElements, ElementContracts } from "@kontent-ai/management-sdk";

import { omit } from "../../../utils/object.js";
import { Replace } from "../../../utils/types.js";
import { EnvironmentModel } from "../generateSyncModel.js";
import { ContentTypeSnippetsSyncModel } from "../types/fileContentModel.js";
import {
transformAssetElement,
transformCustomElement,
transformGuidelinesElement,
transformLinkedItemsElement,
transformMultipleChoiceElement,
transformRichText,
transformTaxonomyElement,
} from "./elementTransformers.js";

export const transformContentTypeSnippetsModel = (
environmentModel: EnvironmentModel
) => {
environmentModel.contentTypeSnippets.map(snippet => {
environmentModel: EnvironmentModel,
) =>environmentModel.contentTypeSnippets.map(snippet => {
const syncSnippetElements: ContentTypeSnippetsSyncModel["elements"] = snippet.elements
.map(element => {
switch (element.type) {
case "guidelines":
return { ...element, codename: element.codename as string };
return transformGuidelinesElement(
element as unknown as ContentTypeElements.IGuidelinesElement,
environmentModel.assets,
environmentModel.items,
) as unknown as Replace<ElementContracts.IContentTypeElementContract, "codename", string>;
case "modular_content":
return { ...element, codename: element.codename as string };
return transformLinkedItemsElement(
element as ContentTypeElements.ILinkedItemsElement,
environmentModel.contentTypes,
environmentModel.items,
);
case "taxonomy":
return { ...element, codename: element.codename as string };
return transformTaxonomyElement(
element as ContentTypeElements.ITaxonomyElement,
environmentModel.taxonomyGroups,
);
case "multiple_choice":
return { ...element, codename: element.codename as string };
return transformMultipleChoiceElement(element as ContentTypeElements.IMultipleChoiceElement);
case "custom":
return { ...element, codename: element.codename as string };
return transformCustomElement(element as ContentTypeElements.ICustomElement, snippet);
case "asset":
return { ...element, codename: element.codename as string };
return transformAssetElement(element as ContentTypeElements.IAssetElement, environmentModel.assets);
case "rich_text":
return { ...element, codename: element.codename as string };
return transformRichText(element as ContentTypeElements.IRichTextElement, environmentModel.contentTypes);
default:
return { ...omit(element, ["id"]), codename: element.codename as string };
}
});

return { ...omit(snippet, ["id", "last_modified"]), elements: syncSnippetElements };
});

return [] as ContentTypeSnippetsSyncModel[];
};
199 changes: 199 additions & 0 deletions src/modules/sync/modelTransfomers/elementTransformers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import {
AssetContracts,
ContentItemContracts,
ContentTypeContracts,
ContentTypeElements,
ContentTypeSnippetContracts,
TaxonomyContracts,
} from "@kontent-ai/management-sdk";

import { replaceRichTextReferences } from "../../../commands/importExportEntities/entities/utils/richText.js";
import { logWarning } from "../../../log.js";
import { omit } from "../../../utils/object.js";

export const transformCustomElement = (
element: ContentTypeElements.ICustomElement,
snippet: ContentTypeSnippetContracts.IContentTypeSnippetContract,
) => {
const syncAllowedElements = element.allowed_elements?.map(element => ({
codename: snippet.elements.find(el => el.id === element.id!)?.codename!,
}));

return {
...omit(element, ["id"]),
allowed_elements: syncAllowedElements,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

export const transformMultipleChoiceElement = (element: ContentTypeElements.IMultipleChoiceElement) => {
const defaultOptionId = element.default?.global.value.map(o => o.id);
const defaultOptionCodename = defaultOptionId?.map(id => element.options.find(option => option.id === id))!;
const defaultOption = { default: { global: { value: [{ codename: defaultOptionCodename[0]?.codename }] } } };

const options = element.options.map(option => omit(option, ["id"]));

return {
...omit(element, ["id"]),
default: defaultOption,
options,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

export const transformAssetElement = (
element: ContentTypeElements.IAssetElement,
assets: ReadonlyArray<AssetContracts.IAssetModelContract>,
) => {
const defaultAssetsIds = element.default?.global.value.map(a => a.id);
const defaultAssetsReferences = defaultAssetsIds?.map(id => {
const asset = assets.find(asset => asset.id === id);

return {
codename: asset?.codename,
external_id: asset?.external_id ?? asset?.id,
};
})!;

const defaultAssets = { global: { value: defaultAssetsReferences } };

return {
...omit(element, ["id"]),
default: defaultAssets,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

export const transformRichText = (
element: ContentTypeElements.IRichTextElement,
contentTypes: ReadonlyArray<ContentTypeContracts.IContentTypeContract>,
) => {
const allowedContentTypes = element.allowed_content_types?.map(c => ({
codename: contentTypes.find(t => c.id === t.id)?.codename,
}));
const allowedItemLinkTypes = element.allowed_item_link_types?.map(c => ({
codename: contentTypes.find(t => c.id === t.id)?.codename,
}));

return {
...omit(element, ["id"]),
allowed_content_types: allowedContentTypes,
allowed_item_link_types: allowedItemLinkTypes,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

type TermType = {
id: string;
codename: string;
external_id: string;
};

export const transformTaxonomyElement = (
element: ContentTypeElements.ITaxonomyElement,
taxonomies: ReadonlyArray<TaxonomyContracts.ITaxonomyContract>,
) => {
const taxonomyGroup = taxonomies.find(t => t.id === element.taxonomy_group.id);
const taxonomyGroupReference = { codename: taxonomyGroup?.codename };

const travserseTerms = (term: TaxonomyContracts.ITaxonomyContract): TermType[] => {
if (!term.terms.length) {
return [{
id: term.id,
codename: term.codename,
external_id: term.external_id ?? term.id,
}];
}

return term.terms.flatMap(t => travserseTerms(t));
};

const terms = taxonomyGroup?.terms.flatMap(travserseTerms);
const defaultTermsReferences = element.default?.global.value.map(t => ({
codename: terms?.find(term => term.id === t.id)?.codename,
}));
const defaultTerms = { global: { value: defaultTermsReferences } };

return {
...omit(element, ["id"]),
taxonomy_group: taxonomyGroupReference,
name: element.name as string,
default: defaultTerms,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

export const transformLinkedItemsElement = (
element: ContentTypeElements.ILinkedItemsElement,
contentTypes: ReadonlyArray<ContentTypeContracts.IContentTypeContract>,
items: ReadonlyArray<ContentItemContracts.IContentItemModelContract>,
) => {
const allowedContentTypes = element.allowed_content_types?.map(type => ({
codename: contentTypes.find(t => type.id === t.id)?.codename,
}));

const defaultValues = element.default?.global.value.map(itemReference => {
const item = items.find(i => i.id === itemReference.id);

return {
codename: item?.codename,
external_id: item?.external_id ?? item?.id,
};
});

const defaultReference = { global: { value: defaultValues } };

return {
...omit(element, ["id"]),
allowed_content_Types: allowedContentTypes,
default: defaultReference,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

export const transformGuidelinesElement = (
element: ContentTypeElements.IGuidelinesElement,
assets: ReadonlyArray<AssetContracts.IAssetModelContract>,
items: ReadonlyArray<ContentItemContracts.IContentItemModelContract>
) => {
const guidelines = replaceRichTextReferences({
richText: element.guidelines,
replaceAssetId: (oldAssetId, _, asExternalId) => {
const asset = assets.find(a => a.id === oldAssetId)
if(!asset){
logWarning({}, "standard", `could not find given asset with id ${oldAssetId}`);
return asExternalId(oldAssetId);
}
return asExternalId((asset.external_id as string|undefined) ?? oldAssetId);
},
replaceItemId: (oldItemId, _, asExternalId) => {
const item = items.find(i => i.id === oldItemId);
if(!item){
logWarning({}, "standard", `could not find given item with id ${oldItemId}`);
return asExternalId(oldItemId);
}
return asExternalId(item.external_id ?? oldItemId);
},
replaceItemLinkId: (oldItemId, _, asExternalId) => {
const item = items.find(i => i.id === oldItemId);
if(!item){
logWarning({}, "standard", `could not find given item with id ${oldItemId}`);
return asExternalId(oldItemId);
}
return asExternalId(item.external_id ?? oldItemId);
}
})

return {
...omit(element, ["id"]),
guidelines,
codename: element.codename as string,
external_id: element.external_id ?? element.id,
};
};

0 comments on commit 5cfd4ac

Please sign in to comment.