From b723aac1805e6766cc471ff99c0856953b5bd8a8 Mon Sep 17 00:00:00 2001 From: Levente Orban Date: Mon, 10 Nov 2025 10:14:32 +0100 Subject: [PATCH 1/2] fix: federation config refactor --- federation.config.js => src/lib/config/federation.config.js | 0 src/lib/fetchFederatedEvents.ts | 2 +- src/routes/api/federation/info/+server.ts | 2 +- src/routes/instance/+page.server.ts | 2 +- src/routes/instance/+page.svelte | 5 +---- 5 files changed, 4 insertions(+), 7 deletions(-) rename federation.config.js => src/lib/config/federation.config.js (100%) diff --git a/federation.config.js b/src/lib/config/federation.config.js similarity index 100% rename from federation.config.js rename to src/lib/config/federation.config.js diff --git a/src/lib/fetchFederatedEvents.ts b/src/lib/fetchFederatedEvents.ts index 02db235..d9c55a5 100644 --- a/src/lib/fetchFederatedEvents.ts +++ b/src/lib/fetchFederatedEvents.ts @@ -3,7 +3,7 @@ import { join } from 'path'; import { logger } from '$lib/logger'; import type { Event } from '$lib/types'; -import config from '../../federation.config.js'; +import config from '$lib/config/federation.config.js'; console.log(config.instances); diff --git a/src/routes/api/federation/info/+server.ts b/src/routes/api/federation/info/+server.ts index 13519a6..71aabc4 100644 --- a/src/routes/api/federation/info/+server.ts +++ b/src/routes/api/federation/info/+server.ts @@ -4,7 +4,7 @@ import { database } from '$lib/database/db'; import { events } from '$lib/database/schema'; import { eq, count } from 'drizzle-orm'; import { logger } from '$lib/logger'; -import federationConfig from '../../../../../federation.config.js'; +import federationConfig from '$lib/config/federation.config.js'; import { FEDERATION_INSTANCE } from '$env/static/private'; diff --git a/src/routes/instance/+page.server.ts b/src/routes/instance/+page.server.ts index 1f4450e..ea93b71 100644 --- a/src/routes/instance/+page.server.ts +++ b/src/routes/instance/+page.server.ts @@ -1,6 +1,6 @@ import type { PageServerLoad } from './$types'; import { logger } from '$lib/logger'; -import federationConfig from '../../../federation.config.js'; +import federationConfig from '$lib/config/federation.config.js'; interface InstanceInfo { name: string; diff --git a/src/routes/instance/+page.svelte b/src/routes/instance/+page.svelte index 4ad5c67..146ab6e 100644 --- a/src/routes/instance/+page.svelte +++ b/src/routes/instance/+page.svelte @@ -130,10 +130,7 @@

{t('instance.description')} - {t('instance.configFile')} + {t('instance.configFile')} {t('instance.file')}

From a1fa879f36c5edd34dfb4638e1d3d016bac218b5 Mon Sep 17 00:00:00 2001 From: Levente Orban Date: Mon, 10 Nov 2025 11:46:02 +0100 Subject: [PATCH 2/2] fix: improve the federation.config --- .env.docker.example | 10 +++++ README.md | 15 ++++++- docker-compose.yml | 4 ++ src/lib/config/federation.config.js | 6 +-- src/lib/fetchFederatedEvents.ts | 65 ----------------------------- src/routes/instance/+page.svelte | 2 +- 6 files changed, 31 insertions(+), 71 deletions(-) diff --git a/.env.docker.example b/.env.docker.example index c85b0f8..42149bc 100644 --- a/.env.docker.example +++ b/.env.docker.example @@ -10,4 +10,14 @@ APP_VERSION=latest PORT=5173 HOSTNAME=0.0.0.0 +# Logger configuration +LOG_PRETTY=true +LOG_LEVEL="trace" + +# If you don't want to use the default home page you can turn off +# in this case the /discovery page remain the home of your site PUBLIC_LANDING_INFO=true + +# Federation config +FEDERATION_INSTANCE=false + diff --git a/README.md b/README.md index a36d6d5..31b1236 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,17 @@ make db-only npm run dev -- --open ``` +#### Build the image in local + +``` +docker build \ + --build-arg LOG_PRETTY=${LOG_PRETTY:-true} \ + --build-arg LOG_LEVEL=${LOG_LEVEL:-trace} \ + --build-arg PUBLIC_LANDING_INFO=${PUBLIC_LANDING_INFO:-true} \ + --build-arg FEDERATION_INSTANCE=${FEDERATION_INSTANCE:-true} \ + -t cactoide-example . +``` + Your app will be available at `http://localhost:5173`. You can use the Makefile commands to run the application or the database, eg.: `make db-only`. Use the `database/seed.sql` if you want to populate your database with dummy data. @@ -103,12 +114,12 @@ Your instance will automatically expose: To add your instance to the global federation list (so other instances can discover your events): 1. Fork the [Cactoide repository](https://github.com/polaroi8d/cactoide) -2. Add your instance URL to the `instances` array in [`federation.config.js`](https://github.com/polaroi8d/cactoide/blob/main/federation.config.js): +2. Add your instance URL to the `instances` array in `federation.config.js`: 3. Open a pull request to the main repository Once merged, your instance will appear in the federation network, and other instances will be able to discover and display your public events. -You can view all registered federated instances in the main repository: [`federation.config.js`](https://github.com/polaroi8d/cactoide/blob/main/federation.config.js) file. +You can view all registered federated instances in the main repository: `federation.config.js` file. ### Options diff --git a/docker-compose.yml b/docker-compose.yml index 668c6d9..19c01b2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,10 @@ services: DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database} PORT: 3000 HOSTNAME: ${HOSTNAME:-0.0.0.0} + LOG_PRETTY: ${LOG_PRETTY:-true} + LOG_LEVEL: ${LOG_LEVEL:-trace} + PUBLIC_LANDING_INFO: ${PUBLIC_LANDING_INFO:-true} + FEDERATION_INSTANCE: ${FEDERATION_INSTANCE:-true} depends_on: postgres: condition: service_healthy diff --git a/src/lib/config/federation.config.js b/src/lib/config/federation.config.js index 6fbf1a4..3f88a87 100644 --- a/src/lib/config/federation.config.js +++ b/src/lib/config/federation.config.js @@ -1,9 +1,9 @@ const config = { name: 'Cactoide Genesis', instances: [ - { - url: 'cactoide.org' - } + // { + // url: 'cactoide.org' + // } // { // url: 'YOUR_INSTANCE_URL' // } diff --git a/src/lib/fetchFederatedEvents.ts b/src/lib/fetchFederatedEvents.ts index d9c55a5..1a09812 100644 --- a/src/lib/fetchFederatedEvents.ts +++ b/src/lib/fetchFederatedEvents.ts @@ -1,76 +1,18 @@ -import { readFileSync } from 'fs'; -import { join } from 'path'; import { logger } from '$lib/logger'; import type { Event } from '$lib/types'; import config from '$lib/config/federation.config.js'; -console.log(config.instances); - -interface FederationConfig { - name: string; - instances: Array<{ url: string }>; -} - interface FederationEventsResponse { events: Array; count?: number; } -/** - * Reads the federation config file - */ -async function readFederationConfig(): Promise { - try { - const configPath = join(process.cwd(), 'federation.config.js'); - - // Use dynamic import to load the config file as a module - // This is safer than eval and works with ES modules - const configModule = await import(configPath + '?t=' + Date.now()); - const config = (configModule.default || configModule.config) as FederationConfig; - - if (config && config.instances && Array.isArray(config.instances)) { - return config; - } - - logger.warn('Invalid federation config structure'); - return null; - } catch (error) { - // If dynamic import fails, try reading as text and parsing - try { - const configPath = join(process.cwd(), 'federation.config.js'); - const configContent = readFileSync(configPath, 'utf-8'); - - // Try to extract JSON-like structure - const configMatch = configContent.match(/instances:\s*\[([\s\S]*?)\]/); - if (configMatch) { - // Simple parsing - extract URLs - const urlMatches = configContent.matchAll(/url:\s*['"]([^'"]+)['"]/g); - const instances = Array.from(urlMatches, (match) => ({ url: match[1] })); - - if (instances.length > 0) { - return { - name: 'Federated Instances', - instances - }; - } - } - } catch (fallbackError) { - logger.error({ error: fallbackError }, 'Error parsing federation.config.js as fallback'); - } - - logger.error({ error }, 'Error reading federation.config.js'); - return null; - } -} - /** * Fetches events from a single federated instance */ async function fetchEventsFromInstance(instanceUrl: string): Promise { try { - // Ensure URL has protocol and append /api/federation/events - const apiUrl = `http://${instanceUrl}/api/federation/events`; logger.debug({ apiUrl }, 'Fetching events from federated instance'); @@ -120,18 +62,11 @@ async function fetchEventsFromInstance(instanceUrl: string): Promise { * Fetches events from all configured federated instances */ export async function fetchAllFederatedEvents(): Promise { - const config = await readFederationConfig(); - if (!config || !config.instances || config.instances.length === 0) { logger.debug('No federation config or instances found'); return []; } - logger.info( - { instanceCount: config.instances.length }, - 'Fetching events from federated instances' - ); - // Fetch from all instances in parallel const fetchPromises = config.instances.map((instance) => fetchEventsFromInstance(instance.url)); diff --git a/src/routes/instance/+page.svelte b/src/routes/instance/+page.svelte index 146ab6e..317cca7 100644 --- a/src/routes/instance/+page.svelte +++ b/src/routes/instance/+page.svelte @@ -130,7 +130,7 @@

{t('instance.description')} - {t('instance.configFile')} + {t('instance.configFile')} {t('instance.file')}