Skip to content

Commit

Permalink
fix throwing, logging warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanKiral committed Apr 5, 2024
1 parent 969af06 commit 172e9bf
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/commands/generateSyncModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const generateModel = async (params: SyncParams) => {
);

logInfo(params, "standard", "Transforming the model.");
const syncModel = transformSyncModel(environmentModel);
const syncModel = transformSyncModel(environmentModel, params);

const fileName = await logOnError(
params,
Expand Down
4 changes: 2 additions & 2 deletions src/modules/sync/generateSyncModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const fetchModel = async (config: ManagementClientBaseOptions): Promise<E
};
};

export const transformSyncModel = (environmentModel: EnvironmentModel): FileContentModel => {
export const transformSyncModel = (environmentModel: EnvironmentModel, logOptions: LogOptions): FileContentModel => {
/**
* The internalIds should be replaced by codenames.
* Unnecesary fields for syncing like lastModified should be removed.
Expand All @@ -79,7 +79,7 @@ export const transformSyncModel = (environmentModel: EnvironmentModel): FileCont
// TODO

const contentTypeModel = transformContentTypeModel(environmentModel);
const contentTypeSnippetModel = transformContentTypeSnippetsModel(environmentModel);
const contentTypeSnippetModel = transformContentTypeSnippetsModel(environmentModel, logOptions);
const taxonomyGroupsModel = transformTaxonomyGroupsModel(environmentModel.taxonomyGroups);

return {
Expand Down
9 changes: 7 additions & 2 deletions src/modules/sync/modelTransfomers/contentTypeSnippets.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LogOptions } from "../../../log.js";
import { omit } from "../../../utils/object.js";
import { EnvironmentModel } from "../generateSyncModel.js";
import { ContentTypeSnippetsWithUnionElements, SnippetElement } from "../types/contractModels.js";
Expand All @@ -15,11 +16,12 @@ import {

export const transformContentTypeSnippetsModel = (
environmentModel: EnvironmentModel,
logOptions: LogOptions,
) =>
environmentModel.contentTypeSnippets.map(snippet => {
const syncSnippetElements = snippet.elements
.map<SyncSnippetElement>(element =>
omit(transformElement(element, snippet, environmentModel), ["content_group"])
omit(transformElement(element, snippet, environmentModel, logOptions), ["content_group"])
);

return {
Expand All @@ -33,19 +35,22 @@ const transformElement = (
element: SnippetElement,
snippet: ContentTypeSnippetsWithUnionElements,
environmentModel: EnvironmentModel,
logOptions: LogOptions,
) => {
switch (element.type) {
case "guidelines":
return transformGuidelinesElement(
element,
environmentModel.assets,
environmentModel.items,
logOptions,
);
case "modular_content":
return transformLinkedItemsElement(
element,
environmentModel.contentTypes,
environmentModel.items,
logOptions,
);
case "taxonomy":
return transformTaxonomyElement(
Expand All @@ -59,7 +64,7 @@ const transformElement = (
case "asset":
return transformAssetElement(element, environmentModel.assets);
case "rich_text":
return transformRichTextElement(element, environmentModel.contentTypes);
return transformRichTextElement(element, environmentModel.contentTypes, logOptions);
default:
return transformDefaultElement(element);
}
Expand Down
129 changes: 87 additions & 42 deletions src/modules/sync/modelTransfomers/elementTransformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import {
itemExternalIdLinkAttributeName,
itemLinkRegex,
} from "../../../constants/richText.js";
import { logWarning } from "../../../log.js";
import { LogOptions, logWarning } from "../../../log.js";
import { omit } from "../../../utils/object.js";
import { notNullOrUndefined } from "../../../utils/typeguards.js";
import { CodenameReference, Replace } from "../../../utils/types.js";
import { customAssetCodenameAttributeName, customItemLinkCodenameAttributeName } from "../../constants/syncRichText.js";
import { ContentTypeSnippetsWithUnionElements } from "../types/contractModels.js";
Expand All @@ -36,29 +37,41 @@ type ElementWithOldContentGroup<E extends { content_group?: CodenameReference }>
true
>;

const throwError = (msg: string) => {
throw new Error(msg);
};

const findContentType = (
typeReference: SharedContracts.IReferenceObjectContract,
contentTypes: ReadonlyArray<ContentTypeContracts.IContentTypeContract>,
warnMessage: string,
logOptions: LogOptions
) => {
const type = contentTypes.find(t => typeReference.id === t.id);

if (!type) {
throw new Error(`Could not find type with id ${typeReference.id}`);
const foundType = contentTypes.find(t => typeReference.id == t.id);

if (!foundType) {
logWarning(
logOptions,
"standard",
warnMessage,
);
return undefined;
}

return { codename: type.codename };
return foundType;
};

const replaceRichTextReferences = (
richText: string,
assets: ReadonlyArray<AssetContracts.IAssetModelContract>,
items: ReadonlyArray<ContentItemContracts.IContentItemModelContract>,
logOptions: LogOptions
): string =>
richText
.replaceAll(assetRegex, (_, oldAssetId /* from the regex capture group*/) => {
const asset = assets.find(a => a.id === oldAssetId);
if (!asset) {
logWarning({}, "standard", `Found asset id "${oldAssetId}" of a non-existent asset in the rich text.`);
logWarning(logOptions, "standard", `Found asset id "${oldAssetId}" of a non-existent asset in the rich text.`);
return `${assetExternalIdAttributeName}="${oldAssetId}"`;
}

Expand All @@ -69,7 +82,7 @@ const replaceRichTextReferences = (
.replaceAll(itemLinkRegex, (_, oldItemId /* from the regex capture group*/) => {
const item = items.find(i => i.id === oldItemId);
if (!item) {
logWarning({}, "standard", `Found asset id "${oldItemId}" of a non-existent asset in the rich text.`);
logWarning(logOptions, "standard", `Found asset id "${oldItemId}" of a non-existent asset in the rich text.`);
return `${itemExternalIdAttributeName}="${oldItemId}"`;
}

Expand All @@ -81,7 +94,8 @@ export const transformCustomElement = (
snippet: ContentTypeSnippetsWithUnionElements,
): ElementWithOldContentGroup<SyncCustomElement> => {
const syncAllowedElements = element.allowed_elements?.map(element => ({
codename: snippet.elements.find(el => el.id === element.id!)?.codename!,
codename: snippet.elements.find(el => el.id === element.id)?.codename
?? throwError(`Could not find codename of element ${element.id} in ${snippet.codename}`),
}));

return {
Expand All @@ -96,8 +110,14 @@ export const transformMultipleChoiceElement = (
element: ContentTypeElements.IMultipleChoiceElement,
): ElementWithOldContentGroup<SyncMultipleChoiceElement> => {
const defaultOptionId = element.default?.global.value.map(o => o.id);
const defaultOptionCodename = defaultOptionId?.map(id => element.options.find(option => option.id === id))!;
const defaultOption = { global: { value: [{ codename: defaultOptionCodename[0]?.codename ?? "" }] } };
// even though mapi says its array, default option can be only one
const defaultOptionCodename = defaultOptionId?.map(id =>
element.options.find(option => option.id === id)?.codename
?? throwError(`Could not find the codename of option in element ${element.codename}`)
);
const defaultOption = defaultOptionCodename
? { global: { value: [{ codename: defaultOptionCodename[0] ?? "" }] } }
: undefined;

const options = element.options.map(option => ({
...omit(option, ["id"]),
Expand All @@ -120,15 +140,16 @@ export const transformAssetElement = (
): ElementWithOldContentGroup<SyncAssetElement> => {
const defaultAssetsIds = element.default?.global.value.map(a => a.id);
const defaultAssetsReferences = defaultAssetsIds?.map(id => {
const asset = assets.find(asset => asset.id === id);
const asset = assets.find(asset => asset.id === id) ?? throwError(`could not find asset with id ${id}`);

return {
codename: asset?.codename ?? "",
external_id: asset?.external_id ?? asset?.id ?? "",
codename: asset.codename,
// external id should be optional in sdks.
external_id: (asset.external_id as string | undefined) ?? asset.id,
};
})!;

const defaultAssets = { global: { value: defaultAssetsReferences } };
const defaultAssets = defaultAssetsReferences.length ? { global: { value: defaultAssetsReferences } } : undefined;

return {
...omit(element, ["id"]),
Expand All @@ -141,9 +162,24 @@ export const transformAssetElement = (
export const transformRichTextElement = (
element: ContentTypeElements.IRichTextElement,
contentTypes: ReadonlyArray<ContentTypeContracts.IContentTypeContract>,
logOptions: LogOptions
): ElementWithOldContentGroup<SyncRichTextElement> => {
const allowedContentTypes = element.allowed_content_types?.map(c => findContentType(c, contentTypes));
const allowedItemLinkTypes = element.allowed_item_link_types?.map(c => findContentType(c, contentTypes));
const allowedContentTypes = element.allowed_content_types?.map(type =>
findContentType(
type,
contentTypes,
`could not find type with id ${type.id} to be used in allowed_content_types in element with codename ${element.codename}. Skipping it`,
logOptions
)
).filter(notNullOrUndefined);
const allowedItemLinkTypes = element.allowed_item_link_types?.map(type =>
findContentType(
type,
contentTypes,
`could not find type with id ${type.id} to be used in allowed_item_link_types in element with codename ${element.codename}. Skipping it`,
logOptions
)
).filter(notNullOrUndefined);

return {
...omit(element, ["id"]),
Expand All @@ -154,34 +190,33 @@ export const transformRichTextElement = (
};
};

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

export const transformTaxonomyElement = (
element: ContentTypeElements.ITaxonomyElement,
taxonomies: ReadonlyArray<TaxonomyContracts.ITaxonomyContract>,
): ElementWithOldContentGroup<SyncTaxonomyElement> => {
const taxonomyGroup = taxonomies.find(t => t.id === element.taxonomy_group.id);
if (!taxonomyGroup) {
throw new Error(`Could not find taxonomy group with id ${element.taxonomy_group.id}`);
}
const taxonomyGroup = taxonomies.find(t => t.id === element.taxonomy_group.id)
?? throwError(`Could not find taxonomy group with id ${element.taxonomy_group.id}`);
const taxonomyGroupReference = { codename: taxonomyGroup.codename };

const travserseTerms = (term: TaxonomyContracts.ITaxonomyContract): TermType[] => [{
id: term.id,
codename: term.codename,
external_id: term.external_id ?? term.id,
}, ...term.terms.flatMap(travserseTerms)];
const findTerm = (
term: TaxonomyContracts.ITaxonomyContract,
id: string,
): TaxonomyContracts.ITaxonomyContract | null => {
if (term.id === id) {
return term;
}

const terms = taxonomyGroup.terms.flatMap(travserseTerms);
const defaultTermsReferences = element.default?.global.value.map(t => {
const term = terms.find(term => term.id === t.id);
if (!term) {
throw new Error(`Could not find taxonomy term with id ${t.id}`);
for (const t of term.terms) {
const termResult = findTerm(t, id);
if (termResult) {
return termResult;
}
}
return null;
};

const defaultTermsReferences = element.default?.global.value.map(t => {
const term = findTerm(taxonomyGroup, t.id as string) ?? throwError(`Could not find taxonomy term with id ${t.id}`);

return { codename: term.codename };
});
Expand All @@ -201,21 +236,30 @@ export const transformLinkedItemsElement = (
element: ContentTypeElements.ILinkedItemsElement,
contentTypes: ReadonlyArray<ContentTypeContracts.IContentTypeContract>,
items: ReadonlyArray<ContentItemContracts.IContentItemModelContract>,
logOptions: LogOptions,
): ElementWithOldContentGroup<SyncLinkedItemsElement> => {
const allowedContentTypes = element.allowed_content_types?.map(type => findContentType(type, contentTypes));
const allowedContentTypes = element.allowed_content_types?.map(type =>
findContentType(
type,
contentTypes,
`could not find type with id ${type.id} to be used in allowed_content_types in element with codename ${element.codename}. Skipping it`,
logOptions
)
).filter(notNullOrUndefined);

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

if (!item) {
throw new Error(`Could not find item with id ${itemReference.id}`);
if(!item){
logWarning(logOptions, 'standard', `could not find item with id ${itemReference.id}. Skipping it`);
return null;
}

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

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

Expand All @@ -232,9 +276,10 @@ export const transformGuidelinesElement = (
element: ContentTypeElements.IGuidelinesElement,
assets: ReadonlyArray<AssetContracts.IAssetModelContract>,
items: ReadonlyArray<ContentItemContracts.IContentItemModelContract>,
logOptions: LogOptions,
): ElementWithOldContentGroup<SyncGuidelinesElement> => ({
...omit(element, ["id"]),
guidelines: replaceRichTextReferences(element.guidelines, assets, items),
guidelines: replaceRichTextReferences(element.guidelines, assets, items, logOptions),
codename: element.codename as string,
external_id: element.external_id ?? element.id,
});
Expand Down

0 comments on commit 172e9bf

Please sign in to comment.