From c25e67b892c9033745900c148d6e2255aeddcedf Mon Sep 17 00:00:00 2001 From: Behzad-rabiei Date: Sun, 15 Jun 2025 16:36:35 +0200 Subject: [PATCH 1/2] chore: chnage metadata namespace field to namespaces --- src/docs/platform.doc.yml | 4 ++-- src/validations/platform.validation.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/docs/platform.doc.yml b/src/docs/platform.doc.yml index 7a76e09..456d0a1 100644 --- a/src/docs/platform.doc.yml +++ b/src/docs/platform.doc.yml @@ -165,13 +165,13 @@ paths: type: string description: Metadata for Notion. - type: object - required: [baseURL, path, namespace] + required: [baseURL, path, namespaces] properties: baseURL: type: string path: type: string - namespace: + namespaces: type: array items: type: number diff --git a/src/validations/platform.validation.ts b/src/validations/platform.validation.ts index f022c19..cb171ce 100644 --- a/src/validations/platform.validation.ts +++ b/src/validations/platform.validation.ts @@ -39,7 +39,7 @@ const mediaWikiUpdateMetadata = () => { return Joi.object().keys({ baseURL: Joi.string().required(), path: Joi.string().required(), - namespace: Joi.array().items(Joi.number()).required(), + namespaces: Joi.array().items(Joi.number()).required(), }); }; @@ -94,7 +94,7 @@ const mediaWikiMetadata = () => { return Joi.object().keys({ baseURL: Joi.string().required(), path: Joi.string().required(), - namespace: Joi.array().items(Joi.number()).required(), + namespaces: Joi.array().items(Joi.number()).required(), }); }; From bdd3acaa263101f7896752eab1757356fc1dfe5c Mon Sep 17 00:00:00 2001 From: Behzad-rabiei Date: Sun, 15 Jun 2025 19:31:48 +0200 Subject: [PATCH 2/2] chore: add migration script to fix namespace field --- .migrate | 14 +- ...72787797-add-activated-field-to-modules.ts | 29 ---- .../db/1744651967487-add-modules.ts | 64 -------- ...690421-change-mediawiki-namespace-field.ts | 144 ++++++++++++++++++ 4 files changed, 155 insertions(+), 96 deletions(-) delete mode 100644 src/migrations/db/1738072787797-add-activated-field-to-modules.ts delete mode 100644 src/migrations/db/1744651967487-add-modules.ts create mode 100644 src/migrations/db/1749998690421-change-mediawiki-namespace-field.ts diff --git a/.migrate b/.migrate index 78be70f..5fe9a7a 100644 --- a/.migrate +++ b/.migrate @@ -1,9 +1,17 @@ { - "lastRun": "1744651967487-add-modules.ts", + "lastRun": "1749998690421-change-mediawiki-namespace-field.ts", "migrations": [ + { + "title": "1738072787797-add-activated-field-to-modules.ts", + "timestamp": 1750008625370 + }, { "title": "1744651967487-add-modules.ts", - "timestamp": 1744652563722 + "timestamp": 1750008625414 + }, + { + "title": "1749998690421-change-mediawiki-namespace-field.ts", + "timestamp": 1750008625431 } ] -} +} \ No newline at end of file diff --git a/src/migrations/db/1738072787797-add-activated-field-to-modules.ts b/src/migrations/db/1738072787797-add-activated-field-to-modules.ts deleted file mode 100644 index aefd1ad..0000000 --- a/src/migrations/db/1738072787797-add-activated-field-to-modules.ts +++ /dev/null @@ -1,29 +0,0 @@ -import 'dotenv/config'; - -import mongoose from 'mongoose'; - -import { Module } from '@togethercrew.dev/db'; - -import config from '../../config'; -import logger from '../../config/logger'; - -async function connectToMongoDB() { - try { - await mongoose.connect(config.mongoose.serverURL); - logger.info('Connected to MongoDB!'); - } catch (error) { - logger.fatal('Failed to connect to MongoDB!'); - throw error; - } -} - -export const up = async () => { - await connectToMongoDB(); - - const result = await Module.updateMany({}, { $set: { activated: true } }); - logger.info(`Up migration: added activated field to ${result.modifiedCount} module(s).`); - - await mongoose.connection.close(); -}; - -export const down = async () => {}; diff --git a/src/migrations/db/1744651967487-add-modules.ts b/src/migrations/db/1744651967487-add-modules.ts deleted file mode 100644 index 793eacc..0000000 --- a/src/migrations/db/1744651967487-add-modules.ts +++ /dev/null @@ -1,64 +0,0 @@ -import 'dotenv/config'; - -import mongoose from 'mongoose'; - -import { Community, Module, ModuleNames } from '@togethercrew.dev/db'; - -import config from '../../config'; -import logger from '../../config/logger'; - -async function connectToMongoDB() { - try { - await mongoose.connect(config.mongoose.serverURL); - logger.info('Connected to MongoDB!'); - } catch (error) { - logger.fatal('Failed to connect to MongoDB!'); - throw error; - } -} - -export const up = async () => { - await connectToMongoDB(); - - try { - const communities = await Community.find({}).exec(); - logger.info(`Found ${communities.length} communities.`); - - const newModuleNames = [ModuleNames.Announcements, ModuleNames.CommunityHealth, ModuleNames.CommunityInsights]; - - for (const community of communities) { - for (const moduleName of newModuleNames) { - const newModule = new Module({ - name: moduleName, - community: community._id, - activated: true, - options: { platforms: [] }, - }); - await newModule.save(); - logger.info(`Created module "${moduleName}" for community ${community._id}`); - } - } - } catch (error) { - logger.error('Error during migration up:', error); - throw error; - } finally { - await mongoose.connection.close(); - logger.info('MongoDB connection closed.'); - } -}; - -export const down = async () => { - await connectToMongoDB(); - - try { - const moduleNamesToDelete = [ModuleNames.Announcements, ModuleNames.CommunityHealth, ModuleNames.CommunityInsights]; - const result = await Module.deleteMany({ name: { $in: moduleNamesToDelete } }); - logger.info(`Migration down: deleted ${result.deletedCount} modules.`); - } catch (error) { - logger.error('Error during migration down:', error); - throw error; - } finally { - await mongoose.connection.close(); - logger.info('MongoDB connection closed.'); - } -}; diff --git a/src/migrations/db/1749998690421-change-mediawiki-namespace-field.ts b/src/migrations/db/1749998690421-change-mediawiki-namespace-field.ts new file mode 100644 index 0000000..226de59 --- /dev/null +++ b/src/migrations/db/1749998690421-change-mediawiki-namespace-field.ts @@ -0,0 +1,144 @@ +import 'dotenv/config'; + +import mongoose from 'mongoose'; + +import { Module, ModuleNames, Platform, PlatformNames } from '@togethercrew.dev/db'; + +import config from '../../config'; +import logger from '../../config/logger'; + +async function connectToMongoDB() { + try { + await mongoose.connect(config.mongoose.serverURL); + logger.info('Connected to MongoDB!'); + } catch (error) { + logger.fatal('Failed to connect to MongoDB!'); + throw error; + } +} + +export const up = async () => { + await connectToMongoDB(); + + try { + const platforms = await Platform.find({ name: PlatformNames.MediaWiki }); + logger.info(`Found ${platforms.length} MediaWiki platforms to update.`); + + for (const platform of platforms) { + const metadata = platform.metadata || {}; + + if ('namespace' in metadata) { + metadata.namespaces = [0]; + delete metadata.namespace; + } else { + metadata.namespaces = [0]; + } + + await Platform.updateOne({ _id: platform._id }, { $set: { metadata } }); + + logger.info(`Updated platform ${platform._id} metadata`); + } + + const modules = await Module.find({ name: ModuleNames.Hivemind }).exec(); + logger.info(`Found ${modules.length} hivemind modules to update.`); + + for (const module of modules) { + if (!module.options?.platforms) continue; + + const mediaWikiPlatform = module.options.platforms.find((p) => p.name === PlatformNames.MediaWiki); + if (!mediaWikiPlatform) continue; + + const metadata = mediaWikiPlatform.metadata || {}; + let needsUpdate = false; + + if (!mediaWikiPlatform.metadata || 'namespace' in metadata || !('namespaces' in metadata)) { + needsUpdate = true; + + if ('namespace' in metadata) { + metadata.namespaces = [0]; + delete metadata.namespace; + } else { + metadata.namespaces = [0]; + } + } + + if (needsUpdate) { + await Module.updateOne( + { _id: module._id }, + { $set: { 'options.platforms.$[platform].metadata': metadata } }, + { arrayFilters: [{ 'platform.name': 'mediaWiki' }] }, + ); + logger.info(`Updated hivemind module ${module._id} platform metadata`); + } + } + + logger.info('Successfully updated all MediaWiki platforms and modules'); + } catch (error) { + logger.error('Error during migration up:', error); + throw error; + } finally { + await mongoose.connection.close(); + logger.info('MongoDB connection closed.'); + } +}; + +export const down = async () => { + await connectToMongoDB(); + + try { + const platforms = await Platform.find({ name: PlatformNames.MediaWiki }); + logger.info(`Found ${platforms.length} MediaWiki platforms to revert.`); + + for (const platform of platforms) { + const metadata = platform.metadata || {}; + + if ('namespaces' in metadata) { + metadata.namespace = metadata.namespaces[0]; + delete metadata.namespaces; + } + + await Platform.updateOne({ _id: platform._id }, { $set: { metadata } }); + + logger.info(`Reverted platform ${platform._id} metadata`); + } + + const modules = await Module.find({ name: ModuleNames.Hivemind }); + logger.info(`Found ${modules.length} hivemind modules to revert.`); + + for (const module of modules) { + if (!module.options?.platforms) continue; + + let needsUpdate = false; + const updatedPlatforms = module.options.platforms.map((platform) => { + if (platform.name === PlatformNames.MediaWiki) { + const metadata = platform.metadata || {}; + + if ('namespaces' in metadata) { + metadata.namespace = metadata.namespaces[0]; + delete metadata.namespaces; + needsUpdate = true; + } + + return { + ...platform, + metadata, + }; + } + return platform; + }); + + if (needsUpdate) { + await Module.updateOne({ _id: module._id }, { $set: { 'options.platforms': updatedPlatforms } }); + logger.info(`Reverted hivemind module ${module._id} platform metadata`); + } + } + + logger.info('Successfully reverted all MediaWiki platforms and modules'); + } catch (error) { + logger.error('Error during migration down:', error); + throw error; + } finally { + await mongoose.connection.close(); + logger.info('MongoDB connection closed.'); + } +};