mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
Replace config manager with unjs/c12
This commit is contained in:
parent
6b2e4044b6
commit
6a54c5b805
30 changed files with 744 additions and 733 deletions
|
|
@ -1,377 +0,0 @@
|
|||
import { MediaBackendType } from "media-manager";
|
||||
|
||||
export interface ConfigType {
|
||||
database: {
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
database: string;
|
||||
};
|
||||
|
||||
redis: {
|
||||
queue: {
|
||||
host: string;
|
||||
port: number;
|
||||
password: string;
|
||||
database: number | null;
|
||||
};
|
||||
cache: {
|
||||
host: string;
|
||||
port: number;
|
||||
password: string;
|
||||
database: number | null;
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
meilisearch: {
|
||||
host: string;
|
||||
port: number;
|
||||
api_key: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
signups: {
|
||||
tos_url: string;
|
||||
rules: string[];
|
||||
registration: boolean;
|
||||
};
|
||||
|
||||
oidc: {
|
||||
providers: {
|
||||
name: string;
|
||||
id: string;
|
||||
url: string;
|
||||
client_id: string;
|
||||
client_secret: string;
|
||||
icon: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
http: {
|
||||
base_url: string;
|
||||
bind: string;
|
||||
bind_port: string;
|
||||
banned_ips: string[];
|
||||
banned_user_agents: string[];
|
||||
bait: {
|
||||
enabled: boolean;
|
||||
send_file?: string;
|
||||
bait_ips: string[];
|
||||
bait_user_agents: string[];
|
||||
};
|
||||
};
|
||||
|
||||
instance: {
|
||||
name: string;
|
||||
description: string;
|
||||
banner: string;
|
||||
logo: string;
|
||||
};
|
||||
|
||||
smtp: {
|
||||
server: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
tls: boolean;
|
||||
};
|
||||
|
||||
validation: {
|
||||
max_displayname_size: number;
|
||||
max_bio_size: number;
|
||||
max_username_size: number;
|
||||
max_note_size: number;
|
||||
max_avatar_size: number;
|
||||
max_header_size: number;
|
||||
max_media_size: number;
|
||||
max_media_attachments: number;
|
||||
max_media_description_size: number;
|
||||
max_poll_options: number;
|
||||
max_poll_option_size: number;
|
||||
min_poll_duration: number;
|
||||
max_poll_duration: number;
|
||||
|
||||
username_blacklist: string[];
|
||||
blacklist_tempmail: boolean;
|
||||
email_blacklist: string[];
|
||||
url_scheme_whitelist: string[];
|
||||
|
||||
enforce_mime_types: boolean;
|
||||
allowed_mime_types: string[];
|
||||
};
|
||||
|
||||
media: {
|
||||
backend: MediaBackendType;
|
||||
deduplicate_media: boolean;
|
||||
conversion: {
|
||||
convert_images: boolean;
|
||||
convert_to: string;
|
||||
};
|
||||
local_uploads_folder: string;
|
||||
};
|
||||
|
||||
s3: {
|
||||
endpoint: string;
|
||||
access_key: string;
|
||||
secret_access_key: string;
|
||||
region: string;
|
||||
bucket_name: string;
|
||||
public_url: string;
|
||||
};
|
||||
|
||||
defaults: {
|
||||
visibility: string;
|
||||
language: string;
|
||||
avatar: string;
|
||||
header: string;
|
||||
};
|
||||
|
||||
email: {
|
||||
send_on_report: boolean;
|
||||
send_on_suspend: boolean;
|
||||
send_on_unsuspend: boolean;
|
||||
};
|
||||
|
||||
activitypub: {
|
||||
use_tombstones: boolean;
|
||||
reject_activities: string[];
|
||||
force_followers_only: string[];
|
||||
discard_reports: string[];
|
||||
discard_deletes: string[];
|
||||
discard_banners: string[];
|
||||
discard_avatars: string[];
|
||||
discard_updates: string[];
|
||||
discard_follows: string[];
|
||||
force_sensitive: string[];
|
||||
remove_media: string[];
|
||||
fetch_all_collection_members: boolean;
|
||||
authorized_fetch: boolean;
|
||||
};
|
||||
|
||||
filters: {
|
||||
note_filters: string[];
|
||||
username_filters: string[];
|
||||
displayname_filters: string[];
|
||||
bio_filters: string[];
|
||||
emoji_filters: string[];
|
||||
};
|
||||
|
||||
logging: {
|
||||
log_requests: boolean;
|
||||
log_requests_verbose: boolean;
|
||||
log_ip: boolean;
|
||||
log_filters: boolean;
|
||||
};
|
||||
|
||||
ratelimits: {
|
||||
duration_coeff: number;
|
||||
max_coeff: number;
|
||||
};
|
||||
|
||||
custom_ratelimits: Record<
|
||||
string,
|
||||
{
|
||||
duration: number;
|
||||
max: number;
|
||||
}
|
||||
>;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const configDefaults: ConfigType = {
|
||||
http: {
|
||||
bind: "http://0.0.0.0",
|
||||
bind_port: "8000",
|
||||
base_url: "http://lysand.localhost:8000",
|
||||
banned_ips: [],
|
||||
banned_user_agents: [],
|
||||
bait: {
|
||||
enabled: false,
|
||||
send_file: "",
|
||||
bait_ips: [],
|
||||
bait_user_agents: [],
|
||||
},
|
||||
},
|
||||
database: {
|
||||
host: "localhost",
|
||||
port: 5432,
|
||||
username: "postgres",
|
||||
password: "postgres",
|
||||
database: "lysand",
|
||||
},
|
||||
redis: {
|
||||
queue: {
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
password: "",
|
||||
database: 0,
|
||||
},
|
||||
cache: {
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
password: "",
|
||||
database: 1,
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
meilisearch: {
|
||||
host: "localhost",
|
||||
port: 1491,
|
||||
api_key: "",
|
||||
enabled: false,
|
||||
},
|
||||
signups: {
|
||||
tos_url: "",
|
||||
rules: [],
|
||||
registration: false,
|
||||
},
|
||||
oidc: {
|
||||
providers: [],
|
||||
},
|
||||
instance: {
|
||||
banner: "",
|
||||
description: "",
|
||||
logo: "",
|
||||
name: "",
|
||||
},
|
||||
smtp: {
|
||||
password: "",
|
||||
port: 465,
|
||||
server: "",
|
||||
tls: true,
|
||||
username: "",
|
||||
},
|
||||
media: {
|
||||
backend: MediaBackendType.LOCAL,
|
||||
deduplicate_media: true,
|
||||
conversion: {
|
||||
convert_images: false,
|
||||
convert_to: "webp",
|
||||
},
|
||||
local_uploads_folder: "uploads",
|
||||
},
|
||||
email: {
|
||||
send_on_report: false,
|
||||
send_on_suspend: false,
|
||||
send_on_unsuspend: false,
|
||||
},
|
||||
s3: {
|
||||
access_key: "",
|
||||
bucket_name: "",
|
||||
endpoint: "",
|
||||
public_url: "",
|
||||
region: "",
|
||||
secret_access_key: "",
|
||||
},
|
||||
validation: {
|
||||
max_displayname_size: 50,
|
||||
max_bio_size: 6000,
|
||||
max_note_size: 5000,
|
||||
max_avatar_size: 5_000_000,
|
||||
max_header_size: 5_000_000,
|
||||
max_media_size: 40_000_000,
|
||||
max_media_attachments: 10,
|
||||
max_media_description_size: 1000,
|
||||
max_poll_options: 20,
|
||||
max_poll_option_size: 500,
|
||||
min_poll_duration: 60,
|
||||
max_poll_duration: 1893456000,
|
||||
max_username_size: 30,
|
||||
|
||||
username_blacklist: [
|
||||
".well-known",
|
||||
"~",
|
||||
"about",
|
||||
"activities",
|
||||
"api",
|
||||
"auth",
|
||||
"dev",
|
||||
"inbox",
|
||||
"internal",
|
||||
"main",
|
||||
"media",
|
||||
"nodeinfo",
|
||||
"notice",
|
||||
"oauth",
|
||||
"objects",
|
||||
"proxy",
|
||||
"push",
|
||||
"registration",
|
||||
"relay",
|
||||
"settings",
|
||||
"status",
|
||||
"tag",
|
||||
"users",
|
||||
"web",
|
||||
"search",
|
||||
"mfa",
|
||||
],
|
||||
|
||||
blacklist_tempmail: false,
|
||||
|
||||
email_blacklist: [],
|
||||
|
||||
url_scheme_whitelist: [
|
||||
"http",
|
||||
"https",
|
||||
"ftp",
|
||||
"dat",
|
||||
"dweb",
|
||||
"gopher",
|
||||
"hyper",
|
||||
"ipfs",
|
||||
"ipns",
|
||||
"irc",
|
||||
"xmpp",
|
||||
"ircs",
|
||||
"magnet",
|
||||
"mailto",
|
||||
"mumble",
|
||||
"ssb",
|
||||
],
|
||||
|
||||
enforce_mime_types: false,
|
||||
allowed_mime_types: [],
|
||||
},
|
||||
defaults: {
|
||||
visibility: "public",
|
||||
language: "en",
|
||||
avatar: "",
|
||||
header: "",
|
||||
},
|
||||
activitypub: {
|
||||
use_tombstones: true,
|
||||
reject_activities: [],
|
||||
force_followers_only: [],
|
||||
discard_reports: [],
|
||||
discard_deletes: [],
|
||||
discard_banners: [],
|
||||
discard_avatars: [],
|
||||
force_sensitive: [],
|
||||
discard_updates: [],
|
||||
discard_follows: [],
|
||||
remove_media: [],
|
||||
fetch_all_collection_members: false,
|
||||
authorized_fetch: false,
|
||||
},
|
||||
filters: {
|
||||
note_filters: [],
|
||||
username_filters: [],
|
||||
displayname_filters: [],
|
||||
bio_filters: [],
|
||||
emoji_filters: [],
|
||||
},
|
||||
logging: {
|
||||
log_requests: false,
|
||||
log_requests_verbose: false,
|
||||
log_ip: false,
|
||||
log_filters: true,
|
||||
},
|
||||
ratelimits: {
|
||||
duration_coeff: 1,
|
||||
max_coeff: 1,
|
||||
},
|
||||
custom_ratelimits: {},
|
||||
};
|
||||
579
packages/config-manager/config.type.ts
Normal file
579
packages/config-manager/config.type.ts
Normal file
|
|
@ -0,0 +1,579 @@
|
|||
import { MediaBackendType } from "~packages/media-manager";
|
||||
|
||||
export interface Config {
|
||||
database: {
|
||||
/** @default "localhost" */
|
||||
host: string;
|
||||
|
||||
/** @default 5432 */
|
||||
port: number;
|
||||
|
||||
/** @default "lysand" */
|
||||
username: string;
|
||||
|
||||
/** @default "lysand" */
|
||||
password: string;
|
||||
|
||||
/** @default "lysand" */
|
||||
database: string;
|
||||
};
|
||||
|
||||
redis: {
|
||||
queue: {
|
||||
/** @default "localhost" */
|
||||
host: string;
|
||||
|
||||
/** @default 6379 */
|
||||
port: number;
|
||||
|
||||
/** @default "" */
|
||||
password: string;
|
||||
|
||||
/** @default 0 */
|
||||
database: number;
|
||||
};
|
||||
|
||||
cache: {
|
||||
/** @default "localhost" */
|
||||
host: string;
|
||||
|
||||
/** @default 6379 */
|
||||
port: number;
|
||||
|
||||
/** @default "" */
|
||||
password: string;
|
||||
|
||||
/** @default 1 */
|
||||
database: number;
|
||||
|
||||
/** @default false */
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
meilisearch: {
|
||||
/** @default "localhost" */
|
||||
host: string;
|
||||
|
||||
/** @default 7700 */
|
||||
port: number;
|
||||
|
||||
/** @default "______________________________" */
|
||||
api_key: string;
|
||||
|
||||
/** @default false */
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
signups: {
|
||||
/** @default "https://my-site.com/tos" */
|
||||
tos_url: string;
|
||||
|
||||
/** @default true */
|
||||
registration: boolean;
|
||||
|
||||
/** @default ["Do not harass others","Be nice to people","Don't spam","Don't post illegal content"] */
|
||||
rules: string[];
|
||||
};
|
||||
|
||||
oidc: {
|
||||
/** @default [] */
|
||||
providers: Record<string, any>[];
|
||||
};
|
||||
|
||||
http: {
|
||||
/** @default "https://lysand.social" */
|
||||
base_url: string;
|
||||
|
||||
/** @default "0.0.0.0" */
|
||||
bind: string;
|
||||
|
||||
/** @default "8080" */
|
||||
bind_port: string;
|
||||
|
||||
banned_ips: any[];
|
||||
|
||||
banned_user_agents: any[];
|
||||
|
||||
bait: {
|
||||
/** @default false */
|
||||
enabled: boolean;
|
||||
|
||||
/** @default "" */
|
||||
send_file: string;
|
||||
|
||||
/** @default ["127.0.0.1","::1"] */
|
||||
bait_ips: string[];
|
||||
|
||||
/** @default ["curl","wget"] */
|
||||
bait_user_agents: string[];
|
||||
};
|
||||
};
|
||||
|
||||
smtp: {
|
||||
/** @default "smtp.example.com" */
|
||||
server: string;
|
||||
|
||||
/** @default 465 */
|
||||
port: number;
|
||||
|
||||
/** @default "test@example.com" */
|
||||
username: string;
|
||||
|
||||
/** @default "____________" */
|
||||
password: string;
|
||||
|
||||
/** @default true */
|
||||
tls: boolean;
|
||||
|
||||
/** @default false */
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
media: {
|
||||
/** @default "local" */
|
||||
backend: MediaBackendType;
|
||||
|
||||
/** @default true */
|
||||
deduplicate_media: boolean;
|
||||
|
||||
/** @default "uploads" */
|
||||
local_uploads_folder: string;
|
||||
|
||||
conversion: {
|
||||
/** @default false */
|
||||
convert_images: boolean;
|
||||
|
||||
/** @default "webp" */
|
||||
convert_to: string;
|
||||
};
|
||||
};
|
||||
|
||||
s3: {
|
||||
/** @default "myhostname.banana.com" */
|
||||
endpoint: string;
|
||||
|
||||
/** @default "_____________" */
|
||||
access_key: string;
|
||||
|
||||
/** @default "_________________" */
|
||||
secret_access_key: string;
|
||||
|
||||
/** @default "" */
|
||||
region: string;
|
||||
|
||||
/** @default "lysand" */
|
||||
bucket_name: string;
|
||||
|
||||
/** @default "https://cdn.test.com" */
|
||||
public_url: string;
|
||||
};
|
||||
|
||||
email: {
|
||||
/** @default false */
|
||||
send_on_report: boolean;
|
||||
|
||||
/** @default false */
|
||||
send_on_suspend: boolean;
|
||||
|
||||
/** @default false */
|
||||
send_on_unsuspend: boolean;
|
||||
|
||||
/** @default false */
|
||||
verify_email: boolean;
|
||||
};
|
||||
|
||||
validation: {
|
||||
/** @default 50 */
|
||||
max_displayname_size: number;
|
||||
|
||||
/** @default 160 */
|
||||
max_bio_size: number;
|
||||
|
||||
/** @default 5000 */
|
||||
max_note_size: number;
|
||||
|
||||
/** @default 5000000 */
|
||||
max_avatar_size: number;
|
||||
|
||||
/** @default 5000000 */
|
||||
max_header_size: number;
|
||||
|
||||
/** @default 40000000 */
|
||||
max_media_size: number;
|
||||
|
||||
/** @default 10 */
|
||||
max_media_attachments: number;
|
||||
|
||||
/** @default 1000 */
|
||||
max_media_description_size: number;
|
||||
|
||||
/** @default 20 */
|
||||
max_poll_options: number;
|
||||
|
||||
/** @default 500 */
|
||||
max_poll_option_size: number;
|
||||
|
||||
/** @default 60 */
|
||||
min_poll_duration: number;
|
||||
|
||||
/** @default 1893456000 */
|
||||
max_poll_duration: number;
|
||||
|
||||
/** @default 30 */
|
||||
max_username_size: number;
|
||||
|
||||
/** @default [".well-known","~","about","activities","api","auth","dev","inbox","internal","main","media","nodeinfo","notice","oauth","objects","proxy","push","registration","relay","settings","status","tag","users","web","search","mfa"] */
|
||||
username_blacklist: string[];
|
||||
|
||||
/** @default false */
|
||||
blacklist_tempmail: boolean;
|
||||
|
||||
email_blacklist: any[];
|
||||
|
||||
/** @default ["http","https","ftp","dat","dweb","gopher","hyper","ipfs","ipns","irc","xmpp","ircs","magnet","mailto","mumble","ssb","gemini"] */
|
||||
url_scheme_whitelist: string[];
|
||||
|
||||
/** @default false */
|
||||
enforce_mime_types: boolean;
|
||||
|
||||
/** @default ["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"] */
|
||||
allowed_mime_types: string[];
|
||||
};
|
||||
|
||||
defaults: {
|
||||
/** @default "public" */
|
||||
visibility: string;
|
||||
|
||||
/** @default "en" */
|
||||
language: string;
|
||||
|
||||
/** @default "" */
|
||||
avatar: string;
|
||||
|
||||
/** @default "" */
|
||||
header: string;
|
||||
};
|
||||
|
||||
federation: {
|
||||
blocked: any[];
|
||||
|
||||
followers_only: any[];
|
||||
|
||||
discard: {
|
||||
reports: any[];
|
||||
|
||||
deletes: any[];
|
||||
|
||||
updates: any[];
|
||||
|
||||
media: any[];
|
||||
|
||||
follows: any[];
|
||||
|
||||
likes: any[];
|
||||
|
||||
reactions: any[];
|
||||
|
||||
banners: any[];
|
||||
|
||||
avatars: any[];
|
||||
};
|
||||
};
|
||||
|
||||
instance: {
|
||||
/** @default "Lysand" */
|
||||
name: string;
|
||||
|
||||
/** @default "A test instance of Lysand" */
|
||||
description: string;
|
||||
|
||||
/** @default "" */
|
||||
logo: string;
|
||||
|
||||
/** @default "" */
|
||||
banner: string;
|
||||
};
|
||||
|
||||
filters: {
|
||||
note_content: any[];
|
||||
|
||||
emoji: any[];
|
||||
|
||||
username: any[];
|
||||
|
||||
displayname: any[];
|
||||
|
||||
bio: any[];
|
||||
};
|
||||
|
||||
logging: {
|
||||
/** @default false */
|
||||
log_requests: boolean;
|
||||
|
||||
/** @default false */
|
||||
log_requests_verbose: boolean;
|
||||
|
||||
/** @default false */
|
||||
log_ip: boolean;
|
||||
|
||||
/** @default true */
|
||||
log_filters: boolean;
|
||||
|
||||
storage: {
|
||||
/** @default "logs/requests.log" */
|
||||
requests: string;
|
||||
};
|
||||
};
|
||||
|
||||
ratelimits: {
|
||||
/** @default 1 */
|
||||
duration_coeff: number;
|
||||
|
||||
/** @default 1 */
|
||||
max_coeff: number;
|
||||
};
|
||||
|
||||
/** @default {} */
|
||||
custom_ratelimits: Record<
|
||||
string,
|
||||
{
|
||||
/** @default 30 */
|
||||
duration: number;
|
||||
|
||||
/** @default 60 */
|
||||
max: number;
|
||||
}
|
||||
>;
|
||||
}
|
||||
|
||||
export const defaultConfig: Config = {
|
||||
database: {
|
||||
host: "localhost",
|
||||
port: 5432,
|
||||
username: "lysand",
|
||||
password: "lysand",
|
||||
database: "lysand",
|
||||
},
|
||||
redis: {
|
||||
queue: {
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
password: "",
|
||||
database: 0,
|
||||
},
|
||||
cache: {
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
password: "",
|
||||
database: 1,
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
meilisearch: {
|
||||
host: "localhost",
|
||||
port: 7700,
|
||||
api_key: "______________________________",
|
||||
enabled: false,
|
||||
},
|
||||
signups: {
|
||||
tos_url: "https://my-site.com/tos",
|
||||
registration: true,
|
||||
rules: [
|
||||
"Do not harass others",
|
||||
"Be nice to people",
|
||||
"Don't spam",
|
||||
"Don't post illegal content",
|
||||
],
|
||||
},
|
||||
oidc: {
|
||||
providers: [[]],
|
||||
},
|
||||
http: {
|
||||
base_url: "https://lysand.social",
|
||||
bind: "0.0.0.0",
|
||||
bind_port: "8080",
|
||||
banned_ips: [],
|
||||
banned_user_agents: [],
|
||||
bait: {
|
||||
enabled: false,
|
||||
send_file: "",
|
||||
bait_ips: ["127.0.0.1", "::1"],
|
||||
bait_user_agents: ["curl", "wget"],
|
||||
},
|
||||
},
|
||||
smtp: {
|
||||
server: "smtp.example.com",
|
||||
port: 465,
|
||||
username: "test@example.com",
|
||||
password: "____________",
|
||||
tls: true,
|
||||
enabled: false,
|
||||
},
|
||||
media: {
|
||||
backend: MediaBackendType.LOCAL,
|
||||
deduplicate_media: true,
|
||||
local_uploads_folder: "uploads",
|
||||
conversion: {
|
||||
convert_images: false,
|
||||
convert_to: "webp",
|
||||
},
|
||||
},
|
||||
s3: {
|
||||
endpoint: "myhostname.banana.com",
|
||||
access_key: "_____________",
|
||||
secret_access_key: "_________________",
|
||||
region: "",
|
||||
bucket_name: "lysand",
|
||||
public_url: "https://cdn.test.com",
|
||||
},
|
||||
email: {
|
||||
send_on_report: false,
|
||||
send_on_suspend: false,
|
||||
send_on_unsuspend: false,
|
||||
verify_email: false,
|
||||
},
|
||||
validation: {
|
||||
max_displayname_size: 50,
|
||||
max_bio_size: 160,
|
||||
max_note_size: 5000,
|
||||
max_avatar_size: 5000000,
|
||||
max_header_size: 5000000,
|
||||
max_media_size: 40000000,
|
||||
max_media_attachments: 10,
|
||||
max_media_description_size: 1000,
|
||||
max_poll_options: 20,
|
||||
max_poll_option_size: 500,
|
||||
min_poll_duration: 60,
|
||||
max_poll_duration: 1893456000,
|
||||
max_username_size: 30,
|
||||
username_blacklist: [
|
||||
".well-known",
|
||||
"~",
|
||||
"about",
|
||||
"activities",
|
||||
"api",
|
||||
"auth",
|
||||
"dev",
|
||||
"inbox",
|
||||
"internal",
|
||||
"main",
|
||||
"media",
|
||||
"nodeinfo",
|
||||
"notice",
|
||||
"oauth",
|
||||
"objects",
|
||||
"proxy",
|
||||
"push",
|
||||
"registration",
|
||||
"relay",
|
||||
"settings",
|
||||
"status",
|
||||
"tag",
|
||||
"users",
|
||||
"web",
|
||||
"search",
|
||||
"mfa",
|
||||
],
|
||||
blacklist_tempmail: false,
|
||||
email_blacklist: [],
|
||||
url_scheme_whitelist: [
|
||||
"http",
|
||||
"https",
|
||||
"ftp",
|
||||
"dat",
|
||||
"dweb",
|
||||
"gopher",
|
||||
"hyper",
|
||||
"ipfs",
|
||||
"ipns",
|
||||
"irc",
|
||||
"xmpp",
|
||||
"ircs",
|
||||
"magnet",
|
||||
"mailto",
|
||||
"mumble",
|
||||
"ssb",
|
||||
"gemini",
|
||||
],
|
||||
enforce_mime_types: false,
|
||||
allowed_mime_types: [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/gif",
|
||||
"image/heic",
|
||||
"image/heif",
|
||||
"image/webp",
|
||||
"image/avif",
|
||||
"video/webm",
|
||||
"video/mp4",
|
||||
"video/quicktime",
|
||||
"video/ogg",
|
||||
"audio/wave",
|
||||
"audio/wav",
|
||||
"audio/x-wav",
|
||||
"audio/x-pn-wave",
|
||||
"audio/vnd.wave",
|
||||
"audio/ogg",
|
||||
"audio/vorbis",
|
||||
"audio/mpeg",
|
||||
"audio/mp3",
|
||||
"audio/webm",
|
||||
"audio/flac",
|
||||
"audio/aac",
|
||||
"audio/m4a",
|
||||
"audio/x-m4a",
|
||||
"audio/mp4",
|
||||
"audio/3gpp",
|
||||
"video/x-ms-asf",
|
||||
],
|
||||
},
|
||||
defaults: {
|
||||
visibility: "public",
|
||||
language: "en",
|
||||
avatar: "",
|
||||
header: "",
|
||||
},
|
||||
federation: {
|
||||
blocked: [],
|
||||
followers_only: [],
|
||||
discard: {
|
||||
reports: [],
|
||||
deletes: [],
|
||||
updates: [],
|
||||
media: [],
|
||||
follows: [],
|
||||
likes: [],
|
||||
reactions: [],
|
||||
banners: [],
|
||||
avatars: [],
|
||||
},
|
||||
},
|
||||
instance: {
|
||||
name: "Lysand",
|
||||
description: "A test instance of Lysand",
|
||||
logo: "",
|
||||
banner: "",
|
||||
},
|
||||
filters: {
|
||||
note_content: [],
|
||||
emoji: [],
|
||||
username: [],
|
||||
displayname: [],
|
||||
bio: [],
|
||||
},
|
||||
logging: {
|
||||
log_requests: false,
|
||||
log_requests_verbose: false,
|
||||
log_ip: false,
|
||||
log_filters: true,
|
||||
storage: {
|
||||
requests: "logs/requests.log",
|
||||
},
|
||||
},
|
||||
ratelimits: {
|
||||
duration_coeff: 1,
|
||||
max_coeff: 1,
|
||||
},
|
||||
custom_ratelimits: {},
|
||||
};
|
||||
|
|
@ -5,122 +5,22 @@
|
|||
* Fuses both and provides a way to retrieve individual values
|
||||
*/
|
||||
|
||||
import { parse, stringify, type JsonMap } from "@iarna/toml";
|
||||
import type { ConfigType } from "./config-type.type";
|
||||
import { configDefaults } from "./config-type.type";
|
||||
import merge from "merge-deep-ts";
|
||||
import { watchConfig } from "c12";
|
||||
import { defaultConfig, type Config } from "./config.type";
|
||||
|
||||
export class ConfigManager {
|
||||
constructor(
|
||||
public config: {
|
||||
configPathOverride?: string;
|
||||
internalConfigPathOverride?: string;
|
||||
}
|
||||
) {}
|
||||
const { config } = await watchConfig<Config>({
|
||||
configFile: "./config/config.toml",
|
||||
defaultConfig: defaultConfig,
|
||||
overrides:
|
||||
(
|
||||
await watchConfig<Config>({
|
||||
configFile: "./config/config.internal.toml",
|
||||
defaultConfig: {} as Config,
|
||||
})
|
||||
).config ?? undefined,
|
||||
});
|
||||
|
||||
/**
|
||||
* @summary Reads the config files and returns the merge as a JSON object
|
||||
* @returns {Promise<T = ConfigType>} The merged config file as a JSON object
|
||||
*/
|
||||
async getConfig<T = ConfigType>() {
|
||||
const config = await this.readConfig<T>();
|
||||
const internalConfig = await this.readInternalConfig<T>();
|
||||
const exportedConfig = config ?? defaultConfig;
|
||||
|
||||
return this.mergeConfigs<T>(
|
||||
configDefaults as T,
|
||||
config,
|
||||
internalConfig
|
||||
);
|
||||
}
|
||||
|
||||
getConfigPath() {
|
||||
return (
|
||||
this.config.configPathOverride ||
|
||||
process.cwd() + "/config/config.toml"
|
||||
);
|
||||
}
|
||||
|
||||
getInternalConfigPath() {
|
||||
return (
|
||||
this.config.internalConfigPathOverride ||
|
||||
process.cwd() + "/config/config.internal.toml"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Reads the internal config file and returns it as a JSON object
|
||||
* @returns {Promise<T = ConfigType>} The internal config file as a JSON object
|
||||
*/
|
||||
private async readInternalConfig<T = ConfigType>() {
|
||||
const config = Bun.file(this.getInternalConfigPath());
|
||||
|
||||
if (!(await config.exists())) {
|
||||
await Bun.write(config, "");
|
||||
}
|
||||
|
||||
return this.parseConfig<T>(await config.text());
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Reads the config file and returns it as a JSON object
|
||||
* @returns {Promise<T = ConfigType>} The config file as a JSON object
|
||||
*/
|
||||
private async readConfig<T = ConfigType>() {
|
||||
const config = Bun.file(this.getConfigPath());
|
||||
|
||||
if (!(await config.exists())) {
|
||||
throw new Error(
|
||||
`Error while reading config at path ${this.getConfigPath()}: Config file not found`
|
||||
);
|
||||
}
|
||||
|
||||
return this.parseConfig<T>(await config.text());
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Parses a TOML string and returns it as a JSON object
|
||||
* @param text The TOML string to parse
|
||||
* @returns {T = ConfigType} The parsed TOML string as a JSON object
|
||||
* @throws {Error} If the TOML string is invalid
|
||||
* @private
|
||||
*/
|
||||
private parseConfig<T = ConfigType>(text: string) {
|
||||
try {
|
||||
// To all [Symbol] keys from the object
|
||||
return JSON.parse(JSON.stringify(parse(text))) as T;
|
||||
} catch (e: any) {
|
||||
throw new Error(
|
||||
`Error while parsing config at path ${this.getConfigPath()}: ${e}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes changed values to the internal config
|
||||
* @param config The new config object
|
||||
*/
|
||||
async writeConfig<T = ConfigType>(config: T) {
|
||||
const path = this.getInternalConfigPath();
|
||||
const file = Bun.file(path);
|
||||
|
||||
await Bun.write(
|
||||
file,
|
||||
`# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT IT MANUALLY, EDIT THE STANDARD CONFIG.TOML INSTEAD.\n${stringify(
|
||||
config as JsonMap
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Merges two config objects together, with
|
||||
* the latter configs' values taking precedence
|
||||
* @param configs
|
||||
* @returns
|
||||
*/
|
||||
private mergeConfigs<T = ConfigType>(...configs: T[]) {
|
||||
return merge(configs) as T;
|
||||
}
|
||||
}
|
||||
|
||||
export type { ConfigType };
|
||||
export const defaultConfig = configDefaults;
|
||||
export { exportedConfig as config };
|
||||
export type { Config };
|
||||
|
|
|
|||
|
|
@ -1,96 +0,0 @@
|
|||
// FILEPATH: /home/jessew/Dev/lysand/packages/config-manager/config-manager.test.ts
|
||||
import { stringify } from "@iarna/toml";
|
||||
import { ConfigManager } from "..";
|
||||
import { describe, beforeEach, spyOn, it, expect } from "bun:test";
|
||||
|
||||
describe("ConfigManager", () => {
|
||||
let configManager: ConfigManager;
|
||||
|
||||
beforeEach(() => {
|
||||
configManager = new ConfigManager({
|
||||
configPathOverride: "./config/config.toml",
|
||||
internalConfigPathOverride: "./config/config.internal.toml",
|
||||
});
|
||||
});
|
||||
|
||||
it("should get the correct config path", () => {
|
||||
expect(configManager.getConfigPath()).toEqual("./config/config.toml");
|
||||
});
|
||||
|
||||
it("should get the correct internal config path", () => {
|
||||
expect(configManager.getInternalConfigPath()).toEqual(
|
||||
"./config/config.internal.toml"
|
||||
);
|
||||
});
|
||||
|
||||
it("should read the config file correctly", async () => {
|
||||
const mockConfig = { key: "value" };
|
||||
|
||||
// @ts-expect-error This is a mock
|
||||
spyOn(Bun, "file").mockImplementationOnce(() => ({
|
||||
exists: () =>
|
||||
new Promise(resolve => {
|
||||
resolve(true);
|
||||
}),
|
||||
text: () =>
|
||||
new Promise(resolve => {
|
||||
resolve(stringify(mockConfig));
|
||||
}),
|
||||
}));
|
||||
|
||||
const config = await configManager.getConfig<typeof mockConfig>();
|
||||
|
||||
expect(config).toContainKeys(Object.keys(mockConfig));
|
||||
});
|
||||
|
||||
it("should read the internal config file correctly", async () => {
|
||||
const mockConfig = { key: "value" };
|
||||
|
||||
// @ts-expect-error This is a mock
|
||||
spyOn(Bun, "file").mockImplementationOnce(() => ({
|
||||
exists: () =>
|
||||
new Promise(resolve => {
|
||||
resolve(true);
|
||||
}),
|
||||
text: () =>
|
||||
new Promise(resolve => {
|
||||
resolve(stringify(mockConfig));
|
||||
}),
|
||||
}));
|
||||
|
||||
const config =
|
||||
// @ts-expect-error Force call private function for testing
|
||||
await configManager.readInternalConfig<typeof mockConfig>();
|
||||
|
||||
expect(config).toEqual(mockConfig);
|
||||
});
|
||||
|
||||
it("should write to the internal config file correctly", async () => {
|
||||
const mockConfig = { key: "value" };
|
||||
|
||||
spyOn(Bun, "write").mockImplementationOnce(
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
resolve(10);
|
||||
})
|
||||
);
|
||||
|
||||
await configManager.writeConfig(mockConfig);
|
||||
});
|
||||
|
||||
it("should merge configs correctly", () => {
|
||||
const config1 = { key1: "value1", key2: "value2" };
|
||||
const config2 = { key2: "newValue2", key3: "value3" };
|
||||
// @ts-expect-error Force call private function for testing
|
||||
const mergedConfig = configManager.mergeConfigs<Record<string, string>>(
|
||||
config1,
|
||||
config2
|
||||
);
|
||||
|
||||
expect(mergedConfig).toEqual({
|
||||
key1: "value1",
|
||||
key2: "newValue2",
|
||||
key3: "value3",
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue