feat(image-export) : capture guide sections in browser
CI / Verify (push) Successful in 58s
CI / Build immutable images and deploy (push) Successful in 2m54s

This commit is contained in:
2026-09-02 22:28:28 +07:00 Unverified
parent ded10ebb36
commit dd672e5331
6 changed files with 272 additions and 1266 deletions
-18
View File
@@ -4,10 +4,8 @@ import { cacheLife, cacheTag } from "next/cache";
import { getPublicPage, listPublicCharacters } from "@/lib/content/queries";
import {
getPublicArtifactExport,
getPublicGuide,
getPublicTeamExport,
getPublicWeaponExport,
listGuideCards,
} from "@/lib/guides/queries";
import {
@@ -71,19 +69,3 @@ export async function getCachedPublicTeamExport(teamId: string) {
if (result) cacheTag(pageCacheTag(result.guideId));
return result;
}
export async function getCachedPublicWeaponExport(guideId: string) {
"use cache: remote";
cacheLife({ stale: 15, revalidate: 60, expire: 60 * 60 });
const result = await getPublicWeaponExport(guideId);
cacheTag(pageCacheTag(guideId));
return result;
}
export async function getCachedPublicArtifactExport(guideId: string) {
"use cache: remote";
cacheLife({ stale: 15, revalidate: 60, expire: 60 * 60 });
const result = await getPublicArtifactExport(guideId);
cacheTag(pageCacheTag(guideId));
return result;
}
-98
View File
@@ -187,102 +187,4 @@ export async function getPublicTeamExport(teamId: string) {
};
}
export async function getPublicWeaponExport(guideId: string) {
const [row] = await getDb()
.select({ guide: guides, note: guideSections.note })
.from(guides)
.innerJoin(
guideSections,
and(
eq(guideSections.guideId, guides.id),
eq(guideSections.slug, "weapon"),
eq(guideSections.enabled, true),
),
)
.where(and(eq(guides.id, guideId), isNull(guides.trashedAt)))
.limit(1);
if (!row) return null;
const weapons = await getDb()
.select({ recommendation: weaponRecommendations, weapon: catalogWeapons })
.from(weaponRecommendations)
.innerJoin(
catalogWeapons,
eq(catalogWeapons.key, weaponRecommendations.weaponKey),
)
.where(eq(weaponRecommendations.guideId, guideId))
.orderBy(asc(weaponRecommendations.sortOrder));
return {
guideName: row.guide.name,
note: row.note,
weapons: weapons.map(({ recommendation, weapon }) => ({
...recommendation,
weapon: { ...weapon, imageUrl: publicMediaUrl(weapon.imageKey) },
})),
};
}
export async function getPublicArtifactExport(guideId: string) {
const [row] = await getDb()
.select({ guide: guides, character: catalogCharacters })
.from(guides)
.innerJoin(
guideSections,
and(
eq(guideSections.guideId, guides.id),
eq(guideSections.slug, "artifact"),
eq(guideSections.enabled, true),
),
)
.innerJoin(
catalogCharacters,
eq(catalogCharacters.key, guides.characterKey),
)
.where(and(eq(guides.id, guideId), isNull(guides.trashedAt)))
.limit(1);
if (!row) return null;
const [groups, profile] = await Promise.all([
getDb().select().from(artifactGroups).where(eq(artifactGroups.guideId, guideId)).orderBy(asc(artifactGroups.sortOrder)),
getDb().select().from(artifactProfiles).where(eq(artifactProfiles.guideId, guideId)).limit(1),
]);
const recommendations = groups.length
? await getDb()
.select({ recommendation: artifactRecommendations, artifact: catalogArtifacts })
.from(artifactRecommendations)
.innerJoin(
catalogArtifacts,
eq(catalogArtifacts.key, artifactRecommendations.firstArtifactKey),
)
.where(inArray(artifactRecommendations.groupId, groups.map((group) => group.id)))
.orderBy(asc(artifactRecommendations.sortOrder))
: [];
const secondKeys = recommendations
.map(({ recommendation }) => recommendation.secondArtifactKey)
.filter((key): key is string => Boolean(key));
const secondArtifacts = secondKeys.length
? await getDb().select().from(catalogArtifacts).where(inArray(catalogArtifacts.key, secondKeys))
: [];
return {
guideName: row.guide.name,
character: catalogCharacterWithUrls(row.character),
groups: groups.map((group) => ({
...group,
rows: recommendations
.filter(({ recommendation }) => recommendation.groupId === group.id)
.map(({ recommendation, artifact }) => {
const second = secondArtifacts.find((item) => item.key === recommendation.secondArtifactKey);
return {
...recommendation,
first: { ...artifact, imageUrl: publicMediaUrl(artifact.imageKey) },
second: second ? { ...second, imageUrl: publicMediaUrl(second.imageKey) } : null,
};
}),
})),
profile: profile[0] ?? null,
};
}
export type PublicGuide = NonNullable<Awaited<ReturnType<typeof getPublicGuide>>>;