feat(marketing-pages): add Payload-backed pages + site-settings repos (constructor-injected config)

This commit is contained in:
2026-05-05 08:31:12 +02:00
parent ff6fec7eab
commit 5ffffe4905
2 changed files with 129 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
import "reflect-metadata";
import { injectable } from "inversify";
import { getPayload } from "payload";
import type { SanitizedConfig } from "payload";
import type { IPagesRepository } from "../../application/repositories/pages-repository.interface";
import type { Page } from "../../entities/page";
type PayloadPageDoc = {
id: string | number;
title?: string | null;
slug?: string | null;
hero?:
| {
heading?: string | null;
subheading?: string | null;
image?: string | number | { id: string | number } | null;
}
| null;
layout?: unknown[] | null;
status?: string | null;
publishedAt?: string | null;
seo?: { title?: string | null; description?: string | null } | null;
createdAt?: string | null;
updatedAt?: string | null;
};
function mapDoc(doc: PayloadPageDoc): Page {
const imageId =
doc.hero && typeof doc.hero.image === "object" && doc.hero.image !== null
? String(doc.hero.image.id)
: doc.hero?.image != null
? String(doc.hero.image)
: undefined;
return {
id: String(doc.id),
title: doc.title ?? "",
slug: doc.slug ?? "",
hero: {
heading: doc.hero?.heading ?? "",
subheading: doc.hero?.subheading ?? undefined,
imageId,
},
layout: doc.layout ?? [],
status: doc.status === "published" ? "published" : "draft",
publishedAt: doc.publishedAt ? new Date(doc.publishedAt) : null,
seo: {
title: doc.seo?.title ?? "",
description: doc.seo?.description ?? undefined,
},
createdAt: doc.createdAt ? new Date(doc.createdAt) : new Date(0),
updatedAt: doc.updatedAt ? new Date(doc.updatedAt) : new Date(0),
};
}
@injectable()
export class PayloadPagesRepository implements IPagesRepository {
private config: SanitizedConfig;
constructor(config: SanitizedConfig) {
this.config = config;
}
async getPageBySlug(slug: string): Promise<Page | undefined> {
const payload = await getPayload({ config: this.config });
const result = await payload.find({
collection: "pages",
where: { slug: { equals: slug } },
limit: 1,
overrideAccess: false,
});
const doc = result.docs[0] as PayloadPageDoc | undefined;
return doc ? mapDoc(doc) : undefined;
}
async getPages(options?: {
status?: string;
limit?: number;
offset?: number;
}): Promise<Page[]> {
const payload = await getPayload({ config: this.config });
const where: Record<string, { equals: string }> = {};
if (options?.status) where.status = { equals: options.status };
const result = await payload.find({
collection: "pages",
where: where as never,
limit: options?.limit ?? 50,
page: options?.offset
? Math.floor(options.offset / (options.limit ?? 50)) + 1
: 1,
overrideAccess: false,
});
return result.docs.map((d) => mapDoc(d as PayloadPageDoc));
}
}

View File

@@ -0,0 +1,33 @@
import "reflect-metadata";
import { injectable } from "inversify";
import { getPayload } from "payload";
import type { SanitizedConfig } from "payload";
import type { ISiteSettingsRepository } from "../../application/repositories/site-settings-repository.interface";
import type { SiteSettings } from "../../entities/site-settings";
type PayloadSiteSettings = {
siteName?: string | null;
siteDescription?: string | null;
};
@injectable()
export class PayloadSiteSettingsRepository implements ISiteSettingsRepository {
private config: SanitizedConfig;
constructor(config: SanitizedConfig) {
this.config = config;
}
async getSiteSettings(): Promise<SiteSettings> {
const payload = await getPayload({ config: this.config });
const doc = (await payload.findGlobal({
slug: "site-settings",
overrideAccess: false,
})) as PayloadSiteSettings;
return {
siteName: doc.siteName ?? "My App",
siteDescription: doc.siteDescription ?? undefined,
};
}
}