diff --git a/Cargo.lock b/Cargo.lock index c6ba96e683..6cb32a21d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,12 +220,14 @@ dependencies = [ "parse-display", "pretty_assertions", "rand", + "redis", "regex", "schemars", "sea-orm", "serde", "serde_json", "serde_yaml", + "strum 0.26.2", "thiserror", "tokio", "url", @@ -524,6 +526,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1858,6 +1870,21 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redis" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6472825949c09872e8f2c50bde59fcefc17748b6be5c90fd67cd8b4daca73bfd" +dependencies = [ + "combine", + "itoa", + "percent-encoding", + "ryu", + "sha1_smol", + "socket2", + "url", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -2070,6 +2097,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + [[package]] name = "ryu" version = "1.0.17" @@ -2150,7 +2183,7 @@ dependencies = [ "serde", "serde_json", "sqlx", - "strum", + "strum 0.25.0", "thiserror", "time", "tracing", @@ -2295,6 +2328,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.10.8" @@ -2676,6 +2715,28 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.58", +] + [[package]] name = "subtle" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 7ca43c960b..0bde324447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,12 +26,14 @@ pretty_assertions = "1.4.0" proc-macro2 = "1.0.79" quote = "1.0.36" rand = "0.8.5" +redis = "0.25.3" regex = "1.10.4" schemars = "0.8.16" sea-orm = "0.12.15" serde = "1.0.197" serde_json = "1.0.115" serde_yaml = "0.9.34" +strum = "0.26.2" syn = "2.0.58" thiserror = "1.0.58" tokio = "1.37.0" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index af9e10cdc1..93c57dc321 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -30,12 +30,14 @@ jsonschema = { workspace = true } once_cell = { workspace = true } parse-display = { workspace = true } rand = { workspace = true } +redis = { workspace = true } regex = { workspace = true } schemars = { workspace = true, features = ["chrono"] } sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } serde_yaml = { workspace = true } +strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } url = { workspace = true } diff --git a/packages/backend-rs/Makefile b/packages/backend-rs/Makefile index 11b614c82a..abe6045801 100644 --- a/packages/backend-rs/Makefile +++ b/packages/backend-rs/Makefile @@ -6,6 +6,7 @@ SRC += $(call recursive_wildcard, src, *) .PHONY: regenerate-entities regenerate-entities: + rm --recursive --force src/model/entity sea-orm-cli generate entity \ --output-dir='src/model/entity' \ --database-url='postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@localhost:25432/$(POSTGRES_DB)' \ @@ -16,8 +17,9 @@ regenerate-entities: jsname=$$(printf '%s\n' "$${base%.*}" | perl -pe 's/(^|_)./uc($$&)/ge;s/_//g'); \ attribute=$$(printf 'cfg_attr(feature = "napi", napi_derive::napi(object, js_name = "%s", use_nullable = true))' "$${jsname}"); \ sed -i "s/NAPI_EXTRA_ATTR_PLACEHOLDER/$${attribute}/" "$${file}"; \ + sed -i 's/#\[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)\]/#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = "camelCase")]/' "$${file}"; \ done - sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ + sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = "camelCase")]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \ src/model/entity/sea_orm_active_enums.rs cargo fmt --all -- diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 04b26c3e5a..50489a846d 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -12,7 +12,7 @@ export interface EnvConfig { withLogTime: boolean slow: boolean } -export function readEnvironmentConfig(): EnvConfig +export function loadEnv(): EnvConfig export interface ServerConfig { url: string port: number @@ -29,7 +29,7 @@ export interface ServerConfig { /** `NapiValue` is not implemented for `u64` */ maxFileSize?: number accessLog?: string - clusterLimits?: WorkerConfig + clusterLimits?: WorkerConfigInternal cuid?: IdConfig outgoingAddress?: string deliverJobConcurrency?: number @@ -70,13 +70,17 @@ export interface RedisConfig { pass?: string tls?: TlsConfig db: number - prefix: string + prefix?: string } export interface TlsConfig { host: string rejectUnauthorized: boolean } export interface WorkerConfig { + web: number + queue: number +} +export interface WorkerConfigInternal { web?: number queue?: number } @@ -121,7 +125,68 @@ export interface ObjectStorageConfig { setPublicReadOnUpload?: boolean s3ForcePathStyle?: boolean } -export function readServerConfig(): ServerConfig +export interface Config { + url: string + port: number + bind?: string + disableHsts?: boolean + db: DbConfig + redis: RedisConfig + cacheServer?: RedisConfig + proxy?: string + proxySmtp?: string + proxyBypassHosts?: Array + allowedPrivateNetworks?: Array + maxFileSize?: number + accessLog?: string + clusterLimits: WorkerConfig + cuid?: IdConfig + outgoingAddress?: string + deliverJobConcurrency?: number + inboxJobConcurrency?: number + deliverJobPerSec?: number + inboxJobPerSec?: number + deliverJobMaxAttempts?: number + inboxJobMaxAttempts?: number + logLevel?: Array + syslog?: SysLogConfig + proxyRemoteFiles?: boolean + mediaProxy?: string + summalyProxyUrl?: string + reservedUsernames?: Array + maxUserSignups?: number + isManagedHosting?: boolean + maxNoteLength?: number + maxCaptionLength?: number + deepl?: DeepLConfig + libreTranslate?: LibreTranslateConfig + email?: EmailConfig + objectStorage?: ObjectStorageConfig + version: string + host: string + hostname: string + redisKeyPrefix: string + scheme: string + wsScheme: string + apiUrl: string + wsUrl: string + authUrl: string + driveUrl: string + userAgent: string + clientEntry: Manifest +} +export interface Manifest { + file: string + name: string + src: string + isEntry: boolean + isDynamicEntry: boolean + imports: Array + dynamicImports: Array + css: Array + assets: Array +} +export function loadConfig(): Config export interface Acct { username: string host: string | null @@ -1039,6 +1104,7 @@ export interface Webhook { latestSentAt: Date | null latestStatus: number | null } +export function addNoteToAntenna(antennaId: string, note: Note): void /** Initializes Cuid2 generator. Must be called before any [create_id]. */ export function initIdGenerator(length: number, fingerprint: string): void export function getTimestamp(id: string): number diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 6d64f6ec75..9a5e3d1a92 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,10 +310,10 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { readEnvironmentConfig, readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding +const { loadEnv, loadConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, addNoteToAntenna, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding -module.exports.readEnvironmentConfig = readEnvironmentConfig -module.exports.readServerConfig = readServerConfig +module.exports.loadEnv = loadEnv +module.exports.loadConfig = loadConfig module.exports.stringToAcct = stringToAcct module.exports.acctToString = acctToString module.exports.checkWordMute = checkWordMute @@ -349,6 +349,7 @@ module.exports.RelayStatusEnum = RelayStatusEnum module.exports.UserEmojimodpermEnum = UserEmojimodpermEnum module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum +module.exports.addNoteToAntenna = addNoteToAntenna module.exports.initIdGenerator = initIdGenerator module.exports.getTimestamp = getTimestamp module.exports.genId = genId diff --git a/packages/backend-rs/src/config/environment.rs b/packages/backend-rs/src/config/environment.rs index 7d66aec7ba..1825af326a 100644 --- a/packages/backend-rs/src/config/environment.rs +++ b/packages/backend-rs/src/config/environment.rs @@ -11,7 +11,7 @@ pub struct EnvConfig { } #[crate::export] -pub fn read_environment_config() -> EnvConfig { +pub fn load_env() -> EnvConfig { let node_env = std::env::var("NODE_ENV").unwrap_or_default().to_lowercase(); let is_testing = node_env == "test"; diff --git a/packages/backend-rs/src/config/mod.rs b/packages/backend-rs/src/config/mod.rs index b708f2b265..6155f15e54 100644 --- a/packages/backend-rs/src/config/mod.rs +++ b/packages/backend-rs/src/config/mod.rs @@ -1,2 +1,4 @@ +pub use server::CONFIG; + pub mod environment; pub mod server; diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 125bae90b9..5a4ee481cd 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -6,7 +6,7 @@ use std::fs; #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] #[crate::export(object, use_nullable = false)] -pub struct ServerConfig { +struct ServerConfig { pub url: String, pub port: u16, /// host to listen on @@ -25,7 +25,7 @@ pub struct ServerConfig { /// `NapiValue` is not implemented for `u64` pub max_file_size: Option, pub access_log: Option, - pub cluster_limits: Option, + pub cluster_limits: Option, pub cuid: Option, pub outgoing_address: Option, @@ -82,8 +82,7 @@ pub struct RedisConfig { pub tls: Option, #[serde(default)] pub db: u32, - #[serde(default)] - pub prefix: String, + pub prefix: Option, } #[derive(Clone, Debug, PartialEq, Deserialize)] @@ -94,10 +93,16 @@ pub struct TlsConfig { pub reject_unauthorized: bool, } +#[crate::export(object, use_nullable = false)] +pub struct WorkerConfig { + pub web: u32, + pub queue: u32, +} + #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] #[crate::export(object, use_nullable = false)] -pub struct WorkerConfig { +pub struct WorkerConfigInternal { pub web: Option, pub queue: Option, } @@ -167,17 +172,207 @@ pub struct ObjectStorageConfig { pub s3_force_path_style: Option, } -#[crate::export] -pub fn read_server_config() -> ServerConfig { +#[crate::export(object, use_nullable = false)] +pub struct Config { + // ServerConfig (from default.yml) + pub url: String, + pub port: u16, + pub bind: Option, + pub disable_hsts: Option, + pub db: DbConfig, + pub redis: RedisConfig, + pub cache_server: Option, + pub proxy: Option, + pub proxy_smtp: Option, + pub proxy_bypass_hosts: Option>, + pub allowed_private_networks: Option>, + pub max_file_size: Option, + pub access_log: Option, + pub cluster_limits: WorkerConfig, + pub cuid: Option, + pub outgoing_address: Option, + pub deliver_job_concurrency: Option, + pub inbox_job_concurrency: Option, + pub deliver_job_per_sec: Option, + pub inbox_job_per_sec: Option, + pub deliver_job_max_attempts: Option, + pub inbox_job_max_attempts: Option, + pub log_level: Option>, + pub syslog: Option, + pub proxy_remote_files: Option, + pub media_proxy: Option, + pub summaly_proxy_url: Option, + pub reserved_usernames: Option>, + pub max_user_signups: Option, + pub is_managed_hosting: Option, + pub max_note_length: Option, + pub max_caption_length: Option, + pub deepl: Option, + pub libre_translate: Option, + pub email: Option, + pub object_storage: Option, + + // Mixin + pub version: String, + pub host: String, + pub hostname: String, + pub redis_key_prefix: String, + pub scheme: String, + pub ws_scheme: String, + pub api_url: String, + pub ws_url: String, + pub auth_url: String, + pub drive_url: String, + pub user_agent: String, + pub client_entry: Manifest, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +struct Meta { + pub version: String, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +struct ManifestJson { + #[serde(rename = "src/init.ts")] + pub init_ts: Manifest, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct Manifest { + pub file: String, + pub name: String, + pub src: String, + pub is_entry: bool, + pub is_dynamic_entry: bool, + pub imports: Vec, + pub dynamic_imports: Vec, + pub css: Vec, + pub assets: Vec, +} + +fn read_config_file() -> ServerConfig { let cwd = env::current_dir().unwrap(); let yml = fs::File::open(cwd.join("../../.config/default.yml")) .expect("Failed to open '.config/default.yml'"); - let mut data: ServerConfig = serde_yaml::from_reader(yml).expect("Failed to parse yaml"); + let mut data: ServerConfig = + serde_yaml::from_reader(yml).expect("Failed to parse .config/default.yml"); + data.url = url::Url::parse(&data.url) .expect("Config url is invalid") .origin() .ascii_serialization(); + + if data.bind.is_none() { + data.bind = std::env::var("BIND").ok() + } + data } -pub static SERVER_CONFIG: Lazy = Lazy::new(read_server_config); +fn read_meta() -> Meta { + let cwd = env::current_dir().unwrap(); + let meta_json = fs::File::open(cwd.join("../../built/meta.json")) + .expect("Failed to open 'built/meta.json'"); + serde_json::from_reader(meta_json).expect("Failed to parse built/meta.json") +} + +fn read_manifest() -> Manifest { + let cwd = env::current_dir().unwrap(); + let manifest_json = fs::File::open(cwd.join("../../built/_client_dist_/manifest.json")) + .expect("Failed to open 'built/_client_dist_/manifest.json'"); + let manifest: ManifestJson = serde_json::from_reader(manifest_json) + .expect("Failed to parse built/_client_dist_/manifest.json"); + + manifest.init_ts +} + +#[crate::export] +fn load_config() -> Config { + let server_config = read_config_file(); + let version = read_meta().version; + let manifest = read_manifest(); + let url = url::Url::parse(&server_config.url).expect("Config url is invalid"); + let hostname = url + .host_str() + .expect("Hostname is missing in the config url") + .to_owned(); + let host = match url.port() { + Some(port) => format!("{}:{}", hostname, port), + None => hostname.clone(), + }; + let scheme = url.scheme().to_owned(); + let ws_scheme = scheme.replace("http", "ws"); + + let cluster_limits = match server_config.cluster_limits { + Some(cl) => WorkerConfig { + web: cl.web.unwrap_or(1), + queue: cl.queue.unwrap_or(1), + }, + None => WorkerConfig { web: 1, queue: 1 }, + }; + + let redis_key_prefix = if let Some(cache_server) = &server_config.cache_server { + cache_server.prefix.clone() + } else { + server_config.redis.prefix.clone() + } + .unwrap_or(hostname.clone()); + + Config { + url: server_config.url, + port: server_config.port, + bind: server_config.bind, + disable_hsts: server_config.disable_hsts, + db: server_config.db, + redis: server_config.redis, + cache_server: server_config.cache_server, + proxy: server_config.proxy, + proxy_smtp: server_config.proxy_smtp, + proxy_bypass_hosts: server_config.proxy_bypass_hosts, + allowed_private_networks: server_config.allowed_private_networks, + max_file_size: server_config.max_file_size, + access_log: server_config.access_log, + cluster_limits, + cuid: server_config.cuid, + outgoing_address: server_config.outgoing_address, + deliver_job_concurrency: server_config.deliver_job_concurrency, + inbox_job_concurrency: server_config.inbox_job_concurrency, + deliver_job_per_sec: server_config.deliver_job_per_sec, + inbox_job_per_sec: server_config.inbox_job_per_sec, + deliver_job_max_attempts: server_config.deliver_job_max_attempts, + inbox_job_max_attempts: server_config.inbox_job_max_attempts, + log_level: server_config.log_level, + syslog: server_config.syslog, + proxy_remote_files: server_config.proxy_remote_files, + media_proxy: server_config.media_proxy, + summaly_proxy_url: server_config.summaly_proxy_url, + reserved_usernames: server_config.reserved_usernames, + max_user_signups: server_config.max_user_signups, + is_managed_hosting: server_config.is_managed_hosting, + max_note_length: server_config.max_note_length, + max_caption_length: server_config.max_caption_length, + deepl: server_config.deepl, + libre_translate: server_config.libre_translate, + email: server_config.email, + object_storage: server_config.object_storage, + + ws_url: format!("{}://{}", ws_scheme, host), + api_url: format!("{}://{}/api", scheme, host), + auth_url: format!("{}://{}/auth", scheme, host), + drive_url: format!("{}://{}/files", scheme, host), + user_agent: format!("Firefish/{} ({})", version, url), + version, + host, + hostname, + redis_key_prefix, + scheme, + ws_scheme, + client_entry: manifest, + } +} + +pub static CONFIG: Lazy = Lazy::new(load_config); diff --git a/packages/backend-rs/src/database/mod.rs b/packages/backend-rs/src/database/mod.rs index f598e35cc7..7a6277068b 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -1,34 +1,6 @@ -use crate::config::server::SERVER_CONFIG; -use sea_orm::{Database, DbConn, DbErr}; +pub use postgresql::db_conn; +pub use redis::key as redis_key; +pub use redis::redis_conn; -static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); - -async fn init_database() -> Result<&'static DbConn, DbErr> { - let database_uri = format!( - "postgres://{}:{}@{}:{}/{}", - SERVER_CONFIG.db.user, - urlencoding::encode(&SERVER_CONFIG.db.pass), - SERVER_CONFIG.db.host, - SERVER_CONFIG.db.port, - SERVER_CONFIG.db.db, - ); - let conn = Database::connect(database_uri).await?; - Ok(DB_CONN.get_or_init(move || conn)) -} - -pub async fn db_conn() -> Result<&'static DbConn, DbErr> { - match DB_CONN.get() { - Some(conn) => Ok(conn), - None => init_database().await, - } -} - -#[cfg(test)] -mod unit_test { - use super::db_conn; - - #[tokio::test] - async fn connect_test() { - assert!(db_conn().await.is_ok()); - } -} +pub mod postgresql; +pub mod redis; diff --git a/packages/backend-rs/src/database/postgresql.rs b/packages/backend-rs/src/database/postgresql.rs new file mode 100644 index 0000000000..ec0945fbe3 --- /dev/null +++ b/packages/backend-rs/src/database/postgresql.rs @@ -0,0 +1,35 @@ +use crate::config::CONFIG; +use sea_orm::{Database, DbConn, DbErr}; + +static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + +async fn init_database() -> Result<&'static DbConn, DbErr> { + let database_uri = format!( + "postgres://{}:{}@{}:{}/{}", + CONFIG.db.user, + urlencoding::encode(&CONFIG.db.pass), + CONFIG.db.host, + CONFIG.db.port, + CONFIG.db.db, + ); + let conn = Database::connect(database_uri).await?; + Ok(DB_CONN.get_or_init(move || conn)) +} + +pub async fn db_conn() -> Result<&'static DbConn, DbErr> { + match DB_CONN.get() { + Some(conn) => Ok(conn), + None => init_database().await, + } +} + +#[cfg(test)] +mod unit_test { + use super::db_conn; + + #[tokio::test] + async fn connect() { + assert!(db_conn().await.is_ok()); + assert!(db_conn().await.is_ok()); + } +} diff --git a/packages/backend-rs/src/database/redis.rs b/packages/backend-rs/src/database/redis.rs new file mode 100644 index 0000000000..f8f6c712de --- /dev/null +++ b/packages/backend-rs/src/database/redis.rs @@ -0,0 +1,68 @@ +use crate::config::CONFIG; +use redis::{Client, Connection, RedisError}; + +static REDIS_CLIENT: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + +fn init_redis() -> Result { + let redis_url = { + let mut params = vec!["redis://".to_owned()]; + + let redis = if let Some(cache_server) = &CONFIG.cache_server { + cache_server + } else { + &CONFIG.redis + }; + + if let Some(user) = &redis.user { + params.push(user.to_string()) + } + if let Some(pass) = &redis.pass { + params.push(format!(":{}@", pass)) + } + params.push(redis.host.to_string()); + params.push(format!(":{}", redis.port)); + params.push(format!("/{}", redis.db)); + + params.concat() + }; + + Client::open(redis_url) +} + +pub fn redis_conn() -> Result { + match REDIS_CLIENT.get() { + Some(client) => Ok(client.get_connection()?), + None => init_redis()?.get_connection(), + } +} + +#[inline] +/// prefix redis key +pub fn key(key: impl ToString) -> String { + format!("{}:{}", CONFIG.redis_key_prefix, key.to_string()) +} + +#[cfg(test)] +mod unit_test { + use super::redis_conn; + use pretty_assertions::assert_eq; + use redis::Commands; + + #[test] + fn connect() { + assert!(redis_conn().is_ok()); + assert!(redis_conn().is_ok()); + } + + #[test] + fn access() { + let mut redis = redis_conn().unwrap(); + + let key = "CARGO_UNIT_TEST_KEY"; + let value = "CARGO_UNIT_TEST_VALUE"; + + assert_eq!(redis.set::<&str, &str, String>(key, value).unwrap(), "OK"); + assert_eq!(redis.get::<&str, String>(key).unwrap(), value); + assert_eq!(redis.del::<&str, u32>(key).unwrap(), 1); + } +} diff --git a/packages/backend-rs/src/lib.rs b/packages/backend-rs/src/lib.rs index bef7a41808..0dcc4e6251 100644 --- a/packages/backend-rs/src/lib.rs +++ b/packages/backend-rs/src/lib.rs @@ -4,4 +4,5 @@ pub mod config; pub mod database; pub mod misc; pub mod model; +pub mod service; pub mod util; diff --git a/packages/backend-rs/src/misc/convert_host.rs b/packages/backend-rs/src/misc/convert_host.rs index 34a0792c62..8f054488de 100644 --- a/packages/backend-rs/src/misc/convert_host.rs +++ b/packages/backend-rs/src/misc/convert_host.rs @@ -1,4 +1,4 @@ -use crate::config::server::SERVER_CONFIG; +use crate::config::CONFIG; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -14,21 +14,21 @@ pub enum Error { pub fn get_full_ap_account(username: &str, host: Option<&str>) -> Result { Ok(match host { Some(host) => format!("{}@{}", username, to_puny(host)?), - None => format!("{}@{}", username, extract_host(&SERVER_CONFIG.url)?), + None => format!("{}@{}", username, extract_host(&CONFIG.url)?), }) } #[crate::export] pub fn is_self_host(host: Option<&str>) -> Result { Ok(match host { - Some(host) => extract_host(&SERVER_CONFIG.url)? == to_puny(host)?, + Some(host) => extract_host(&CONFIG.url)? == to_puny(host)?, None => true, }) } #[crate::export] pub fn is_same_origin(uri: &str) -> Result { - Ok(url::Url::parse(uri)?.origin().ascii_serialization() == SERVER_CONFIG.url) + Ok(url::Url::parse(uri)?.origin().ascii_serialization() == CONFIG.url) } #[crate::export] diff --git a/packages/backend-rs/src/model/entity/abuse_user_report.rs b/packages/backend-rs/src/model/entity/abuse_user_report.rs index 4d781f06dd..e12b2f4d31 100644 --- a/packages/backend-rs/src/model/entity/abuse_user_report.rs +++ b/packages/backend-rs/src/model/entity/abuse_user_report.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "abuse_user_report")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/access_token.rs b/packages/backend-rs/src/model/entity/access_token.rs index 3083bb8c90..8b79877b8b 100644 --- a/packages/backend-rs/src/model/entity/access_token.rs +++ b/packages/backend-rs/src/model/entity/access_token.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "access_token")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/ad.rs b/packages/backend-rs/src/model/entity/ad.rs index 98ec50ea91..8a7b9abb86 100644 --- a/packages/backend-rs/src/model/entity/ad.rs +++ b/packages/backend-rs/src/model/entity/ad.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "ad")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement.rs b/packages/backend-rs/src/model/entity/announcement.rs index 311571c113..4532614a24 100644 --- a/packages/backend-rs/src/model/entity/announcement.rs +++ b/packages/backend-rs/src/model/entity/announcement.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "announcement")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/announcement_read.rs b/packages/backend-rs/src/model/entity/announcement_read.rs index 157e402aa6..de54dae082 100644 --- a/packages/backend-rs/src/model/entity/announcement_read.rs +++ b/packages/backend-rs/src/model/entity/announcement_read.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "announcement_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/antenna.rs b/packages/backend-rs/src/model/entity/antenna.rs index 1edd6e8761..4074f5f106 100644 --- a/packages/backend-rs/src/model/entity/antenna.rs +++ b/packages/backend-rs/src/model/entity/antenna.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::AntennaSrcEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "antenna")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/antenna_note.rs b/packages/backend-rs/src/model/entity/antenna_note.rs deleted file mode 100644 index c86fb349d4..0000000000 --- a/packages/backend-rs/src/model/entity/antenna_note.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] -#[sea_orm(table_name = "antenna_note")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - #[sea_orm(column_name = "noteId")] - pub note_id: String, - #[sea_orm(column_name = "antennaId")] - pub antenna_id: String, - pub read: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::antenna::Entity", - from = "Column::AntennaId", - to = "super::antenna::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Antenna, - #[sea_orm( - belongs_to = "super::note::Entity", - from = "Column::NoteId", - to = "super::note::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Note, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Antenna.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Note.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend-rs/src/model/entity/app.rs b/packages/backend-rs/src/model/entity/app.rs index d9517ed211..8d2aa5373a 100644 --- a/packages/backend-rs/src/model/entity/app.rs +++ b/packages/backend-rs/src/model/entity/app.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "app")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/attestation_challenge.rs b/packages/backend-rs/src/model/entity/attestation_challenge.rs index 0c131066dd..999952943d 100644 --- a/packages/backend-rs/src/model/entity/attestation_challenge.rs +++ b/packages/backend-rs/src/model/entity/attestation_challenge.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "attestation_challenge")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/auth_session.rs b/packages/backend-rs/src/model/entity/auth_session.rs index f022a5e632..fac397308d 100644 --- a/packages/backend-rs/src/model/entity/auth_session.rs +++ b/packages/backend-rs/src/model/entity/auth_session.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "auth_session")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/blocking.rs b/packages/backend-rs/src/model/entity/blocking.rs index 2f5a3e0482..d7773108ab 100644 --- a/packages/backend-rs/src/model/entity/blocking.rs +++ b/packages/backend-rs/src/model/entity/blocking.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "blocking")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel.rs b/packages/backend-rs/src/model/entity/channel.rs index 52f8059030..4f3ec777ee 100644 --- a/packages/backend-rs/src/model/entity/channel.rs +++ b/packages/backend-rs/src/model/entity/channel.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_following.rs b/packages/backend-rs/src/model/entity/channel_following.rs index 01a25ccb83..d45b2c9706 100644 --- a/packages/backend-rs/src/model/entity/channel_following.rs +++ b/packages/backend-rs/src/model/entity/channel_following.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel_following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/channel_note_pining.rs b/packages/backend-rs/src/model/entity/channel_note_pining.rs index 0a41efd3e8..9080c0181e 100644 --- a/packages/backend-rs/src/model/entity/channel_note_pining.rs +++ b/packages/backend-rs/src/model/entity/channel_note_pining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "channel_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip.rs b/packages/backend-rs/src/model/entity/clip.rs index 6cbbcf4756..05dc66fa48 100644 --- a/packages/backend-rs/src/model/entity/clip.rs +++ b/packages/backend-rs/src/model/entity/clip.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "clip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/clip_note.rs b/packages/backend-rs/src/model/entity/clip_note.rs index 262f4a9b50..a76b5d5d8a 100644 --- a/packages/backend-rs/src/model/entity/clip_note.rs +++ b/packages/backend-rs/src/model/entity/clip_note.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "clip_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_file.rs b/packages/backend-rs/src/model/entity/drive_file.rs index a6926e7af2..699fa182a5 100644 --- a/packages/backend-rs/src/model/entity/drive_file.rs +++ b/packages/backend-rs/src/model/entity/drive_file.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::DriveFileUsageHintEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "drive_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/drive_folder.rs b/packages/backend-rs/src/model/entity/drive_folder.rs index 727a698ce3..e4f6fccb6f 100644 --- a/packages/backend-rs/src/model/entity/drive_folder.rs +++ b/packages/backend-rs/src/model/entity/drive_folder.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "drive_folder")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/emoji.rs b/packages/backend-rs/src/model/entity/emoji.rs index 530dfe12f5..374781c4d2 100644 --- a/packages/backend-rs/src/model/entity/emoji.rs +++ b/packages/backend-rs/src/model/entity/emoji.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "emoji")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/follow_request.rs b/packages/backend-rs/src/model/entity/follow_request.rs index 4a6b572433..332eeed204 100644 --- a/packages/backend-rs/src/model/entity/follow_request.rs +++ b/packages/backend-rs/src/model/entity/follow_request.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "follow_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/following.rs b/packages/backend-rs/src/model/entity/following.rs index f19e46140e..6f3255ecc9 100644 --- a/packages/backend-rs/src/model/entity/following.rs +++ b/packages/backend-rs/src/model/entity/following.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "following")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_like.rs b/packages/backend-rs/src/model/entity/gallery_like.rs index f4ede4169a..db519bc91b 100644 --- a/packages/backend-rs/src/model/entity/gallery_like.rs +++ b/packages/backend-rs/src/model/entity/gallery_like.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "gallery_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/gallery_post.rs b/packages/backend-rs/src/model/entity/gallery_post.rs index 797bf38242..5492417911 100644 --- a/packages/backend-rs/src/model/entity/gallery_post.rs +++ b/packages/backend-rs/src/model/entity/gallery_post.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "gallery_post")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/hashtag.rs b/packages/backend-rs/src/model/entity/hashtag.rs index e2bb816b26..56b9314e08 100644 --- a/packages/backend-rs/src/model/entity/hashtag.rs +++ b/packages/backend-rs/src/model/entity/hashtag.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "hashtag")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/instance.rs b/packages/backend-rs/src/model/entity/instance.rs index 8b598f72b1..839c6206df 100644 --- a/packages/backend-rs/src/model/entity/instance.rs +++ b/packages/backend-rs/src/model/entity/instance.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "instance")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/messaging_message.rs b/packages/backend-rs/src/model/entity/messaging_message.rs index 304f876d1a..b5f5d818a0 100644 --- a/packages/backend-rs/src/model/entity/messaging_message.rs +++ b/packages/backend-rs/src/model/entity/messaging_message.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "messaging_message")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs index fcba9e0be9..3bf205d040 100644 --- a/packages/backend-rs/src/model/entity/meta.rs +++ b/packages/backend-rs/src/model/entity/meta.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "meta")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/migrations.rs b/packages/backend-rs/src/model/entity/migrations.rs index 235156ba4e..f0d55ba123 100644 --- a/packages/backend-rs/src/model/entity/migrations.rs +++ b/packages/backend-rs/src/model/entity/migrations.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "migrations")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/moderation_log.rs b/packages/backend-rs/src/model/entity/moderation_log.rs index b76f2c33df..e51ac4cc0d 100644 --- a/packages/backend-rs/src/model/entity/moderation_log.rs +++ b/packages/backend-rs/src/model/entity/moderation_log.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "moderation_log")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muted_note.rs b/packages/backend-rs/src/model/entity/muted_note.rs index 7c2880a03d..b1345565b7 100644 --- a/packages/backend-rs/src/model/entity/muted_note.rs +++ b/packages/backend-rs/src/model/entity/muted_note.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::MutedNoteReasonEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "muted_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/muting.rs b/packages/backend-rs/src/model/entity/muting.rs index 917e6a2e20..b9850b3a42 100644 --- a/packages/backend-rs/src/model/entity/muting.rs +++ b/packages/backend-rs/src/model/entity/muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note.rs b/packages/backend-rs/src/model/entity/note.rs index 5903216c1a..85947ea35d 100644 --- a/packages/backend-rs/src/model/entity/note.rs +++ b/packages/backend-rs/src/model/entity/note.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::NoteVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_edit.rs b/packages/backend-rs/src/model/entity/note_edit.rs index edfb35029a..0fb10b82a8 100644 --- a/packages/backend-rs/src/model/entity/note_edit.rs +++ b/packages/backend-rs/src/model/entity/note_edit.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_edit")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_favorite.rs b/packages/backend-rs/src/model/entity/note_favorite.rs index 76d45e9e98..12e5c641b1 100644 --- a/packages/backend-rs/src/model/entity/note_favorite.rs +++ b/packages/backend-rs/src/model/entity/note_favorite.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_favorite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_file.rs b/packages/backend-rs/src/model/entity/note_file.rs index 2c52a4e5e8..9d13c7506d 100644 --- a/packages/backend-rs/src/model/entity/note_file.rs +++ b/packages/backend-rs/src/model/entity/note_file.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_file")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_reaction.rs b/packages/backend-rs/src/model/entity/note_reaction.rs index dd870a3e7f..9d5de3fab4 100644 --- a/packages/backend-rs/src/model/entity/note_reaction.rs +++ b/packages/backend-rs/src/model/entity/note_reaction.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_reaction")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_thread_muting.rs b/packages/backend-rs/src/model/entity/note_thread_muting.rs index 965001189e..fbbb30e948 100644 --- a/packages/backend-rs/src/model/entity/note_thread_muting.rs +++ b/packages/backend-rs/src/model/entity/note_thread_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_thread_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_unread.rs b/packages/backend-rs/src/model/entity/note_unread.rs index ba96aed69f..2b74e3a63c 100644 --- a/packages/backend-rs/src/model/entity/note_unread.rs +++ b/packages/backend-rs/src/model/entity/note_unread.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_unread")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/note_watching.rs b/packages/backend-rs/src/model/entity/note_watching.rs index 5b3b331e90..817431daaa 100644 --- a/packages/backend-rs/src/model/entity/note_watching.rs +++ b/packages/backend-rs/src/model/entity/note_watching.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "note_watching")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/notification.rs b/packages/backend-rs/src/model/entity/notification.rs index 6ed5f718aa..e2273017e5 100644 --- a/packages/backend-rs/src/model/entity/notification.rs +++ b/packages/backend-rs/src/model/entity/notification.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::NotificationTypeEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "notification")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page.rs b/packages/backend-rs/src/model/entity/page.rs index e1652a372b..a88b53459d 100644 --- a/packages/backend-rs/src/model/entity/page.rs +++ b/packages/backend-rs/src/model/entity/page.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::PageVisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "page")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/page_like.rs b/packages/backend-rs/src/model/entity/page_like.rs index c1e59ef0e1..7f7caabde5 100644 --- a/packages/backend-rs/src/model/entity/page_like.rs +++ b/packages/backend-rs/src/model/entity/page_like.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "page_like")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/password_reset_request.rs b/packages/backend-rs/src/model/entity/password_reset_request.rs index 058eaedebe..de78019087 100644 --- a/packages/backend-rs/src/model/entity/password_reset_request.rs +++ b/packages/backend-rs/src/model/entity/password_reset_request.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "password_reset_request")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll.rs b/packages/backend-rs/src/model/entity/poll.rs index 6bcbcac08b..2e65674b15 100644 --- a/packages/backend-rs/src/model/entity/poll.rs +++ b/packages/backend-rs/src/model/entity/poll.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::PollNotevisibilityEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "poll")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/poll_vote.rs b/packages/backend-rs/src/model/entity/poll_vote.rs index 0f2df2f5db..47e68084cc 100644 --- a/packages/backend-rs/src/model/entity/poll_vote.rs +++ b/packages/backend-rs/src/model/entity/poll_vote.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "poll_vote")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_note.rs b/packages/backend-rs/src/model/entity/promo_note.rs index c4e012b1a9..8b13b8987b 100644 --- a/packages/backend-rs/src/model/entity/promo_note.rs +++ b/packages/backend-rs/src/model/entity/promo_note.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "promo_note")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/promo_read.rs b/packages/backend-rs/src/model/entity/promo_read.rs index 10fe176405..3e6d822d29 100644 --- a/packages/backend-rs/src/model/entity/promo_read.rs +++ b/packages/backend-rs/src/model/entity/promo_read.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "promo_read")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registration_ticket.rs b/packages/backend-rs/src/model/entity/registration_ticket.rs index 55d60d78b0..ab735b2422 100644 --- a/packages/backend-rs/src/model/entity/registration_ticket.rs +++ b/packages/backend-rs/src/model/entity/registration_ticket.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "registration_ticket")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/registry_item.rs b/packages/backend-rs/src/model/entity/registry_item.rs index 74ae18cef3..cb129128b7 100644 --- a/packages/backend-rs/src/model/entity/registry_item.rs +++ b/packages/backend-rs/src/model/entity/registry_item.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "registry_item")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/relay.rs b/packages/backend-rs/src/model/entity/relay.rs index c035a74bec..f2eeb571f4 100644 --- a/packages/backend-rs/src/model/entity/relay.rs +++ b/packages/backend-rs/src/model/entity/relay.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::RelayStatusEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "relay")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/renote_muting.rs b/packages/backend-rs/src/model/entity/renote_muting.rs index b6604cad88..308e4c1563 100644 --- a/packages/backend-rs/src/model/entity/renote_muting.rs +++ b/packages/backend-rs/src/model/entity/renote_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "renote_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/reply_muting.rs b/packages/backend-rs/src/model/entity/reply_muting.rs index 84fe0cbbfa..77891d1ee2 100644 --- a/packages/backend-rs/src/model/entity/reply_muting.rs +++ b/packages/backend-rs/src/model/entity/reply_muting.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "reply_muting")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs index 36281f4dc5..a9c974b9c4 100644 --- a/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs +++ b/packages/backend-rs/src/model/entity/sea_orm_active_enums.rs @@ -2,7 +2,10 @@ use sea_orm::entity::prelude::*; -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "antenna_src_enum")] @@ -20,7 +23,10 @@ pub enum AntennaSrcEnum { #[sea_orm(string_value = "users")] Users, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -34,7 +40,10 @@ pub enum DriveFileUsageHintEnum { #[sea_orm(string_value = "userBanner")] UserBanner, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -52,7 +61,10 @@ pub enum MutedNoteReasonEnum { #[sea_orm(string_value = "word")] Word, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -72,7 +84,10 @@ pub enum NoteVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -106,7 +121,10 @@ pub enum NotificationTypeEnum { #[sea_orm(string_value = "reply")] Reply, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -122,7 +140,10 @@ pub enum PageVisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -140,7 +161,10 @@ pub enum PollNotevisibilityEnum { #[sea_orm(string_value = "specified")] Specified, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status_enum")] @@ -152,7 +176,10 @@ pub enum RelayStatusEnum { #[sea_orm(string_value = "requesting")] Requesting, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -170,7 +197,10 @@ pub enum UserEmojimodpermEnum { #[sea_orm(string_value = "unauthorized")] Unauthorized, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( @@ -186,7 +216,10 @@ pub enum UserProfileFfvisibilityEnum { #[sea_orm(string_value = "public")] Public, } -#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[derive( + Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize, +)] +#[serde(rename_all = "camelCase")] #[cfg_attr(not(feature = "napi"), derive(Clone))] #[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))] #[sea_orm( diff --git a/packages/backend-rs/src/model/entity/signin.rs b/packages/backend-rs/src/model/entity/signin.rs index 491f079a82..d5584f9d84 100644 --- a/packages/backend-rs/src/model/entity/signin.rs +++ b/packages/backend-rs/src/model/entity/signin.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "signin")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/sw_subscription.rs b/packages/backend-rs/src/model/entity/sw_subscription.rs index 4aa275f77b..fe694177f3 100644 --- a/packages/backend-rs/src/model/entity/sw_subscription.rs +++ b/packages/backend-rs/src/model/entity/sw_subscription.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "sw_subscription")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/used_username.rs b/packages/backend-rs/src/model/entity/used_username.rs index 9e108a8a4f..8557955034 100644 --- a/packages/backend-rs/src/model/entity/used_username.rs +++ b/packages/backend-rs/src/model/entity/used_username.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "used_username")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user.rs b/packages/backend-rs/src/model/entity/user.rs index 8af0b27e88..f8a2b09324 100644 --- a/packages/backend-rs/src/model/entity/user.rs +++ b/packages/backend-rs/src/model/entity/user.rs @@ -3,7 +3,8 @@ use super::sea_orm_active_enums::UserEmojimodpermEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group.rs b/packages/backend-rs/src/model/entity/user_group.rs index 7d9ae71b24..387c50d422 100644 --- a/packages/backend-rs/src/model/entity/user_group.rs +++ b/packages/backend-rs/src/model/entity/user_group.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invitation.rs b/packages/backend-rs/src/model/entity/user_group_invitation.rs index c449a48078..289acf89df 100644 --- a/packages/backend-rs/src/model/entity/user_group_invitation.rs +++ b/packages/backend-rs/src/model/entity/user_group_invitation.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_invitation")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_invite.rs b/packages/backend-rs/src/model/entity/user_group_invite.rs index 3df43af3f6..62fcf0c524 100644 --- a/packages/backend-rs/src/model/entity/user_group_invite.rs +++ b/packages/backend-rs/src/model/entity/user_group_invite.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_invite")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_group_joining.rs b/packages/backend-rs/src/model/entity/user_group_joining.rs index 2ff31b3a5f..b29bdd11eb 100644 --- a/packages/backend-rs/src/model/entity/user_group_joining.rs +++ b/packages/backend-rs/src/model/entity/user_group_joining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_group_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_ip.rs b/packages/backend-rs/src/model/entity/user_ip.rs index d6eadc7f71..9847fb8d65 100644 --- a/packages/backend-rs/src/model/entity/user_ip.rs +++ b/packages/backend-rs/src/model/entity/user_ip.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_ip")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_keypair.rs b/packages/backend-rs/src/model/entity/user_keypair.rs index d59853158a..dad29ab3b3 100644 --- a/packages/backend-rs/src/model/entity/user_keypair.rs +++ b/packages/backend-rs/src/model/entity/user_keypair.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_keypair")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list.rs b/packages/backend-rs/src/model/entity/user_list.rs index 356ec5318c..30dc6db715 100644 --- a/packages/backend-rs/src/model/entity/user_list.rs +++ b/packages/backend-rs/src/model/entity/user_list.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_list")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_list_joining.rs b/packages/backend-rs/src/model/entity/user_list_joining.rs index 037d7af181..972cc34bb6 100644 --- a/packages/backend-rs/src/model/entity/user_list_joining.rs +++ b/packages/backend-rs/src/model/entity/user_list_joining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_list_joining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_note_pining.rs b/packages/backend-rs/src/model/entity/user_note_pining.rs index f0a80a66c9..26f05274fd 100644 --- a/packages/backend-rs/src/model/entity/user_note_pining.rs +++ b/packages/backend-rs/src/model/entity/user_note_pining.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_note_pining")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_pending.rs b/packages/backend-rs/src/model/entity/user_pending.rs index 1fa13c2829..43a5c2f1e2 100644 --- a/packages/backend-rs/src/model/entity/user_pending.rs +++ b/packages/backend-rs/src/model/entity/user_pending.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_pending")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_profile.rs b/packages/backend-rs/src/model/entity/user_profile.rs index a121118926..644817aa8d 100644 --- a/packages/backend-rs/src/model/entity/user_profile.rs +++ b/packages/backend-rs/src/model/entity/user_profile.rs @@ -4,7 +4,8 @@ use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; use super::sea_orm_active_enums::UserProfileMutingnotificationtypesEnum; use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_profile")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_publickey.rs b/packages/backend-rs/src/model/entity/user_publickey.rs index ad6a456ead..f8bc8629eb 100644 --- a/packages/backend-rs/src/model/entity/user_publickey.rs +++ b/packages/backend-rs/src/model/entity/user_publickey.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_publickey")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/user_security_key.rs b/packages/backend-rs/src/model/entity/user_security_key.rs index aae6dfa8c6..a4694cf177 100644 --- a/packages/backend-rs/src/model/entity/user_security_key.rs +++ b/packages/backend-rs/src/model/entity/user_security_key.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "user_security_key")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/model/entity/webhook.rs b/packages/backend-rs/src/model/entity/webhook.rs index e7656056b9..430cf9fcc0 100644 --- a/packages/backend-rs/src/model/entity/webhook.rs +++ b/packages/backend-rs/src/model/entity/webhook.rs @@ -2,7 +2,8 @@ use sea_orm::entity::prelude::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] #[sea_orm(table_name = "webhook")] #[cfg_attr( feature = "napi", diff --git a/packages/backend-rs/src/service/add_note_to_antenna.rs b/packages/backend-rs/src/service/add_note_to_antenna.rs new file mode 100644 index 0000000000..4f294cc881 --- /dev/null +++ b/packages/backend-rs/src/service/add_note_to_antenna.rs @@ -0,0 +1,23 @@ +use crate::database::{redis_conn, redis_key}; +use crate::model::entity::note; +use crate::service::stream::{publish_to_stream, Error, Stream}; +use crate::util::id::get_timestamp; +use redis::{streams::StreamMaxlen, Commands}; + +type Note = note::Model; + +#[crate::export] +pub fn add_note_to_antenna(antenna_id: String, note: &Note) -> Result<(), Error> { + redis_conn()?.xadd_maxlen( + redis_key(format!("antennaTimeline:{}", antenna_id)), + StreamMaxlen::Approx(200), + format!("{}-*", get_timestamp(¬e.id)), + &[("note", ¬e.id)], + )?; + + publish_to_stream( + &Stream::Antenna { antenna_id }, + Some("note"), + Some(serde_json::to_string(note)?), + ) +} diff --git a/packages/backend-rs/src/service/mod.rs b/packages/backend-rs/src/service/mod.rs new file mode 100644 index 0000000000..cc239e3f9e --- /dev/null +++ b/packages/backend-rs/src/service/mod.rs @@ -0,0 +1,2 @@ +pub mod add_note_to_antenna; +pub mod stream; diff --git a/packages/backend-rs/src/service/stream.rs b/packages/backend-rs/src/service/stream.rs new file mode 100644 index 0000000000..6c5e6be4dd --- /dev/null +++ b/packages/backend-rs/src/service/stream.rs @@ -0,0 +1,93 @@ +use crate::config::CONFIG; +use crate::database::redis_conn; +use redis::{Commands, RedisError}; + +#[derive(strum::Display)] +pub enum Stream { + #[strum(serialize = "internal")] + Internal, + #[strum(serialize = "broadcast")] + Broadcast, + #[strum(to_string = "adminStream:{user_id}")] + Admin { user_id: String }, + #[strum(to_string = "user:{user_id}")] + User { user_id: String }, + #[strum(to_string = "channelStream:{channel_id}")] + Channel { channel_id: String }, + #[strum(to_string = "noteStream:{note_id}")] + Note { note_id: String }, + #[strum(serialize = "notesStream")] + Notes, + #[strum(to_string = "userListStream:{list_id}")] + UserList { list_id: String }, + #[strum(to_string = "mainStream:{user_id}")] + Main { user_id: String }, + #[strum(to_string = "driveStream:{user_id}")] + Drive { user_id: String }, + #[strum(to_string = "antennaStream:{antenna_id}")] + Antenna { antenna_id: String }, + #[strum(to_string = "messagingStream:{sender_user_id}-{receiver_user_id}")] + Chat { + sender_user_id: String, + receiver_user_id: String, + }, + #[strum(to_string = "messagingStream:{group_id}")] + GroupChat { group_id: String }, + #[strum(to_string = "messagingIndexStream:{user_id}")] + MessagingIndex { user_id: String }, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Redis error: {0}")] + RedisError(#[from] RedisError), + #[error("Json (de)serialization error: {0}")] + JsonError(#[from] serde_json::Error), + #[error("Value error: {0}")] + ValueError(String), +} + +pub fn publish_to_stream( + stream: &Stream, + kind: Option<&str>, + value: Option, +) -> Result<(), Error> { + let message = if let Some(kind) = kind { + format!( + "{{ \"type\": \"{}\", \"body\": {} }}", + kind, + value.unwrap_or("null".to_string()), + ) + } else { + value.ok_or(Error::ValueError("Invalid streaming message".to_string()))? + }; + + redis_conn()?.publish( + &CONFIG.host, + format!( + "{{ \"channel\": \"{}\", \"message\": {} }}", + stream, message, + ), + )?; + + Ok(()) +} + +#[cfg(test)] +mod unit_test { + use super::Stream; + use pretty_assertions::assert_eq; + + #[test] + fn channel_to_string() { + assert_eq!(Stream::Internal.to_string(), "internal"); + assert_eq!(Stream::Broadcast.to_string(), "broadcast"); + assert_eq!( + Stream::Admin { + user_id: "9tb42br63g5apjcq".to_string() + } + .to_string(), + "adminStream:9tb42br63g5apjcq" + ); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 9289c2f7ea..0599a39d4b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -178,6 +178,7 @@ "ts-loader": "9.5.1", "ts-node": "10.9.2", "tsconfig-paths": "4.2.0", + "type-fest": "4.15.0", "typescript": "5.4.5", "webpack": "^5.91.0", "ws": "8.16.0" diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts index 9854d2dce4..3e542a6e36 100644 --- a/packages/backend/src/boot/index.ts +++ b/packages/backend/src/boot/index.ts @@ -3,7 +3,7 @@ import chalk from "chalk"; import Xev from "xev"; import Logger from "@/services/logger.js"; -import { envOption } from "@/config/index.js"; +import { envOption } from "@/config.js"; import { inspect } from "node:util"; // for typeorm diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 3ba2d0cf50..090a84f6ea 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -8,9 +8,8 @@ import chalkTemplate from "chalk-template"; import semver from "semver"; import Logger from "@/services/logger.js"; -import loadConfig from "@/config/load.js"; -import type { Config } from "@/config/types.js"; -import { envOption } from "@/config/index.js"; +import type { Config } from "backend-rs"; +import { config, envOption } from "@/config.js"; import { showMachineInfo } from "@/misc/show-machine-info.js"; import { db, initDb } from "@/db/postgre.js"; import { inspect } from "node:util"; @@ -87,15 +86,12 @@ function greet() { * Init master process */ export async function masterMain() { - let config!: Config; - // initialize app try { greet(); showEnvironment(); await showMachineInfo(bootLogger); showNodejsVersion(); - config = loadConfigBoot(); await connectDb(); } catch (e) { bootLogger.error( @@ -154,28 +150,6 @@ function showNodejsVersion(): void { } } -function loadConfigBoot(): Config { - const configLogger = bootLogger.createSubLogger("config"); - let config; - - try { - config = loadConfig(); - } catch (exception) { - if (exception.code === "ENOENT") { - configLogger.error("Configuration file not found", null, true); - process.exit(1); - } else if (e instanceof Error) { - configLogger.error(e.message); - process.exit(1); - } - throw exception; - } - - configLogger.succ("Loaded"); - - return config; -} - async function connectDb(): Promise { const dbLogger = bootLogger.createSubLogger("db"); @@ -195,23 +169,31 @@ async function connectDb(): Promise { } async function spawnWorkers( - clusterLimits: Required, + clusterLimits: Config["clusterLimits"], ): Promise { - const modes = ["web", "queue"]; const cpus = os.cpus().length; - for (const mode of modes.filter((mode) => clusterLimits[mode] > cpus)) { + + if (clusterLimits.queue > cpus) { bootLogger.warn( - `configuration warning: cluster limit for ${mode} exceeds number of cores (${cpus})`, + "config: queue cluster limit exceeds the number of cpu cores", ); } - const total = modes.reduce((acc, mode) => acc + clusterLimits[mode], 0); + if (clusterLimits.web > cpus) { + bootLogger.warn( + "config: web cluster limit exceeds the number of cpu cores", + ); + } + + const total = clusterLimits.queue + clusterLimits.web; + + // workers = ["web", "web", ..., "web", "queue", "queue", ..., "queue"] const workers = new Array(total); - workers.fill("web", 0, clusterLimits?.web); - workers.fill("queue", clusterLimits?.web); + workers.fill("web", 0, clusterLimits.web); + workers.fill("queue", clusterLimits.web); bootLogger.info( - `Starting ${clusterLimits?.web} web workers and ${clusterLimits?.queue} queue workers (total ${total})...`, + `Starting ${clusterLimits.web} web workers and ${clusterLimits.queue} queue workers (total ${total})...`, ); await Promise.all(workers.map((mode) => spawnWorker(mode))); bootLogger.succ("All workers started"); diff --git a/packages/backend/src/boot/worker.ts b/packages/backend/src/boot/worker.ts index 647ea40fbd..cae861230f 100644 --- a/packages/backend/src/boot/worker.ts +++ b/packages/backend/src/boot/worker.ts @@ -1,5 +1,5 @@ import cluster from "node:cluster"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { initDb } from "@/db/postgre.js"; import { initIdGenerator } from "backend-rs"; import os from "node:os"; diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts new file mode 100644 index 0000000000..c91294b611 --- /dev/null +++ b/packages/backend/src/config.ts @@ -0,0 +1,4 @@ +import { loadConfig, loadEnv } from "backend-rs"; + +export const config = loadConfig(); +export const envOption = loadEnv(); diff --git a/packages/backend/src/config/index.ts b/packages/backend/src/config/index.ts deleted file mode 100644 index fe87e5026a..0000000000 --- a/packages/backend/src/config/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import load from "./load.js"; -import { readEnvironmentConfig } from "backend-rs"; - -export default load(); -export const envOption = readEnvironmentConfig(); diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts deleted file mode 100644 index 682bf309d2..0000000000 --- a/packages/backend/src/config/load.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Config loader - */ - -import * as fs from "node:fs"; -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; -import type { Mixin } from "./types.js"; -import { readServerConfig } from "backend-rs"; - -const _filename = fileURLToPath(import.meta.url); -const _dirname = dirname(_filename); - -/** - * Path of configuration directory - */ -const dir = `${_dirname}/../../../../.config`; - -/** - * Path of configuration file - */ -const path = - process.env.NODE_ENV === "test" ? `${dir}/test.yml` : `${dir}/default.yml`; - -export default function load() { - const meta = JSON.parse( - fs.readFileSync(`${_dirname}/../../../../built/meta.json`, "utf-8"), - ); - const clientManifest = JSON.parse( - fs.readFileSync( - `${_dirname}/../../../../built/_client_dist_/manifest.json`, - "utf-8", - ), - ); - const config = readServerConfig(); - - const mixin = {} as Mixin; - - const url = tryCreateUrl(config.url); - - config.url = url.origin; - - config.port = config.port || parseInt(process.env.PORT || "", 10); - config.bind = config.bind || process.env.BIND; - - mixin.version = meta.version; - mixin.host = url.host; - mixin.hostname = url.hostname; - mixin.scheme = url.protocol.replace(/:$/, ""); - mixin.wsScheme = mixin.scheme.replace("http", "ws"); - mixin.wsUrl = `${mixin.wsScheme}://${mixin.host}`; - mixin.apiUrl = `${mixin.scheme}://${mixin.host}/api`; - mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`; - mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`; - mixin.userAgent = `Firefish/${meta.version} (${config.url})`; - mixin.clientEntry = clientManifest["src/init.ts"]; - - if (config.proxyRemoteFiles == null) config.proxyRemoteFiles = true; - if (!config.redis.prefix) config.redis.prefix = mixin.hostname; - if (config.cacheServer && !config.cacheServer.prefix) - config.cacheServer.prefix = mixin.hostname; - - if (!config.clusterLimits) { - config.clusterLimits = { - web: 1, - queue: 1, - }; - } else { - config.clusterLimits = { - web: 1, - queue: 1, - ...config.clusterLimits, - }; - - if (config.clusterLimits.web! < 1 || config.clusterLimits.queue! < 1) { - throw new Error("Invalid cluster limits"); - } - } - - return Object.assign(config, mixin); -} - -function tryCreateUrl(url: string) { - try { - return new URL(url); - } catch (e) { - throw new Error(`url="${url}" is not a valid URL.`); - } -} diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts deleted file mode 100644 index 6b593d3b2d..0000000000 --- a/packages/backend/src/config/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { ServerConfig } from "backend-rs"; - -/** - * Firefish が自動的に(ユーザーが設定した情報から推論して)設定する情報 - */ -export type Mixin = { - version: string; - host: string; - hostname: string; - scheme: string; - wsScheme: string; - apiUrl: string; - wsUrl: string; - authUrl: string; - driveUrl: string; - userAgent: string; - clientEntry: string; -}; - -export type Config = ServerConfig & Mixin; diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 39ff99fda7..2c52e2b009 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH, DB_MAX_NOTE_TEXT_LENGTH, diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index 6baccaa271..1295136054 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -5,7 +5,7 @@ pg.types.setTypeParser(20, Number); import type { Logger } from "typeorm"; import { DataSource } from "typeorm"; import * as highlight from "cli-highlight"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { User } from "@/models/entities/user.js"; import { DriveFile } from "@/models/entities/drive-file.js"; @@ -77,7 +77,6 @@ import { NoteFile } from "@/models/entities/note-file.js"; import { entities as charts } from "@/services/chart/entities.js"; import { dbLogger } from "./logger.js"; -import { redisClient } from "./redis.js"; const sqlLogger = dbLogger.createSubLogger("sql", "gray", false); diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index 215effd8ea..72c23d84e2 100644 --- a/packages/backend/src/db/redis.ts +++ b/packages/backend/src/db/redis.ts @@ -1,5 +1,5 @@ import Redis from "ioredis"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export function createConnection() { let source = config.redis; @@ -12,7 +12,7 @@ export function createConnection() { family: source.family ?? 0, password: source.pass, username: source.user ?? "default", - keyPrefix: `${source.prefix}:`, + keyPrefix: `${config.redisKeyPrefix}:`, db: source.db || 0, tls: source.tls, }); diff --git a/packages/backend/src/mfm/to-html.ts b/packages/backend/src/mfm/to-html.ts index 7b7c0967a1..64aa9d7164 100644 --- a/packages/backend/src/mfm/to-html.ts +++ b/packages/backend/src/mfm/to-html.ts @@ -1,7 +1,7 @@ import { type HTMLElement, Window } from "happy-dom"; import type * as mfm from "mfm-js"; import katex from "katex"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { intersperse } from "@/prelude/array.js"; import type { IMentionedRemoteUsers } from "@/models/entities/note.js"; diff --git a/packages/backend/src/misc/captcha.ts b/packages/backend/src/misc/captcha.ts index c163d4d82d..d0969b0205 100644 --- a/packages/backend/src/misc/captcha.ts +++ b/packages/backend/src/misc/captcha.ts @@ -1,7 +1,7 @@ import fetch from "node-fetch"; import { URLSearchParams } from "node:url"; import { getAgentByUrl } from "@/misc/fetch.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { inspect } from "node:util"; export async function verifyRecaptcha(secret: string, response: string) { diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index 663d354ead..f516265106 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -2,8 +2,8 @@ import * as fs from "node:fs"; import * as stream from "node:stream"; import * as util from "node:util"; import got, * as Got from "got"; +import { config } from "@/config.js"; import { getAgentByHostname, StatusError } from "./fetch.js"; -import config from "@/config/index.js"; import chalk from "chalk"; import Logger from "@/services/logger.js"; import IPCIDR from "ip-cidr"; diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 2cfd6b95f7..1f8c70a196 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -4,7 +4,7 @@ import type { URL } from "node:url"; import CacheableLookup from "cacheable-lookup"; import fetch, { type RequestRedirect } from "node-fetch"; import { HttpProxyAgent, HttpsProxyAgent } from "hpagent"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { isValidUrl } from "./is-valid-url.js"; export async function getJson( diff --git a/packages/backend/src/misc/populate-emojis.ts b/packages/backend/src/misc/populate-emojis.ts index 4ca60b222f..f2656ea28a 100644 --- a/packages/backend/src/misc/populate-emojis.ts +++ b/packages/backend/src/misc/populate-emojis.ts @@ -4,7 +4,7 @@ import type { Emoji } from "@/models/entities/emoji.js"; import type { Note } from "@/models/entities/note.js"; import { Cache } from "./cache.js"; import { decodeReaction, isSelfHost, toPuny } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query } from "@/prelude/url.js"; import { redisClient } from "@/db/redis.js"; import type { NoteEdit } from "@/models/entities/note-edit.js"; diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index 18b139caff..ac0b1e5f17 100644 --- a/packages/backend/src/models/repositories/drive-file.ts +++ b/packages/backend/src/models/repositories/drive-file.ts @@ -4,7 +4,7 @@ import type { User } from "@/models/entities/user.js"; import { toPuny } from "backend-rs"; import { awaitAll } from "@/prelude/await-all.js"; import type { Packed } from "@/misc/schema.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query, appendQuery } from "@/prelude/url.js"; import { Users, DriveFolders } from "../index.js"; import { deepClone } from "@/misc/clone.js"; diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 3bc943965b..040106b410 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -2,7 +2,7 @@ import { In, Not } from "typeorm"; import Ajv from "ajv"; import type { ILocalUser, IRemoteUser } from "@/models/entities/user.js"; import { User } from "@/models/entities/user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Packed } from "@/misc/schema.js"; import type { Promiseable } from "@/prelude/await-all.js"; import { awaitAll } from "@/prelude/await-all.js"; diff --git a/packages/backend/src/models/schema/federation-instance.ts b/packages/backend/src/models/schema/federation-instance.ts index 7a8af7f51d..338e079e28 100644 --- a/packages/backend/src/models/schema/federation-instance.ts +++ b/packages/backend/src/models/schema/federation-instance.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; export const packedFederationInstanceSchema = { type: "object", diff --git a/packages/backend/src/ormconfig.ts b/packages/backend/src/ormconfig.ts index a1891e00df..293be57cae 100644 --- a/packages/backend/src/ormconfig.ts +++ b/packages/backend/src/ormconfig.ts @@ -1,6 +1,6 @@ import { DataSource } from "typeorm"; -import config from "./config/index.js"; -import { entities } from "./db/postgre.js"; +import { config } from "@/config.js"; +import { entities } from "@/db/postgre.js"; export default new DataSource({ type: "postgres", diff --git a/packages/backend/src/prelude/undefined-to-null.ts b/packages/backend/src/prelude/undefined-to-null.ts new file mode 100644 index 0000000000..013be3cf9e --- /dev/null +++ b/packages/backend/src/prelude/undefined-to-null.ts @@ -0,0 +1,76 @@ +// https://gist.github.com/tkrotoff/a6baf96eb6b61b445a9142e5555511a0 +import type { Primitive } from "type-fest"; + +type NullToUndefined = T extends null + ? undefined + : T extends Primitive | Function | Date | RegExp + ? T + : T extends Array + ? Array> + : T extends Map + ? Map> + : T extends Set + ? Set> + : T extends object + ? { [K in keyof T]: NullToUndefined } + : unknown; + +type UndefinedToNull = T extends undefined + ? null + : T extends Primitive | Function | Date | RegExp + ? T + : T extends Array + ? Array> + : T extends Map + ? Map> + : T extends Set + ? Set> + : T extends object + ? { [K in keyof T]: UndefinedToNull } + : unknown; + +function _nullToUndefined(obj: T): NullToUndefined { + if (obj === null) { + return undefined as any; + } + + if (typeof obj === "object") { + if (obj instanceof Map) { + obj.forEach((value, key) => obj.set(key, _nullToUndefined(value))); + } else { + for (const key in obj) { + obj[key] = _nullToUndefined(obj[key]) as any; + } + } + } + + return obj as any; +} + +function _undefinedToNull(obj: T): UndefinedToNull { + if (obj === undefined) { + return null as any; + } + + if (typeof obj === "object") { + if (obj instanceof Map) { + obj.forEach((value, key) => obj.set(key, _undefinedToNull(value))); + } else { + for (const key in obj) { + obj[key] = _undefinedToNull(obj[key]) as any; + } + } + } + + return obj as any; +} + +/** + * Recursively converts all undefined values to null. + * + * @param obj object to convert + * @returns a copy of the object with all its undefined values converted to null + */ +export function undefinedToNull(obj: T) { + return _undefinedToNull(structuredClone(obj)); +} diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index e4e413be52..6272a5e668 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -1,11 +1,10 @@ import type httpSignature from "@peertube/http-signature"; import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import type { DriveFile } from "@/models/entities/drive-file.js"; import type { IActivity } from "@/remote/activitypub/type.js"; import type { Webhook, webhookEventTypes } from "@/models/entities/webhook.js"; -import { envOption } from "@/config/index.js"; import processDeliver from "./processors/deliver.js"; import processInbox from "./processors/inbox.js"; @@ -24,10 +23,9 @@ import { objectStorageQueue, endedPollNotificationQueue, webhookDeliverQueue, - backgroundQueue, } from "./queues.js"; import type { ThinUser } from "./types.js"; -import { Note } from "@/models/entities/note.js"; +import type { Note } from "@/models/entities/note.js"; function renderError(e: Error): any { return { diff --git a/packages/backend/src/queue/initialize.ts b/packages/backend/src/queue/initialize.ts index a874005fbd..32cc0005e9 100644 --- a/packages/backend/src/queue/initialize.ts +++ b/packages/backend/src/queue/initialize.ts @@ -1,5 +1,5 @@ import Bull from "bull"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export function initialize(name: string, limitPerSec = -1) { return new Bull(name, { diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index a1ca3a91c5..157751c1aa 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -9,7 +9,7 @@ import { format as dateFormat } from "date-fns"; import { Users, Emojis } from "@/models/index.js"; import { createTemp, createTempDir } from "@/misc/create-temp.js"; import { downloadUrl } from "@/misc/download-url.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { IsNull } from "typeorm"; import { inspect } from "node:util"; diff --git a/packages/backend/src/queue/processors/webhook-deliver.ts b/packages/backend/src/queue/processors/webhook-deliver.ts index 12c9a05498..63a16c373b 100644 --- a/packages/backend/src/queue/processors/webhook-deliver.ts +++ b/packages/backend/src/queue/processors/webhook-deliver.ts @@ -3,7 +3,7 @@ import Logger from "@/services/logger.js"; import type { WebhookDeliverJobData } from "../types.js"; import { getResponse, StatusError } from "@/misc/fetch.js"; import { Webhooks } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const logger = new Logger("webhook"); diff --git a/packages/backend/src/queue/queues.ts b/packages/backend/src/queue/queues.ts index 6b0eb2de42..06b9567e74 100644 --- a/packages/backend/src/queue/queues.ts +++ b/packages/backend/src/queue/queues.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { initialize as initializeQueue } from "./initialize.js"; import type { DeliverJobData, diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts index 12ea63a931..04d989064f 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -1,6 +1,6 @@ import { URL } from "url"; import httpSignature, { IParsedSignature } from "@peertube/http-signature"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { toPuny } from "backend-rs"; import DbResolver from "@/remote/activitypub/db-resolver.js"; diff --git a/packages/backend/src/remote/activitypub/db-resolver.ts b/packages/backend/src/remote/activitypub/db-resolver.ts index a753606a14..088a2db9da 100644 --- a/packages/backend/src/remote/activitypub/db-resolver.ts +++ b/packages/backend/src/remote/activitypub/db-resolver.ts @@ -1,5 +1,5 @@ import escapeRegexp from "escape-regexp"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; import type { CacheableRemoteUser, diff --git a/packages/backend/src/remote/activitypub/kernel/flag/index.ts b/packages/backend/src/remote/activitypub/kernel/flag/index.ts index 0f83f6b449..c556605865 100644 --- a/packages/backend/src/remote/activitypub/kernel/flag/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/flag/index.ts @@ -1,5 +1,5 @@ import type { CacheableRemoteUser } from "@/models/entities/user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { IFlag } from "../../type.js"; import { getApIds } from "../../type.js"; import { AbuseUserReports, Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/accept.ts b/packages/backend/src/remote/activitypub/renderer/accept.ts index fd145dcf97..2d27a1b29d 100644 --- a/packages/backend/src/remote/activitypub/renderer/accept.ts +++ b/packages/backend/src/remote/activitypub/renderer/accept.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"]; host: null }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/add.ts b/packages/backend/src/remote/activitypub/renderer/add.ts index d8203ac1ea..14c71694e1 100644 --- a/packages/backend/src/remote/activitypub/renderer/add.ts +++ b/packages/backend/src/remote/activitypub/renderer/add.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; export default (user: ILocalUser, target: any, object: any) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/announce.ts b/packages/backend/src/remote/activitypub/renderer/announce.ts index 1fd1842acf..0cc9bec6f4 100644 --- a/packages/backend/src/remote/activitypub/renderer/announce.ts +++ b/packages/backend/src/remote/activitypub/renderer/announce.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; export default (object: any, note: Note) => { diff --git a/packages/backend/src/remote/activitypub/renderer/block.ts b/packages/backend/src/remote/activitypub/renderer/block.ts index c2ea267f38..5169e0d550 100644 --- a/packages/backend/src/remote/activitypub/renderer/block.ts +++ b/packages/backend/src/remote/activitypub/renderer/block.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Blocking } from "@/models/entities/blocking.js"; /** diff --git a/packages/backend/src/remote/activitypub/renderer/create.ts b/packages/backend/src/remote/activitypub/renderer/create.ts index 857f5722cc..89b14b88b2 100644 --- a/packages/backend/src/remote/activitypub/renderer/create.ts +++ b/packages/backend/src/remote/activitypub/renderer/create.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; export default (object: any, note: Note) => { diff --git a/packages/backend/src/remote/activitypub/renderer/delete.ts b/packages/backend/src/remote/activitypub/renderer/delete.ts index 70bdc34922..0d2105941e 100644 --- a/packages/backend/src/remote/activitypub/renderer/delete.ts +++ b/packages/backend/src/remote/activitypub/renderer/delete.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"]; host: null }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/emoji.ts b/packages/backend/src/remote/activitypub/renderer/emoji.ts index 3d9b8cd55b..dab0e8cac7 100644 --- a/packages/backend/src/remote/activitypub/renderer/emoji.ts +++ b/packages/backend/src/remote/activitypub/renderer/emoji.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Emoji } from "@/models/entities/emoji.js"; export default (emoji: Emoji) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/flag.ts b/packages/backend/src/remote/activitypub/renderer/flag.ts index 44da33f5c2..1fa260be5e 100644 --- a/packages/backend/src/remote/activitypub/renderer/flag.ts +++ b/packages/backend/src/remote/activitypub/renderer/flag.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; // to anonymise reporters, the reporting actor must be a system user diff --git a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts index ad7f05bf84..b62d9c4011 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Relay } from "@/models/entities/relay.js"; import type { ILocalUser } from "@/models/entities/user.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/follow-user.ts b/packages/backend/src/remote/activitypub/renderer/follow-user.ts index 22ee429ff6..93228a6327 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-user.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-user.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/follow.ts b/packages/backend/src/remote/activitypub/renderer/follow.ts index 3ff89c12aa..30ad799507 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/hashtag.ts b/packages/backend/src/remote/activitypub/renderer/hashtag.ts index a00cd1ff5e..ab6651f55d 100644 --- a/packages/backend/src/remote/activitypub/renderer/hashtag.ts +++ b/packages/backend/src/remote/activitypub/renderer/hashtag.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; export default (tag: string) => ({ type: "Hashtag", diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index 2b6229b3e4..a085443d23 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -1,5 +1,5 @@ import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; import type { User } from "@/models/entities/user.js"; import { LdSignature } from "../misc/ld-signature.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/key.ts b/packages/backend/src/remote/activitypub/renderer/key.ts index 084bb5361a..1e01640e59 100644 --- a/packages/backend/src/remote/activitypub/renderer/key.ts +++ b/packages/backend/src/remote/activitypub/renderer/key.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import type { UserKeypair } from "@/models/entities/user-keypair.js"; import { createPublicKey } from "node:crypto"; diff --git a/packages/backend/src/remote/activitypub/renderer/like.ts b/packages/backend/src/remote/activitypub/renderer/like.ts index 6f810cd201..ea0df3e359 100644 --- a/packages/backend/src/remote/activitypub/renderer/like.ts +++ b/packages/backend/src/remote/activitypub/renderer/like.ts @@ -1,5 +1,5 @@ import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { NoteReaction } from "@/models/entities/note-reaction.js"; import type { Note } from "@/models/entities/note.js"; import { Emojis } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/mention.ts b/packages/backend/src/remote/activitypub/renderer/mention.ts index e7f0435c16..c935c7d325 100644 --- a/packages/backend/src/remote/activitypub/renderer/mention.ts +++ b/packages/backend/src/remote/activitypub/renderer/mention.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, ILocalUser } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index f1344c1b03..dc978f1e0e 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -1,5 +1,5 @@ import { In, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js"; import type { DriveFile } from "@/models/entities/drive-file.js"; import { DriveFiles, Notes, Users, Emojis, Polls } from "@/models/index.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/person.ts b/packages/backend/src/remote/activitypub/renderer/person.ts index bba963d72e..c6371440b4 100644 --- a/packages/backend/src/remote/activitypub/renderer/person.ts +++ b/packages/backend/src/remote/activitypub/renderer/person.ts @@ -1,6 +1,6 @@ import { URL } from "node:url"; import * as mfm from "mfm-js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { DriveFiles, UserProfiles } from "@/models/index.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/question.ts b/packages/backend/src/remote/activitypub/renderer/question.ts index cb89aa7583..ac62734395 100644 --- a/packages/backend/src/remote/activitypub/renderer/question.ts +++ b/packages/backend/src/remote/activitypub/renderer/question.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import type { Note } from "@/models/entities/note.js"; import type { Poll } from "@/models/entities/poll.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/read.ts b/packages/backend/src/remote/activitypub/renderer/read.ts index 212e7e8ddf..9ea15b10f7 100644 --- a/packages/backend/src/remote/activitypub/renderer/read.ts +++ b/packages/backend/src/remote/activitypub/renderer/read.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import type { MessagingMessage } from "@/models/entities/messaging-message.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/reject.ts b/packages/backend/src/remote/activitypub/renderer/reject.ts index 7ac4452411..75c3b9d065 100644 --- a/packages/backend/src/remote/activitypub/renderer/reject.ts +++ b/packages/backend/src/remote/activitypub/renderer/reject.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/remove.ts b/packages/backend/src/remote/activitypub/renderer/remove.ts index e3b3fef856..270744dd30 100644 --- a/packages/backend/src/remote/activitypub/renderer/remove.ts +++ b/packages/backend/src/remote/activitypub/renderer/remove.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (user: { id: User["id"] }, target: any, object: any) => ({ diff --git a/packages/backend/src/remote/activitypub/renderer/undo.ts b/packages/backend/src/remote/activitypub/renderer/undo.ts index 4394c4bf2f..a0285ea9c7 100644 --- a/packages/backend/src/remote/activitypub/renderer/undo.ts +++ b/packages/backend/src/remote/activitypub/renderer/undo.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => { diff --git a/packages/backend/src/remote/activitypub/renderer/update.ts b/packages/backend/src/remote/activitypub/renderer/update.ts index ecb0ed2192..b47f7c5cda 100644 --- a/packages/backend/src/remote/activitypub/renderer/update.ts +++ b/packages/backend/src/remote/activitypub/renderer/update.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; export default (object: any, user: { id: User["id"] }) => { diff --git a/packages/backend/src/remote/activitypub/renderer/vote.ts b/packages/backend/src/remote/activitypub/renderer/vote.ts index 21234a112d..118e6761ab 100644 --- a/packages/backend/src/remote/activitypub/renderer/vote.ts +++ b/packages/backend/src/remote/activitypub/renderer/vote.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { Note } from "@/models/entities/note.js"; import type { IRemoteUser, User } from "@/models/entities/user.js"; import type { PollVote } from "@/models/entities/poll-vote.js"; diff --git a/packages/backend/src/remote/activitypub/request.ts b/packages/backend/src/remote/activitypub/request.ts index f6d33b8549..8e3bc764d3 100644 --- a/packages/backend/src/remote/activitypub/request.ts +++ b/packages/backend/src/remote/activitypub/request.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; import type { User, ILocalUser } from "@/models/entities/user.js"; import { StatusError, getResponse } from "@/misc/fetch.js"; diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 79b7962b72..65e6f1d635 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { getInstanceActor } from "@/services/instance-actor.js"; import { fetchMeta } from "backend-rs"; diff --git a/packages/backend/src/remote/resolve-user.ts b/packages/backend/src/remote/resolve-user.ts index 0883386371..69a99c767a 100644 --- a/packages/backend/src/remote/resolve-user.ts +++ b/packages/backend/src/remote/resolve-user.ts @@ -1,7 +1,7 @@ import { URL } from "node:url"; import chalk from "chalk"; import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, IRemoteUser } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; import { toPuny } from "backend-rs"; diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index 71d95709b7..1e070f91f9 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -31,7 +31,7 @@ import Following from "./activitypub/following.js"; import Followers from "./activitypub/followers.js"; import Outbox, { packActivity } from "./activitypub/outbox.js"; import { serverLogger } from "./index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type Koa from "koa"; import * as crypto from "node:crypto"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/activitypub/featured.ts b/packages/backend/src/server/activitypub/featured.ts index e7ea6f238e..671c7ac67e 100644 --- a/packages/backend/src/server/activitypub/featured.ts +++ b/packages/backend/src/server/activitypub/featured.ts @@ -1,5 +1,5 @@ import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; import renderNote from "@/remote/activitypub/renderer/note.js"; diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts index 576a672d6d..603e93ebe8 100644 --- a/packages/backend/src/server/activitypub/followers.ts +++ b/packages/backend/src/server/activitypub/followers.ts @@ -1,5 +1,5 @@ import { IsNull, LessThan } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import * as url from "@/prelude/url.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts index 76b4e79716..be5a4e9643 100644 --- a/packages/backend/src/server/activitypub/following.ts +++ b/packages/backend/src/server/activitypub/following.ts @@ -1,5 +1,5 @@ import { LessThan, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import * as url from "@/prelude/url.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index 305102cf12..06319565e5 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -1,5 +1,5 @@ import { Brackets, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-collection.js"; import renderOrderedCollectionPage from "@/remote/activitypub/renderer/ordered-collection-page.js"; diff --git a/packages/backend/src/server/api/2fa.ts b/packages/backend/src/server/api/2fa.ts index 7318f0f433..5a6479939d 100644 --- a/packages/backend/src/server/api/2fa.ts +++ b/packages/backend/src/server/api/2fa.ts @@ -1,6 +1,6 @@ import * as crypto from "node:crypto"; import * as jsrsasign from "jsrsasign"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const ECC_PRELUDE = Buffer.from([0x04]); const NULL_BYTE = Buffer.from([0]); diff --git a/packages/backend/src/server/api/common/signin.ts b/packages/backend/src/server/api/common/signin.ts index e59a39ac41..e5ca09df95 100644 --- a/packages/backend/src/server/api/common/signin.ts +++ b/packages/backend/src/server/api/common/signin.ts @@ -1,6 +1,6 @@ import type Koa from "koa"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { Signins } from "@/models/index.js"; import { genId } from "backend-rs"; diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index 58b88b7d02..40b59c8ed5 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -8,7 +8,7 @@ import { genId, hashPassword, toPuny } from "backend-rs"; import { UserKeypair } from "@/models/entities/user-keypair.js"; import { UsedUsername } from "@/models/entities/used-username.js"; import { db } from "@/db/postgre.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export async function signup(opts: { username: User["username"]; diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts index fd4ad9401a..01d08f7a3d 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Meta } from "@/models/entities/meta.js"; import { insertModerationLog } from "@/services/insert-moderation-log.js"; import { db } from "@/db/postgre.js"; diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index ab04800944..ecfed950d3 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; import define from "@/server/api/define.js"; diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index 26a1fddfcb..f20219aa82 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -1,5 +1,5 @@ import { v4 as uuid } from "uuid"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; import { ApiError } from "@/server/api/error.js"; import { Apps, AuthSessions } from "@/models/index.js"; diff --git a/packages/backend/src/server/api/endpoints/fetch-rss.ts b/packages/backend/src/server/api/endpoints/fetch-rss.ts index bda3c455d1..489aaab0f5 100644 --- a/packages/backend/src/server/api/endpoints/fetch-rss.ts +++ b/packages/backend/src/server/api/endpoints/fetch-rss.ts @@ -1,6 +1,6 @@ import Parser from "rss-parser"; import { getResponse } from "@/misc/fetch.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; const rssParser = new Parser(); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 6c99217e7d..0951369dd8 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -6,7 +6,7 @@ import { AttestationChallenges, Users, } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { procedures, hash } from "@/server/api/2fa.js"; import { publishMainStream } from "@/services/stream.js"; import { verifyPassword } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index c0e6137d5d..eb926a6098 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -1,6 +1,6 @@ import * as OTPAuth from "otpauth"; import * as QRCode from "qrcode"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { UserProfiles } from "@/models/index.js"; import define from "@/server/api/define.js"; import { verifyPassword } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index 4784d3ee20..381bb1dea9 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -10,7 +10,7 @@ import deleteFollowing from "@/services/following/delete.js"; import create from "@/services/following/create.js"; import { getUser } from "@/server/api/common/getters.js"; import { Followings, Users } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { publishMainStream } from "@/services/stream.js"; import { stringToAcct } from "backend-rs"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 234127f584..185d1c8dc9 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -1,7 +1,7 @@ import { publishMainStream } from "@/services/stream.js"; import define from "@/server/api/define.js"; import rndstr from "rndstr"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, UserProfiles } from "@/models/index.js"; import { sendEmail } from "@/services/send-email.js"; import { ApiError } from "@/server/api/error.js"; diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index ec8f701976..f35ae9cc6b 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,6 +1,6 @@ import JSON5 from "json5"; import { IsNull, MoreThan } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Ads, Emojis, Users } from "@/models/index.js"; import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js"; diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index 9855b06513..00936c9d22 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -1,6 +1,6 @@ import rndstr from "rndstr"; import { IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, UserProfiles, PasswordResetRequests } from "@/models/index.js"; import { sendEmail } from "@/services/send-email.js"; import { genId } from "backend-rs"; diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts index cd634a798a..3818a3c28f 100644 --- a/packages/backend/src/server/api/endpoints/username/available.ts +++ b/packages/backend/src/server/api/endpoints/username/available.ts @@ -1,6 +1,6 @@ import { IsNull } from "typeorm"; import { Users, UsedUsernames } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import define from "@/server/api/define.js"; export const meta = { diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts index 493661b2a2..7e5cd892bc 100644 --- a/packages/backend/src/server/api/index.ts +++ b/packages/backend/src/server/api/index.ts @@ -12,7 +12,7 @@ import { getClient, } from "./mastodon/ApiMastodonCompatibleService.js"; import { AccessTokens, Users } from "@/models/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import endpoints from "./endpoints.js"; import compatibility from "./compatibility.js"; import handler from "./api-handler.js"; diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts index 5c304929a1..862310fb3e 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/meta.ts @@ -1,5 +1,5 @@ import { Entity } from "megalodon"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Users, Notes } from "@/models/index.js"; import { IsNull } from "typeorm"; diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 8b2f92b745..79dc48a8bb 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -1,5 +1,5 @@ import endpoints from "@/server/api/endpoints.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { errors as basicErrors } from "./errors.js"; import { schemas, convertSchemaToOpenApiSchema } from "./schemas.js"; diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index a7eb623062..d8bbbf74ad 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -1,7 +1,7 @@ import type Koa from "koa"; import * as OTPAuth from "otpauth"; import signin from "@/server/api/common/signin.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, Signins, diff --git a/packages/backend/src/server/api/private/signup.ts b/packages/backend/src/server/api/private/signup.ts index 5af5d65b50..4dd4ffb231 100644 --- a/packages/backend/src/server/api/private/signup.ts +++ b/packages/backend/src/server/api/private/signup.ts @@ -3,7 +3,7 @@ import rndstr from "rndstr"; import { verifyHcaptcha, verifyRecaptcha } from "@/misc/captcha.js"; import { Users, RegistrationTickets, UserPendings } from "@/models/index.js"; import { signup } from "@/server/api/common/signup.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { sendEmail } from "@/services/send-email.js"; import { fetchMeta, genId, hashPassword } from "backend-rs"; import { validateEmailForAccount } from "@/services/validate-email-for-account.js"; diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index fcfb7ecda3..2722a6610a 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -22,7 +22,7 @@ export default class extends Channel { this.listId = params.listId as string; // Check existence and owner - const exist = await UserLists.exist({ + const exist = await UserLists.exists({ where: { id: this.listId, userId: this.user!.id, diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index 416a041b52..313719e207 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from "events"; +import type { EventEmitter } from "node:events"; import type * as websocket from "websocket"; import readNote from "@/services/note/read.js"; import type { User } from "@/models/entities/user.js"; diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index 91095a46d3..8b4ac9e502 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -1,4 +1,4 @@ -import type { EventEmitter } from "events"; +import type { EventEmitter } from "node:events"; import type Emitter from "strict-event-emitter-types"; import type { Channel } from "@/models/entities/channel.js"; import type { User } from "@/models/entities/user.js"; diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index 17358a4758..54d6e8bf5f 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -13,7 +13,7 @@ import koaLogger from "koa-logger"; import * as slow from "koa-slow"; import { IsNull } from "typeorm"; -import config, { envOption } from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import Logger from "@/services/logger.js"; import { Users } from "@/models/index.js"; import { fetchMeta } from "backend-rs"; diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index 7359878b19..91e5fd8034 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -1,5 +1,5 @@ import Router from "@koa/router"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { fetchMeta } from "backend-rs"; import { Users, Notes } from "@/models/index.js"; import { IsNull, MoreThan } from "typeorm"; diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index f3b3c97c32..3beffc82f0 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -1,6 +1,6 @@ import { Feed } from "feed"; import { In, IsNull } from "typeorm"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import type { Note } from "@/models/entities/note.js"; import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js"; diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 4473165be7..b0687f084f 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -16,7 +16,7 @@ import { KoaAdapter } from "@bull-board/koa"; import { In, IsNull } from "typeorm"; import { fetchMeta, metaToPugArgs } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { Users, Notes, diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index a4c615c7ab..77c8a57cf4 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -1,6 +1,6 @@ import type Koa from "koa"; import { fetchMeta } from "backend-rs"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import manifest from "./manifest.json" assert { type: "json" }; export const manifestHandler = async (ctx: Koa.Context) => { diff --git a/packages/backend/src/server/web/url-preview.ts b/packages/backend/src/server/web/url-preview.ts index f59f3f357a..8fd757ef14 100644 --- a/packages/backend/src/server/web/url-preview.ts +++ b/packages/backend/src/server/web/url-preview.ts @@ -2,7 +2,7 @@ import type Koa from "koa"; import summaly from "summaly"; import { fetchMeta } from "backend-rs"; import Logger from "@/services/logger.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { query } from "@/prelude/url.js"; import { getJson } from "@/misc/fetch.js"; import { inspect } from "node:util"; diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index fc339eaad6..4a244db57f 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -1,6 +1,6 @@ import Router from "@koa/router"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { type Acct, stringToAcct } from "backend-rs"; import { links } from "./nodeinfo.js"; import { escapeAttribute, escapeValue } from "@/prelude/xml.js"; diff --git a/packages/backend/src/services/add-note-to-antenna.ts b/packages/backend/src/services/add-note-to-antenna.ts deleted file mode 100644 index 66bc898263..0000000000 --- a/packages/backend/src/services/add-note-to-antenna.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Antenna } from "@/models/entities/antenna.js"; -import type { Note } from "@/models/entities/note.js"; -import { getTimestamp } from "backend-rs"; -import { redisClient } from "@/db/redis.js"; -import { publishAntennaStream } from "@/services/stream.js"; -import type { User } from "@/models/entities/user.js"; - -export async function addNoteToAntenna( - antenna: Antenna, - note: Note, - _noteUser: { id: User["id"] }, -) { - redisClient.xadd( - `antennaTimeline:${antenna.id}`, - "MAXLEN", - "~", - "200", - `${getTimestamp(note.id)}-*`, - "note", - note.id, - ); - - publishAntennaStream(antenna.id, "note", note); -} diff --git a/packages/backend/src/services/drive/internal-storage.ts b/packages/backend/src/services/drive/internal-storage.ts index b2a663b3ea..6413f7920e 100644 --- a/packages/backend/src/services/drive/internal-storage.ts +++ b/packages/backend/src/services/drive/internal-storage.ts @@ -3,7 +3,7 @@ import * as fsPromises from "node:fs/promises"; import * as Path from "node:path"; import { fileURLToPath } from "node:url"; import { dirname } from "node:path"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); diff --git a/packages/backend/src/services/fetch-rel-me.ts b/packages/backend/src/services/fetch-rel-me.ts index 70faa01aa7..88f9c2ab1e 100644 --- a/packages/backend/src/services/fetch-rel-me.ts +++ b/packages/backend/src/services/fetch-rel-me.ts @@ -1,6 +1,6 @@ import { Window } from "happy-dom"; import type { HTMLAnchorElement, HTMLLinkElement } from "happy-dom"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; async function getRelMeLinks(url: string): Promise { try { diff --git a/packages/backend/src/services/following/requests/create.ts b/packages/backend/src/services/following/requests/create.ts index d2f2c1ca41..146e20efd9 100644 --- a/packages/backend/src/services/following/requests/create.ts +++ b/packages/backend/src/services/following/requests/create.ts @@ -6,7 +6,7 @@ import type { User } from "@/models/entities/user.js"; import { Blockings, FollowRequests, Users } from "@/models/index.js"; import { genId } from "backend-rs"; import { createNotification } from "@/services/create-notification.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; export default async function ( follower: { diff --git a/packages/backend/src/services/i/pin.ts b/packages/backend/src/services/i/pin.ts index 2d2675a535..b44ba5f9fa 100644 --- a/packages/backend/src/services/i/pin.ts +++ b/packages/backend/src/services/i/pin.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import renderAdd from "@/remote/activitypub/renderer/add.js"; import renderRemove from "@/remote/activitypub/renderer/remove.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; diff --git a/packages/backend/src/services/logger.ts b/packages/backend/src/services/logger.ts index f4b4454ef8..aec4542b82 100644 --- a/packages/backend/src/services/logger.ts +++ b/packages/backend/src/services/logger.ts @@ -2,7 +2,7 @@ import cluster from "node:cluster"; import chalk from "chalk"; import { default as convertColor } from "color-convert"; import { format as dateFormat } from "date-fns"; -import config, { envOption } from "@/config/index.js"; +import { config, envOption } from "@/config.js"; import * as SyslogPro from "syslog-pro"; diff --git a/packages/backend/src/services/messages/delete.ts b/packages/backend/src/services/messages/delete.ts index 77caba80ce..2d8f6b9baf 100644 --- a/packages/backend/src/services/messages/delete.ts +++ b/packages/backend/src/services/messages/delete.ts @@ -1,4 +1,4 @@ -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { MessagingMessages, Users } from "@/models/index.js"; import type { MessagingMessage } from "@/models/entities/messaging-message.js"; import { diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 0a4ddc517f..206f6a50ad 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -10,7 +10,7 @@ import renderCreate from "@/remote/activitypub/renderer/create.js"; import renderAnnounce from "@/remote/activitypub/renderer/announce.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { resolveUser } from "@/remote/resolve-user.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { updateHashtags } from "@/services/update-hashtag.js"; import { concat } from "@/prelude/array.js"; import { insertNoteUnread } from "@/services/note/unread.js"; @@ -44,8 +44,7 @@ import { Poll } from "@/models/entities/poll.js"; import { createNotification } from "@/services/create-notification.js"; import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js"; import { checkHitAntenna } from "@/misc/check-hit-antenna.js"; -import { checkWordMute } from "backend-rs"; -import { addNoteToAntenna } from "@/services/add-note-to-antenna.js"; +import { addNoteToAntenna, checkWordMute } from "backend-rs"; import { countSameRenotes } from "@/misc/count-same-renotes.js"; import { deliverToRelays, getCachedRelays } from "../relay.js"; import type { Channel } from "@/models/entities/channel.js"; @@ -63,6 +62,7 @@ import { Mutex } from "redis-semaphore"; import { langmap } from "@/misc/langmap.js"; import Logger from "@/services/logger.js"; import { inspect } from "node:util"; +import { undefinedToNull } from "@/prelude/undefined-to-null.js"; const logger = new Logger("create-note"); @@ -399,7 +399,8 @@ export default async ( for (const antenna of await getAntennas()) { checkHitAntenna(antenna, note, user).then((hit) => { if (hit) { - addNoteToAntenna(antenna, note, user); + // TODO: do this more sanely + addNoteToAntenna(antenna.id, undefinedToNull(note) as Note); } }); } diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index be3bf1e8b2..c709792fef 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -5,7 +5,7 @@ import renderAnnounce from "@/remote/activitypub/renderer/announce.js"; import renderUndo from "@/remote/activitypub/renderer/undo.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderTombstone from "@/remote/activitypub/renderer/tombstone.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js"; import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js"; import { Notes, Users, Instances } from "@/models/index.js"; diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index 3f1f2cfb1a..86dd2a32e2 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -1,5 +1,5 @@ import push from "web-push"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { SwSubscriptions } from "@/models/index.js"; import { fetchMeta, getNoteSummary } from "backend-rs"; import type { Packed } from "@/misc/schema.js"; diff --git a/packages/backend/src/services/send-email.ts b/packages/backend/src/services/send-email.ts index 11a899d267..bcbecce356 100644 --- a/packages/backend/src/services/send-email.ts +++ b/packages/backend/src/services/send-email.ts @@ -1,7 +1,7 @@ import * as nodemailer from "nodemailer"; import { fetchMeta } from "backend-rs"; import Logger from "@/services/logger.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import { inspect } from "node:util"; export const logger = new Logger("email"); diff --git a/packages/backend/src/services/stream.ts b/packages/backend/src/services/stream.ts index bd09bc3f2c..7f1862b74d 100644 --- a/packages/backend/src/services/stream.ts +++ b/packages/backend/src/services/stream.ts @@ -3,13 +3,13 @@ import type { User } from "@/models/entities/user.js"; import type { Note } from "@/models/entities/note.js"; import type { UserList } from "@/models/entities/user-list.js"; import type { UserGroup } from "@/models/entities/user-group.js"; -import config from "@/config/index.js"; -import type { Antenna } from "@/models/entities/antenna.js"; +import { config } from "@/config.js"; +// import type { Antenna } from "@/models/entities/antenna.js"; import type { Channel } from "@/models/entities/channel.js"; import type { StreamChannels, AdminStreamTypes, - AntennaStreamTypes, + // AntennaStreamTypes, BroadcastTypes, ChannelStreamTypes, DriveStreamTypes, @@ -134,17 +134,18 @@ class Publisher { ); }; - public publishAntennaStream = ( - antennaId: Antenna["id"], - type: K, - value?: AntennaStreamTypes[K], - ): void => { - this.publish( - `antennaStream:${antennaId}`, - type, - typeof value === "undefined" ? null : value, - ); - }; + /* ported to backend-rs */ + // public publishAntennaStream = ( + // antennaId: Antenna["id"], + // type: K, + // value?: AntennaStreamTypes[K], + // ): void => { + // this.publish( + // `antennaStream:${antennaId}`, + // type, + // typeof value === "undefined" ? null : value, + // ); + // }; public publishMessagingStream = ( userId: User["id"], @@ -217,7 +218,7 @@ export const publishNoteStream = publisher.publishNoteStream; export const publishNotesStream = publisher.publishNotesStream; export const publishChannelStream = publisher.publishChannelStream; export const publishUserListStream = publisher.publishUserListStream; -export const publishAntennaStream = publisher.publishAntennaStream; +// export const publishAntennaStream = publisher.publishAntennaStream; export const publishMessagingStream = publisher.publishMessagingStream; export const publishGroupMessagingStream = publisher.publishGroupMessagingStream; diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index f72b8ffcb1..0babd31bc5 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -1,7 +1,7 @@ import renderDelete from "@/remote/activitypub/renderer/delete.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { deliver } from "@/queue/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users, Followings } from "@/models/index.js"; import { Not, IsNull } from "typeorm"; diff --git a/packages/backend/src/services/unsuspend-user.ts b/packages/backend/src/services/unsuspend-user.ts index 69447a4a26..72d7e30d66 100644 --- a/packages/backend/src/services/unsuspend-user.ts +++ b/packages/backend/src/services/unsuspend-user.ts @@ -2,7 +2,7 @@ import renderDelete from "@/remote/activitypub/renderer/delete.js"; import renderUndo from "@/remote/activitypub/renderer/undo.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import { deliver } from "@/queue/index.js"; -import config from "@/config/index.js"; +import { config } from "@/config.js"; import type { User } from "@/models/entities/user.js"; import { Users, Followings } from "@/models/index.js"; import { Not, IsNull } from "typeorm"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b591ffe9c1..16a4ad6ad4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -521,6 +521,9 @@ importers: tsconfig-paths: specifier: 4.2.0 version: 4.2.0 + type-fest: + specifier: 4.15.0 + version: 4.15.0 typescript: specifier: 5.4.5 version: 5.4.5 @@ -16632,6 +16635,11 @@ packages: engines: {node: '>=8'} dev: true + /type-fest@4.15.0: + resolution: {integrity: sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==} + engines: {node: '>=16'} + dev: true + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'}