// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers // All rights reserved. // Licensed under the Apache License, Version 2.0 // // or the MIT license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. //! App Protocol (between LocalBroker and Verifier) use serde::{Deserialize, Serialize}; use ng_repo::errors::NgError; use ng_repo::types::*; use crate::types::*; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppFetchContentV0 { Get, // does not subscribe. more to be detailed Subscribe, // more to be detailed Update, //Invoke, ReadQuery, // more to be detailed WriteQuery, // more to be detailed } impl AppFetchContentV0 { pub fn get_or_subscribe(subscribe: bool) -> Self { if !subscribe { AppFetchContentV0::Get } else { AppFetchContentV0::Subscribe } } } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum NgAccessV0 { ReadCap(ReadCap), Token(Digest), #[serde(with = "serde_bytes")] ExtRequest(Vec), Key(BlockKey), Inbox(Digest), } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum TargetBranchV0 { Chat, Stream, Context, Ontology, BranchId(BranchId), Named(String), // branch or commit Commits(Vec), // only possible if access to their branch is given. must belong to the same branch. } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum NuriTargetV0 { UserSite, // targets the whole data set of the user PublicStore, ProtectedStore, PrivateStore, AllDialogs, Dialog(String), // shortname of a Dialog AllGroups, Group(String), // shortname of a Group Repo(RepoId), Identity(UserId), } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct NuriV0 { pub target: NuriTargetV0, pub entire_store: bool, // If it is a store, will (try to) include all the docs belonging to the store pub object: Option, // used only for FileGet. // cannot be used for queries. only to download an object (file,commit..) pub branch: Option, // if None, the main branch is chosen pub overlay: Option, pub access: Vec, pub topic: Option, pub locator: Vec, } impl NuriV0 { pub fn new_repo_target_from_string(repo_id_string: String) -> Result { let repo_id: RepoId = repo_id_string.as_str().try_into()?; Ok(Self { target: NuriTargetV0::Repo(repo_id), entire_store: false, object: None, branch: None, overlay: None, access: vec![], topic: None, locator: vec![], }) } pub fn new_private_store_target() -> Self { Self { target: NuriTargetV0::PrivateStore, entire_store: false, object: None, branch: None, overlay: None, access: vec![], topic: None, locator: vec![], } } pub fn new(_from: String) -> Self { todo!(); } } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppRequestCommandV0 { Fetch(AppFetchContentV0), Pin, UnPin, Delete, Create, FileGet, // needs the Nuri of branch/doc/store AND ObjectId FilePut, // needs the Nuri of branch/doc/store } impl AppRequestCommandV0 { pub fn is_stream(&self) -> bool { match self { Self::FilePut | Self::Create | Self::Delete | Self::UnPin | Self::Pin => false, Self::Fetch(_) | Self::FileGet => true, } } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppRequestV0 { pub command: AppRequestCommandV0, pub nuri: NuriV0, pub payload: Option, pub session_id: u64, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppRequest { V0(AppRequestV0), } impl AppRequest { pub fn set_session_id(&mut self, session_id: u64) { match self { Self::V0(v0) => v0.session_id = session_id, } } pub fn session_id(&self) -> u64 { match self { Self::V0(v0) => v0.session_id, } } pub fn command(&self) -> &AppRequestCommandV0 { match self { Self::V0(v0) => &v0.command, } } pub fn new( command: AppRequestCommandV0, nuri: NuriV0, payload: Option, ) -> Self { AppRequest::V0(AppRequestV0 { command, nuri, payload, session_id: 0, }) } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppSessionStopV0 { pub session_id: u64, pub force_close: bool, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppSessionStop { V0(AppSessionStopV0), } impl AppSessionStop { pub fn session_id(&self) -> u64 { match self { Self::V0(v0) => v0.session_id, } } pub fn is_force_close(&self) -> bool { match self { Self::V0(v0) => v0.force_close, } } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppSessionStartV0 { pub session_id: u64, pub credentials: Option, pub user_id: UserId, pub detach: bool, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppSessionStart { V0(AppSessionStartV0), } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppSessionStartResponseV0 { pub private_store: RepoId, pub protected_store: RepoId, pub public_store: RepoId, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppSessionStartResponse { V0(AppSessionStartResponseV0), } impl AppSessionStart { pub fn session_id(&self) -> u64 { match self { Self::V0(v0) => v0.session_id, } } pub fn credentials(&self) -> &Option { match self { Self::V0(v0) => &v0.credentials, } } pub fn user_id(&self) -> &UserId { match self { Self::V0(v0) => &v0.user_id, } } } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum DocQuery { V0(String), // Sparql } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GraphUpdate { add: Vec, remove: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum DiscreteUpdate { /// A yrs::Update #[serde(with = "serde_bytes")] YMap(Vec), #[serde(with = "serde_bytes")] YXml(Vec), #[serde(with = "serde_bytes")] YText(Vec), /// An automerge::Patch #[serde(with = "serde_bytes")] Automerge(Vec), } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DocUpdate { heads: Vec, graph: Option, discrete: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DocAddFile { pub filename: Option, pub object: ObjectRef, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DocCreate { store: StoreRepo, content_type: BranchContentType, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DocDelete { /// Nuri of doc to delete nuri: String, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppRequestPayloadV0 { Create(DocCreate), Query(DocQuery), Update(DocUpdate), AddFile(DocAddFile), //RemoveFile Delete(DocDelete), //Invoke(InvokeArguments), SmallFilePut(SmallFile), RandomAccessFilePut(String), // content_type RandomAccessFilePutChunk((u32, serde_bytes::ByteBuf)), // end the upload with an empty vec } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppRequestPayload { V0(AppRequestPayloadV0), } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum DiscretePatch { /// A yrs::Update #[serde(with = "serde_bytes")] YMap(Vec), #[serde(with = "serde_bytes")] YXml(Vec), #[serde(with = "serde_bytes")] YText(Vec), /// An automerge::Patch #[serde(with = "serde_bytes")] Automerge(Vec), } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GraphPatch { /// oxigraph::model::GroundQuad serialized to n-quads with oxrdfio pub adds: Vec, pub removes: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum DiscreteState { /// A yrs::StateVector #[serde(with = "serde_bytes")] YMap(Vec), #[serde(with = "serde_bytes")] YXml(Vec), #[serde(with = "serde_bytes")] YText(Vec), // the output of Automerge::save() #[serde(with = "serde_bytes")] Automerge(Vec), } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GraphState { pub tuples: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppState { heads: Vec, graph: Option, // there is always a graph present in the branch. but it might not have been asked in the request discrete: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AppPatch { heads: Vec, graph: Option, discrete: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FileName { pub heads: Vec, pub name: Option, pub reference: ObjectRef, pub nuri: String, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FileMetaV0 { pub content_type: String, pub size: u64, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppResponseV0 { SessionStart(AppSessionStartResponse), State(AppState), Patch(AppPatch), Text(String), File(FileName), FileUploading(u32), FileUploaded(ObjectRef), #[serde(with = "serde_bytes")] FileBinary(Vec), FileMeta(FileMetaV0), QueryResult, // see sparesults Ok, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum AppResponse { V0(AppResponseV0), }