137 lines
3.1 KiB
TypeScript
137 lines
3.1 KiB
TypeScript
import { PrismaClient } from '@prisma/client'
|
|
import {
|
|
FIXED_PROJECT_TYPE_TAGS,
|
|
inferProjectTypeSlug,
|
|
inferTagCategory,
|
|
} from '../src/lib/tag-taxonomy'
|
|
|
|
const prisma = new PrismaClient()
|
|
|
|
async function ensureFixedProjectTypeTags() {
|
|
const result = await Promise.all(
|
|
FIXED_PROJECT_TYPE_TAGS.map((item) =>
|
|
prisma.tag.upsert({
|
|
where: { slug: item.slug },
|
|
update: {
|
|
name: item.name,
|
|
nameEn: item.nameEn,
|
|
category: 'FIXED_PROJECT_TYPE',
|
|
},
|
|
create: {
|
|
name: item.name,
|
|
nameEn: item.nameEn,
|
|
slug: item.slug,
|
|
category: 'FIXED_PROJECT_TYPE',
|
|
},
|
|
})
|
|
)
|
|
)
|
|
|
|
return new Map(result.map((tag) => [tag.slug, tag.id]))
|
|
}
|
|
|
|
async function backfillTagCategories() {
|
|
const tags = await prisma.tag.findMany()
|
|
let updated = 0
|
|
|
|
for (const tag of tags) {
|
|
const inferredCategory = inferTagCategory({
|
|
slug: tag.slug,
|
|
name: tag.name,
|
|
nameEn: tag.nameEn,
|
|
})
|
|
|
|
if (tag.category !== inferredCategory) {
|
|
await prisma.tag.update({
|
|
where: { id: tag.id },
|
|
data: { category: inferredCategory },
|
|
})
|
|
updated += 1
|
|
}
|
|
}
|
|
|
|
return updated
|
|
}
|
|
|
|
async function backfillProjectFixedTypes(fixedTypeIdMap: Map<string, string>) {
|
|
const projects = await prisma.project.findMany({
|
|
where: { status: 'ACTIVE' },
|
|
include: {
|
|
tags: {
|
|
include: {
|
|
tag: true,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const createData: Array<{ projectId: string; tagId: string }> = []
|
|
|
|
for (const project of projects) {
|
|
const fixedTypeSlug = inferProjectTypeSlug({
|
|
name: project.name,
|
|
nameEn: project.nameEn,
|
|
description: project.description,
|
|
descriptionEn: project.descriptionEn,
|
|
tags: project.tags.map((tag) => ({
|
|
slug: tag.tag.slug,
|
|
name: tag.tag.name,
|
|
nameEn: tag.tag.nameEn,
|
|
})),
|
|
})
|
|
|
|
const fixedTypeTagId = fixedTypeIdMap.get(fixedTypeSlug)
|
|
if (!fixedTypeTagId) {
|
|
throw new Error(`Missing fixed project type tag: ${fixedTypeSlug}`)
|
|
}
|
|
|
|
createData.push({
|
|
projectId: project.id,
|
|
tagId: fixedTypeTagId,
|
|
})
|
|
}
|
|
|
|
const removed = await prisma.projectTag.deleteMany({
|
|
where: {
|
|
tag: {
|
|
category: 'FIXED_PROJECT_TYPE',
|
|
},
|
|
},
|
|
})
|
|
|
|
const inserted = await prisma.projectTag.createMany({
|
|
data: createData,
|
|
skipDuplicates: true,
|
|
})
|
|
|
|
return {
|
|
projectCount: projects.length,
|
|
inserted: inserted.count,
|
|
removed: removed.count,
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log('[taxonomy] start')
|
|
|
|
const fixedTypeIdMap = await ensureFixedProjectTypeTags()
|
|
const updatedTagCategoryCount = await backfillTagCategories()
|
|
const projectResult = await backfillProjectFixedTypes(fixedTypeIdMap)
|
|
|
|
console.log('[taxonomy] done', {
|
|
updatedTagCategoryCount,
|
|
projectCount: projectResult.projectCount,
|
|
insertedProjectTypeLinks: projectResult.inserted,
|
|
removedOldProjectTypeLinks: projectResult.removed,
|
|
})
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error('[taxonomy] failed', error)
|
|
process.exit(1)
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect()
|
|
})
|