mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 14:15:28 +00:00
fix: missing federation.config error
This commit is contained in:
@@ -10,4 +10,14 @@ APP_VERSION=latest
|
|||||||
PORT=5173
|
PORT=5173
|
||||||
HOSTNAME=0.0.0.0
|
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
|
PUBLIC_LANDING_INFO=true
|
||||||
|
|
||||||
|
# Federation config
|
||||||
|
FEDERATION_INSTANCE=false
|
||||||
|
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -59,6 +59,17 @@ make db-only
|
|||||||
npm run dev -- --open
|
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`.
|
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.
|
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):
|
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)
|
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
|
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.
|
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
|
### Options
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ services:
|
|||||||
DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database}
|
DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database}
|
||||||
PORT: 3000
|
PORT: 3000
|
||||||
HOSTNAME: ${HOSTNAME:-0.0.0.0}
|
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:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const config = {
|
const config = {
|
||||||
name: 'Cactoide Genesis',
|
name: 'Cactoide Genesis',
|
||||||
instances: [
|
instances: [
|
||||||
{
|
// {
|
||||||
url: 'cactoide.org'
|
// url: 'cactoide.org'
|
||||||
}
|
// }
|
||||||
// {
|
// {
|
||||||
// url: 'YOUR_INSTANCE_URL'
|
// url: 'YOUR_INSTANCE_URL'
|
||||||
// }
|
// }
|
||||||
@@ -1,76 +1,18 @@
|
|||||||
import { readFileSync } from 'fs';
|
|
||||||
import { join } from 'path';
|
|
||||||
import { logger } from '$lib/logger';
|
import { logger } from '$lib/logger';
|
||||||
import type { Event } from '$lib/types';
|
import type { Event } from '$lib/types';
|
||||||
|
|
||||||
import config from '../../federation.config.js';
|
import config from '$lib/config/federation.config.js';
|
||||||
|
|
||||||
console.log(config.instances);
|
|
||||||
|
|
||||||
interface FederationConfig {
|
|
||||||
name: string;
|
|
||||||
instances: Array<{ url: string }>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FederationEventsResponse {
|
interface FederationEventsResponse {
|
||||||
events: Array<Event & { federation?: boolean }>;
|
events: Array<Event & { federation?: boolean }>;
|
||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the federation config file
|
|
||||||
*/
|
|
||||||
async function readFederationConfig(): Promise<FederationConfig | null> {
|
|
||||||
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
|
* Fetches events from a single federated instance
|
||||||
*/
|
*/
|
||||||
async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
||||||
try {
|
try {
|
||||||
// Ensure URL has protocol and append /api/federation/events
|
|
||||||
|
|
||||||
const apiUrl = `http://${instanceUrl}/api/federation/events`;
|
const apiUrl = `http://${instanceUrl}/api/federation/events`;
|
||||||
|
|
||||||
logger.debug({ apiUrl }, 'Fetching events from federated instance');
|
logger.debug({ apiUrl }, 'Fetching events from federated instance');
|
||||||
@@ -120,18 +62,11 @@ async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
|||||||
* Fetches events from all configured federated instances
|
* Fetches events from all configured federated instances
|
||||||
*/
|
*/
|
||||||
export async function fetchAllFederatedEvents(): Promise<Event[]> {
|
export async function fetchAllFederatedEvents(): Promise<Event[]> {
|
||||||
const config = await readFederationConfig();
|
|
||||||
|
|
||||||
if (!config || !config.instances || config.instances.length === 0) {
|
if (!config || !config.instances || config.instances.length === 0) {
|
||||||
logger.debug('No federation config or instances found');
|
logger.debug('No federation config or instances found');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
|
||||||
{ instanceCount: config.instances.length },
|
|
||||||
'Fetching events from federated instances'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch from all instances in parallel
|
// Fetch from all instances in parallel
|
||||||
const fetchPromises = config.instances.map((instance) => fetchEventsFromInstance(instance.url));
|
const fetchPromises = config.instances.map((instance) => fetchEventsFromInstance(instance.url));
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { database } from '$lib/database/db';
|
|||||||
import { events } from '$lib/database/schema';
|
import { events } from '$lib/database/schema';
|
||||||
import { eq, count } from 'drizzle-orm';
|
import { eq, count } from 'drizzle-orm';
|
||||||
import { logger } from '$lib/logger';
|
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';
|
import { FEDERATION_INSTANCE } from '$env/static/private';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { logger } from '$lib/logger';
|
import { logger } from '$lib/logger';
|
||||||
import federationConfig from '../../../federation.config.js';
|
import federationConfig from '$lib/config/federation.config.js';
|
||||||
|
|
||||||
interface InstanceInfo {
|
interface InstanceInfo {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -130,10 +130,7 @@
|
|||||||
|
|
||||||
<p class="py-8 text-center text-slate-400">
|
<p class="py-8 text-center text-slate-400">
|
||||||
{t('instance.description')}
|
{t('instance.description')}
|
||||||
<a
|
{t('instance.configFile')}
|
||||||
href="https://github.com/cactoide/cactoide/blob/main/federation.config.js"
|
|
||||||
class="text-violet-300/80">{t('instance.configFile')}</a
|
|
||||||
>
|
|
||||||
{t('instance.file')}
|
{t('instance.file')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user