From 07c00a8b7f3c2b7714db45a200560b824fa7b292 Mon Sep 17 00:00:00 2001 From: Brendan Allan Date: Wed, 12 Jul 2023 11:32:53 +0700 Subject: [PATCH] [ENG-846] Preferences (#1047) * preferences table + trait * cleaner implementation * router + ts type * preference test * per-column list view preferences * preference read + write * add some docs * migration + docs * remove ts expect error --- Cargo.lock | Bin 246006 -> 246245 bytes .../authjs-adapter-drizzle-mysql/index.ts | 1 - core/Cargo.toml | 1 + .../20230711114013_preferences/migration.sql | 5 + core/prisma/schema.prisma | 8 + core/src/api/mod.rs | 3 + core/src/api/preferences.rs | 21 +++ core/src/lib.rs | 1 + core/src/preferences/kv.rs | 159 ++++++++++++++++++ core/src/preferences/mod.rs | 151 +++++++++++++++++ core/src/sync/manager.rs | 1 + interface/package.json | 2 + interface/util/uuid.ts | 1 + packages/client/src/core.ts | 14 ++ pnpm-lock.yaml | Bin 917577 -> 916247 bytes 15 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 core/prisma/migrations/20230711114013_preferences/migration.sql create mode 100644 core/src/api/preferences.rs create mode 100644 core/src/preferences/kv.rs create mode 100644 core/src/preferences/mod.rs create mode 100644 interface/util/uuid.ts diff --git a/Cargo.lock b/Cargo.lock index 10d75055968f3cb29b00a4b06cb50b60e44d536b..445fd550ce09a73cf895e28c21fc08f8e9c33e74 100644 GIT binary patch delta 127 zcmey?$p5sNzoCV33)8`T=G=m^>Gm$niS{X}78ZuaNydprX_ltRriR8AX{n}`My5$= zNfzc7CWhvwDHawfW=Uyj2Bwxti5AJJ29^eii58ZI#)g*WrqdM#8O5eIykX>JRZuF* eEtoDC#3a4_U_R4p8IT?A%X*l$FY93rFaZD-+bA6X delta 29 lcmaFb%>S*CzoCV33)8{;?aK?8Udy!4?q%9OyO-I^1OUu94AB4p diff --git a/apps/landing/src/app/api/[...auth]/authjs-adapter-drizzle-mysql/index.ts b/apps/landing/src/app/api/[...auth]/authjs-adapter-drizzle-mysql/index.ts index 2673edadf..0d1543bcb 100644 --- a/apps/landing/src/app/api/[...auth]/authjs-adapter-drizzle-mysql/index.ts +++ b/apps/landing/src/app/api/[...auth]/authjs-adapter-drizzle-mysql/index.ts @@ -17,7 +17,6 @@ */ import type { Adapter } from '@auth/core/adapters'; import { and, eq } from 'drizzle-orm'; -// @ts-expect-error import { v4 as uuid } from 'uuid'; import type { DbClient, Schema } from './schema'; diff --git a/core/Cargo.toml b/core/Cargo.toml index 5c7804177..e39d8618a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -58,6 +58,7 @@ serde_json = "1.0" futures = "0.3" rmp = "^0.8.11" rmp-serde = "^1.1.1" +rmpv = "^1.0.0" blake3 = "1.3.3" hostname = "0.3.1" uuid = { version = "1.3.3", features = ["v4", "serde"] } diff --git a/core/prisma/migrations/20230711114013_preferences/migration.sql b/core/prisma/migrations/20230711114013_preferences/migration.sql new file mode 100644 index 000000000..2552b1fe3 --- /dev/null +++ b/core/prisma/migrations/20230711114013_preferences/migration.sql @@ -0,0 +1,5 @@ +-- CreateTable +CREATE TABLE "preference" ( + "key" TEXT NOT NULL PRIMARY KEY, + "value" BLOB +); diff --git a/core/prisma/schema.prisma b/core/prisma/schema.prisma index 01273b7fb..1745b19ed 100644 --- a/core/prisma/schema.prisma +++ b/core/prisma/schema.prisma @@ -458,3 +458,11 @@ model IndexerRulesInLocation { @@id([location_id, indexer_rule_id]) @@map("indexer_rule_in_location") } + +/// @shared(id: key) +model Preference { + key String @id + value Bytes? + + @@map("preference") +} diff --git a/core/src/api/mod.rs b/core/src/api/mod.rs index 6b2b3fec3..3bc083bd8 100644 --- a/core/src/api/mod.rs +++ b/core/src/api/mod.rs @@ -28,6 +28,7 @@ mod libraries; mod locations; mod nodes; mod p2p; +mod preferences; mod search; mod sync; mod tags; @@ -82,6 +83,7 @@ pub(crate) fn mount() -> Arc { .merge("p2p.", p2p::mount()) .merge("nodes.", nodes::mount()) .merge("sync.", sync::mount()) + .merge("preferences.", preferences::mount()) .merge("invalidation.", utils::mount_invalidate()) .build( #[allow(clippy::let_and_return)] @@ -98,6 +100,7 @@ pub(crate) fn mount() -> Arc { }, ) .arced(); + InvalidRequests::validate(r.clone()); // This validates all invalidation calls. r diff --git a/core/src/api/preferences.rs b/core/src/api/preferences.rs new file mode 100644 index 000000000..ac455604c --- /dev/null +++ b/core/src/api/preferences.rs @@ -0,0 +1,21 @@ +use rspc::alpha::AlphaRouter; + +use super::{utils::library, Ctx, R}; +use crate::preferences::LibraryPreferences; + +pub(crate) fn mount() -> AlphaRouter { + R.router() + .procedure("update", { + R.with2(library()) + .mutation(|(_, library), args: LibraryPreferences| async move { + args.write(&library.db).await?; + + Ok(()) + }) + }) + .procedure("get", { + R.with2(library()).query(|(_, library), _: ()| async move { + Ok(LibraryPreferences::read(&library.db).await?) + }) + }) +} diff --git a/core/src/lib.rs b/core/src/lib.rs index 4885040b2..7aaf7e5f3 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -33,6 +33,7 @@ pub(crate) mod location; pub(crate) mod node; pub(crate) mod object; pub(crate) mod p2p; +pub(crate) mod preferences; pub(crate) mod sync; pub(crate) mod util; pub(crate) mod volume; diff --git a/core/src/preferences/kv.rs b/core/src/preferences/kv.rs new file mode 100644 index 000000000..f7927a239 --- /dev/null +++ b/core/src/preferences/kv.rs @@ -0,0 +1,159 @@ +use std::collections::BTreeMap; + +use crate::prisma::{preference, PrismaClient}; +use itertools::Itertools; +use rmpv::Value; +use serde::{de::DeserializeOwned, Serialize}; + +use super::Preferences; + +#[derive(Debug)] +pub struct PreferenceKey(Vec); + +impl PreferenceKey { + pub fn new(value: impl Into) -> Self { + Self( + value + .into() + .split('.') + .map(ToString::to_string) + .collect_vec(), + ) + } + + pub fn prepend_path(&mut self, prefix: &str) { + self.0 = [prefix.to_string()] + .into_iter() + .chain(self.0.drain(..)) + .collect_vec(); + } +} + +impl std::fmt::Display for PreferenceKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0.join(".")) + } +} + +#[derive(Debug)] +pub struct PreferenceValue(Vec); + +impl PreferenceValue { + pub fn new(value: impl Serialize) -> Self { + let mut bytes = vec![]; + + rmp_serde::encode::write_named(&mut bytes, &value).unwrap(); + + // let value = rmpv::decode::read_value(&mut bytes.as_slice()).unwrap(); + + Self(bytes) + } + + pub fn from_value(value: Value) -> Self { + let mut bytes = vec![]; + + rmpv::encode::write_value(&mut bytes, &value).unwrap(); + + Self(bytes) + } +} + +#[derive(Debug)] +pub struct PreferenceKVs(Vec<(PreferenceKey, PreferenceValue)>); + +impl IntoIterator for PreferenceKVs { + type Item = (PreferenceKey, PreferenceValue); + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +#[derive(Debug)] +pub enum Entry { + Value(Vec), + Nested(Entries), +} + +impl Entry { + pub fn expect_value(self) -> T { + match self { + Self::Value(value) => rmp_serde::decode::from_read(value.as_slice()).unwrap(), + _ => panic!("Expected value"), + } + } + + pub fn expect_nested(self) -> Entries { + match self { + Self::Nested(entries) => entries, + _ => panic!("Expected nested entry"), + } + } +} + +pub type Entries = BTreeMap; + +impl PreferenceKVs { + pub fn new(values: Vec<(PreferenceKey, PreferenceValue)>) -> Self { + Self(values) + } + + pub fn with_prefix(mut self, prefix: &str) -> Self { + for (key, _) in &mut self.0 { + key.prepend_path(prefix); + } + + self + } + + pub fn to_upserts(self, db: &PrismaClient) -> Vec { + self.0 + .into_iter() + .map(|(key, value)| { + let value = vec![preference::value::set(Some(value.0))]; + + db.preference().upsert( + preference::key::equals(key.to_string()), + preference::create(key.to_string(), value.clone()), + value, + ) + }) + .collect() + } + + pub fn parse(self) -> T { + let entries = self + .0 + .into_iter() + .fold(BTreeMap::new(), |mut acc, (key, value)| { + let key_parts = key.0; + let key_parts_len = key_parts.len(); + + { + let mut curr_map: &mut BTreeMap = &mut acc; + + for (i, part) in key_parts.into_iter().enumerate() { + if i >= key_parts_len - 1 { + curr_map.insert(part, Entry::Value(value.0)); + break; + } else { + curr_map = match curr_map + .entry(part) + .or_insert(Entry::Nested(BTreeMap::new())) + { + Entry::Nested(map) => map, + _ => unreachable!(), + }; + } + } + } + + acc + }); + + dbg!(&entries); + + T::from_entries(entries) + } +} diff --git a/core/src/preferences/mod.rs b/core/src/preferences/mod.rs new file mode 100644 index 000000000..65521a4f1 --- /dev/null +++ b/core/src/preferences/mod.rs @@ -0,0 +1,151 @@ +mod kv; + +pub use kv::*; +use specta::Type; + +use crate::prisma::PrismaClient; +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +// Preferences are a set of types that are serialized as a list of key-value pairs, +// where nested type keys are serialized as a dot-separated path. +// They are serailized as a list because this allows preferences to be a synchronisation boundary, +// whereas their values (referred to as settings) will be overwritten. + +#[derive(Clone, Serialize, Deserialize, Type, Debug)] +pub struct LibraryPreferences { + #[serde(default)] + #[specta(optional)] + location: HashMap, +} + +impl LibraryPreferences { + pub async fn write(self, db: &PrismaClient) -> prisma_client_rust::Result<()> { + let kvs = self.to_kvs(); + + db._batch(kvs.to_upserts(&db)).await?; + + Ok(()) + } + + pub async fn read(db: &PrismaClient) -> prisma_client_rust::Result { + let kvs = db.preference().find_many(vec![]).exec().await?; + + let prefs = PreferenceKVs::new( + kvs.into_iter() + .filter_map(|data| { + let a = rmpv::decode::read_value(&mut data.value?.as_slice()).unwrap(); + + Some((PreferenceKey::new(data.key), PreferenceValue::from_value(a))) + }) + .collect(), + ); + + Ok(prefs.parse()) + } +} + +#[derive(Clone, Serialize, Deserialize, Type, Debug)] +pub struct LocationPreferences { + /// View settings for the location - all writes are overwrites! + #[specta(optional)] + view: Option, +} + +#[derive(Clone, Serialize, Deserialize, Type, Debug)] +pub struct LocationViewSettings { + layout: ExplorerLayout, + list: ListViewSettings, +} + +#[derive(Clone, Serialize, Deserialize, Type, Default, Debug)] +pub struct ListViewSettings { + columns: HashMap, + sort_col: Option, +} + +#[derive(Clone, Serialize, Deserialize, Type, Default, Debug)] +pub struct ListViewColumnSettings { + hide: bool, + size: Option, +} + +#[derive(Clone, Serialize, Deserialize, Type, Debug)] +pub enum ExplorerLayout { + Grid, + List, + Media, +} + +impl Preferences for HashMap +where + V: Preferences, +{ + fn to_kvs(self) -> PreferenceKVs { + PreferenceKVs::new( + self.into_iter() + .flat_map(|(id, value)| { + let mut buf = Uuid::encode_buffer(); + + let id = id.as_simple().encode_lower(&mut buf); + + value.to_kvs().with_prefix(id) + }) + .collect(), + ) + } + + fn from_entries(entries: Entries) -> Self { + entries + .into_iter() + .map(|(key, value)| { + let id = Uuid::parse_str(&key).unwrap(); + + (id, V::from_entries(value.expect_nested())) + }) + .collect() + } +} + +impl Preferences for LibraryPreferences { + fn to_kvs(self) -> PreferenceKVs { + let Self { location } = self; + + location.to_kvs().with_prefix("location") + } + + fn from_entries(mut entries: Entries) -> Self { + Self { + location: entries + .remove("location") + .map(|value| HashMap::from_entries(value.expect_nested())) + .unwrap_or_default(), + } + } +} + +impl Preferences for LocationPreferences { + fn to_kvs(self) -> PreferenceKVs { + let Self { view } = self; + + PreferenceKVs::new( + [view.map(|view| (PreferenceKey::new("view"), PreferenceValue::new(view)))] + .into_iter() + .flatten() + .collect(), + ) + } + + fn from_entries(mut entries: Entries) -> Self { + Self { + view: entries.remove("view").map(|view| view.expect_value()), + } + } +} + +pub trait Preferences { + fn to_kvs(self) -> PreferenceKVs; + fn from_entries(entries: Entries) -> Self; +} diff --git a/core/src/sync/manager.rs b/core/src/sync/manager.rs index 0331fab5e..db9d49ba6 100644 --- a/core/src/sync/manager.rs +++ b/core/src/sync/manager.rs @@ -303,6 +303,7 @@ impl SyncManager { .await?; } }, + ModelSyncData::Preference(_, _) => todo!(), } if let CRDTOperationType::Shared(shared_op) = op.typ { diff --git a/interface/package.json b/interface/package.json index 6ed9841c4..effea049f 100644 --- a/interface/package.json +++ b/interface/package.json @@ -37,6 +37,7 @@ "@tanstack/react-table": "^8.8.5", "@tanstack/react-virtual": "3.0.0-beta.54", "@types/react-scroll-sync": "^0.8.4", + "@types/uuid": "^9.0.2", "@vitejs/plugin-react": "^2.1.0", "autoprefixer": "^10.4.12", "class-variance-authority": "^0.5.3", @@ -67,6 +68,7 @@ "use-count-up": "^3.0.1", "use-debounce": "^8.0.4", "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", "valtio": "^1.7.4" }, "devDependencies": { diff --git a/interface/util/uuid.ts b/interface/util/uuid.ts new file mode 100644 index 000000000..a56a94278 --- /dev/null +++ b/interface/util/uuid.ts @@ -0,0 +1 @@ +export { stringify } from 'uuid'; diff --git a/packages/client/src/core.ts b/packages/client/src/core.ts index 4fe053d78..cb2893fe0 100644 --- a/packages/client/src/core.ts +++ b/packages/client/src/core.ts @@ -19,6 +19,7 @@ export type Procedures = { { key: "locations.list", input: LibraryArgs, result: { id: number; pub_id: number[]; name: string | null; path: string | null; total_capacity: number | null; available_capacity: number | null; is_archived: boolean | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; date_created: string | null; node_id: number | null; node: Node | null }[] } | { key: "nodeState", input: never, result: NodeState } | { key: "nodes.listLocations", input: LibraryArgs, result: ExplorerItem[] } | + { key: "preferences.get", input: LibraryArgs, result: LibraryPreferences } | { key: "search.objects", input: LibraryArgs, result: SearchData } | { key: "search.paths", input: LibraryArgs, result: SearchData } | { key: "sync.messages", input: LibraryArgs, result: CRDTOperation[] } | @@ -61,6 +62,7 @@ export type Procedures = { { key: "p2p.acceptSpacedrop", input: [string, string | null], result: null } | { key: "p2p.pair", input: LibraryArgs, result: number } | { key: "p2p.spacedrop", input: SpacedropArgs, result: string | null } | + { key: "preferences.update", input: LibraryArgs, result: null } | { key: "tags.assign", input: LibraryArgs, result: null } | { key: "tags.create", input: LibraryArgs, result: Tag } | { key: "tags.delete", input: LibraryArgs, result: null } | @@ -97,6 +99,8 @@ export type EditLibraryArgs = { id: string; name: LibraryName | null; descriptio export type ExplorerItem = { type: "Path"; has_local_thumbnail: boolean; thumbnail_key: string[] | null; item: FilePathWithObject } | { type: "Object"; has_local_thumbnail: boolean; thumbnail_key: string[] | null; item: ObjectWithFilePaths } | { type: "Location"; has_local_thumbnail: boolean; thumbnail_key: string[] | null; item: Location } +export type ExplorerLayout = "Grid" | "List" | "Media" + export type FileCopierJobInit = { source_location_id: number; target_location_id: number; sources_file_path_ids: number[]; target_location_relative_directory_path: string; target_file_name_suffix: string | null } export type FileCutterJobInit = { source_location_id: number; target_location_id: number; sources_file_path_ids: number[]; target_location_relative_directory_path: string } @@ -158,8 +162,14 @@ export type LibraryConfigWrapped = { uuid: string; config: SanitisedLibraryConfi export type LibraryName = string +export type LibraryPreferences = { location?: { [key: string]: LocationPreferences } } + export type LightScanArgs = { location_id: number; sub_path: string } +export type ListViewColumnSettings = { hide: boolean; size: number | null } + +export type ListViewSettings = { columns: { [key: string]: ListViewColumnSettings }; sort_col: string | null } + export type Location = { id: number; pub_id: number[]; name: string | null; path: string | null; total_capacity: number | null; available_capacity: number | null; is_archived: boolean | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; date_created: string | null; node_id: number | null } /** @@ -169,6 +179,8 @@ export type Location = { id: number; pub_id: number[]; name: string | null; path */ export type LocationCreateArgs = { path: string; dry_run: boolean; indexer_rules_ids: number[] } +export type LocationPreferences = { view?: LocationViewSettings | null } + /** * `LocationUpdateArgs` is the argument received from the client using `rspc` to update a location. * It contains the id of the location to be updated, possible a name to change the current location's name @@ -179,6 +191,8 @@ export type LocationCreateArgs = { path: string; dry_run: boolean; indexer_rules */ export type LocationUpdateArgs = { id: number; name: string | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; indexer_rules_ids: number[] } +export type LocationViewSettings = { layout: ExplorerLayout; list: ListViewSettings } + export type LocationWithIndexerRules = { id: number; pub_id: number[]; name: string | null; path: string | null; total_capacity: number | null; available_capacity: number | null; is_archived: boolean | null; generate_preview_media: boolean | null; sync_preview_media: boolean | null; hidden: boolean | null; date_created: string | null; node_id: number | null; indexer_rules: { indexer_rule: IndexerRule }[] } export type MaybeNot = T | { not: T } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1935a70039d5ea1cae132f8063f2baadf925ae8..65a0758a91ec55f84a20dda2922159059559fe66 100644 GIT binary patch delta 21544 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∈9j(rt(1~M975zpRe&d@3-PR(nD7-N7e@o$ zUONyL$ru+M`%}f3l%w<2V_iLB|dgp!1 zZ$ES*5eFWAW_jNB{cw5Un9U)$`=`sd0_2Cw+wIJcm#^L^vtikto>S`s^B2pzPJaBl ze{){U)ij(Sh9f^8E?A9jyc^S!8UnLANXzF9gjkC8`%6MD?uBwRg+inWsjy8%iPc9_ ztej#?W+yx@vJoj9=S#IlIF~Q+r2*Jpf=n*tm#Zt_fhU&tfSe2uHEa-gZ~wnFoLguk zRT#%flV;oPIj+0avg|`^ZLRG_JDuh-nXaO_Hl3u+W6n1-hyVZg|IX_M z)TbA8XUGqK_l!2%utSS_>kdjClOqNldbBaajPRXk>mgW<)BT7g)^q4Rm`SJJ|4=^~ zu5q4;R7v(sF6WI|x$HKImYFOBk22wm&9xRWd6e0R5Rgn16_zEVQkqCHyg8JqB%OJy zC%`3B5e_&?!R3kN^RmlRr6tHh)niIzgF|0*!!;L=G-E^wBeuy50Tnl_-if0Ac6ap6 zqtV7+1iE8W*JQPFb5zxDD<>QVb3R~}U4YK4@GTN7*vhApS{_vyB~&?ynGWKw5_WVa&Zs6(~8~pkqe)} zH8d7-=S%d2Rvj7y)1sWs@c~;U=~!YzzBFGpPxB6QTAt3AL<$BpWQ)oi>o*$~#56^l zV3(U&GX!VA0o)YpDPBkKARdhF^(6|1{xz^8xu z1NEFSwJKc%rCXkQ#5&G4F(`ZwnTFI3a&k1v*oyRgBvmYC5}}|c=BUPt;X+Chq=ZLe zdCu*QdPRq=N(ph6G1&QqSSSDx?CJ#17OX|@{O zpCVVh_}4CVP>;vL8Fp>HAiK*^5UiboDQw9SGFKM=6MycgkN^B zPW^cccaiby_<2qJ5CRtL3)(iG3XXVrl{bb<)`c%;dKKKTIt0$Htd_4F+;s=mr