mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 04:55:42 +09:00
chore(repo): remove dead code and useless tests (#3375)
This commit is contained in:
1 parent
7e177a1c90
commit
1cd62eb661
1391 files changed
+783
-120415
No files matched your search
@@ -785,13 +785,6 @@ export async function loadConfig(): Promise<MasterConfig> {
|
||||
return cachedConfig;
|
||||
}
|
||||
|
||||
export function getConfig(): MasterConfig {
|
||||
if (!cachedConfig) {
|
||||
throw new Error('Config not loaded. Call loadConfig() first.');
|
||||
}
|
||||
return cachedConfig;
|
||||
}
|
||||
|
||||
export function resetConfig(): void {
|
||||
cachedConfig = null;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import {generateKeyPairSync} from 'node:crypto';
|
||||
import {mkdtempSync, rmSync, writeFileSync} from 'node:fs';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {join} from 'node:path';
|
||||
import {getConfig, loadConfig, resetConfig} from '@fluxer/config/src/ConfigLoader';
|
||||
import {loadConfig, resetConfig} from '@fluxer/config/src/ConfigLoader';
|
||||
import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest';
|
||||
|
||||
const MINIMAL_ENV: Record<string, string> = {
|
||||
@@ -101,25 +101,6 @@ describe('ConfigLoader', () => {
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_SUDO_MODE_SECRET and FLUXER_SUDO_MODE_SECRET_FILE are both set');
|
||||
});
|
||||
|
||||
test('getConfig throws when config is not loaded', () => {
|
||||
expect(() => getConfig()).toThrow('Config not loaded');
|
||||
});
|
||||
|
||||
test('resetConfig clears the cache', async () => {
|
||||
stubMinimalEnv();
|
||||
await loadConfig();
|
||||
expect(() => getConfig()).not.toThrow();
|
||||
resetConfig();
|
||||
expect(() => getConfig()).toThrow('Config not loaded');
|
||||
});
|
||||
|
||||
test('derives endpoints from domain config', async () => {
|
||||
stubMinimalEnv();
|
||||
const config = await loadConfig();
|
||||
expect(config.endpoints.api).toBe('http://localhost:8088/api');
|
||||
expect(config.endpoints.gateway).toBe('ws://localhost:8088/gateway');
|
||||
});
|
||||
|
||||
test('endpoint overrides take precedence over derived endpoints', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_API_ENDPOINT: 'https://custom-api.example.com',
|
||||
@@ -312,22 +293,6 @@ describe('ConfigLoader', () => {
|
||||
expect(config.services.api.storage_change_feed?.skip_buckets).toBeUndefined();
|
||||
});
|
||||
|
||||
test('reads the email reply-to address', async () => {
|
||||
stubMinimalEnv({FLUXER_EMAIL_REPLY_TO_EMAIL: '[email protected]'});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.integrations.email.reply_to_email).toBe('[email protected]');
|
||||
});
|
||||
|
||||
test('leaves the email reply-to address empty when unset or blank', async () => {
|
||||
stubMinimalEnv({FLUXER_EMAIL_REPLY_TO_EMAIL: ' '});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.integrations.email.reply_to_email).toBe('');
|
||||
});
|
||||
|
||||
test.each(['support', 'Support <[email protected]>', '[email protected],[email protected]', ' [email protected]'])(
|
||||
'rejects %j as the email reply-to address',
|
||||
async (value) => {
|
||||
@@ -381,25 +346,6 @@ describe('ConfigLoader', () => {
|
||||
expect(config.integrations.voice.default_region?.id).toBe('local');
|
||||
});
|
||||
|
||||
test('ignores FLUXER_GATEWAY_PUSH_ENABLED, which only the gateway reads', async () => {
|
||||
stubMinimalEnv({FLUXER_GATEWAY_PUSH_ENABLED: 'false'});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.services.gateway).not.toHaveProperty('push_enabled');
|
||||
});
|
||||
|
||||
test('accepts the crosspost worker lane', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_API_WORKER_MODE: 'single_lane',
|
||||
FLUXER_API_WORKER_LANE: 'crosspost',
|
||||
FLUXER_API_WORKER_LANE_CONCURRENCY_OVERRIDES: '{"crosspost":4}',
|
||||
});
|
||||
const config = await loadConfig();
|
||||
expect(config.services.api.worker?.lane).toBe('crosspost');
|
||||
expect(config.services.api.worker?.lane_concurrency_overrides?.crosspost).toBe(4);
|
||||
});
|
||||
|
||||
test('rejects an unknown worker lane', async () => {
|
||||
stubMinimalEnv({FLUXER_API_WORKER_MODE: 'single_lane', FLUXER_API_WORKER_LANE: 'publishing'});
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_API_WORKER_LANE');
|
||||
@@ -410,26 +356,6 @@ describe('ConfigLoader', () => {
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_API_WORKER_TASK');
|
||||
});
|
||||
|
||||
test('leaves the storage change feed disabled by default', async () => {
|
||||
stubMinimalEnv();
|
||||
const config = await loadConfig();
|
||||
expect(config.services.api.storage_change_feed).toEqual({enabled: false, stream: 'STORAGE_CHANGES'});
|
||||
});
|
||||
|
||||
test('maps the storage change feed environment variables', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_API_STORAGE_CHANGE_FEED_ENABLED: 'true',
|
||||
FLUXER_API_STORAGE_CHANGE_FEED_STREAM: 'BACKUP_CHANGES',
|
||||
FLUXER_API_STORAGE_CHANGE_FEED_SKIP_BUCKETS: 'fluxer-uploads, fluxer-harvests',
|
||||
});
|
||||
const config = await loadConfig();
|
||||
expect(config.services.api.storage_change_feed).toEqual({
|
||||
enabled: true,
|
||||
stream: 'BACKUP_CHANGES',
|
||||
skip_buckets: ['fluxer-uploads', 'fluxer-harvests'],
|
||||
});
|
||||
});
|
||||
|
||||
test('rejects a storage change feed stream name that JetStream cannot use', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_API_STORAGE_CHANGE_FEED_ENABLED: 'true',
|
||||
@@ -453,50 +379,11 @@ describe('ConfigLoader', () => {
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_LIVEKIT_DEFAULT_REGION must be valid JSON');
|
||||
});
|
||||
|
||||
test('keeps Postgres prepared statements on by default', async () => {
|
||||
stubMinimalEnv();
|
||||
expect((await loadConfig()).database.postgres.prepared_statements).toBe(true);
|
||||
});
|
||||
|
||||
test('rejects a non-boolean Postgres prepared statements value', async () => {
|
||||
stubMinimalEnv({FLUXER_POSTGRES_PREPARED_STATEMENTS: 'maybe'});
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_POSTGRES_PREPARED_STATEMENTS');
|
||||
});
|
||||
|
||||
test('keeps the api http timeouts at their defaults', async () => {
|
||||
stubMinimalEnv();
|
||||
const config = await loadConfig();
|
||||
expect(config.services.api.headers_timeout_ms).toBe(30_000);
|
||||
expect(config.services.api.request_timeout_ms).toBe(120_000);
|
||||
});
|
||||
|
||||
test('reads the api http timeouts from the environment', async () => {
|
||||
stubMinimalEnv({FLUXER_API_HEADERS_TIMEOUT_MS: '45000', FLUXER_API_REQUEST_TIMEOUT_MS: '600000'});
|
||||
const config = await loadConfig();
|
||||
expect(config.services.api.headers_timeout_ms).toBe(45_000);
|
||||
expect(config.services.api.request_timeout_ms).toBe(600_000);
|
||||
});
|
||||
|
||||
test('rejects a non-numeric api header timeout', async () => {
|
||||
stubMinimalEnv({FLUXER_API_HEADERS_TIMEOUT_MS: 'soon'});
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_API_HEADERS_TIMEOUT_MS');
|
||||
});
|
||||
|
||||
test('rejects a non-numeric api request timeout', async () => {
|
||||
stubMinimalEnv({FLUXER_API_REQUEST_TIMEOUT_MS: 'soon'});
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_API_REQUEST_TIMEOUT_MS');
|
||||
});
|
||||
|
||||
test('applies the KV mode from the environment', async () => {
|
||||
stubMinimalEnv({FLUXER_KV_MODE: 'cluster'});
|
||||
expect((await loadConfig()).internal.kv_mode).toBe('cluster');
|
||||
});
|
||||
|
||||
test('rejects an unknown KV mode', async () => {
|
||||
stubMinimalEnv({FLUXER_KV_MODE: 'sentinel'});
|
||||
await expect(loadConfig()).rejects.toThrow('Invalid FLUXER_KV_MODE: sentinel');
|
||||
});
|
||||
|
||||
test('reads the profile pseudonym secret and requires it in production', async () => {
|
||||
stubMinimalEnv();
|
||||
expect((await loadConfig()).auth.profile_pseudonym_secret).toBe('test-profile-pseudonym-secret');
|
||||
@@ -567,56 +454,6 @@ describe('ConfigLoader', () => {
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_POSTGRES_SSL must be true');
|
||||
});
|
||||
|
||||
test('parses self-host branding, setup, and search engine environment variables', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_SEARCH_ENGINE: 'meilisearch',
|
||||
FLUXER_SEARCH_URL: 'http://meilisearch:7700',
|
||||
FLUXER_SEARCH_API_KEY: 'meili-key',
|
||||
FLUXER_SELF_HOSTED: 'true',
|
||||
FLUXER_APP_PRODUCT_NAME: 'Example Chat',
|
||||
FLUXER_APP_ICON_URL: 'https://assets.example/icon.png',
|
||||
FLUXER_APP_SYMBOL_URL: 'https://assets.example/symbol.png',
|
||||
FLUXER_APP_LOGO_URL: 'https://assets.example/logo.png',
|
||||
FLUXER_APP_WORDMARK_URL: 'https://assets.example/wordmark.png',
|
||||
FLUXER_APP_FAVICON_URL: 'https://assets.example/favicon.png',
|
||||
FLUXER_APP_THEME_COLOR: '#123456',
|
||||
FLUXER_APP_STATUS_PAGE_URL: 'https://status.example',
|
||||
FLUXER_APP_STATUS_PAGE_INCIDENT_HISTORY_URL: 'https://status.example/history',
|
||||
FLUXER_INSTANCE_SETUP_CONFIGURED: 'true',
|
||||
});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.integrations.search.engine).toBe('meilisearch');
|
||||
expect(config.integrations.search.url).toBe('http://meilisearch:7700');
|
||||
expect(config.integrations.search.api_key).toBe('meili-key');
|
||||
expect(config.instance.self_hosted).toBe(true);
|
||||
expect(config.instance.branding).toEqual({
|
||||
product_name: 'Example Chat',
|
||||
icon_url: 'https://assets.example/icon.png',
|
||||
symbol_url: 'https://assets.example/symbol.png',
|
||||
logo_url: 'https://assets.example/logo.png',
|
||||
wordmark_url: 'https://assets.example/wordmark.png',
|
||||
favicon_url: 'https://assets.example/favicon.png',
|
||||
theme_color: '#123456',
|
||||
status_page_url: 'https://status.example',
|
||||
status_page_incident_history_url: 'https://status.example/history',
|
||||
});
|
||||
expect(config.instance.setup.configured).toBe(true);
|
||||
});
|
||||
|
||||
test('leaves the account identity unset by default', async () => {
|
||||
stubMinimalEnv();
|
||||
const config = await loadConfig();
|
||||
expect(config.instance.account_identity).toBeNull();
|
||||
});
|
||||
|
||||
test('treats an empty account identity as unset', async () => {
|
||||
stubMinimalEnv({FLUXER_ACCOUNT_IDENTITY: ' '});
|
||||
const config = await loadConfig();
|
||||
expect(config.instance.account_identity).toBeNull();
|
||||
});
|
||||
|
||||
test.each([
|
||||
['email', 'email'],
|
||||
['username', 'username'],
|
||||
@@ -647,19 +484,6 @@ describe('ConfigLoader', () => {
|
||||
await expect(loadConfig()).rejects.toThrow('FLUXER_ACCOUNT_IDENTITY must be email or username');
|
||||
});
|
||||
|
||||
test('leaves both stores off with no apps, packages or products by default', async () => {
|
||||
stubMinimalEnv();
|
||||
const config = await loadConfig();
|
||||
expect(config.integrations.app_store).toEqual({enabled: false, apps: [], products: {}});
|
||||
expect(config.integrations.google_play).toEqual({
|
||||
enabled: false,
|
||||
packages: [],
|
||||
token_uri: 'https://oauth2.googleapis.com/token',
|
||||
products: {},
|
||||
});
|
||||
expect(config.integrations.store_billing).toEqual({sandbox_user_ids: [], sandbox_entitles_all: false});
|
||||
});
|
||||
|
||||
test('loads a valid store catalogue', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_APP_STORE_ENABLED: 'true',
|
||||
@@ -727,27 +551,6 @@ describe('ConfigLoader', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('defaults the cache purge adapter to none', async () => {
|
||||
stubMinimalEnv();
|
||||
expect((await loadConfig()).integrations.cache_purge).toEqual({
|
||||
adapter: 'none',
|
||||
http: {endpoint: '', token: '', timeout_ms: 10_000},
|
||||
});
|
||||
});
|
||||
|
||||
test('reads the http cache purge settings from the environment', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_CACHE_PURGE_ADAPTER: 'http',
|
||||
FLUXER_CACHE_PURGE_HTTP_ENDPOINT: 'https://purge.internal/purge',
|
||||
FLUXER_CACHE_PURGE_HTTP_TOKEN: 'purge-token',
|
||||
FLUXER_CACHE_PURGE_HTTP_TIMEOUT_MS: '5000',
|
||||
});
|
||||
expect((await loadConfig()).integrations.cache_purge).toEqual({
|
||||
adapter: 'http',
|
||||
http: {endpoint: 'https://purge.internal/purge', token: 'purge-token', timeout_ms: 5000},
|
||||
});
|
||||
});
|
||||
|
||||
test('rejects an unknown cache purge adapter', async () => {
|
||||
stubMinimalEnv({FLUXER_CACHE_PURGE_ADAPTER: 'varnish'});
|
||||
await expect(loadConfig()).rejects.toThrow('Invalid FLUXER_CACHE_PURGE_ADAPTER: varnish');
|
||||
@@ -820,63 +623,6 @@ describe('ConfigLoader', () => {
|
||||
expect((await loadConfig()).integrations.cache_purge.adapter).toBe('none');
|
||||
});
|
||||
|
||||
test('leaves the optional outbound lookups unset by default', async () => {
|
||||
stubMinimalEnv();
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.integrations.breached_password_check.enabled).toBeUndefined();
|
||||
});
|
||||
|
||||
test('reads the optional outbound lookup switches from the environment', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_BREACHED_PASSWORD_CHECK_ENABLED: 'false',
|
||||
});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.integrations.breached_password_check.enabled).toBe(false);
|
||||
});
|
||||
|
||||
test('leaves Bluesky login off with no legal URLs by default', async () => {
|
||||
stubMinimalEnv();
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.auth.bluesky.enabled).toBe(false);
|
||||
expect(config.auth.bluesky.tos_uri).toBe('');
|
||||
expect(config.auth.bluesky.policy_uri).toBe('');
|
||||
expect(config.auth.bluesky.keys).toEqual([]);
|
||||
});
|
||||
|
||||
test('applies explicit Bluesky legal URLs from the environment', async () => {
|
||||
stubMinimalEnv({
|
||||
FLUXER_AUTH_BLUESKY_ENABLED: 'true',
|
||||
FLUXER_AUTH_BLUESKY_TOS_URI: 'https://chat.example.com/terms',
|
||||
FLUXER_AUTH_BLUESKY_POLICY_URI: 'https://chat.example.com/privacy',
|
||||
});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.auth.bluesky.enabled).toBe(true);
|
||||
expect(config.auth.bluesky.tos_uri).toBe('https://chat.example.com/terms');
|
||||
expect(config.auth.bluesky.policy_uri).toBe('https://chat.example.com/privacy');
|
||||
});
|
||||
|
||||
test('reads the upload relay secret through the override table', async () => {
|
||||
const secret = Buffer.alloc(32, 9).toString('base64');
|
||||
stubMinimalEnv({FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64: secret});
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
expect(config.services.media_proxy.upload_relay.secret_base64).toBe(secret);
|
||||
});
|
||||
|
||||
test('defaults the upload relay body limit to the media proxy ceiling', async () => {
|
||||
stubMinimalEnv();
|
||||
expect((await loadConfig()).services.media_proxy.upload_relay.max_body_bytes).toBe(524_288_000);
|
||||
});
|
||||
|
||||
test('rejects a missing upload relay secret', async () => {
|
||||
stubMinimalEnv();
|
||||
vi.stubEnv('FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64', '');
|
||||
@@ -939,11 +685,6 @@ describe('ConfigLoader', () => {
|
||||
expect(config.auth.vapid.private_key).toBe(pair.privateKey);
|
||||
});
|
||||
|
||||
test('requires a complete environment', async () => {
|
||||
vi.stubEnv('FLUXER_ENV', 'test');
|
||||
await expect(loadConfig()).rejects.toThrow();
|
||||
});
|
||||
|
||||
test('inserts the public port into the LiveKit url', async () => {
|
||||
stubMinimalEnv({FLUXER_LIVEKIT_URL: 'http://localhost/livekit'});
|
||||
|
||||
|
||||
@@ -3,61 +3,13 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
buildUrl,
|
||||
canonicalizeDomain,
|
||||
type DerivedEndpoints,
|
||||
type DomainConfig,
|
||||
deriveDomain,
|
||||
deriveEndpointsFromDomain,
|
||||
normalizePublicEndpoint,
|
||||
parsePublicOrigin,
|
||||
} from '@fluxer/config/src/EndpointDerivation';
|
||||
import {describe, expect, test} from 'vitest';
|
||||
|
||||
describe('buildUrl', () => {
|
||||
test.each([
|
||||
['http', 'example.com', 80, '/path', 'http://example.com/path'],
|
||||
['https', 'example.com', 443, '/path', 'https://example.com/path'],
|
||||
['ws', 'example.com', 80, '/gateway', 'ws://example.com/gateway'],
|
||||
['wss', 'example.com', 443, '/gateway', 'wss://example.com/gateway'],
|
||||
['http', 'localhost', 8088, '/api', 'http://localhost:8088/api'],
|
||||
['https', 'example.com', 8443, '/api', 'https://example.com:8443/api'],
|
||||
['https', 'example.com', undefined, '/api', 'https://example.com/api'],
|
||||
['https', 'example.com', 443, undefined, 'https://example.com'],
|
||||
['https', 'example.com', 443, '', 'https://example.com'],
|
||||
['https', 'example.com', 443, '/', 'https://example.com/'],
|
||||
] as const)('%s %s:%s%s becomes %s', (scheme, domain, port, path, expected) => {
|
||||
expect(buildUrl(scheme, domain, port, path)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deriveDomain', () => {
|
||||
const baseConfig: DomainConfig = {
|
||||
base_domain: 'fluxer.dev',
|
||||
public_scheme: 'https',
|
||||
};
|
||||
test.each([
|
||||
'api',
|
||||
'api_client',
|
||||
'app',
|
||||
'gateway',
|
||||
'media',
|
||||
'static_cdn',
|
||||
'admin',
|
||||
'marketing',
|
||||
'invite',
|
||||
'gift',
|
||||
] as const)('uses the base domain for %s without an override', (endpoint) => {
|
||||
expect(deriveDomain(endpoint, baseConfig)).toBe('fluxer.dev');
|
||||
});
|
||||
test.each([
|
||||
['static_cdn', {static_cdn_domain: 'cdn.fluxer.dev'}, 'cdn.fluxer.dev'],
|
||||
['invite', {invite_domain: 'fluxer.gg'}, 'fluxer.gg'],
|
||||
['gift', {gift_domain: 'fluxer.gift'}, 'fluxer.gift'],
|
||||
] as const)('uses the custom %s domain', (endpoint, overrides, expected) => {
|
||||
expect(deriveDomain(endpoint, {...baseConfig, ...overrides})).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
interface EndpointScenario {
|
||||
name: string;
|
||||
config: DomainConfig;
|
||||
@@ -65,189 +17,6 @@ interface EndpointScenario {
|
||||
}
|
||||
|
||||
const endpointScenarios: Array<EndpointScenario> = [
|
||||
{
|
||||
name: 'development',
|
||||
config: {
|
||||
base_domain: 'localhost',
|
||||
public_scheme: 'http',
|
||||
public_port: 8088,
|
||||
},
|
||||
expected: {
|
||||
api: 'http://localhost:8088/api',
|
||||
api_client: 'http://localhost:8088/api',
|
||||
app: 'http://localhost:8088',
|
||||
gateway: 'ws://localhost:8088/gateway',
|
||||
media: 'http://localhost:8088/media',
|
||||
static_cdn: 'http://localhost:8088',
|
||||
admin: 'http://localhost:8088/admin',
|
||||
marketing: 'http://localhost:8088/marketing',
|
||||
invite: 'http://localhost:8088/invite',
|
||||
gift: 'http://localhost:8088/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'production',
|
||||
config: {
|
||||
base_domain: 'fluxer.app',
|
||||
public_scheme: 'https',
|
||||
public_port: 443,
|
||||
},
|
||||
expected: {
|
||||
api: 'https://fluxer.app/api',
|
||||
api_client: 'https://fluxer.app/api',
|
||||
app: 'https://fluxer.app',
|
||||
gateway: 'wss://fluxer.app/gateway',
|
||||
media: 'https://fluxer.app/media',
|
||||
static_cdn: 'https://fluxer.app',
|
||||
admin: 'https://fluxer.app/admin',
|
||||
marketing: 'https://fluxer.app/marketing',
|
||||
invite: 'https://fluxer.app/invite',
|
||||
gift: 'https://fluxer.app/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'staging',
|
||||
config: {
|
||||
base_domain: 'staging.fluxer.dev',
|
||||
public_scheme: 'https',
|
||||
public_port: 8443,
|
||||
},
|
||||
expected: {
|
||||
api: 'https://staging.fluxer.dev:8443/api',
|
||||
api_client: 'https://staging.fluxer.dev:8443/api',
|
||||
app: 'https://staging.fluxer.dev:8443',
|
||||
gateway: 'wss://staging.fluxer.dev:8443/gateway',
|
||||
media: 'https://staging.fluxer.dev:8443/media',
|
||||
static_cdn: 'https://staging.fluxer.dev:8443',
|
||||
admin: 'https://staging.fluxer.dev:8443/admin',
|
||||
marketing: 'https://staging.fluxer.dev:8443/marketing',
|
||||
invite: 'https://staging.fluxer.dev:8443/invite',
|
||||
gift: 'https://staging.fluxer.dev:8443/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'custom CDN',
|
||||
config: {
|
||||
base_domain: 'fluxer.app',
|
||||
public_scheme: 'https',
|
||||
public_port: 443,
|
||||
static_cdn_domain: 'cdn.fluxer.app',
|
||||
},
|
||||
expected: {
|
||||
api: 'https://fluxer.app/api',
|
||||
api_client: 'https://fluxer.app/api',
|
||||
app: 'https://fluxer.app',
|
||||
gateway: 'wss://fluxer.app/gateway',
|
||||
media: 'https://fluxer.app/media',
|
||||
static_cdn: 'https://cdn.fluxer.app',
|
||||
admin: 'https://fluxer.app/admin',
|
||||
marketing: 'https://fluxer.app/marketing',
|
||||
invite: 'https://fluxer.app/invite',
|
||||
gift: 'https://fluxer.app/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'custom invite and gift domains',
|
||||
config: {
|
||||
base_domain: 'fluxer.app',
|
||||
public_scheme: 'https',
|
||||
public_port: 443,
|
||||
invite_domain: 'fluxer.gg',
|
||||
gift_domain: 'fluxer.gift',
|
||||
},
|
||||
expected: {
|
||||
api: 'https://fluxer.app/api',
|
||||
api_client: 'https://fluxer.app/api',
|
||||
app: 'https://fluxer.app',
|
||||
gateway: 'wss://fluxer.app/gateway',
|
||||
media: 'https://fluxer.app/media',
|
||||
static_cdn: 'https://fluxer.app',
|
||||
admin: 'https://fluxer.app/admin',
|
||||
marketing: 'https://fluxer.app/marketing',
|
||||
invite: 'https://fluxer.gg/invite',
|
||||
gift: 'https://fluxer.gift/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'canary',
|
||||
config: {
|
||||
base_domain: 'canary.fluxer.app',
|
||||
public_scheme: 'https',
|
||||
public_port: 443,
|
||||
static_cdn_domain: 'cdn-canary.fluxer.app',
|
||||
},
|
||||
expected: {
|
||||
api: 'https://canary.fluxer.app/api',
|
||||
api_client: 'https://canary.fluxer.app/api',
|
||||
app: 'https://canary.fluxer.app',
|
||||
gateway: 'wss://canary.fluxer.app/gateway',
|
||||
media: 'https://canary.fluxer.app/media',
|
||||
static_cdn: 'https://cdn-canary.fluxer.app',
|
||||
admin: 'https://canary.fluxer.app/admin',
|
||||
marketing: 'https://canary.fluxer.app/marketing',
|
||||
invite: 'https://canary.fluxer.app/invite',
|
||||
gift: 'https://canary.fluxer.app/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'standard HTTP port',
|
||||
config: {
|
||||
base_domain: 'example.com',
|
||||
public_scheme: 'http',
|
||||
public_port: 80,
|
||||
},
|
||||
expected: {
|
||||
api: 'http://example.com/api',
|
||||
api_client: 'http://example.com/api',
|
||||
app: 'http://example.com',
|
||||
gateway: 'ws://example.com/gateway',
|
||||
media: 'http://example.com/media',
|
||||
static_cdn: 'http://example.com',
|
||||
admin: 'http://example.com/admin',
|
||||
marketing: 'http://example.com/marketing',
|
||||
invite: 'http://example.com/invite',
|
||||
gift: 'http://example.com/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'unspecified port',
|
||||
config: {
|
||||
base_domain: 'example.com',
|
||||
public_scheme: 'https',
|
||||
},
|
||||
expected: {
|
||||
api: 'https://example.com/api',
|
||||
api_client: 'https://example.com/api',
|
||||
app: 'https://example.com',
|
||||
gateway: 'wss://example.com/gateway',
|
||||
media: 'https://example.com/media',
|
||||
static_cdn: 'https://example.com',
|
||||
admin: 'https://example.com/admin',
|
||||
marketing: 'https://example.com/marketing',
|
||||
invite: 'https://example.com/invite',
|
||||
gift: 'https://example.com/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'IPv4',
|
||||
config: {
|
||||
base_domain: '127.0.0.1',
|
||||
public_scheme: 'http',
|
||||
public_port: 8088,
|
||||
},
|
||||
expected: {
|
||||
api: 'http://127.0.0.1:8088/api',
|
||||
api_client: 'http://127.0.0.1:8088/api',
|
||||
app: 'http://127.0.0.1:8088',
|
||||
gateway: 'ws://127.0.0.1:8088/gateway',
|
||||
media: 'http://127.0.0.1:8088/media',
|
||||
static_cdn: 'http://127.0.0.1:8088',
|
||||
admin: 'http://127.0.0.1:8088/admin',
|
||||
marketing: 'http://127.0.0.1:8088/marketing',
|
||||
invite: 'http://127.0.0.1:8088/invite',
|
||||
gift: 'http://127.0.0.1:8088/gift',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'external CDN uses HTTPS without the public port',
|
||||
config: {
|
||||
@@ -277,107 +46,6 @@ describe('deriveEndpointsFromDomain', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizePublicEndpoint', () => {
|
||||
test('leaves a default https install untouched', () => {
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev', 'fluxer.dev', 443)).toBe('https://fluxer.dev');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', 'fluxer.dev', 443)).toBe('https://fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('wss://fluxer.dev/gateway', 'fluxer.dev', 443)).toBe('wss://fluxer.dev/gateway');
|
||||
});
|
||||
test('leaves a default http install untouched', () => {
|
||||
expect(normalizePublicEndpoint('http://fluxer.dev', 'fluxer.dev', 80)).toBe('http://fluxer.dev');
|
||||
expect(normalizePublicEndpoint('http://fluxer.dev/media', 'fluxer.dev', 80)).toBe('http://fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('ws://fluxer.dev/gateway', 'fluxer.dev', 80)).toBe('ws://fluxer.dev/gateway');
|
||||
});
|
||||
test('inserts a non-standard port', () => {
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev', 'fluxer.dev', 8443)).toBe('https://fluxer.dev:8443');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:8443/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('wss://fluxer.dev/gateway', 'fluxer.dev', 8443)).toBe(
|
||||
'wss://fluxer.dev:8443/gateway',
|
||||
);
|
||||
});
|
||||
test('judges standard ports against the url scheme, not the public scheme', () => {
|
||||
expect(normalizePublicEndpoint('http://fluxer.dev/media', 'fluxer.dev', 443)).toBe('http://fluxer.dev:443/media');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', 'fluxer.dev', 80)).toBe('https://fluxer.dev:80/media');
|
||||
});
|
||||
test('leaves a foreign host untouched', () => {
|
||||
expect(normalizePublicEndpoint('https://cdn.example.net/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://cdn.example.net/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://sub.fluxer.dev', 'fluxer.dev', 8443)).toBe('https://sub.fluxer.dev');
|
||||
});
|
||||
test('leaves an already ported url untouched', () => {
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev:8443/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:8443/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev:9000/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:9000/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev:443/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:443/media',
|
||||
);
|
||||
});
|
||||
test('is idempotent', () => {
|
||||
const once = normalizePublicEndpoint('https://fluxer.dev/media', 'fluxer.dev', 8443);
|
||||
expect(normalizePublicEndpoint(once, 'fluxer.dev', 8443)).toBe(once);
|
||||
});
|
||||
test('preserves path, query, fragment, trailing slash, and case', () => {
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/Media/', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:8443/Media/',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media?a=B#Frag', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:8443/media?a=B#Frag',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev?a=B', 'fluxer.dev', 8443)).toBe('https://fluxer.dev:8443?a=B');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev#Frag', 'fluxer.dev', 8443)).toBe('https://fluxer.dev:8443#Frag');
|
||||
expect(normalizePublicEndpoint('https://user:[email protected]/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://user:[email protected]:8443/media',
|
||||
);
|
||||
});
|
||||
test('matches the host case-insensitively and ignores a trailing dot', () => {
|
||||
expect(normalizePublicEndpoint('https://FLUXER.dev/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://FLUXER.dev:8443/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev./media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev.:8443/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', 'FLUXER.dev.', 8443)).toBe(
|
||||
'https://fluxer.dev:8443/media',
|
||||
);
|
||||
});
|
||||
test('leaves unparseable and non-http values untouched', () => {
|
||||
expect(normalizePublicEndpoint('not a url', 'fluxer.dev', 8443)).toBe('not a url');
|
||||
expect(normalizePublicEndpoint('', 'fluxer.dev', 8443)).toBe('');
|
||||
expect(normalizePublicEndpoint('android:apk-key-hash:abc', 'fluxer.dev', 8443)).toBe('android:apk-key-hash:abc');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev:/media', 'fluxer.dev', 8443)).toBe('https://fluxer.dev:/media');
|
||||
});
|
||||
test('leaves malformed authorities untouched', () => {
|
||||
expect(normalizePublicEndpoint('https:fluxer.dev/media', 'fluxer.dev', 8443)).toBe('https:fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('https:/fluxer.dev/media', 'fluxer.dev', 8443)).toBe('https:/fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('https:////fluxer.dev/media', 'fluxer.dev', 8443)).toBe(
|
||||
'https:////fluxer.dev/media',
|
||||
);
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev\\media', 'fluxer.dev', 8443)).toBe(
|
||||
'https://fluxer.dev:8443\\media',
|
||||
);
|
||||
});
|
||||
test('leaves everything untouched without a usable port or base domain', () => {
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', 'fluxer.dev')).toBe('https://fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', '', 8443)).toBe('https://fluxer.dev/media');
|
||||
expect(normalizePublicEndpoint('https://fluxer.dev/media', ' ', 8443)).toBe('https://fluxer.dev/media');
|
||||
});
|
||||
});
|
||||
|
||||
describe('canonicalizeDomain', () => {
|
||||
test('lowercases, trims and drops the root dot', () => {
|
||||
expect(canonicalizeDomain(' CHAT.Example.COM. ')).toBe('chat.example.com');
|
||||
});
|
||||
test('leaves an empty value empty', () => {
|
||||
expect(canonicalizeDomain(' ')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parsePublicOrigin', () => {
|
||||
test('reads scheme, host and a non-standard port', () => {
|
||||
expect(parsePublicOrigin('https://chat.example.com:8443')).toEqual({
|
||||
|
||||
@@ -3,53 +3,9 @@
|
||||
import {mkdtempSync, rmSync, writeFileSync} from 'node:fs';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {join} from 'node:path';
|
||||
import {
|
||||
buildNamedFluxerEnvOverrides,
|
||||
readEnvValue,
|
||||
setNestedValue,
|
||||
} from '@fluxer/config/src/config_loader/EnvironmentOverrides';
|
||||
import {buildNamedFluxerEnvOverrides, readEnvValue} from '@fluxer/config/src/config_loader/EnvironmentOverrides';
|
||||
import {afterAll, describe, expect, test} from 'vitest';
|
||||
|
||||
describe('setNestedValue', () => {
|
||||
test('sets a top-level key', () => {
|
||||
const target: Record<string, unknown> = {};
|
||||
setNestedValue(target, ['port'], 8080);
|
||||
expect(target).toEqual({port: 8080});
|
||||
});
|
||||
test('sets a nested key', () => {
|
||||
const target: Record<string, unknown> = {};
|
||||
setNestedValue(target, ['database', 'host'], 'localhost');
|
||||
expect(target).toEqual({database: {host: 'localhost'}});
|
||||
});
|
||||
test('sets a deeply nested key', () => {
|
||||
const target: Record<string, unknown> = {};
|
||||
setNestedValue(target, ['a', 'b', 'c'], 'deep');
|
||||
expect(target).toEqual({a: {b: {c: 'deep'}}});
|
||||
});
|
||||
test('does nothing for empty keys', () => {
|
||||
const target: Record<string, unknown> = {existing: true};
|
||||
setNestedValue(target, [], 'value');
|
||||
expect(target).toEqual({existing: true});
|
||||
});
|
||||
test('overwrites non-object intermediate values', () => {
|
||||
const target: Record<string, unknown> = {a: 'string'};
|
||||
setNestedValue(target, ['a', 'b'], 'nested');
|
||||
expect(target).toEqual({a: {b: 'nested'}});
|
||||
});
|
||||
test('creates arrays for numeric path keys', () => {
|
||||
const target: Record<string, unknown> = {};
|
||||
setNestedValue(target, ['auth', 'bluesky', 'keys', 0, 'kid'], 'key-1');
|
||||
setNestedValue(target, ['auth', 'bluesky', 'keys', 0, 'private_key_path'], '/etc/fluxer/keys/key.pem');
|
||||
expect(target).toEqual({
|
||||
auth: {
|
||||
bluesky: {
|
||||
keys: [{kid: 'key-1', private_key_path: '/etc/fluxer/keys/key.pem'}],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildNamedFluxerEnvOverrides', () => {
|
||||
test('builds canonical split env overrides', () => {
|
||||
const overrides = buildNamedFluxerEnvOverrides({
|
||||
|
||||
Reference in new issue
Block a user