diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..587b786e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.json -diff diff --git a/lib/data/endpoint-response.json b/lib/data/endpoint-response.json index d7f28fb1..e0e4cc39 100644 --- a/lib/data/endpoint-response.json +++ b/lib/data/endpoint-response.json @@ -1 +1 @@ -{"name":"WP-API Testbed","description":"Just another WordPress site","url":"http://wpapi.loc/wp","home":"http://wpapi.loc","namespaces":["wp/v2","oembed/1.0"],"authentication":{"oauth1":{"request":"http://wpapi.loc/oauth1/request","authorize":"http://wpapi.loc/oauth1/authorize","access":"http://wpapi.loc/oauth1/access","version":"0.1"}},"routes":{"/":{"namespace":"","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view"}}}],"_links":{"self":"http://wpapi.loc/wp-json/"}},"/wp/v2":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"namespace":{"required":false,"default":"wp/v2"},"context":{"required":false,"default":"view"}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2"}},"/wp/v2/posts":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"after":{"required":false,"description":"Limit response to resources published after a given ISO8601 compliant date."},"author":{"required":false,"default":[],"description":"Limit result set to posts assigned to specific authors."},"author_exclude":{"required":false,"default":[],"description":"Ensure result set excludes posts assigned to specific authors."},"before":{"required":false,"description":"Limit response to resources published before a given ISO8601 compliant date."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"desc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"date","enum":["date","id","include","title","slug"],"description":"Sort collection by object attribute."},"slug":{"required":false,"description":"Limit result set to posts with a specific slug."},"status":{"required":false,"default":"publish","description":"Limit result set to posts assigned a specific status."},"filter":{"required":false,"description":"Use WP Query arguments to modify the response; private query vars require appropriate authorization."},"categories":{"required":false,"default":[],"description":"Limit result set to all items that have the specified term assigned in the categories taxonomy."},"tags":{"required":false,"default":[],"description":"Limit result set to all items that have the specified term assigned in the tags taxonomy."}}},{"methods":["POST"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"title":{"required":false,"description":"The title for the object."},"content":{"required":false,"description":"The content for the object."},"author":{"required":false,"description":"The id for the author of the object."},"excerpt":{"required":false,"description":"The excerpt for the object."},"featured_media":{"required":false,"description":"The id of the featured media for the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"format":{"required":false,"enum":["standard","aside","chat","gallery","link","image","quote","status","video","audio"],"description":"The format for the object."},"sticky":{"required":false,"description":"Whether or not the object should be treated as sticky."},"categories":{"required":false,"description":"The terms assigned to the object in the category taxonomy."},"tags":{"required":false,"description":"The terms assigned to the object in the post_tag taxonomy."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/posts"}},"/wp/v2/posts/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"title":{"required":false,"description":"The title for the object."},"content":{"required":false,"description":"The content for the object."},"author":{"required":false,"description":"The id for the author of the object."},"excerpt":{"required":false,"description":"The excerpt for the object."},"featured_media":{"required":false,"description":"The id of the featured media for the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"format":{"required":false,"enum":["standard","aside","chat","gallery","link","image","quote","status","video","audio"],"description":"The format for the object."},"sticky":{"required":false,"description":"Whether or not the object should be treated as sticky."},"categories":{"required":false,"description":"The terms assigned to the object in the category taxonomy."},"tags":{"required":false,"description":"The terms assigned to the object in the post_tag taxonomy."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Whether to bypass trash and force deletion."}}}]},"/wp/v2/posts/(?P[\\d]+)/revisions":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}]},"/wp/v2/posts/(?P[\\d]+)/revisions/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["DELETE"],"args":[]}]},"/wp/v2/pages":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"after":{"required":false,"description":"Limit response to resources published after a given ISO8601 compliant date."},"author":{"required":false,"default":[],"description":"Limit result set to posts assigned to specific authors."},"author_exclude":{"required":false,"default":[],"description":"Ensure result set excludes posts assigned to specific authors."},"before":{"required":false,"description":"Limit response to resources published before a given ISO8601 compliant date."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"menu_order":{"required":false,"description":"Limit result set to resources with a specific menu_order value."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"desc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"date","enum":["date","id","include","title","slug","menu_order"],"description":"Sort collection by object attribute."},"parent":{"required":false,"default":[],"description":"Limit result set to those of particular parent ids."},"parent_exclude":{"required":false,"default":[],"description":"Limit result set to all items except those of a particular parent id."},"slug":{"required":false,"description":"Limit result set to posts with a specific slug."},"status":{"required":false,"default":"publish","description":"Limit result set to posts assigned a specific status."},"filter":{"required":false,"description":"Use WP Query arguments to modify the response; private query vars require appropriate authorization."}}},{"methods":["POST"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"parent":{"required":false,"description":"The id for the parent of the object."},"title":{"required":false,"description":"The title for the object."},"content":{"required":false,"description":"The content for the object."},"author":{"required":false,"description":"The id for the author of the object."},"excerpt":{"required":false,"description":"The excerpt for the object."},"featured_media":{"required":false,"description":"The id of the featured media for the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"menu_order":{"required":false,"description":"The order of the object in relation to other object of its type."},"template":{"required":false,"enum":[],"description":"The theme file to use to display the object."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/pages"}},"/wp/v2/pages/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"parent":{"required":false,"description":"The id for the parent of the object."},"title":{"required":false,"description":"The title for the object."},"content":{"required":false,"description":"The content for the object."},"author":{"required":false,"description":"The id for the author of the object."},"excerpt":{"required":false,"description":"The excerpt for the object."},"featured_media":{"required":false,"description":"The id of the featured media for the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"menu_order":{"required":false,"description":"The order of the object in relation to other object of its type."},"template":{"required":false,"enum":[],"description":"The theme file to use to display the object."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Whether to bypass trash and force deletion."}}}]},"/wp/v2/pages/(?P[\\d]+)/revisions":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}]},"/wp/v2/pages/(?P[\\d]+)/revisions/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["DELETE"],"args":[]}]},"/wp/v2/media":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"after":{"required":false,"description":"Limit response to resources published after a given ISO8601 compliant date."},"author":{"required":false,"default":[],"description":"Limit result set to posts assigned to specific authors."},"author_exclude":{"required":false,"default":[],"description":"Ensure result set excludes posts assigned to specific authors."},"before":{"required":false,"description":"Limit response to resources published before a given ISO8601 compliant date."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"desc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"date","enum":["date","id","include","title","slug"],"description":"Sort collection by object attribute."},"parent":{"required":false,"default":[],"description":"Limit result set to those of particular parent ids."},"parent_exclude":{"required":false,"default":[],"description":"Limit result set to all items except those of a particular parent id."},"slug":{"required":false,"description":"Limit result set to posts with a specific slug."},"status":{"required":false,"default":"inherit","enum":["inherit","private","trash"],"description":"Limit result set to posts assigned a specific status."},"filter":{"required":false,"description":"Use WP Query arguments to modify the response; private query vars require appropriate authorization."},"media_type":{"required":false,"enum":["image","video","text","application","audio"],"description":"Limit result set to attachments of a particular media type."},"mime_type":{"required":false,"description":"Limit result set to attachments of a particular mime type."}}},{"methods":["POST"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"title":{"required":false,"description":"The title for the object."},"author":{"required":false,"description":"The id for the author of the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"alt_text":{"required":false,"description":"Alternative text to display when resource is not displayed."},"caption":{"required":false,"description":"The caption for the resource."},"description":{"required":false,"description":"The description for the resource."},"post":{"required":false,"description":"The id for the associated post of the resource."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/media"}},"/wp/v2/media/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"title":{"required":false,"description":"The title for the object."},"author":{"required":false,"description":"The id for the author of the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"alt_text":{"required":false,"description":"Alternative text to display when resource is not displayed."},"caption":{"required":false,"description":"The caption for the resource."},"description":{"required":false,"description":"The description for the resource."},"post":{"required":false,"description":"The id for the associated post of the resource."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Whether to bypass trash and force deletion."}}}]},"/wp/v2/types":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/types"}},"/wp/v2/types/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}]},"/wp/v2/statuses":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/statuses"}},"/wp/v2/statuses/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}]},"/wp/v2/taxonomies":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"type":{"required":false,"description":"Limit results to resources associated with a specific post type."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/taxonomies"}},"/wp/v2/taxonomies/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}}]},"/wp/v2/categories":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"order":{"required":false,"default":"asc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"name","enum":["id","include","name","slug","term_group","description","count"],"description":"Sort collection by resource attribute."},"hide_empty":{"required":false,"default":false,"description":"Whether to hide resources not assigned to any posts."},"parent":{"required":false,"description":"Limit result set to resources assigned to a specific parent."},"post":{"required":false,"description":"Limit result set to resources assigned to a specific post."},"slug":{"required":false,"description":"Limit result set to resources with a specific slug."}}},{"methods":["POST"],"args":{"description":{"required":false,"description":"HTML description of the resource."},"name":{"required":true,"description":"HTML title for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource unique to its type."},"parent":{"required":false,"description":"The id for the parent of the resource."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/categories"}},"/wp/v2/categories/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"description":{"required":false,"description":"HTML description of the resource."},"name":{"required":false,"description":"HTML title for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource unique to its type."},"parent":{"required":false,"description":"The id for the parent of the resource."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Required to be true, as resource does not support trashing."}}}]},"/wp/v2/tags":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"asc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"name","enum":["id","include","name","slug","term_group","description","count"],"description":"Sort collection by resource attribute."},"hide_empty":{"required":false,"default":false,"description":"Whether to hide resources not assigned to any posts."},"post":{"required":false,"description":"Limit result set to resources assigned to a specific post."},"slug":{"required":false,"description":"Limit result set to resources with a specific slug."}}},{"methods":["POST"],"args":{"description":{"required":false,"description":"HTML description of the resource."},"name":{"required":true,"description":"HTML title for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource unique to its type."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/tags"}},"/wp/v2/tags/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"description":{"required":false,"description":"HTML description of the resource."},"name":{"required":false,"description":"HTML title for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource unique to its type."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Required to be true, as resource does not support trashing."}}}]},"/wp/v2/users":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"asc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"name","enum":["id","include","name","registered_date"],"description":"Sort collection by object attribute."},"slug":{"required":false,"description":"Limit result set to resources with a specific slug."},"roles":{"required":false,"description":"Limit result set to resources matching at least one specific role provided. Accepts csv list or single role."}}},{"methods":["POST"],"args":{"username":{"required":true,"description":"Login name for the resource."},"name":{"required":false,"description":"Display name for the resource."},"first_name":{"required":false,"description":"First name for the resource."},"last_name":{"required":false,"description":"Last name for the resource."},"email":{"required":true,"description":"The email address for the resource."},"url":{"required":false,"description":"URL of the resource."},"description":{"required":false,"description":"Description of the resource."},"nickname":{"required":false,"description":"The nickname for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource."},"roles":{"required":false,"description":"Roles assigned to the resource."},"password":{"required":true,"description":"Password for the resource (never included)."},"capabilities":{"required":false,"description":"All capabilities assigned to the resource."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/users"}},"/wp/v2/users/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"username":{"required":false,"description":"Login name for the resource."},"name":{"required":false,"description":"Display name for the resource."},"first_name":{"required":false,"description":"First name for the resource."},"last_name":{"required":false,"description":"Last name for the resource."},"email":{"required":false,"description":"The email address for the resource."},"url":{"required":false,"description":"URL of the resource."},"description":{"required":false,"description":"Description of the resource."},"nickname":{"required":false,"description":"The nickname for the resource."},"slug":{"required":false,"description":"An alphanumeric identifier for the resource."},"roles":{"required":false,"description":"Roles assigned to the resource."},"password":{"required":false,"description":"Password for the resource (never included)."},"capabilities":{"required":false,"description":"All capabilities assigned to the resource."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Required to be true, as resource does not support trashing."},"reassign":{"required":false}}}]},"/wp/v2/users/me":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/users/me"}},"/wp/v2/comments":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"after":{"required":false,"description":"Limit response to resources published after a given ISO8601 compliant date."},"author":{"required":false,"description":"Limit result set to comments assigned to specific user ids. Requires authorization."},"author_exclude":{"required":false,"description":"Ensure result set excludes comments assigned to specific user ids. Requires authorization."},"author_email":{"required":false,"description":"Limit result set to that from a specific author email. Requires authorization."},"before":{"required":false,"description":"Limit response to resources published before a given ISO8601 compliant date."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"karma":{"required":false,"description":"Limit result set to that of a particular comment karma. Requires authorization."},"offset":{"required":false,"description":"Offset the result set by a specific number of comments."},"order":{"required":false,"default":"asc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"date_gmt","enum":["date","date_gmt","id","include","post","parent","type"],"description":"Sort collection by object attribute."},"parent":{"required":false,"default":[],"description":"Limit result set to resources of specific parent ids."},"parent_exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific parent ids."},"post":{"required":false,"default":[],"description":"Limit result set to resources assigned to specific post ids."},"status":{"required":false,"default":"approve","description":"Limit result set to comments assigned a specific status. Requires authorization."},"type":{"required":false,"default":"comment","description":"Limit result set to comments assigned a specific type. Requires authorization."}}},{"methods":["POST"],"args":{"author":{"required":false,"description":"The id of the user object, if author was a user."},"author_email":{"required":false,"description":"Email address for the object author."},"author_name":{"required":false,"default":"","description":"Display name for the object author."},"author_url":{"required":false,"description":"URL for the object author."},"content":{"required":false,"default":"","description":"The content for the object."},"date":{"required":false,"description":"The date the object was published."},"date_gmt":{"required":false,"description":"The date the object was published as GMT."},"karma":{"required":false,"description":"Karma for the object."},"parent":{"required":false,"default":0,"description":"The id for the parent of the object."},"post":{"required":false,"default":0,"description":"The id of the associated post object."},"status":{"required":false,"description":"State of the object."},"type":{"required":false,"default":"","description":"Type of Comment for the object."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/comments"}},"/wp/v2/comments/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."}}},{"methods":["POST","PUT","PATCH"],"args":{"author":{"required":false,"description":"The id of the user object, if author was a user."},"author_email":{"required":false,"description":"Email address for the object author."},"author_name":{"required":false,"description":"Display name for the object author."},"author_url":{"required":false,"description":"URL for the object author."},"content":{"required":false,"description":"The content for the object."},"date":{"required":false,"description":"The date the object was published."},"date_gmt":{"required":false,"description":"The date the object was published as GMT."},"karma":{"required":false,"description":"Karma for the object."},"parent":{"required":false,"description":"The id for the parent of the object."},"post":{"required":false,"description":"The id of the associated post object."},"status":{"required":false,"description":"State of the object."},"type":{"required":false,"description":"Type of Comment for the object."}}},{"methods":["DELETE"],"args":{"force":{"required":false,"default":false,"description":"Whether to bypass trash and force deletion."}}}]},"/oembed/1.0":{"namespace":"oembed/1.0","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"namespace":{"required":false,"default":"oembed/1.0"},"context":{"required":false,"default":"view"}}}],"_links":{"self":"http://wpapi.loc/wp-json/oembed/1.0"}},"/oembed/1.0/embed":{"namespace":"oembed/1.0","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"url":{"required":true},"format":{"required":false,"default":"json"},"maxwidth":{"required":false,"default":600}}}],"_links":{"self":"http://wpapi.loc/wp-json/oembed/1.0/embed"}}},"_links":{"help":[{"href":"http://v2.wp-api.org/"}]}} +{"name":"WP-API Testbed","description":"Just another WordPress site","url":"http://wpapi.loc/wp","home":"http://wpapi.loc","namespaces":["wp/v2","oembed/1.0"],"authentication":{"oauth1":{"request":"http://wpapi.loc/oauth1/request","authorize":"http://wpapi.loc/oauth1/authorize","access":"http://wpapi.loc/oauth1/access","version":"0.1"}},"routes":{"/":{"namespace":"","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"namespace":{"required":false},"context":{"required":false}}}]},"/wp/v2/posts":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"after":{"required":false},"author":{"required":false},"author_exclude":{"required":false},"before":{"required":false},"exclude":{"required":false},"include":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"slug":{"required":false},"status":{"required":false},"filter":{"required":false},"categories":{"required":false},"tags":{"required":false}}},{"methods":["POST"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"title":{"required":false},"content":{"required":false},"author":{"required":false},"excerpt":{"required":false},"featured_media":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"format":{"required":false},"sticky":{"required":false},"categories":{"required":false},"tags":{"required":false}}}]},"/wp/v2/posts/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"title":{"required":false},"content":{"required":false},"author":{"required":false},"excerpt":{"required":false},"featured_media":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"format":{"required":false},"sticky":{"required":false},"categories":{"required":false},"tags":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/wp/v2/posts/(?P[\\d]+)/revisions":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/posts/(?P[\\d]+)/revisions/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["DELETE"],"args":{}}]},"/wp/v2/pages":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"after":{"required":false},"author":{"required":false},"author_exclude":{"required":false},"before":{"required":false},"exclude":{"required":false},"include":{"required":false},"menu_order":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"parent":{"required":false},"parent_exclude":{"required":false},"slug":{"required":false},"status":{"required":false},"filter":{"required":false}}},{"methods":["POST"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"parent":{"required":false},"title":{"required":false},"content":{"required":false},"author":{"required":false},"excerpt":{"required":false},"featured_media":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"menu_order":{"required":false},"template":{"required":false}}}]},"/wp/v2/pages/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"parent":{"required":false},"title":{"required":false},"content":{"required":false},"author":{"required":false},"excerpt":{"required":false},"featured_media":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"menu_order":{"required":false},"template":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/wp/v2/pages/(?P[\\d]+)/revisions":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/pages/(?P[\\d]+)/revisions/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["DELETE"],"args":{}}]},"/wp/v2/media":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"after":{"required":false},"author":{"required":false},"author_exclude":{"required":false},"before":{"required":false},"exclude":{"required":false},"include":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"parent":{"required":false},"parent_exclude":{"required":false},"slug":{"required":false},"status":{"required":false},"filter":{"required":false},"media_type":{"required":false},"mime_type":{"required":false}}},{"methods":["POST"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"title":{"required":false},"author":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"alt_text":{"required":false},"caption":{"required":false},"description":{"required":false},"post":{"required":false}}}]},"/wp/v2/media/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"date":{"required":false},"date_gmt":{"required":false},"password":{"required":false},"slug":{"required":false},"status":{"required":false},"title":{"required":false},"author":{"required":false},"comment_status":{"required":false},"ping_status":{"required":false},"alt_text":{"required":false},"caption":{"required":false},"description":{"required":false},"post":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/wp/v2/types":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/types/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/statuses":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/statuses/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/taxonomies":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"type":{"required":false}}}]},"/wp/v2/taxonomies/(?P[\\w-]+)":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/categories":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"exclude":{"required":false},"include":{"required":false},"order":{"required":false},"orderby":{"required":false},"hide_empty":{"required":false},"parent":{"required":false},"post":{"required":false},"slug":{"required":false}}},{"methods":["POST"],"args":{"description":{"required":false},"name":{"required":true},"slug":{"required":false},"parent":{"required":false}}}]},"/wp/v2/categories/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"description":{"required":false},"name":{"required":false},"slug":{"required":false},"parent":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/wp/v2/tags":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"exclude":{"required":false},"include":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"hide_empty":{"required":false},"post":{"required":false},"slug":{"required":false}}},{"methods":["POST"],"args":{"description":{"required":false},"name":{"required":true},"slug":{"required":false}}}]},"/wp/v2/tags/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"description":{"required":false},"name":{"required":false},"slug":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/wp/v2/users":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"exclude":{"required":false},"include":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"slug":{"required":false},"roles":{"required":false}}},{"methods":["POST"],"args":{"username":{"required":true},"name":{"required":false},"first_name":{"required":false},"last_name":{"required":false},"email":{"required":true},"url":{"required":false},"description":{"required":false},"nickname":{"required":false},"slug":{"required":false},"roles":{"required":false},"password":{"required":true},"capabilities":{"required":false}}}]},"/wp/v2/users/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"username":{"required":false},"name":{"required":false},"first_name":{"required":false},"last_name":{"required":false},"email":{"required":false},"url":{"required":false},"description":{"required":false},"nickname":{"required":false},"slug":{"required":false},"roles":{"required":false},"password":{"required":false},"capabilities":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false},"reassign":{"required":false}}}]},"/wp/v2/users/me":{"namespace":"wp/v2","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}}]},"/wp/v2/comments":{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false},"page":{"required":false},"per_page":{"required":false},"search":{"required":false},"after":{"required":false},"author":{"required":false},"author_exclude":{"required":false},"author_email":{"required":false},"before":{"required":false},"exclude":{"required":false},"include":{"required":false},"karma":{"required":false},"offset":{"required":false},"order":{"required":false},"orderby":{"required":false},"parent":{"required":false},"parent_exclude":{"required":false},"post":{"required":false},"status":{"required":false},"type":{"required":false}}},{"methods":["POST"],"args":{"author":{"required":false},"author_email":{"required":false},"author_name":{"required":false},"author_url":{"required":false},"content":{"required":false},"date":{"required":false},"date_gmt":{"required":false},"karma":{"required":false},"parent":{"required":false},"post":{"required":false},"status":{"required":false},"type":{"required":false}}}]},"/wp/v2/comments/(?P[\\d]+)":{"namespace":"wp/v2","methods":["GET","POST","PUT","PATCH","DELETE"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false}}},{"methods":["POST","PUT","PATCH"],"args":{"author":{"required":false},"author_email":{"required":false},"author_name":{"required":false},"author_url":{"required":false},"content":{"required":false},"date":{"required":false},"date_gmt":{"required":false},"karma":{"required":false},"parent":{"required":false},"post":{"required":false},"status":{"required":false},"type":{"required":false}}},{"methods":["DELETE"],"args":{"force":{"required":false}}}]},"/oembed/1.0":{"namespace":"oembed/1.0","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"namespace":{"required":false},"context":{"required":false}}}]},"/oembed/1.0/embed":{"namespace":"oembed/1.0","methods":["GET"],"endpoints":[{"methods":["GET"],"args":{"url":{"required":true},"format":{"required":false},"maxwidth":{"required":false}}}]}}} \ No newline at end of file diff --git a/lib/data/generate-endpoint-response-json.js b/lib/data/generate-endpoint-response-json.js new file mode 100755 index 00000000..64fbfc70 --- /dev/null +++ b/lib/data/generate-endpoint-response-json.js @@ -0,0 +1,146 @@ +#!/bin/sh #/* jshint ignore:start */ +':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@" +/* jshint ignore:end */ +// ^^^ Lovely polyglot script to permit usage via node _or_ via bash: see +// http://unix.stackexchange.com/questions/65235/universal-node-js-shebang + +/** + * To avoid requiring that auto-discovery be utilized every time the API client + * is initialized, this library ships with a built-in route definition from a + * vanilla WordPress REST API installation. That file may be updated by + * installing the API plugin on a clean WP development instance, with no other + * plugins running, and downloading the JSON output from `yourwpsite.com/wp-json/` + * into the "endpoint-response.json" file in this directory. + * + * That file can also be generated by running this script against the same live + * WP REST API instance to download that same file, the difference being that, + * if the `endpoint-response.json` file is downloaded through this script, it + * will be run through the `simplifyObject` utility to cut out about 1/3 of the + * bytes of the response by removing properties that do not effect route generation. + * + * This script is NOT intended to be a dependency of any part of wp.js, and is + * provided purely as a utility for upgrading the built-in copy of the endpoint + * response JSON file that is used to bootstrap the default route handlers. + * + * @example + * + * # Invoke directly, run against default endpoint (details below) + * ./generate-endpoint-response-json.js + * + * # Invoke with `node` CLI, run against default endpoint + * node ./generate-endpoint-response-json --endpoint=http://my-site.com/wp-json + * + * This script runs against http://wpapi.loc/wp-json by default, but it can be + * run against an arbitrary WordPress REST API endpoint by passing the --endpoint + * argument on the CLI: + * + * @example + * + * # Invoke directly, run against an arbitrary WordPress API root + * ./generate-endpoint-response-json.js --endpoint=http://my-site.com/wp-json + * + * # Invoke with `node` CLI, run against an arbitrary WordPress API root + * node ./generate-endpoint-response-json --endpoint=http://my-site.com/wp-json + * + * Either form will update the `endpoint-response.json` file in this directory, + * providing that the endpoint data is downloaded successfully. + * + * This script also has some utility for downloading a custom JSON file for your + * own WP REST API-enabled site, so that you can bootstrap your own routes without + * incurring an HTTP request. To output to a different directory than the default + * (which is this directory, `lib/data/`), pass an --output argument on the CLI: + * + * @example + * + * # Output to your current working directory + * ./path/to/this/dir/generate-endpoint-response-json.js --output=. + * + * # Output to an arbitrary absolute path + * ./path/to/this/dir/generate-endpoint-response-json.js --output=/home/mordor/output.json + * + * These command-line flags may be combined, and you will usually want to use + * --endpoint alongside --output to download your own JSON into your own directory. + */ +'use strict'; + +var agent = require( 'superagent' ); +var fs = require( 'fs' ); +var path = require( 'path' ); +var simplifyObject = require( './simplify-object' ); + +// Parse the arguments object +var argv = require( 'minimist' )( process.argv.slice( 2 ) ); + +// The output directory defaults to this directory. To customize it specify your +// own directory with --output=your/output/directory (relative or absolute) +var outputPath = argv.output ? + // Nested ternary, don't try this at home: this is to support absolute paths + argv.output[ 0 ] === '/' ? argv.output : path.join( process.cwd(), argv.output ) : + path.dirname( __filename ); + +// Specify your own API endpoint with --endpoint=http://your-endpoint.com/wp-json +var endpoint = argv.endpoint || 'http://wpapi.loc/wp-json'; + +// This directory will be called to kick off the JSON download: it uses +// superagent internally for HTTP transport that respects HTTP redirects. +function getJSON( cbFn ) { + agent + .get( endpoint ) + .set( 'Accept', 'application/json' ) + .end(function( err, res ) { + // Inspect the error and then the response to infer various error states + if ( err ) { + console.error( '\nSomething went wrong! Could not download endpoint JSON.' ); + if ( err.status ) { + console.error( 'Error ' + err.status ); + } + if ( err.response && err.response.error ) { + console.error( err.response.error ); + } + return process.exit( 1 ); + } + + if ( res.type !== 'application/json' ) { + console.error( '\nError: expected response type "application/json", got ' + res.type ); + console.error( 'Could not save endpoint-response.json' ); + return process.exit( 1 ); + } + + cbFn( res ); + }); +} + +// The only assumption we want to make about the URL is that it should be a web +// URL of _some_ sort, which generally means it has "http" in it somewhere. We +// can't assume much else due to how customizable the location of API root is +// within your WP install. +if ( ! /http/i.test( endpoint ) ) { + console.error( '\nError: ' + endpoint ); + console.error( 'This does not appear to be a valid URL. Please double-check the URL format\n' + + '(should be e.g. "http://your-domain.com/wp-json") and try again.' ); + process.exit( 1 ); +} + +fs.stat( outputPath, function( err, stats ) { + if ( err || ! stats.isDirectory() ) { + console.error( '\nError: ' + outputPath ); + console.error( 'This is not a valid directory. Please double-check the path and try again.' ); + process.exit( 1 ); + } + + // If we made it this far, our arguments look good! Carry on. + getJSON(function( response ) { + // Extract the JSON + var endpointJSON = JSON.parse( JSON.stringify( response.body ) ); + var slimJSON = simplifyObject( endpointJSON ); + + var outputFilePath = path.join( outputPath, 'endpoint-response.json' ); + fs.writeFile( outputFilePath, JSON.stringify( slimJSON ), function( err ) { + if ( err ) { + console.error( '\nSomething went wrong! Could not save ' + outputFilePath ); + return process.exit( 1 ); + } + console.log( '\nSuccessfully saved ' + outputFilePath ); + }); + }); +}); diff --git a/lib/data/simplify-object.js b/lib/data/simplify-object.js new file mode 100644 index 00000000..79803088 --- /dev/null +++ b/lib/data/simplify-object.js @@ -0,0 +1,55 @@ +'use strict'; + +/** + * Walk through the keys and values of a provided object, removing any properties + * which would be inessential to the generation of the route tree used to deduce + * route handlers from a `wp-json/` root API endpoint. This module is not used by + * the wordpress-rest-api module itself, but is rather a dependency of the script + * that is used to create the `endpoint-response.json` file that is shipped along + * with this module for use in generating the "default" routes. + * + * @param {*} obj An arbitrary JS value, probably an object + * @returns {*} The passed-in value, with non-essential args properties and all + * _links properties removes. + */ +function simplifyObject( obj ) { + // Pass through falsy values, Dates and RegExp values without modification + if ( ! obj || obj instanceof Date || obj instanceof RegExp ) { + return obj; + } + + // Map arrays through simplifyObject + if ( Array.isArray( obj ) ) { + return obj.map( simplifyObject ); + } + + // Reduce through objects to run each property through simplifyObject + if ( typeof obj === 'object' ) { + return Object.keys( obj ).reduce(function( newObj, key ) { + // Omit _links objects entirely + if ( key === '_links' ) { + return newObj; + } + + // If the key is "args", omit all keys of second-level descendants + // other than "required" + if ( key === 'args' ) { + newObj.args = Object.keys( obj.args ).reduce(function( slimArgs, arg ) { + slimArgs[ arg ] = { + required: obj.args[ arg ].required + }; + return slimArgs; + }, {}); + } else { + // Pass all other objects through simplifyObject + newObj[ key ] = simplifyObject( obj[ key ] ); + } + return newObj; + }, {}); + } + + // All other types pass through without modification + return obj; +} + +module.exports = simplifyObject; diff --git a/package.json b/package.json index 65cb1ea8..98ddd6d5 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,11 @@ "wordpress" ], "scripts": { + "download-endpoint-json": "node ./lib/data/generate-endpoint-response-json", "docs": "grunt yuidoc", "jshint": "jshint --reporter=node_modules/jshint-stylish/index.js Gruntfile.js wp.js lib tests", "jscs": "jscs Gruntfile.js wp.js lib tests --reporter node_modules/jscs-stylish/jscs-stylish.js", - "lint": "npm run jshint && npm run jscs", + "lint": "npm run jshint && npm run jscs || true", "mocha": "_mocha tests --recursive --reporter=nyan", "watch": "grunt watch", "test:all": "_mocha tests --recursive --reporter=nyan", @@ -60,6 +61,7 @@ "jshint": "^2.9.2", "jshint-stylish": "^2.2.0", "load-grunt-tasks": "^0.6.0", + "minimist": "^1.2.0", "mocha": "^1.21.5", "sandboxed-module": "^1.0.3", "sinon": "^1.17.2", diff --git a/tests/unit/lib/data/posts-collection-route-definition.json b/tests/unit/lib/data/posts-collection-route-definition.json new file mode 100644 index 00000000..bd040e84 --- /dev/null +++ b/tests/unit/lib/data/posts-collection-route-definition.json @@ -0,0 +1 @@ +{"namespace":"wp/v2","methods":["GET","POST"],"endpoints":[{"methods":["GET"],"args":{"context":{"required":false,"default":"view","enum":["view","embed","edit"],"description":"Scope under which the request is made; determines fields present in response."},"page":{"required":false,"default":1,"description":"Current page of the collection."},"per_page":{"required":false,"default":10,"description":"Maximum number of items to be returned in result set."},"search":{"required":false,"description":"Limit results to those matching a string."},"after":{"required":false,"description":"Limit response to resources published after a given ISO8601 compliant date."},"author":{"required":false,"default":[],"description":"Limit result set to posts assigned to specific authors."},"author_exclude":{"required":false,"default":[],"description":"Ensure result set excludes posts assigned to specific authors."},"before":{"required":false,"description":"Limit response to resources published before a given ISO8601 compliant date."},"exclude":{"required":false,"default":[],"description":"Ensure result set excludes specific ids."},"include":{"required":false,"default":[],"description":"Limit result set to specific ids."},"offset":{"required":false,"description":"Offset the result set by a specific number of items."},"order":{"required":false,"default":"desc","enum":["asc","desc"],"description":"Order sort attribute ascending or descending."},"orderby":{"required":false,"default":"date","enum":["date","id","include","title","slug"],"description":"Sort collection by object attribute."},"slug":{"required":false,"description":"Limit result set to posts with a specific slug."},"status":{"required":false,"default":"publish","description":"Limit result set to posts assigned a specific status."},"filter":{"required":false,"description":"Use WP Query arguments to modify the response; private query vars require appropriate authorization."},"categories":{"required":false,"default":[],"description":"Limit result set to all items that have the specified term assigned in the categories taxonomy."},"tags":{"required":false,"default":[],"description":"Limit result set to all items that have the specified term assigned in the tags taxonomy."}}},{"methods":["POST"],"args":{"date":{"required":false,"description":"The date the object was published, in the site's timezone."},"date_gmt":{"required":false,"description":"The date the object was published, as GMT."},"password":{"required":false,"description":"A password to protect access to the post."},"slug":{"required":false,"description":"An alphanumeric identifier for the object unique to its type."},"status":{"required":false,"enum":["publish","future","draft","pending","private"],"description":"A named status for the object."},"title":{"required":false,"description":"The title for the object."},"content":{"required":false,"description":"The content for the object."},"author":{"required":false,"description":"The id for the author of the object."},"excerpt":{"required":false,"description":"The excerpt for the object."},"featured_media":{"required":false,"description":"The id of the featured media for the object."},"comment_status":{"required":false,"enum":["open","closed"],"description":"Whether or not comments are open on the object."},"ping_status":{"required":false,"enum":["open","closed"],"description":"Whether or not the object can be pinged."},"format":{"required":false,"enum":["standard","aside","chat","gallery","link","image","quote","status","video","audio"],"description":"The format for the object."},"sticky":{"required":false,"description":"Whether or not the object should be treated as sticky."},"categories":{"required":false,"description":"The terms assigned to the object in the category taxonomy."},"tags":{"required":false,"description":"The terms assigned to the object in the post_tag taxonomy."}}}],"_links":{"self":"http://wpapi.loc/wp-json/wp/v2/posts"}} diff --git a/tests/unit/lib/data/simplify-object.js b/tests/unit/lib/data/simplify-object.js new file mode 100644 index 00000000..1015d614 --- /dev/null +++ b/tests/unit/lib/data/simplify-object.js @@ -0,0 +1,137 @@ +'use strict'; +var expect = require( 'chai' ).expect; + +var simplifyObject = require( '../../../../lib/data/simplify-object' ); + +var fullPostsCollectionRouteDefinition = require( './posts-collection-route-definition.json' ); + +describe( 'simplifyObject', function() { + + it( 'is a function', function() { + expect( simplifyObject ).to.be.a( 'function' ); + }); + + it( 'passes through strings without modification', function() { + expect( simplifyObject( 'foo' ) ).to.be.a( 'string' ); + expect( simplifyObject( 'foo' ) ).to.equal( 'foo' ); + }); + + it( 'passes through numbers without modification', function() { + expect( simplifyObject( 7 ) ).to.be.a( 'number' ); + expect( simplifyObject( 7 ) ).to.equal( 7 ); + }); + + it( 'passes through booleans without modification', function() { + expect( simplifyObject( true ) ).to.be.a( 'boolean' ); + expect( simplifyObject( true ) ).to.equal( true ); + }); + + it( 'passes through arrays of simple values without modification', function() { + expect( simplifyObject([]) ).to.be.an( 'array' ); + expect( simplifyObject([ 1, 2, 3 ]) ).to.deep.equal([ 1, 2, 3 ]); + expect( simplifyObject([ 'a', 'b', 'c' ]) ).to.deep.equal([ 'a', 'b', 'c' ]); + expect( simplifyObject([ true, false ]) ).to.deep.equal([ true, false ]); + }); + + it( 'passes through most objects without modification', function() { + expect( simplifyObject({ + some: 'set', + of: 'basic', + nested: { + properties: [ 'of', 'no', { + particular: 'consequence' + } ], + nr: 7 + } + }) ).to.deep.equal({ + some: 'set', + of: 'basic', + nested: { + properties: [ 'of', 'no', { + particular: 'consequence' + } ], + nr: 7 + } + }); + }); + + it( 'strips out _links properties', function() { + expect( simplifyObject({ + some: 'object with a', + _links: { + prop: 'within it' + } + }) ).to.deep.equal({ + some: 'object with a' + }); + }); + + it( 'removes non-`.required` keys from children of .args objects', function() { + expect( simplifyObject({ + args: { + context: { + required: false, + other: 'properties', + go: 'here' + } + } + }) ).to.deep.equal({ + args: { + context: { + required: false + } + } + }); + }); + + it( 'properly transforms a full route definition object', function() { + expect( simplifyObject( fullPostsCollectionRouteDefinition ) ).to.deep.equal({ + namespace: 'wp/v2', + methods: [ 'GET', 'POST' ], + endpoints: [ { + methods: [ 'GET' ], + args: { + context: { required: false }, + page: { required: false }, + per_page: { required: false }, + search: { required: false }, + after: { required: false }, + author: { required: false }, + author_exclude: { required: false }, + before: { required: false }, + exclude: { required: false }, + include: { required: false }, + offset: { required: false }, + order: { required: false }, + orderby: { required: false }, + slug: { required: false }, + status: { required: false }, + filter: { required: false }, + categories: { required: false }, + tags: { required: false } + } + }, { + methods: [ 'POST' ], + args: { + date: { required: false }, + date_gmt: { required: false }, + password: { required: false }, + slug: { required: false }, + status: { required: false }, + title: { required: false }, + content: { required: false }, + author: { required: false }, + excerpt: { required: false }, + featured_media: { required: false }, + comment_status: { required: false }, + ping_status: { required: false }, + format: { required: false }, + sticky: { required: false }, + categories: { required: false }, + tags: { required: false } + } + } ] + }); + }); + +});