feat: add seed-tags and migrate-community-connections scripts
Idempotent seed for 16 craft + 20 cooperative tags by slug. Migration maps existing offering/lookingFor tags to communityConnections.topics and copies peerSupport fields without deleting originals.
This commit is contained in:
parent
4b6ff19d5f
commit
1cb029a881
2 changed files with 324 additions and 0 deletions
111
scripts/seed-tags.js
Normal file
111
scripts/seed-tags.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Seed Script: Tags
|
||||
*
|
||||
* Upserts craft and cooperative tags by slug (idempotent).
|
||||
* Safe to run multiple times.
|
||||
*/
|
||||
|
||||
import 'dotenv/config'
|
||||
import mongoose from 'mongoose'
|
||||
import Tag from '../server/models/tag.js'
|
||||
import { connectDB } from '../server/utils/mongoose.js'
|
||||
|
||||
// Convert a slug like "qa-and-testing" to "QA and Testing"
|
||||
// Special-cases common abbreviations.
|
||||
const ABBREVIATIONS = new Set(['qa', 'ux', 'ui', 'devops'])
|
||||
|
||||
function slugToLabel(slug) {
|
||||
return slug
|
||||
.split('-')
|
||||
.map((word) => {
|
||||
if (ABBREVIATIONS.has(word)) return word.toUpperCase()
|
||||
return word.charAt(0).toUpperCase() + word.slice(1)
|
||||
})
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
const CRAFT_SLUGS = [
|
||||
'game-design',
|
||||
'programming',
|
||||
'narrative-design',
|
||||
'art-and-animation',
|
||||
'audio-and-music',
|
||||
'production-management',
|
||||
'qa-and-testing',
|
||||
'community-management',
|
||||
'marketing-and-comms',
|
||||
'ux-and-ui-design',
|
||||
'business-development',
|
||||
'devops-and-tools',
|
||||
'localization',
|
||||
'accessibility',
|
||||
'analytics-and-data',
|
||||
'education-and-mentoring',
|
||||
]
|
||||
|
||||
const COOPERATIVE_SLUGS = [
|
||||
'governance',
|
||||
'finance-and-budgeting',
|
||||
'legal-structures',
|
||||
'conflict-resolution',
|
||||
'consensus-decision-making',
|
||||
'revenue-sharing',
|
||||
'cooperative-bylaws',
|
||||
'member-onboarding',
|
||||
'democratic-management',
|
||||
'worker-ownership',
|
||||
'platform-cooperativism',
|
||||
'cooperative-marketing',
|
||||
'shared-resources',
|
||||
'cooperative-funding',
|
||||
'community-building',
|
||||
'equity-and-inclusion',
|
||||
'cooperative-tech',
|
||||
'sustainability',
|
||||
'collective-bargaining',
|
||||
'inter-coop-collaboration',
|
||||
]
|
||||
|
||||
async function seedTags() {
|
||||
await connectDB()
|
||||
|
||||
const tagDefs = [
|
||||
...CRAFT_SLUGS.map((slug) => ({ slug, pool: 'craft', label: slugToLabel(slug) })),
|
||||
...COOPERATIVE_SLUGS.map((slug) => ({ slug, pool: 'cooperative', label: slugToLabel(slug) })),
|
||||
]
|
||||
|
||||
let upserted = 0
|
||||
let unchanged = 0
|
||||
|
||||
for (const { slug, pool, label } of tagDefs) {
|
||||
const result = await Tag.updateOne(
|
||||
{ slug },
|
||||
{ $setOnInsert: { slug, pool, label, active: true, createdAt: new Date() } },
|
||||
{ upsert: true }
|
||||
)
|
||||
if (result.upsertedCount > 0) {
|
||||
console.log(` + Created [${pool}] ${label} (${slug})`)
|
||||
upserted++
|
||||
} else {
|
||||
unchanged++
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n=== Seed Complete ===')
|
||||
console.log(` Total tags defined: ${tagDefs.length}`)
|
||||
console.log(` Newly created: ${upserted}`)
|
||||
console.log(` Already existed: ${unchanged}`)
|
||||
}
|
||||
|
||||
seedTags()
|
||||
.then(() => {
|
||||
console.log('\nTag seed completed successfully')
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('\nTag seed failed:', err)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(() => {
|
||||
mongoose.connection.close()
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue