Skip to content

Commit 91cbfcb

Browse files
committed
Allow pugins to commit changes using their own agent #73
1 parent 933b179 commit 91cbfcb

File tree

25 files changed

+771
-86
lines changed

25 files changed

+771
-86
lines changed

atomic-plugin/src/bindings.rs

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,66 @@ pub mod atomic {
905905
result5
906906
}
907907
}
908+
#[allow(unused_unsafe, clippy::all)]
909+
/// Creates a commit and signs it using the plugin's agent.
910+
/// The commit parameter should be a stringified JSON object of a CommitBuilder.
911+
pub fn commit(commit: &str) -> Result<(), _rt::String> {
912+
unsafe {
913+
#[cfg_attr(target_pointer_width = "64", repr(align(8)))]
914+
#[cfg_attr(target_pointer_width = "32", repr(align(4)))]
915+
struct RetArea(
916+
[::core::mem::MaybeUninit<
917+
u8,
918+
>; 3 * ::core::mem::size_of::<*const u8>()],
919+
);
920+
let mut ret_area = RetArea(
921+
[::core::mem::MaybeUninit::uninit(); 3
922+
* ::core::mem::size_of::<*const u8>()],
923+
);
924+
let vec0 = commit;
925+
let ptr0 = vec0.as_ptr().cast::<u8>();
926+
let len0 = vec0.len();
927+
let ptr1 = ret_area.0.as_mut_ptr().cast::<u8>();
928+
#[cfg(target_arch = "wasm32")]
929+
#[link(wasm_import_module = "atomic:class-extender/host@0.1.0")]
930+
unsafe extern "C" {
931+
#[link_name = "commit"]
932+
fn wit_import2(_: *mut u8, _: usize, _: *mut u8);
933+
}
934+
#[cfg(not(target_arch = "wasm32"))]
935+
unsafe extern "C" fn wit_import2(_: *mut u8, _: usize, _: *mut u8) {
936+
unreachable!()
937+
}
938+
unsafe { wit_import2(ptr0.cast_mut(), len0, ptr1) };
939+
let l3 = i32::from(*ptr1.add(0).cast::<u8>());
940+
let result7 = match l3 {
941+
0 => {
942+
let e = ();
943+
Ok(e)
944+
}
945+
1 => {
946+
let e = {
947+
let l4 = *ptr1
948+
.add(::core::mem::size_of::<*const u8>())
949+
.cast::<*mut u8>();
950+
let l5 = *ptr1
951+
.add(2 * ::core::mem::size_of::<*const u8>())
952+
.cast::<usize>();
953+
let len6 = l5;
954+
let bytes6 = _rt::Vec::from_raw_parts(
955+
l4.cast(),
956+
len6,
957+
len6,
958+
);
959+
_rt::string_lift(bytes6)
960+
};
961+
Err(e)
962+
}
963+
_ => _rt::invalid_enum_discriminant(),
964+
};
965+
result7
966+
}
967+
}
908968
}
909969
}
910970
}
@@ -974,8 +1034,8 @@ pub(crate) use __export_class_extender_impl as export;
9741034
#[unsafe(link_section = "component-type:wit-bindgen:0.41.0:atomic:class-extender@0.1.0:class-extender:encoded world")]
9751035
#[doc(hidden)]
9761036
#[allow(clippy::octal_escapes)]
977-
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 965] = *b"\
978-
\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xc0\x06\x01A\x02\x01\
1037+
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 994] = *b"\
1038+
\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xdd\x06\x01A\x02\x01\
9791039
A\x17\x01B\x0b\x01r\x01\x07subjects\x04\0\x0catomic-agent\x03\0\0\x01r\x02\x07su\
9801040
bjects\x07json-ads\x04\0\x0dresource-json\x03\0\x02\x01p\x03\x01r\x02\x07primary\
9811041
\x03\x0areferenced\x04\x04\0\x11resource-response\x03\0\x05\x01r\x04\x0brequest-\
@@ -984,18 +1044,19 @@ t\x03\0\x07\x01r\x03\x07subjects\x0bcommit-jsons\x08snapshot\x03\x04\0\x0ecommit
9841044
-context\x03\0\x09\x03\0!atomic:class-extender/types@0.1.0\x05\0\x02\x03\0\0\x11\
9851045
resource-response\x03\0\x11resource-response\x03\0\x01\x02\x03\0\0\x0bget-contex\
9861046
t\x03\0\x0bget-context\x03\0\x03\x02\x03\0\0\x0ecommit-context\x03\0\x0ecommit-c\
987-
ontext\x03\0\x05\x02\x03\0\0\x0dresource-json\x02\x03\0\0\x0catomic-agent\x01B\x0f\
1047+
ontext\x03\0\x05\x02\x03\0\0\x0dresource-json\x02\x03\0\0\x0catomic-agent\x01B\x12\
9881048
\x02\x03\x02\x01\x07\x04\0\x0dresource-json\x03\0\0\x02\x03\x02\x01\x08\x04\0\x0c\
9891049
atomic-agent\x03\0\x02\x01ks\x01j\x01\x01\x01s\x01@\x02\x07subjects\x05agent\x04\
9901050
\0\x05\x04\0\x0cget-resource\x01\x06\x01p\x01\x01j\x01\x07\x01s\x01@\x03\x08prop\
9911051
ertys\x05values\x05agent\x04\0\x08\x04\0\x05query\x01\x09\x01@\0\0s\x04\0\x10get\
992-
-plugin-agent\x01\x0a\x04\0\x0aget-config\x01\x0a\x03\0\x20atomic:class-extender\
993-
/host@0.1.0\x05\x09\x01ps\x01@\0\0\x0a\x04\0\x09class-url\x01\x0b\x01k\x02\x01j\x01\
994-
\x0c\x01s\x01@\x01\x03ctx\x04\0\x0d\x04\0\x0fon-resource-get\x01\x0e\x01j\0\x01s\
995-
\x01@\x01\x03ctx\x06\0\x0f\x04\0\x0dbefore-commit\x01\x10\x04\0\x0cafter-commit\x01\
996-
\x10\x04\0*atomic:class-extender/class-extender@0.1.0\x04\0\x0b\x14\x01\0\x0ecla\
997-
ss-extender\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x07\
998-
0.227.1\x10wit-bindgen-rust\x060.41.0";
1052+
-plugin-agent\x01\x0a\x04\0\x0aget-config\x01\x0a\x01j\0\x01s\x01@\x01\x06commit\
1053+
s\0\x0b\x04\0\x06commit\x01\x0c\x03\0\x20atomic:class-extender/host@0.1.0\x05\x09\
1054+
\x01ps\x01@\0\0\x0a\x04\0\x09class-url\x01\x0b\x01k\x02\x01j\x01\x0c\x01s\x01@\x01\
1055+
\x03ctx\x04\0\x0d\x04\0\x0fon-resource-get\x01\x0e\x01j\0\x01s\x01@\x01\x03ctx\x06\
1056+
\0\x0f\x04\0\x0dbefore-commit\x01\x10\x04\0\x0cafter-commit\x01\x10\x04\0*atomic\
1057+
:class-extender/class-extender@0.1.0\x04\0\x0b\x14\x01\0\x0eclass-extender\x03\0\
1058+
\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bi\
1059+
ndgen-rust\x060.41.0";
9991060
#[inline(never)]
10001061
#[doc(hidden)]
10011062
pub fn __link_custom_section_describing_imports() {

atomic-plugin/src/lib.rs

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#[doc(hidden)]
22
pub mod bindings;
33

4+
use std::collections::{HashMap, HashSet};
5+
46
#[doc(hidden)]
57
pub use bindings::*;
68

@@ -21,7 +23,7 @@ pub mod packaging;
2123
#[cfg(not(target_arch = "wasm32"))]
2224
pub use packaging::packaging_impl;
2325

24-
use serde::Deserialize;
26+
use serde::{Deserialize, Serialize};
2527
use serde_json::Value as JsonValue;
2628

2729
pub struct Resource {
@@ -65,6 +67,74 @@ pub struct Commit {
6567
pub url: Option<String>,
6668
}
6769

70+
/// Use this for creating Commits.
71+
#[derive(Clone, Debug, Serialize, Deserialize)]
72+
pub struct CommitBuilder {
73+
/// The subject URL that is to be modified by this Delta.
74+
/// Not the URL of the Commit itself.
75+
/// https://atomicdata.dev/properties/subject
76+
pub subject: String,
77+
/// The set of PropVals that need to be added.
78+
/// Overwrites existing values
79+
/// https://atomicdata.dev/properties/set
80+
set: std::collections::HashMap<String, JsonValue>,
81+
/// The set of PropVals that need to be appended to resource arrays.
82+
push: std::collections::HashMap<String, Vec<String>>,
83+
/// A map of Propvals containing Yjs updates to be applied to the YDocs
84+
y_update: std::collections::HashMap<String, JsonValue>,
85+
/// The set of property URLs that need to be removed
86+
/// https://atomicdata.dev/properties/remove
87+
remove: HashSet<String>,
88+
/// If set to true, deletes the entire resource
89+
/// https://atomicdata.dev/properties/destroy
90+
destroy: bool,
91+
previous_commit: Option<String>,
92+
}
93+
94+
impl CommitBuilder {
95+
pub fn new(subject: String) -> Self {
96+
Self {
97+
subject,
98+
set: HashMap::new(),
99+
push: HashMap::new(),
100+
y_update: HashMap::new(),
101+
remove: HashSet::new(),
102+
destroy: false,
103+
previous_commit: None,
104+
}
105+
}
106+
107+
/// Set Property / Value combinations that will either be created or overwritten.
108+
pub fn set(&mut self, prop: String, val: JsonValue) -> &Self {
109+
self.set.insert(prop, val);
110+
111+
self
112+
}
113+
114+
/// Set Property URLs which values to be removed
115+
pub fn remove(&mut self, prop: String) -> &Self {
116+
self.remove.insert(prop);
117+
118+
self
119+
}
120+
121+
/// Whether the resource needs to be removed fully
122+
pub fn destroy(&mut self, destroy: bool) {
123+
self.destroy = destroy;
124+
}
125+
126+
/// Appends a Resource subject to a ResourceArray.
127+
pub fn push(&mut self, property: &str, value: String) -> &Self {
128+
let Some(vec) = self.push.get_mut(property) else {
129+
self.push.insert(property.to_string(), vec![value]);
130+
return self;
131+
};
132+
133+
vec.push(value.clone());
134+
self
135+
}
136+
}
137+
68138
/// High-level trait for implementing a Class Extender plugin.
69139
pub trait ClassExtender {
70140
fn class_url() -> Vec<String>;
@@ -149,24 +219,23 @@ macro_rules! export_plugin {
149219
};
150220
}
151221

152-
/// Gets a resource from the store, optionally uses the given agent. If no agent is provided the public agent is used.
153-
pub fn get_resource(subject: String, agent: Option<String>) -> Result<Resource, String> {
154-
host::get_resource(&subject, agent.as_deref())
222+
/// Gets a resource from the store by subject, the plugin's agent is used to authorize the request.
223+
pub fn get_resource(subject: String) -> Result<Resource, String> {
224+
host::get_resource(&subject, None)
155225
.map(|json| Resource::try_from(json).map_err(|e| e.to_string()))?
156226
}
157227

158-
pub fn query(
159-
property: String,
160-
value: String,
161-
agent: Option<String>,
162-
) -> Result<Vec<Resource>, String> {
163-
host::query(&property, &value, agent.as_deref()).map(|json| {
228+
/// Queries the store for resources that match the given property and value, the plugin's agent is used to authorize the request.
229+
pub fn query(property: String, value: String) -> Result<Vec<Resource>, String> {
230+
host::query(&property, &value, None).map(|json| {
164231
json.into_iter()
165232
.map(|json| Resource::try_from(json).map_err(|e| e.to_string()))
166233
.collect::<Result<Vec<Resource>, String>>()
167234
})?
168235
}
169236

237+
/// Gets the config of the plugin deserialized to the given type.
238+
/// The user can edit this config at any time.
170239
pub fn get_config<'a, T>() -> Result<T, String>
171240
where
172241
T: for<'de> Deserialize<'de>,
@@ -176,6 +245,13 @@ where
176245
.map_err(|e| format!("Failed to deserialize config: {}", e))
177246
}
178247

248+
/// Creates a commit and signs it using the plugin's agent.
249+
pub fn commit(commit: &CommitBuilder) -> Result<(), String> {
250+
let commit_str =
251+
serde_json::to_string(commit).map_err(|e| format!("Failed to serialize commit: {}", e))?;
252+
host::commit(&commit_str).map_err(|e| format!("Failed to commit: {}", e))
253+
}
254+
179255
impl TryFrom<ResourceJson> for Resource {
180256
type Error = String;
181257

atomic-plugin/wit/class-extender.wit

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ package atomic:class-extender@0.1.0;
33
interface host {
44
use types.{resource-json, atomic-agent};
55

6-
// Returns a resource by subject.
6+
/// Returns a resource by subject.
77
get-resource: func(subject: string, agent: option<string>) -> result<resource-json, string>;
8-
// Returns a list of resources that match the query.
8+
/// Returns a list of resources that match the query.
99
query: func(property: string, value: string, agent: option<string>) -> result<list<resource-json>, string>;
1010
get-plugin-agent: func() -> string;
11-
// Returns the JSON config of the plugin as a string. The user can edit this config at any time.
11+
/// Returns the JSON config of the plugin as a string. The user can edit this config at any time.
1212
get-config: func() -> string;
13+
/**
14+
Creates a commit and signs it using the plugin's agent.
15+
The commit parameter should be a stringified JSON object of a CommitBuilder.
16+
*/
17+
commit: func(commit: string) -> result<_, string>;
1318
}
1419

1520
interface types {

browser/data-browser/src/components/Card.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ export const Card = styled.div.attrs<CardProps>(p => ({
2121
container: ${CARD_CONTAINER} / inline-size;
2222
border: solid 1px
2323
${p => (p.highlight ? p.theme.colors.main : p.theme.colors.bg2)};
24-
box-shadow: ${p =>
25-
p.highlight
26-
? `0 0 0 1px ${p.theme.colors.main}, ${p.theme.boxShadow}`
27-
: p.theme.boxShadow};
2824
2925
padding: ${p => p.theme.size()};
3026
border-radius: ${p => p.theme.radius};

browser/data-browser/src/locales/de.po

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3403,3 +3403,7 @@ msgstr "Ihre Konfiguration ist nicht vollständig mit der neuen Version kompatib
34033403
#: src/chunks/Plugins/UpdatePluginButton.tsx
34043404
msgid "Apply"
34053405
msgstr "Anwenden"
3406+
3407+
#: src/views/Drive/PluginList.tsx
3408+
msgid "No plugins installed"
3409+
msgstr "Keine Plugins installiert"

browser/data-browser/src/locales/en.po

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3385,3 +3385,7 @@ msgstr "Apply"
33853385
#: src/chunks/Plugins/UpdatePluginButton.tsx
33863386
msgid "Your config is not fully compatible with the new version."
33873387
msgstr "Your config is not fully compatible with the new version."
3388+
3389+
#: src/views/Drive/PluginList.tsx
3390+
msgid "No plugins installed"
3391+
msgstr "No plugins installed"

browser/data-browser/src/locales/es.po

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,3 +3369,19 @@ msgstr "Tu configuración no es totalmente compatible con la nueva versión."
33693369
#: src/chunks/Plugins/UpdatePluginButton.tsx
33703370
msgid "Apply"
33713371
msgstr "Aplicar"
3372+
3373+
#: src/views/Drive/PluginList.tsx
3374+
msgid "No plugins installed"
3375+
msgstr "No hay plugins instalados"
3376+
3377+
#: src/chunks/AI/AIChatPage.tsx
3378+
msgid "Failed to create message resource"
3379+
msgstr "No se pudo crear el recurso del mensaje."
3380+
3381+
#: src/chunks/AI/RealAIChat.tsx
3382+
msgid "Changes Saved!"
3383+
msgstr "¡Cambios guardados!"
3384+
3385+
#: src/chunks/AI/RealAIChat.tsx
3386+
msgid "Failed to save changes"
3387+
msgstr "Error al guardar los cambios"

browser/data-browser/src/locales/fr.po

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3400,3 +3400,7 @@ msgstr "Votre configuration n'est pas entièrement compatible avec la nouvelle v
34003400
#: src/chunks/Plugins/UpdatePluginButton.tsx
34013401
msgid "Apply"
34023402
msgstr "Appliquer"
3403+
3404+
#: src/views/Drive/PluginList.tsx
3405+
msgid "No plugins installed"
3406+
msgstr "Aucun plugin installé"

0 commit comments

Comments
 (0)