import type { Category, CategoryDraft, CategoryReference, } from "@commercetools/platform-sdk"; import { v4 as uuidv4 } from "uuid"; import type { Config } from "#src/config.ts"; import { getBaseResourceProperties } from "#src/helpers.ts"; import { parseExpandClause } from "#src/lib/expandParser.ts"; import { CategoryDraftSchema } from "#src/schemas/generated/category.ts"; import type { Writable } from "#src/types.ts"; import type { GetParams } from "../abstract.ts"; import { AbstractResourceRepository, type RepositoryContext, } from "../abstract.ts"; import { createCustomFields, getReferenceFromResourceIdentifier, } from "../helpers.ts"; import { CategoryUpdateHandler } from "./actions.ts"; export class CategoryRepository extends AbstractResourceRepository<"category"> { constructor(config: Config) { super("category", config); this.actions = new CategoryUpdateHandler(this._storage); this.draftSchema = CategoryDraftSchema; } async create( context: RepositoryContext, draft: CategoryDraft, ): Promise { const assets = draft.assets ? await Promise.all( draft.assets.map(async (d) => ({ id: uuidv4(), name: d.name, description: d.description, sources: d.sources, tags: d.tags, key: d.key, custom: await createCustomFields( d.custom, context.projectKey, this._storage, ), })), ) : []; const resource: Category = { ...getBaseResourceProperties(context.clientId), key: draft.key, name: draft.name, slug: draft.slug, description: draft.description, metaDescription: draft.metaDescription, metaKeywords: draft.metaKeywords, orderHint: draft.orderHint || "", externalId: draft.externalId || "", parent: draft.parent ? await getReferenceFromResourceIdentifier( draft.parent, context.projectKey, this._storage, ) : undefined, ancestors: [], // Resolved at runtime assets, custom: await createCustomFields( draft.custom, context.projectKey, this._storage, ), }; return await this.saveNew(context, resource); } async postProcessResource( context: RepositoryContext, resource: Writable, params?: GetParams, ): Promise { let node: Category = resource; const ancestors: CategoryReference[] = []; // TODO: The expand clause here is a hack, the current expand architecture // is not able to handle the case for 'dynamic' fields like ancestors which // are resolved at runtime. We should do the expand resolution post query // execution for all resources const expandClauses = params?.expand?.map(parseExpandClause) ?? []; const addExpand = expandClauses?.find( (c) => c.element === "ancestors" && c.index === "*", ); while (node.parent) { node = await this._storage.getByResourceIdentifier<"category">( context.projectKey, node.parent, ); ancestors.push({ typeId: "category", id: node.id, obj: addExpand ? node : undefined, }); } resource.ancestors = ancestors; return resource; } }