-
Notifications
You must be signed in to change notification settings - Fork 191
Dynamically generate endpoint handlers based on schema #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
lib/parse-route-string.js
Outdated
| "/wp/v2/pages": {}, | ||
| "/wp/v2/pages/(?P<id>[\\d]+)": {}, | ||
| "/wp/v2/pages/(?P<parent>[\\d]+)/revisions": {}, | ||
| "/wp/v2/pages/(?P<parent>[\\d]+)/revisions/(?P<id>[\\d]+)": {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows an example of what the route definitions look like—currently, I parse out the named capture groups from the regexes and use them to construct a representation of each "level" of the tree, where a "level" is one segment of a URL between /s.
Here's what the generated tree looks like for the posts routes defined here:
"dynamic" and "level" are inferred while walking the tree; validate methods are generated based on whether a given input matches the regex defined in a named capture group. "names" represents the list of names given to the same capture group in different routes under the same root resource type; the name could (and hopefully will) be used to auto-generate chaining methods to populate that segment of the URL.
This is the first step of an overall architectural change with two goals: decrease code duplication between endpoints, and enable filtering functionality to be applied to programmatically-generated endpoint handlers (see #145)
Comments are not currently supported as a top-level endpoint. This adds a basic `/comments` endpoint handler, which can - Retrieve a paged collection of comments - Retrieve a specific comment by ID - Retrieve comments by their parent post or page via the `.forPost()` query parameter method Unit tests and integration tests have been added to validate the enumerated behaviors of the endpoint handler work as expected. Further [comment query parameters](http://v2.wp-api.org/reference/comments/) will follow in subsequent PRs, possibly following #145.
This is the first step of an overall architectural change with two goals: decrease code duplication between endpoints, and enable filtering functionality to be applied to programmatically-generated endpoint handlers (see #145)
This PR extracts the filtering and query parameter methods into mixin functions that can be added to a constructor to grant it the specified methods. In addition to this significant (architectural) change, filters and parameter setters no longer have implicit interdependencies: with the exception of .param itself, which is a part of the base WP-Request class, all filter methods depend on each other directly where needed so that any filter can be included into a subclass with no restrictions. The goal of this patch is to 1. decrease code duplication between endpoints 2. better surface and test edge cases in parameter and filter methods 3. simplify the ability to add filtering functionality to programatically- generated endpoint handlers (see #145) To accomplish these goals I - moved CollectionRequest filter methods into a filter mixin module - moved CollectionRequest parameter methods into a parameter mixin module - moved filter and parameter mixins from other endpoints (page, taxonomies, comments) into the filter and parameter mixin modules as appropriate - unit tested the new filter and parameter mixin modules - adjusted how `.filter` and `.param` function to address edge cases exposed during testing, such as unexpected behavior when calling `.filter` or `.param` with no second argument. - allowed filters to initialize their own private state objects (the `this._filters` and `this._taxonomyFilters` objects), so that they can be included into a prototype without any further pre-work required to make them function with that constructor - removed all existing explicit definition of `this._filters` and `this._taxonomyFilters` objects in endpoint request handler constructors, since those objects will now be created only when needed There is currently some duplicate testing logic between the mixin files and the request handler tests themselves; this is not seen as a detriment but since the mixins are fully tested the assertions in the constructor test suites may eventually be replaced with tests that verify the mixins have been applied properly.
c0915f1 to
d77c507
Compare
|
This is an excellent idea and something I'm anxiously anticipating. I've lately been building a newer rendition of my |
0440e53 to
f62246e
Compare
Finish updating comments unit tests to reflect new methodology
667de63 to
aba794e
Compare
aba794e to
5533e3e
Compare
CollectionRequest tests that have not been superceded by the mixin test suite have been moved to WPRequest
|
@jasonphillips This is ready for review. At present there is no functionality exposed to dynamically generate a handler from your own site, but this includes all the plumbing necessary to do so. |
|
That's great, I'll look forward to diving into this. Basically, to answer your prior question, my Falcor router was sitting atop your library as its simpler way into the Wordpress API, but just building out the kind of single-model routing logic needed by Falcor on top of that. So, a Falcor route (here for taxonomy terms) calls my handler classes (base class expects promises from your library in each overridden case) to fetch from the API and restructure the response for Falcor's world, following deeper nested paths in same flight (ie, fetch a post and descend into its connected terms and their properties as well). I have been setting this up to use the live demo.wp-api.org (which always has latest dev code) in my automated tests, but I realized recently that keeping pace with the moving paths of the in-development WP-API is a real challenge. I was about to start down the road you have (parsing the list of endpoints offered by a live WP-API) and then noticed that you've already done the work. From this point I'll probably need to decided whether to keep using your library as a whole to communicate with the API or whether to just take your completed work on parsing the available REST paths / variables and use those directly. This is great though, to have someone push forward in making sense of all the available endpoints so that they can be chained and used logically. |
|
@jasonphillips Thanks for the comment. I haven't used Falcor, so forgive me the confusion: this is a purely JS-side compatibility layer that digests WP API response data and reformulates it into a new structure?
I am not clear on the issue; I had thought that your code would use my library to get the data from WP, then would transform it in some fashion once responded, but I may be misinterpreting because I'm now wondering whether you mean that you were hoping to point the wordpress-rest-api client at endpoints defined in JS, not in PHP. Any clarification would be appreciated! |
|
Also it's important to note that given the looming WCEU deadline, the functionality to actually bind a wp rest api client instance to an arbitrary API endpoint with arbitrary first- or third-party routes is a this-week thing, not an another-four-months thing :) |
|
Basic overview of this patch:
|
My apologies; yes Falcor would typically be run in a node.js process on the server, so that your front-end hits your Falcor instance with data requests and Falcor, in turn, fetches all the data from the third-party service (in this case, from a Wordpress REST API using your client) then restructures and returns it in one batch to front-end client. The main advantage is the ability to express deep paths and complex sets of items to retrieve in one request, then have all those parsed out, fetched, and packaged into a single response by the node.js backend (which might be making any number of calls to the REST API in the background to fulfill those data needs, or can set a built-in cache timeout for the last time it retrieved a particular item, etc). So it helps overcome the main drawback of REST for front-end use, which is that one would often need to make 5 or 10 requests to get all the information needed on a single page (taxonomies, recent posts, a particular full post, its children, its related items, etc). With Falcor all that can be expressed as a set of paths on a global model (
Your initial assumption is correct. I was floating the question as to whether I should depend on your library or just step up and format my own completed requests to the REST server using some of the path parsing you've worked out. But I think the former is still where I'm headed. I look forward to finding some time perhaps today to try your latest code out and see where it leads me. |
- All route handler tests now go in route-handlers/, since they are not testing code from lib/ - All key files in the handler generation flow have been moved out of util/ and up into lib/, since they are now the core functionality of the library - All files in lib/* root have been renamed to remove verbs, exposing the operative methods as named exports - WPRequest folder has been renamed to constructors/
There's a wealth of content in the readme, and an opportunity to write additional user guides. However, the documentation site currently features only the generated API docs, and ever since #145 the generated docs are not as robust as they were before. To better highlight the documentation contained within the REAMDE, in this PR we - Add grunt task to zip built browser bundles (for #196) - Implement a task to generate jekyll-ready pages from README - Generate a documentation index with deep links to the subheds of content extracted from the README file - Update CONTRIBUTING and README files to generate better output - Add a script to print out tasks necessary to release docs branch - Add a docs site favicon and add IE fallback favicon link - Add a convenience package script to run jekyll in dev mode - Add a grunt task to clean leftover files after docs release - Reorganize Grunt tasks into modules within `build/grunt/` - Lint build and bin directories, with support for es2015 syntax - Support arbitrary host when running jekyll in local dev environment There's a lot that could be done to improve the generated documentation, but as-is this closes #196 Closes #205 (this is a squashed PR)

This is an alternative philosophy than the approach in #144, whereby instead of manually configuring a route, the client auto-discovers all possible endpoints and dynamically generates handlers from the route and schema data. This should be considered heavily WIP, but after discussions with @jmeas and @adamsilverstein I have a hunch that dynamically creating a handler by parsing the route definition strings will be a more future-friendly way to create a dynamic route generation method. This PR iterates on this idea with an eye towards replicating all of the internal path-specific methods (
.posts().id( # )for example) dynamically by consuming and parsing the schema data.So far, we generate a tree representing all routes grouped under a common resource base (posts, in the selection above). We next need to walk that tree to deduce the setter methods needed to specify each level of the route.