Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions wordpress_api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#![allow(dead_code)]
use std::sync::Arc;

use posts::*;

mod posts;

pub fn add_custom(left: i32, right: i32) -> i32 {
left + right
}
Expand All @@ -10,6 +17,14 @@ pub fn panic_from_rust() {
std::fs::read_to_string("doesnt_exist.txt").unwrap();
}

struct RequestBuilder {}

impl RequestBuilder {
fn posts(&self) -> Arc<PostsRequestBuilder> {
Arc::new(PostsRequestBuilder {})
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
51 changes: 51 additions & 0 deletions wordpress_api/src/posts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
pub struct PostsRequestBuilder {}

impl PostsRequestBuilder {
pub fn list(&self, params: Option<PostsListParams>) -> PostsRequest {
todo!()
}

pub fn create(&self, params: Option<PostsCreateParams>) -> PostsRequest {
todo!()
}

pub fn retrieve(&self, post_id: u32, params: Option<PostsRetrieveParams>) -> PostsRequest {
todo!()
}

pub fn update(&self, post_id: u32, params: Option<PostsUpdateParams>) -> PostsRequest {
todo!()
}

pub fn delete(&self, post_id: u32, params: Option<PostsDeleteParams>) -> PostsRequest {
todo!()
}
}

pub struct PostsListParams {
pub page: Option<u32>,
pub per_page: Option<u32>,
}

pub struct PostsCreateParams {
pub title: Option<String>,
pub content: Option<String>,
}

pub struct PostsRetrieveParams {
pub password: Option<String>,
}

pub struct PostsUpdateParams {
pub title: Option<String>,
pub content: Option<String>,
}

pub struct PostsDeleteParams {
pub force: Option<bool>,
}

pub struct PostsRequest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need an HTTP method member here too.

I assume we'll give this to a higher-level RestApi object that will hold the hostname, http protocol, etc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap, lots of fields are missing from this.

pub endpoint: String,
pub params: Option<String>,
}
57 changes: 57 additions & 0 deletions wordpress_api/src/wordpress_api.udl
Original file line number Diff line number Diff line change
@@ -1,5 +1,62 @@
// These are test functions that we are keeping while we figure out the design in case
// we need them for further testing.
namespace wordpress_api {
i32 add_custom(i32 a, i32 b);
string combine_strings(string a, string b);
void panic_from_rust();
};

interface RequestBuilder {
PostsRequestBuilder posts();
};

// https://developer.wordpress.org/rest-api/reference/posts/
// TODO: The schema and some of the action arguments for `/posts` endpoint has the notion of `context`.
// This is an `enum` value, but it can only contain partial values per field.
// This is an important design element to get right, because it's a common pattern for the API.
//
// IMPORTANT: This design does not include error handling yet!
interface PostsRequestBuilder {
PostsRequest list(PostsListParams? params);
PostsRequest create(PostsCreateParams? params);
PostsRequest retrieve(u32 post_id, PostsRetrieveParams? params);
PostsRequest update(u32 post_id, PostsUpdateParams? params);
PostsRequest delete(u32 post_id, PostsDeleteParams? params);
};

// If we can represent a trait relationship in UDL, we could use a common Request trait
// However, we'd still want a specific `PostsRequest` type so that we can have a strongly typed
// return value for it.
//
// The reason we can use a `PostsRequest` type and not need a more specific type such as
// `PostsListRequest` is because the API documentation states that the return value for
// all `/posts` requests have the same schema: https://developer.wordpress.org/rest-api/reference/posts/#schema
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this isn't quite true – the schema depends on the context, so view will return different fields than embed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's the case regardless of the action type (list, create etc), right? The documentation specifically says that:

The schema defines all the fields that exist within a post record. Any response from these endpoints can be expected to contain the fields below unless the _filter query parameter is used or the schema field only appears in a specific context.

That's where I was going from. However, the context bit is going to be a difficult problem for us to solve. I've actually left a TODO about that here.


I've been thinking about this after opening the PR, and regardless of the result of this discussion, we are probably going to end up with specific request types.

// If this is not the case, we'll need more specific types.
dictionary PostsRequest {
string endpoint;
string? params;
};

// We should check if it's possible to use the same params for update & create
dictionary PostsCreateParams {
string? title;
string? content;
};

dictionary PostsListParams {
u32? page;
u32? per_page;
};

dictionary PostsRetrieveParams {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, but retrieve, update, and delete operate on a single object. Should we use non-plural nouns for these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a discussion about this on Zoom today, but just for completeness sake, the reason I used Posts was to have a logical naming scheme which uses the endpoint as the first word of the type. However, I think we can always use the singular version of that and still have a logical naming scheme.

string? password;
};

dictionary PostsUpdateParams {
string? title;
string? content;
};

dictionary PostsDeleteParams {
boolean? force;
};