├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE.txt
├── README.md
├── authors.txt
├── demo
├── index.html
├── package.json
└── server.js
├── lib
├── handlers
│ ├── authorsById.js
│ ├── fetchById.js
│ ├── fetchByIndices.js
│ ├── mediaById.js
│ ├── postsById.js
│ ├── postsByIndices.js
│ ├── postsByTerm.js
│ ├── taxonomiesById.js
│ ├── termsById.js
│ ├── termsByIndices.js
│ └── termsByPost.js
└── wordpressRouter.js
├── package.json
├── src
├── handlers
│ ├── authorsById.js
│ ├── fetchById.js
│ ├── fetchByIndices.js
│ ├── mediaById.js
│ ├── postsById.js
│ ├── postsByIndices.js
│ ├── postsByTerm.js
│ ├── taxonomiesById.js
│ ├── termsById.js
│ ├── termsByIndices.js
│ └── termsByPost.js
└── wordpressRouter.js
└── tests
├── fixtures
└── responses
│ ├── postsByIdMultiple
│ ├── postsByIdSingle
│ ├── postsByTermSlug
│ ├── recentPostsBasic
│ ├── taxonomiesMeta
│ └── taxonomyTermsByIndex
└── wordpressRouter.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true,
5 | "es6": true
6 | },
7 |
8 | "ecmaFeatures": {
9 | "arrowFunctions": true,
10 | "binaryLiterals": true,
11 | "blockBindings": true,
12 | "classes": true,
13 | "defaultParams": true,
14 | "destructuring": true,
15 | "forOf": true,
16 | "generators": true,
17 | "modules": true,
18 | "objectLiteralComputedProperties": true,
19 | "objectLiteralDuplicateProperties": true,
20 | "objectLiteralShorthandMethods": true,
21 | "objectLiteralShorthandProperties": true,
22 | "octalLiterals": true,
23 | "regexUFlag": true,
24 | "regexYFlag": true,
25 | "spread": true,
26 | "superInFunctions": true,
27 | "templateStrings": true,
28 | "unicodeCodePointEscapes": true,
29 | "globalReturn": true,
30 | },
31 |
32 | "rules": {
33 |
34 | //
35 | //Possible Errors
36 | //
37 | // The following rules point out areas where you might have made mistakes.
38 | //
39 | "comma-dangle": 2, // disallow or enforce trailing commas
40 | "no-cond-assign": 2, // disallow assignment in conditional expressions
41 | "no-console": 1, // disallow use of console (off by default in the node environment)
42 | "no-constant-condition": 2, // disallow use of constant expressions in conditions
43 | "no-control-regex": 2, // disallow control characters in regular expressions
44 | "no-debugger": 2, // disallow use of debugger
45 | "no-dupe-args": 2, // disallow duplicate arguments in functions
46 | "no-dupe-keys": 2, // disallow duplicate keys when creating object literals
47 | "no-duplicate-case": 2, // disallow a duplicate case label.
48 | "no-empty": 2, // disallow empty statements
49 | "no-empty-class": 2, // disallow the use of empty character classes in regular expressions
50 | "no-ex-assign": 2, // disallow assigning to the exception in a catch block
51 | "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context
52 | "no-extra-parens": 0, // disallow unnecessary parentheses (off by default)
53 | "no-extra-semi": 2, // disallow unnecessary semicolons
54 | "no-func-assign": 2, // disallow overwriting functions written as function declarations
55 | "no-inner-declarations": 2, // disallow function or variable declarations in nested blocks
56 | "no-invalid-regexp": 2, // disallow invalid regular expression strings in the RegExp constructor
57 | "no-irregular-whitespace": 2, // disallow irregular whitespace outside of strings and comments
58 | "no-negated-in-lhs": 2, // disallow negation of the left operand of an in expression
59 | "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions
60 | "no-regex-spaces": 2, // disallow multiple spaces in a regular expression literal
61 | "no-reserved-keys": 2, // disallow reserved words being used as object literal keys (off by default)
62 | "no-sparse-arrays": 2, // disallow sparse arrays
63 | "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement
64 | "use-isnan": 2, // disallow comparisons with the value NaN
65 | "valid-jsdoc": 2, // Ensure JSDoc comments are valid (off by default)
66 | "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string
67 |
68 | //
69 | // Best Practices
70 | //
71 | // These are rules designed to prevent you from making mistakes.
72 | // They either prescribe a better way of doing something or help you avoid footguns.
73 | //
74 | "block-scoped-var": 0, // treat var statements as if they were block scoped (off by default). 0: deep destructuring is not compatible https://github.com/eslint/eslint/issues/1863
75 | "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default)
76 | "consistent-return": 2, // require return statements to either always or never specify values
77 | "curly": 2, // specify curly brace conventions for all control statements
78 | "default-case": 2, // require default case in switch statements (off by default)
79 | "dot-notation": 2, // encourages use of dot notation whenever possible
80 | "eqeqeq": 2, // require the use of === and !==
81 | "guard-for-in": 2, // make sure for-in loops have an if statement (off by default)
82 | "no-alert": 2, // disallow the use of alert, confirm, and prompt
83 | "no-caller": 2, // disallow use of arguments.caller or arguments.callee
84 | "no-div-regex": 2, // disallow division operators explicitly at beginning of regular expression (off by default)
85 | "no-else-return": 2, // disallow else after a return in an if (off by default)
86 | "no-empty-label": 2, // disallow use of labels for anything other then loops and switches
87 | "no-eq-null": 2, // disallow comparisons to null without a type-checking operator (off by default)
88 | "no-eval": 2, // disallow use of eval()
89 | "no-extend-native": 2, // disallow adding to native types
90 | "no-extra-bind": 2, // disallow unnecessary function binding
91 | "no-fallthrough": 2, // disallow fallthrough of case statements
92 | "no-floating-decimal": 2, // disallow the use of leading or trailing decimal points in numeric literals (off by default)
93 | "no-implied-eval": 2, // disallow use of eval()-like methods
94 | "no-iterator": 2, // disallow usage of __iterator__ property
95 | "no-labels": 2, // disallow use of labeled statements
96 | "no-lone-blocks": 2, // disallow unnecessary nested blocks
97 | "no-loop-func": 2, // disallow creation of functions within loops
98 | "no-multi-spaces": 2, // disallow use of multiple spaces
99 | "no-multi-str": 2, // disallow use of multiline strings
100 | "no-native-reassign": 2, // disallow reassignments of native objects
101 | "no-new": 2, // disallow use of new operator when not part of the assignment or comparison
102 | "no-new-func": 2, // disallow use of new operator for Function object
103 | "no-new-wrappers": 2, // disallows creating new instances of String,Number, and Boolean
104 | "no-octal": 2, // disallow use of octal literals
105 | "no-octal-escape": 2, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
106 | "no-param-reassign": 2, // disallow reassignment of function parameters (off by default)
107 | "no-proto": 2, // disallow usage of __proto__ property
108 | "no-redeclare": 2, // disallow declaring the same variable more then once
109 | "no-return-assign": 2, // disallow use of assignment in return statement
110 | "no-script-url": 2, // disallow use of javascript: urls.
111 | "no-self-compare": 2, // disallow comparisons where both sides are exactly the same (off by default)
112 | "no-sequences": 2, // disallow use of comma operator
113 | "no-throw-literal": 2, // restrict what can be thrown as an exception (off by default)
114 | "no-unused-expressions": 2, // disallow usage of expressions in statement position
115 | "no-void": 2, // disallow use of void operator (off by default)
116 | "no-warning-comments": [0, {"terms": ["todo", "fixme"], "location": "start"}], // disallow usage of configurable warning terms in comments": 2, // e.g. TODO or FIXME (off by default)
117 | "no-with": 2, // disallow use of the with statement
118 | "radix": 2, // require use of the second argument for parseInt() (off by default)
119 | "vars-on-top": 2, // requires to declare all vars on top of their containing scope (off by default)
120 | "wrap-iife": 2, // require immediate function invocation to be wrapped in parentheses (off by default)
121 | "yoda": 2, // require or disallow Yoda conditions
122 |
123 | //
124 | // Strict Mode
125 | //
126 | // These rules relate to using strict mode.
127 | //
128 | "strict": 0, // controls location of Use Strict Directives. 0: required by `babel-eslint`
129 |
130 | //
131 | // Variables
132 | //
133 | // These rules have to do with variable declarations.
134 | //
135 | "no-catch-shadow": 2, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment)
136 | "no-delete-var": 2, // disallow deletion of variables
137 | "no-label-var": 2, // disallow labels that share a name with a variable
138 | "no-shadow": 2, // disallow declaration of variables already declared in the outer scope
139 | "no-shadow-restricted-names": 2, // disallow shadowing of names such as arguments
140 | "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block
141 | "no-undef-init": 2, // disallow use of undefined when initializing variables
142 | "no-undefined": 2, // disallow use of undefined variable (off by default)
143 | "no-unused-vars": 0, // disallow declaration of variables that are not used in the code
144 | "no-use-before-define": 2, // disallow use of variables before they are defined
145 |
146 | //
147 | //Stylistic Issues
148 | //
149 | // These rules are purely matters of style and are quite subjective.
150 | //
151 | "indent": [1, 2], // this option sets a specific tab width for your code (off by default)
152 | "brace-style": 1, // enforce one true brace style (off by default)
153 | "camelcase": 0, // require camel case names
154 | "comma-spacing": [1, {"before": false, "after": true}], // enforce spacing before and after comma
155 | "comma-style": [1, "last"], // enforce one true comma style (off by default)
156 | "consistent-this": [1, "_this"], // enforces consistent naming when capturing the current execution context (off by default)
157 | "eol-last": 1, // enforce newline at the end of file, with no multiple empty lines
158 | "func-names": 0, // require function expressions to have a name (off by default)
159 | "func-style": 0, // enforces use of function declarations or expressions (off by default)
160 | "key-spacing": [1, {"beforeColon": false, "afterColon": true}], // enforces spacing between keys and values in object literal properties
161 | "max-nested-callbacks": [1, 3], // specify the maximum depth callbacks can be nested (off by default)
162 | "new-cap": [1, {newIsCap: true, capIsNew: false}], // require a capital letter for constructors
163 | "new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments
164 | "newline-after-var": 0, // allow/disallow an empty newline after var statement (off by default)
165 | "no-array-constructor": 1, // disallow use of the Array constructor
166 | "no-inline-comments": 1, // disallow comments inline after code (off by default)
167 | "no-lonely-if": 1, // disallow if as the only statement in an else block (off by default)
168 | "no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
169 | "no-multiple-empty-lines": [1, {"max": 2}], // disallow multiple empty lines (off by default)
170 | "no-nested-ternary": 1, // disallow nested ternary expressions (off by default)
171 | "no-new-object": 1, // disallow use of the Object constructor
172 | "no-spaced-func": 1, // disallow space between function identifier and application
173 | "no-ternary": 0, // disallow the use of ternary operators (off by default)
174 | "no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines
175 | "no-underscore-dangle": 0, // disallow dangling underscores in identifiers
176 | "no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
177 | "one-var": [1, "never"], // allow just one var statement per function (off by default)
178 | "operator-assignment": [1, "never"], // require assignment operator shorthand where possible or prohibit it entirely (off by default)
179 | "padded-blocks": [1, "never"], // enforce padding within blocks (off by default)
180 | "quote-props": [1, "as-needed"], // require quotes around object literal property names (off by default)
181 | "quotes": [1, "single"], // specify whether double or single quotes should be used
182 | "semi": [1, "always"], // require or disallow use of semicolons instead of ASI
183 | "semi-spacing": [1, {"before": false, "after": true}], // enforce spacing before and after semicolons
184 | "sort-vars": 0, // sort variables within the same declaration block (off by default)
185 | "space-after-keywords": [1, "always"], // require a space after certain keywords (off by default)
186 | "space-before-blocks": [1, "always"], // require or disallow space before blocks (off by default)
187 | "space-before-function-paren": [1, {"anonymous": "always", "named": "never"}], // require or disallow space before function opening parenthesis (off by default)
188 | "space-in-brackets": [1, "never"], // require or disallow spaces inside brackets (off by default)
189 | "space-in-parens": [1, "never"], // require or disallow spaces inside parentheses (off by default)
190 | "space-infix-ops": [1, "always"], // require spaces around operators
191 | "space-return-throw-case": [1, "always"], // require a space after return, throw, and case
192 | "space-unary-ops": [1, {"words": true, "nonwords": false}], // Require or disallow spaces before/after unary operators (words on by default, nonwords off by default)
193 | "spaced-line-comment": [1, "always"], // require or disallow a space immediately following the // in a line comment (off by default)
194 | "wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default)
195 |
196 | //
197 | // ECMAScript 6
198 | //
199 | // These rules are only relevant to ES6 environments and are off by default.
200 | //
201 | "generator-star-spacing": [2, "before"], // enforce the spacing around the * in generator functions (off by default)
202 |
203 | //
204 | // Legacy
205 | //
206 | // The following rules are included for compatibility with JSHint and JSLint.
207 | // While the names of the rules may not match up with the JSHint/JSLint counterpart,
208 | // the functionality is the same.
209 | //
210 | "max-depth": [2, 3], // specify the maximum depth that blocks can be nested (off by default)
211 | "max-len": [2, 100, 2], // specify the maximum length of a line in your program (off by default)
212 | "max-params": [2, 5], // limits the number of parameters that can be used in the function declaration. (off by default)
213 | "max-statements": 0, // specify the maximum number of statement allowed in a function (off by default)
214 | "no-bitwise": 0, // disallow use of bitwise operators (off by default)
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src/
2 | demo/
3 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2012 Netflix, Inc.
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Falcor Wordpress Router
2 |
3 | [](http://badge.fury.io/js/falcor-wordpress)
4 |
5 | This project provides a Falcor Router which acts as a middleman (in node.js) for consuming the [Wordpress REST API](https://github.com/WP-API/WP-API). The goal is a more intelligible, data-centric API for the client with dramatically reduced client network requests.
6 |
7 | ## Getting Started
8 |
9 | ### Basic installation and usage
10 |
11 | ```
12 | npm install falcor-wordpress --save
13 | ```
14 |
15 | Use it within an express app:
16 |
17 | ```javascript
18 | ... // basic express boilerplate, app = express();
19 |
20 | var FalcorServer = require('falcor-express');
21 | var wordpressRouter = require('falcor-wordpress');
22 | var endpoint = 'http://demo.wp-api.org/wp-json';
23 |
24 | app.use('/model.json', FalcorServer.dataSourceRoute(function (req, res) {
25 | // without authentication
26 | return wordpressRouter(endpoint);
27 | }));
28 | ```
29 |
30 | ### Included Demo
31 |
32 | A demo running in express with a simple front-end is included.
33 |
34 | ```
35 | # install library dependencies
36 | npm install
37 |
38 | # install demo dependencies and run
39 | cd demo
40 | npm install
41 | npm start
42 |
43 | # open your browser and visit http://localhost:9090
44 | ```
45 |
46 | The demo page allows you to test live queries against the offical [Wordpress Rest API demo site](http://demo.wp-api.org/), including a number of examples to get you started. Watch the server console to see a list of REST endpoints that are being fetched on each flight.
47 |
48 | **Note:** there are some differences betweeen the 1.0 and 2.0 branches of the WP API. This package targets 2.0, and uses a 2.0 endpoint for its demo.
49 |
50 | ## Currently implemented top-level routes
51 |
52 | Below are the top-level routes available, along with some example paths that might be requested (try these live on the included demo).
53 |
54 | ### postsById
55 |
56 | Basic example: `postsById[171,131]["title","slug","link"]`
57 |
58 | ```json
59 | {
60 | "postsById": {
61 | "131": {
62 | "title": "Ipsam mollitia eveniet hic",
63 | "slug": "ipsam-mollitia-eveniet-hic",
64 | "link": "http://demo.wp-api.org/2015/08/21/ipsam-mollitia-eveniet-hic/"
65 | },
66 | "171": {
67 | "title": "Sint aperiam autem molestiae debitis",
68 | "slug": "sint-aperiam-autem-molestiae-debitis",
69 | "link": "http://demo.wp-api.org/2015/08/12/sint-aperiam-autem-molestiae-debitis/"
70 | }
71 | }
72 | }
73 | ```
74 |
75 | Going deeper: `postsById[131].terms.categories[0].name`
76 |
77 | ```json
78 | {
79 | "postsById": {
80 | "131": {
81 | "terms": {
82 | "categories": {
83 | "0": {
84 | "name": "Illum in fugit assumenda quo et reprehenderit maxime saepe"
85 | }
86 | }
87 | }
88 | }
89 | }
90 | }
91 | ```
92 |
93 | ### recentPosts
94 |
95 | Basic example: `recentPosts[0..2].title`
96 |
97 | ```json
98 | {
99 | "recentPosts": {
100 | "0": {
101 | "title": "Repellat dolor architecto inventore"
102 | },
103 | "1": {
104 | "title": "Dolor adipisci soluta eum ipsam deserunt"
105 | },
106 | "2": {
107 | "title": "Ipsam mollitia eveniet hic"
108 | }
109 | }
110 | }
111 | ```
112 |
113 | Going deeper: `recentPosts[5].terms.categories[0].name`
114 |
115 | ```json
116 | {
117 | "recentPosts": {
118 | "5": {
119 | "terms": {
120 | "categories": {
121 | "0": {
122 | "name": "In fugit quae libero a"
123 | }
124 | }
125 | }
126 | }
127 | }
128 | }
129 | ```
130 |
131 | ## postsByTerm[vocabulary][term-slug]
132 |
133 | Example: `postsByTerm.categories.tool-kit[0..3]['title','id']`
134 |
135 | ```json
136 | {
137 | "postsByTerm": {
138 | "categories": {
139 | "tool-kit": {
140 | "0": {
141 | "title": "Writing Reports, Quick Guide",
142 | "id": 97
143 | },
144 | "1": {
145 | "title": "Analyzing Data, Quick Guide",
146 | "id": 95
147 | },
148 | "2": {
149 | "title": "Measuring Outcomes, Quick Guide",
150 | "id": 92
151 | },
152 | "3": {
153 | "title": "Creating Learning Outcomes, Quick Guide",
154 | "id": 90
155 | }
156 | }
157 | }
158 | }
159 | }
160 | ```
161 |
162 | ## termsById[vocabulary]
163 |
164 | Categories example: `termsById.categories[4,70]['name','description']`
165 |
166 | ```json
167 | {
168 | "termsById": {
169 | "categories": {
170 | "4": {
171 | "name": "Ab iusto",
172 | "description": "Sunt distinctio asperiores dolores quae odit necessitatibus dolor dolore quo doloremque nam incidunt molestiae facilis quisquam voluptatem voluptas et voluptas sapiente laudantium fugiat"
173 | },
174 | "70": {
175 | "name": "Accusantium nulla omnis quos",
176 | "description": "Occaecati placeat et dolores tempore unde est laudantium ipsam tempora accusamus culpa sequi aut aut dolore minus pariatur fugit ut ipsa et distinctio minus amet ut id molestiae assumenda aliquam vel qui quibusdam"
177 | }
178 | }
179 | }
180 | }
181 | ```
182 |
183 | Tags example: `termsById.tags[36]['slug','name']`
184 |
185 | ```json
186 | {
187 | "termsById": {
188 | "tags": {
189 | "36": {
190 | "slug": "accusantium-dolore-porro-nihil-eveniet-dolores-impedit-quisquam",
191 | "name": "Accusantium dolore porro nihil eveniet dolores impedit quisquam"
192 | }
193 | }
194 | }
195 | }
196 | ```
197 |
198 | ## taxonomies
199 |
200 | Metadata: `taxonomies.category.meta['name','slug']`
201 |
202 | ```json
203 | {
204 | "taxonomies": {
205 | "category": {
206 | "meta": {
207 | "name": "Categories",
208 | "slug": "category"
209 | }
210 | }
211 | }
212 | }
213 | ```
214 |
215 | Number of available terms: `taxonomies.categories.terms.length`
216 |
217 | ```json
218 | {
219 | "taxonomies": {
220 | "categories": {
221 | "terms": {
222 | "length": "52"
223 | }
224 | }
225 | }
226 | }
227 | ```
228 |
229 | Terms range: `taxonomies.tags.terms[0..2]['name']`
230 |
231 | ```json
232 | {
233 | "taxonomies": {
234 | "tags": {
235 | "terms": {
236 | "0": {
237 | "name": "Accusantium dolore porro nihil eveniet dolores impedit quisquam"
238 | },
239 | "1": {
240 | "name": "Ad et modi ipsam in iure"
241 | },
242 | "2": {
243 | "name": "Adipisci ut tempora quisquam"
244 | }
245 | }
246 | }
247 | }
248 | }
249 | ```
250 |
251 | ## Other routes
252 |
253 | These are also available at root, though generally more useful where referenced elsewhere:
254 |
255 | `authorsById`
256 | `mediaById`
257 |
258 | **Media** linked as featured image: `postsById[131].featured_media.media_details.sizes.thumbnail.file`
259 |
260 | ```json
261 | {
262 | "postsById": {
263 | "131": {
264 | "featured_media": {
265 | "media_details": {
266 | "sizes": {
267 | "thumbnail": {
268 | "file": "fba2be87-deae-3077-96b4-d1754a1802ca-150x150.jpg"
269 | }
270 | }
271 | }
272 | }
273 | }
274 | }
275 | }
276 | ```
277 |
278 | **Author** of a post: `postsById[171].author.name`
279 |
280 | ```json
281 | {
282 | "postsById": {
283 | "171": {
284 | "author": {
285 | "name": "Cassidy"
286 | }
287 | }
288 | }
289 | }
290 | ```
291 |
292 |
293 |
294 |
295 |
296 | ## Roadmap
297 |
298 | - [x] postsById
299 | - [x] recentPosts
300 | - [x] taxonomies (meta, terms list)
301 | - [x] termsById
302 | - [x] authorsById
303 | - [x] mediaById
304 | - [x] posts by term
305 | - [ ] more linked subqueries
306 | - [ ] additional listings by varied sorts
307 |
--------------------------------------------------------------------------------
/authors.txt:
--------------------------------------------------------------------------------
1 | Jason Phillips
2 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
53 |
54 |
55 |
56 |
Wordpress Falcor Router Demo
57 |
58 |
Path Input
59 |
Try something like:
60 |
61 |
62 |
63 | postsById[171,131]["title","slug","link"]
64 | postsById[171,131].featured_media.guid
65 | postsById[131].terms.categories[0].name
66 | postsById[171].terms.tags.length
67 |
68 | recentPosts[0..3].title
69 | recentPosts[5..8].terms.categories[0].name
70 |
71 |
72 |
73 |
74 | termsById.tags[36]['slug','name']
75 | termsById.categories[4,70]['name','description']
76 |
77 | taxonomies.category.meta['name','slug']
78 | taxonomies.categories.terms.length
79 | taxonomies.tags.terms[0..5]['name','slug']
80 |
81 | authorsById[41].name
82 |
83 |
84 |
85 |
86 |
94 |
95 |
96 |
100 |
101 |
Full Cache
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "falcor-wordpress-example",
3 | "version": "0.0.5",
4 | "description": "A an example falcor server for using the Falcor Wordpress router.",
5 | "author": {
6 | "name": "Jason Phillips",
7 | "url": "https://github.com/jasonphillips"
8 | },
9 | "licenses": [
10 | {
11 | "type": "Apache License, Version 2.0",
12 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
13 | }
14 | ],
15 | "scripts": {
16 | "start": "babel-node server.js | bunyan"
17 | },
18 | "dependencies": {
19 | "body-parser": "^1.12.4",
20 | "bunyan": "^1.4.0",
21 | "express": "~4.11.1",
22 | "falcor-express": "https://github.com/jasonphillips/falcor-express.git#jsonHeader"
23 | },
24 | "devDependencies": {
25 | "babel": "^5.8.23"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This file starts the server and exposes the Router at /model.json
4 | var express = require('express');
5 | var bodyParser = require('body-parser');
6 | var app = express();
7 | var FalcorServer = require('falcor-express');
8 | var wordpressRouter = require('../lib/wordpressRouter.js');
9 |
10 | var bunyan = require('bunyan');
11 | var log = bunyan.createLogger({name: 'express'});
12 | var endpoint = 'http://demo.wp-api.org/wp-json';
13 |
14 | app.use(bodyParser.urlencoded({extended: false}));
15 |
16 | // Simple middleware to handle get/post
17 | app.use('/model.json', FalcorServer.dataSourceRoute(function (req, res) {
18 | // Not using authentication in demo
19 | return wordpressRouter(endpoint);
20 | }));
21 |
22 | app.use(express.static('.'));
23 |
24 | let server = app.listen(9090, function (err) {
25 | if (err) {
26 | log.error(err);
27 | return;
28 | }
29 | log.info('navigate to http://localhost:9090');
30 | });
31 |
--------------------------------------------------------------------------------
/lib/handlers/authorsById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchById = require('./fetchById.js');
16 |
17 | // handler is "authors" rather than "users" because
18 | // it does not request via authentication, and only
19 | // users with posts (authors) are retrievable by
20 | // anonymous request in the WP API 2.0
21 |
22 | var AuthorsById = (function (_FetchById) {
23 | _inherits(AuthorsById, _FetchById);
24 |
25 | function AuthorsById() {
26 | _classCallCheck(this, AuthorsById);
27 |
28 | _get(Object.getPrototypeOf(AuthorsById.prototype), 'constructor', this).apply(this, arguments);
29 | }
30 |
31 | _createClass(AuthorsById, [{
32 | key: 'getIdQuery',
33 | value: function getIdQuery(id) {
34 | return this.wp.users().id(id);
35 | }
36 | }, {
37 | key: 'getReturnPath',
38 | value: function getReturnPath(id, key) {
39 | return typeof key !== 'undefined' ? ['authorsById', id, key] : ['authorsById', id];
40 | }
41 | }]);
42 |
43 | return AuthorsById;
44 | })(FetchById);
45 |
46 | exports['default'] = AuthorsById;
47 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/fetchById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
10 |
11 | var _ = require('lodash');
12 | var jsonGraph = require('falcor-json-graph');
13 | var $ref = jsonGraph.ref;
14 | var $error = jsonGraph.error;
15 |
16 | var FetchById = (function () {
17 | function FetchById(shared, ids, keys) {
18 | _classCallCheck(this, FetchById);
19 |
20 | this.wp = shared.wp;
21 | this.log = shared.log;
22 | this.cacheGet = shared.cacheGet.bind(shared);
23 | this.ids = ids;
24 | this.keys = keys;
25 | }
26 |
27 | // Override with wp api promise
28 |
29 | _createClass(FetchById, [{
30 | key: 'getIdQuery',
31 | value: function getIdQuery(id) {
32 | return null;
33 | }
34 |
35 | // Override with specific Falcor return paths
36 | }, {
37 | key: 'getReturnPath',
38 | value: function getReturnPath(id, key) {
39 | // keyless for error handler
40 | return typeof key !== 'undefined' ? [id, key] : [id];
41 | }
42 |
43 | // Override with cache path to check for already retrieved object
44 | }, {
45 | key: 'getCachedPath',
46 | value: function getCachedPath(id) {
47 | return '' + id;
48 | }
49 |
50 | // Override with keys that should return references {key=>path}
51 | }, {
52 | key: 'getReferenceKeys',
53 | value: function getReferenceKeys() {
54 | return {};
55 | }
56 | }, {
57 | key: 'getPromises',
58 | value: function getPromises() {
59 | var _this = this;
60 |
61 | var promises = _.map(this.ids, function (id) {
62 | var itemPromise = new Promise(function (resolve, reject) {
63 | // check cache for already fetched item this flight
64 | var cached = _this.cacheGet(_this.getCachedPath(id));
65 | if (typeof cached !== 'undefined') {
66 | resolve(cached);
67 | } else {
68 | var query = _this.getIdQuery(id);
69 | _this.log.info('GET: ' + query._renderURI());
70 |
71 | query.then(function (response) {
72 | resolve(response);
73 | })['catch'](function (err) {
74 | _this.log.error(err);
75 | resolve({ error: err.status + ' for ' + err.path });
76 | });
77 | }
78 | });
79 |
80 | return itemPromise;
81 | });
82 |
83 | return promises;
84 | }
85 | }, {
86 | key: 'resolvePromises',
87 | value: function resolvePromises(promises) {
88 | var _this2 = this;
89 |
90 | return Promise.all(promises).then(function (records) {
91 | var results = [];
92 | var referenceKeys = _this2.getReferenceKeys();
93 |
94 | _this2.ids.forEach(function (id, offset) {
95 | var record = records[offset];
96 |
97 | _this2.keys.forEach(function (key) {
98 | if (record.error) {
99 | results.push({
100 | path: _this2.getReturnPath(id, key),
101 | value: $error(record.error)
102 | });
103 | } else if (record.id || record.name) {
104 | var value = record[key];
105 | // reference keys
106 | if (typeof referenceKeys[key] === 'function') {
107 | results.push({
108 | path: _this2.getReturnPath(id, key),
109 | value: $ref(referenceKeys[key](id, value))
110 | });
111 | } else {
112 | if (typeof value === 'object' && value.rendered) {
113 | // handle WP 2.0 {rendered} values
114 | value = value.rendered;
115 | }
116 | results.push({
117 | path: _this2.getReturnPath(id, key),
118 | value: value
119 | });
120 | }
121 | } else {
122 | results.push({
123 | path: _this2.getReturnPath(id),
124 | value: $error(id + ' not found')
125 | });
126 | }
127 | });
128 | });
129 | return results;
130 | });
131 | }
132 | }, {
133 | key: 'buildReturn',
134 | value: function buildReturn() {
135 | return this.resolvePromises(this.getPromises());
136 | }
137 | }]);
138 |
139 | return FetchById;
140 | })();
141 |
142 | exports['default'] = FetchById;
143 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/fetchByIndices.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
8 |
9 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | var _ = require('lodash');
14 | var jsonGraph = require('falcor-json-graph');
15 | var $ref = jsonGraph.ref;
16 | var $error = jsonGraph.error;
17 |
18 | var FetchByIndices = (function () {
19 | function FetchByIndices(shared, indices, filter) {
20 | _classCallCheck(this, FetchByIndices);
21 |
22 | this.wp = shared.wp;
23 | this.log = shared.log;
24 | this.indices = indices;
25 | this.cacheSet = shared.cacheSet.bind(shared);
26 | this.filter = filter;
27 | this.paging = this.getPaging();
28 | }
29 |
30 | // Override with wp api promise
31 |
32 | _createClass(FetchByIndices, [{
33 | key: 'getRootQuery',
34 | value: function getRootQuery() {
35 | return null;
36 | }
37 |
38 | // responses will be references to a byId path
39 | }, {
40 | key: 'getReferencePath',
41 | value: function getReferencePath(record) {
42 | return record.id;
43 | }
44 |
45 | // Override with specific Falcor return paths
46 | }, {
47 | key: 'getReturnPath',
48 | value: function getReturnPath(index) {
49 | return typeof index !== 'undefined' ? [index] : null;
50 | }
51 | }, {
52 | key: 'getPromise',
53 | value: function getPromise() {
54 | var _this = this;
55 |
56 | var rangePromise = new Promise(function (resolve, reject) {
57 | var query = _this.getRootQuery();
58 | if (_this.filter) {
59 | query = query.filter(_this.filter);
60 | }
61 | if (_this.paging) {
62 | query = query.perPage(_this.paging.perPage).page(_this.paging.page);
63 | }
64 | _this.log.info('GET: ' + query._renderURI());
65 |
66 | query.then(function (response) {
67 | resolve(response);
68 | })['catch'](function (err) {
69 | _this.log.error(err);
70 | resolve({ error: err.status + ' for ' + err.path });
71 | });
72 | });
73 | return rangePromise;
74 | }
75 | }, {
76 | key: 'resolvePromise',
77 | value: function resolvePromise(rangePromise) {
78 | var _this2 = this;
79 |
80 | return rangePromise.then(function (records) {
81 | var results = [];
82 | var offset = _this2.paging ? _this2.paging.offset : 0;
83 | var total = _this2.paging && records._paging ? records._paging.total : records.length;
84 | var referencesList = [];
85 |
86 | // build item references and cache objects
87 | _.forEach(records, function (record) {
88 | var refPath = _this2.getReferencePath(record);
89 | referencesList.push($ref(refPath));
90 | _this2.cacheSet(refPath, record);
91 | });
92 |
93 | _this2.indices.forEach(function (index) {
94 | if (index === 'length') {
95 | results.push({
96 | path: _this2.getReturnPath(index),
97 | value: total
98 | });
99 | } else {
100 | results.push({
101 | path: _this2.getReturnPath(index),
102 | value: referencesList[index - offset]
103 | });
104 | }
105 | });
106 |
107 | return results;
108 | })['catch'](function (err) {
109 | _this2.log.error(err);
110 | return [{
111 | path: _this2.getReturnPath(),
112 | value: $error(err.status + ' for ' + err.path)
113 | }];
114 | });
115 | }
116 | }, {
117 | key: 'buildReturn',
118 | value: function buildReturn() {
119 | return this.resolvePromise(this.getPromise());
120 | }
121 | }, {
122 | key: 'getPaging',
123 | value: function getPaging() {
124 | var perPage;var page;
125 | var indices = _.without(this.indices, 'length');
126 | if (!indices.length) {
127 | indices = [0];
128 | }
129 |
130 | var _calculatePage = this.calculatePage(_.min(indices), _.max(indices));
131 |
132 | var _calculatePage2 = _slicedToArray(_calculatePage, 2);
133 |
134 | perPage = _calculatePage2[0];
135 | page = _calculatePage2[1];
136 |
137 | return {
138 | perPage: perPage,
139 | page: page,
140 | offset: perPage * (page - 1)
141 | };
142 | }
143 |
144 | // Calculate smallest page for range
145 | }, {
146 | key: 'calculatePage',
147 | value: function calculatePage(low, high) {
148 | var range = high - low + 1;
149 | if (range < low) {
150 | var perpage = undefined;
151 | for (perpage = range; perpage <= low; perpage++) {
152 | if (low % perpage <= perpage - range) {
153 | var offset = Math.floor(low / perpage);
154 | return [perpage, offset + 1];
155 | }
156 | }
157 | return perpage;
158 | }
159 | return [high + 1, 1];
160 | }
161 | }]);
162 |
163 | return FetchByIndices;
164 | })();
165 |
166 | exports['default'] = FetchByIndices;
167 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/mediaById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchById = require('./fetchById.js');
16 |
17 | var MediaById = (function (_FetchById) {
18 | _inherits(MediaById, _FetchById);
19 |
20 | function MediaById() {
21 | _classCallCheck(this, MediaById);
22 |
23 | _get(Object.getPrototypeOf(MediaById.prototype), 'constructor', this).apply(this, arguments);
24 | }
25 |
26 | _createClass(MediaById, [{
27 | key: 'getIdQuery',
28 | value: function getIdQuery(id) {
29 | return this.wp.media().id(id);
30 | }
31 | }, {
32 | key: 'getReturnPath',
33 | value: function getReturnPath(id, key) {
34 | return typeof key !== 'undefined' ? ['mediaById', id, key] : ['mediaById', id];
35 | }
36 | }]);
37 |
38 | return MediaById;
39 | })(FetchById);
40 |
41 | exports['default'] = MediaById;
42 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/postsById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchById = require('./fetchById.js');
16 |
17 | var PostsById = (function (_FetchById) {
18 | _inherits(PostsById, _FetchById);
19 |
20 | function PostsById() {
21 | _classCallCheck(this, PostsById);
22 |
23 | _get(Object.getPrototypeOf(PostsById.prototype), 'constructor', this).apply(this, arguments);
24 | }
25 |
26 | _createClass(PostsById, [{
27 | key: 'getIdQuery',
28 | value: function getIdQuery(id) {
29 | return this.wp.posts().id(id);
30 | }
31 | }, {
32 | key: 'getReturnPath',
33 | value: function getReturnPath(id, key) {
34 | return typeof key !== 'undefined' ? ['postsById', id, key] : ['postsById', id];
35 | }
36 | }, {
37 | key: 'getCachedPath',
38 | value: function getCachedPath(id) {
39 | return 'postsById[' + id + ']';
40 | }
41 | }, {
42 | key: 'getReferenceKeys',
43 | value: function getReferenceKeys() {
44 | return {
45 | author: function author(id, value) {
46 | return 'authorsById[' + value + ']';
47 | },
48 | featured_media: function featured_media(id, value) {
49 | return 'mediaById[' + value + ']';
50 | },
51 | terms: function terms(id, value) {
52 | return 'termsByPost[' + id + ']';
53 | }
54 | };
55 | }
56 | }]);
57 |
58 | return PostsById;
59 | })(FetchById);
60 |
61 | exports['default'] = PostsById;
62 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/postsByIndices.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchByIndices = require('./FetchByIndices.js');
16 |
17 | var PostsByIndices = (function (_FetchByIndices) {
18 | _inherits(PostsByIndices, _FetchByIndices);
19 |
20 | function PostsByIndices() {
21 | _classCallCheck(this, PostsByIndices);
22 |
23 | _get(Object.getPrototypeOf(PostsByIndices.prototype), 'constructor', this).apply(this, arguments);
24 | }
25 |
26 | _createClass(PostsByIndices, [{
27 | key: 'getRootQuery',
28 | value: function getRootQuery() {
29 | return this.wp.posts();
30 | }
31 | }, {
32 | key: 'getReferencePath',
33 | value: function getReferencePath(record) {
34 | return 'postsById[' + record.id + ']';
35 | }
36 | }, {
37 | key: 'getReturnPath',
38 | value: function getReturnPath(index) {
39 | return typeof index !== 'undefined' ? ['recentPosts', index] : ['recentPosts'];
40 | }
41 | }]);
42 |
43 | return PostsByIndices;
44 | })(FetchByIndices);
45 |
46 | exports['default'] = PostsByIndices;
47 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/postsByTerm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchByIndices = require('./FetchByIndices.js');
16 |
17 | var PostsByTerm = (function (_FetchByIndices) {
18 | _inherits(PostsByTerm, _FetchByIndices);
19 |
20 | function PostsByTerm(shared, indices, filter, vocabulary, term) {
21 | _classCallCheck(this, PostsByTerm);
22 |
23 | _get(Object.getPrototypeOf(PostsByTerm.prototype), 'constructor', this).call(this, shared, indices, filter);
24 | this.vocabulary = vocabulary;
25 | this.term = term;
26 | }
27 |
28 | _createClass(PostsByTerm, [{
29 | key: 'getRootQuery',
30 | value: function getRootQuery() {
31 | return this.wp.posts().taxonomy(this.vocabulary, this.term);
32 | }
33 | }, {
34 | key: 'getReferencePath',
35 | value: function getReferencePath(record) {
36 | return 'postsById[' + record.id + ']';
37 | }
38 | }, {
39 | key: 'getReturnPath',
40 | value: function getReturnPath(index) {
41 | return typeof index !== 'undefined' ? ['postsByTerm', this.vocabulary, this.term, index] : ['postsByTerm', this.vocabulary, this.term];
42 | }
43 | }]);
44 |
45 | return PostsByTerm;
46 | })(FetchByIndices);
47 |
48 | exports['default'] = PostsByTerm;
49 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/taxonomiesById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchById = require('./fetchById.js');
16 |
17 | var TaxonomiesById = (function (_FetchById) {
18 | _inherits(TaxonomiesById, _FetchById);
19 |
20 | function TaxonomiesById() {
21 | _classCallCheck(this, TaxonomiesById);
22 |
23 | _get(Object.getPrototypeOf(TaxonomiesById.prototype), 'constructor', this).apply(this, arguments);
24 | }
25 |
26 | _createClass(TaxonomiesById, [{
27 | key: 'getIdQuery',
28 | value: function getIdQuery(id) {
29 | return this.wp.taxonomies().taxonomy(id);
30 | }
31 | }, {
32 | key: 'getReturnPath',
33 | value: function getReturnPath(id, key) {
34 | return typeof key !== 'undefined' ? ['taxonomies', id, 'meta', key] : ['taxonomies', id, 'meta'];
35 | }
36 | }]);
37 |
38 | return TaxonomiesById;
39 | })(FetchById);
40 |
41 | exports['default'] = TaxonomiesById;
42 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/termsById.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchById = require('./fetchById.js');
16 |
17 | var TermsById = (function (_FetchById) {
18 | _inherits(TermsById, _FetchById);
19 |
20 | function TermsById(shared, ids, keys, vocabulary) {
21 | _classCallCheck(this, TermsById);
22 |
23 | _get(Object.getPrototypeOf(TermsById.prototype), 'constructor', this).call(this, shared, ids, keys);
24 | this.vocabulary = vocabulary;
25 | }
26 |
27 | _createClass(TermsById, [{
28 | key: 'getIdQuery',
29 | value: function getIdQuery(id) {
30 | return this.wp[this.vocabulary]().id(id);
31 | }
32 | }, {
33 | key: 'getReturnPath',
34 | value: function getReturnPath(id, key) {
35 | return typeof key !== 'undefined' ? ['termsById', this.vocabulary, id, key] : ['termsById', this.vocabulary, id];
36 | }
37 | }, {
38 | key: 'getCachedPath',
39 | value: function getCachedPath(id) {
40 | return 'termsById.' + this.vocabulary + '[' + id + ']';
41 | }
42 | }, {
43 | key: 'getReferenceKeys',
44 | value: function getReferenceKeys() {
45 | var _this = this;
46 |
47 | return {
48 | children: function children(id, value) {
49 | return 'taxonomies.' + _this.vocabulary + '.termsByParentId[' + id + ']';
50 | }
51 | };
52 | }
53 | }]);
54 |
55 | return TermsById;
56 | })(FetchById);
57 |
58 | exports['default'] = TermsById;
59 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/termsByIndices.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchByIndices = require('./FetchByIndices.js');
16 |
17 | var TermsByIndices = (function (_FetchByIndices) {
18 | _inherits(TermsByIndices, _FetchByIndices);
19 |
20 | function TermsByIndices(shared, indices, filter, vocabulary, parentId) {
21 | _classCallCheck(this, TermsByIndices);
22 |
23 | _get(Object.getPrototypeOf(TermsByIndices.prototype), 'constructor', this).call(this, shared, indices, filter);
24 | this.vocabulary = vocabulary;
25 | this.parentId = parentId;
26 | }
27 |
28 | _createClass(TermsByIndices, [{
29 | key: 'getRootQuery',
30 | value: function getRootQuery() {
31 | var query = this.wp[this.vocabulary]();
32 | if (this.parentId) {
33 | query = query.parent(this.parentId);
34 | }
35 | return query;
36 | }
37 | }, {
38 | key: 'getReferencePath',
39 | value: function getReferencePath(record) {
40 | return 'termsById.' + this.vocabulary + '[' + record.id + ']';
41 | }
42 | }, {
43 | key: 'getReturnPath',
44 | value: function getReturnPath(index) {
45 | var base = ['taxonomies', this.vocabulary, this.parentId ? 'termsByParentId' : 'terms'];
46 | if (this.parentId) {
47 | base.push(this.parentId);
48 | }
49 | return typeof index !== 'undefined' ? base.concat([index]) : base;
50 | }
51 | }]);
52 |
53 | return TermsByIndices;
54 | })(FetchByIndices);
55 |
56 | exports['default'] = TermsByIndices;
57 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/handlers/termsByPost.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12 |
13 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
14 |
15 | var FetchByIndices = require('./FetchByIndices.js');
16 |
17 | var TermsByPost = (function (_FetchByIndices) {
18 | _inherits(TermsByPost, _FetchByIndices);
19 |
20 | function TermsByPost(shared, indices, filter, postId, vocabulary) {
21 | _classCallCheck(this, TermsByPost);
22 |
23 | _get(Object.getPrototypeOf(TermsByPost.prototype), 'constructor', this).call(this, shared, indices, filter);
24 | this.postId = postId;
25 | this.vocabulary = vocabulary;
26 | }
27 |
28 | _createClass(TermsByPost, [{
29 | key: 'getRootQuery',
30 | value: function getRootQuery() {
31 | return this.wp.taxonomies().collection(this.vocabulary).forPost(this.postId);
32 | }
33 |
34 | // pagination does not exist on post terms
35 | }, {
36 | key: 'getPaging',
37 | value: function getPaging() {
38 | return false;
39 | }
40 | }, {
41 | key: 'getReferencePath',
42 | value: function getReferencePath(record) {
43 | return 'termsById.' + this.vocabulary + '[' + record.id + ']';
44 | }
45 | }, {
46 | key: 'getReturnPath',
47 | value: function getReturnPath(index) {
48 | return typeof index !== 'undefined' ? ['termsByPost', this.postId, this.vocabulary, index] : ['termsByPost', this.postId, this.vocabulary];
49 | }
50 | }]);
51 |
52 | return TermsByPost;
53 | })(FetchByIndices);
54 |
55 | exports['default'] = TermsByPost;
56 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/lib/wordpressRouter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
4 |
5 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
6 |
7 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8 |
9 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
10 |
11 | var Router = require('falcor-router');
12 | var Promise = require('promise');
13 | var _ = require('lodash');
14 |
15 | // falcor basics
16 | var jsonGraph = require('falcor-json-graph');
17 | var $ref = jsonGraph.ref;
18 | var $error = jsonGraph.error;
19 |
20 | // wordpress client for API 2.0
21 | var WP = require('wordpress-rest-api');
22 |
23 | // handlers
24 | var PostsById = require('./handlers/postsById.js');
25 | var PostsByIndices = require('./handlers/postsByIndices.js');
26 | var PostsByTerm = require('./handlers/postsByTerm.js');
27 | var TermsById = require('./handlers/termsById.js');
28 | var TaxonomiesById = require('./handlers/taxonomiesById.js');
29 | var TermsByIndices = require('./handlers/termsByIndices.js');
30 | var TermsByPost = require('./handlers/termsByPost.js');
31 | var AuthorsById = require('./handlers/authorsById.js');
32 | var MediaById = require('./handlers/mediaById.js');
33 |
34 | // logging
35 | var bunyan = require('bunyan');
36 | var log = bunyan.createLogger({ name: 'wordpressRouter' });
37 | log.level(process.env.NODE_ENV === 'production' ? 'fatal' : 'info');
38 |
39 | /*
40 | * Extend Falcor Router
41 | */
42 |
43 | var WordpressRouter = (function (_Router$createClass) {
44 | _inherits(WordpressRouter, _Router$createClass);
45 |
46 | function WordpressRouter(endpoint, auth) {
47 | _classCallCheck(this, WordpressRouter);
48 |
49 | _get(Object.getPrototypeOf(WordpressRouter.prototype), 'constructor', this).call(this);
50 | var options = { endpoint: endpoint };
51 | // auth object should have username, password fields
52 | if (typeof auth !== 'undefined') {
53 | _.merge(options, auth, { auth: true });
54 | }
55 | this.wp = new WP(options);
56 | this.log = log;
57 | // caching for rendundant data in a single flight
58 | this.cache = {};
59 | }
60 |
61 | /*
62 | * Export generator for disposable instances
63 | */
64 |
65 | _createClass(WordpressRouter, [{
66 | key: 'cacheSet',
67 | value: function cacheSet(identifier, value) {
68 | this.cache[identifier] = value;
69 | }
70 | }, {
71 | key: 'cacheGet',
72 | value: function cacheGet(identifier) {
73 | return this.cache[identifier];
74 | }
75 | }]);
76 |
77 | return WordpressRouter;
78 | })(Router.createClass([{
79 | route: 'postsById[{integers:postIds}][{keys:props}]',
80 | get: function get(pathSet) {
81 | var handler = new PostsById(this, pathSet.postIds, pathSet.props);
82 | return handler.buildReturn();
83 | }
84 | }, {
85 | route: 'postsByTerm[{keys:vocabularies}][{keys:terms}][{keys:indices}]',
86 | get: function get(pathSet) {
87 | var _this = this;
88 |
89 | var promises = _.map(pathSet.vocabularies, function (vocabulary) {
90 | return _.map(pathSet.terms, function (term) {
91 | var handler = new PostsByTerm(_this, pathSet.indices, { orderby: 'date' }, vocabulary, term);
92 | return handler.buildReturn();
93 | });
94 | });
95 | return Promise.all(_.flatten(promises)).then(function (records) {
96 | return _.flatten(records);
97 | });
98 | }
99 | }, {
100 | route: 'termsByPost[{integers:postIds}][{keys:vocabularies}][{keys:indices}]',
101 | get: function get(pathSet) {
102 | var _this2 = this;
103 |
104 | var promises = [];
105 | _.forEach(pathSet.postIds, function (postId) {
106 | _.forEach(pathSet.vocabularies, function (vocabulary) {
107 | var handler = new TermsByPost(_this2, pathSet.indices, {}, postId, vocabulary);
108 | promises.push(handler.buildReturn());
109 | });
110 | });
111 | return Promise.all(promises).then(function (records) {
112 | return _.flatten(records);
113 | });
114 | }
115 | }, {
116 | route: 'taxonomies[{keys:vocabularies}].termsByParentId[{integers:parentIds}][{keys:indices}]',
117 | get: function get(pathSet) {
118 | var _this3 = this;
119 |
120 | var promises = [];
121 | _.forEach(pathSet.vocabularies, function (vocabulary) {
122 | _.forEach(pathSet.parentIds, function (parentId) {
123 | var handler = new TermsByIndices(_this3, pathSet.indices, { orderby: 'date' }, vocabulary, parentId);
124 | promises.push(handler.buildReturn());
125 | });
126 | });
127 | return Promise.all(promises).then(function (records) {
128 | return _.flatten(records);
129 | });
130 | }
131 | }, {
132 | route: 'recentPosts[{keys:indices}]',
133 | get: function get(pathSet) {
134 | var handler = new PostsByIndices(this, pathSet.indices, { orderby: 'date' });
135 | return handler.buildReturn();
136 | }
137 | }, {
138 | route: 'taxonomies[{keys:vocabularies}].terms[{keys:indices}]',
139 | get: function get(pathSet) {
140 | var _this4 = this;
141 |
142 | var promises = _.map(pathSet.vocabularies, function (vocabulary) {
143 | var handler = new TermsByIndices(_this4, pathSet.indices, null, vocabulary);
144 | return handler.buildReturn();
145 | });
146 | return Promise.all(promises).then(function (records) {
147 | return _.flatten(records);
148 | });
149 | }
150 | }, {
151 | route: 'taxonomies[{keys:vocabularies}].meta[{keys:props}]',
152 | get: function get(pathSet) {
153 | var handler = new TaxonomiesById(this, pathSet.vocabularies, pathSet.props);
154 | return handler.buildReturn();
155 | }
156 | }, {
157 | route: 'termsById[{keys:vocabularies}][{integers:categoryIds}][{keys:props}]',
158 | get: function get(pathSet) {
159 | var _this5 = this;
160 |
161 | var promises = _.map(pathSet.vocabularies, function (vocabulary) {
162 | var handler = new TermsById(_this5, pathSet.categoryIds, pathSet.props, vocabulary);
163 | return handler.buildReturn();
164 | });
165 | return Promise.all(promises).then(function (records) {
166 | return _.flatten(records);
167 | });
168 | }
169 | }, {
170 | route: 'authorsById[{integers:userIds}][{keys:props}]',
171 | get: function get(pathSet) {
172 | var handler = new AuthorsById(this, pathSet.userIds, pathSet.props);
173 | return handler.buildReturn();
174 | }
175 | }, {
176 | route: 'mediaById[{integers:mediaIds}][{keys:props}]',
177 | get: function get(pathSet) {
178 | var handler = new MediaById(this, pathSet.mediaIds, pathSet.props);
179 | return handler.buildReturn();
180 | }
181 | }]));
182 |
183 | module.exports = function (endpoint, auth) {
184 | return new WordpressRouter(endpoint, auth);
185 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "falcor-wordpress",
3 | "version": "0.3.0",
4 | "description": "A falcor server for consuming the wordpress API.",
5 | "homepage": "https://github.com/jasonphillips/falcor-wordpress",
6 | "main": "./lib/wordpressRouter.js",
7 | "author": {
8 | "name": "Jason Phillips",
9 | "url": "https://github.com/jasonphillips"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/jasonphillips/falcor-wordpress.git"
14 | },
15 | "licenses": [
16 | {
17 | "type": "Apache License, Version 2.0",
18 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
19 | }
20 | ],
21 | "scripts": {
22 | "lint": "eslint src/*.js src/handlers/*.js",
23 | "compile": "babel -d lib/ src/",
24 | "test": "_mocha tests --recursive",
25 | "prepublish": "npm run compile"
26 | },
27 | "dependencies": {
28 | "bunyan": "^1.4.0",
29 | "falcor-json-graph": "~1.1.5",
30 | "falcor-router": "~0.2.9",
31 | "lodash": "^3.10.1",
32 | "promise": "^7.0.4",
33 | "wordpress-rest-api": "https://github.com/kadamwhite/wordpress-rest-api#20160614-dynamic-route-generation-refactor-merge"
34 | },
35 | "devDependencies": {
36 | "babel": "^5.8.23",
37 | "babel-eslint": "^4.1.1",
38 | "chai": "^3.5.0",
39 | "eslint": "^0.21.0",
40 | "falcor": "^0.1.17",
41 | "nock": "^8.0.0",
42 | "sinon": "^1.17.4",
43 | "sinon-chai": "^2.8.0"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/handlers/authorsById.js:
--------------------------------------------------------------------------------
1 | var FetchById = require('./fetchById.js');
2 |
3 | // handler is "authors" rather than "users" because
4 | // it does not request via authentication, and only
5 | // users with posts (authors) are retrievable by
6 | // anonymous request in the WP API 2.0
7 |
8 | class AuthorsById extends FetchById {
9 |
10 | getIdQuery(id) {
11 | return this.wp.users().id(id);
12 | }
13 |
14 | getReturnPath(id, key) {
15 | return (typeof key !== 'undefined') ? ['authorsById', id, key] : ['authorsById', id];
16 | }
17 | }
18 |
19 | export default AuthorsById;
20 |
--------------------------------------------------------------------------------
/src/handlers/fetchById.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var jsonGraph = require('falcor-json-graph');
3 | var $ref = jsonGraph.ref;
4 | var $error = jsonGraph.error;
5 |
6 | class FetchById {
7 |
8 | constructor(shared, ids, keys) {
9 | this.wp = shared.wp;
10 | this.log = shared.log;
11 | this.cacheGet = shared.cacheGet.bind(shared);
12 | this.ids = ids;
13 | this.keys = keys;
14 | }
15 |
16 | // Override with wp api promise
17 | getIdQuery(id) {
18 | return null;
19 | }
20 |
21 | // Override with specific Falcor return paths
22 | getReturnPath(id, key) {
23 | // keyless for error handler
24 | return (typeof key !== 'undefined') ? [id, key] : [id];
25 | }
26 |
27 | // Override with cache path to check for already retrieved object
28 | getCachedPath(id) {
29 | return `${id}`;
30 | }
31 |
32 | // Override with keys that should return references {key=>path}
33 | getReferenceKeys() {
34 | return {};
35 | }
36 |
37 | getPromises() {
38 | var promises = _.map(this.ids, (id) => {
39 | var itemPromise = new Promise((resolve, reject) => {
40 | // check cache for already fetched item this flight
41 | let cached = this.cacheGet(this.getCachedPath(id));
42 | if (typeof cached !== 'undefined') {
43 | resolve(cached);
44 | } else {
45 | let query = this.getIdQuery(id);
46 | this.log.info('GET: ' + query._renderURI());
47 |
48 | query.then((response) => {
49 | resolve(response);
50 | }).catch((err) => {
51 | this.log.error(err);
52 | resolve({error: `${err.status} for ${err.path}`});
53 | });
54 | }
55 | });
56 |
57 | return itemPromise;
58 | });
59 |
60 | return promises;
61 | }
62 |
63 | resolvePromises(promises) {
64 | return Promise.all(promises).then((records) => {
65 | var results = [];
66 | var referenceKeys = this.getReferenceKeys();
67 |
68 | this.ids.forEach((id, offset) => {
69 | var record = records[offset];
70 |
71 | this.keys.forEach((key) => {
72 | if (record.error) {
73 | results.push({
74 | path: this.getReturnPath(id, key),
75 | value: $error(record.error)
76 | });
77 | } else if (record.id || record.name) {
78 | let value = record[key];
79 | // reference keys
80 | if (typeof referenceKeys[key] === 'function') {
81 | results.push({
82 | path: this.getReturnPath(id, key),
83 | value: $ref(referenceKeys[key](id, value))
84 | });
85 | } else {
86 | if (typeof value === 'object' && value.rendered) {
87 | // handle WP 2.0 {rendered} values
88 | value = value.rendered;
89 | }
90 | results.push({
91 | path: this.getReturnPath(id, key),
92 | value: value
93 | });
94 | }
95 | } else {
96 | results.push({
97 | path: this.getReturnPath(id),
98 | value: $error(id + ' not found')
99 | });
100 | }
101 | });
102 | });
103 | return results;
104 | });
105 | }
106 |
107 | buildReturn() {
108 | return this.resolvePromises(this.getPromises());
109 | }
110 | }
111 |
112 | export default FetchById;
113 |
--------------------------------------------------------------------------------
/src/handlers/fetchByIndices.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var jsonGraph = require('falcor-json-graph');
3 | var $ref = jsonGraph.ref;
4 | var $error = jsonGraph.error;
5 |
6 | class FetchByIndices {
7 |
8 | constructor(shared, indices, filter) {
9 | this.wp = shared.wp;
10 | this.log = shared.log;
11 | this.indices = indices;
12 | this.cacheSet = shared.cacheSet.bind(shared);
13 | this.filter = filter;
14 | this.paging = this.getPaging();
15 | }
16 |
17 | // Override with wp api promise
18 | getRootQuery() {
19 | return null;
20 | }
21 |
22 | // responses will be references to a byId path
23 | getReferencePath(record) {
24 | return record.id;
25 | }
26 |
27 | // Override with specific Falcor return paths
28 | getReturnPath(index) {
29 | return (typeof index !== 'undefined') ? [index] : null;
30 | }
31 |
32 | getPromise() {
33 | var rangePromise = new Promise((resolve, reject) => {
34 | var query = this.getRootQuery();
35 | if (this.filter) {
36 | query = query.filter(this.filter);
37 | }
38 | if (this.paging) {
39 | query = query.perPage(this.paging.perPage)
40 | .page(this.paging.page);
41 | }
42 | this.log.info('GET: ' + query._renderURI());
43 |
44 | query
45 | .then((response) => {
46 | resolve(response);
47 | }).catch((err) => {
48 | this.log.error(err);
49 | resolve({error: `${err.status} for ${err.path}`});
50 | });
51 | });
52 | return rangePromise;
53 | }
54 |
55 | resolvePromise(rangePromise) {
56 | return rangePromise.then((records) => {
57 | var results = [];
58 | var offset = this.paging ? this.paging.offset : 0;
59 | var total = (this.paging && records._paging) ? records._paging.total : records.length;
60 | var referencesList = [];
61 |
62 | // build item references and cache objects
63 | _.forEach(records, (record) => {
64 | let refPath = this.getReferencePath(record);
65 | referencesList.push($ref(refPath));
66 | this.cacheSet(refPath, record);
67 | });
68 |
69 | this.indices.forEach((index) => {
70 | if (index === 'length') {
71 | results.push({
72 | path: this.getReturnPath(index),
73 | value: total
74 | });
75 | } else {
76 | results.push({
77 | path: this.getReturnPath(index),
78 | value: referencesList[index - offset]
79 | });
80 | }
81 | });
82 |
83 | return results;
84 | }).catch((err) => {
85 | this.log.error(err);
86 | return [
87 | {
88 | path: this.getReturnPath(),
89 | value: $error(`${err.status} for ${err.path}`)
90 | }
91 | ];
92 | });
93 | }
94 |
95 | buildReturn() {
96 | return this.resolvePromise(this.getPromise());
97 | }
98 |
99 | getPaging() {
100 | var perPage; var page;
101 | var indices = _.without(this.indices, 'length');
102 | if (!indices.length) {
103 | indices = [0];
104 | }
105 | [perPage, page] = this.calculatePage(_.min(indices), _.max(indices));
106 | return {
107 | perPage: perPage,
108 | page: page,
109 | offset: perPage * (page - 1)
110 | };
111 | }
112 |
113 | // Calculate smallest page for range
114 | calculatePage(low, high) {
115 | var range = high - low + 1;
116 | if (range < low) {
117 | let perpage;
118 | for (perpage = range; perpage <= low; perpage++) {
119 | if (low % perpage <= perpage - range) {
120 | let offset = Math.floor(low / perpage);
121 | return [perpage, offset + 1];
122 | }
123 | }
124 | return perpage;
125 | }
126 | return [high + 1, 1];
127 | }
128 | }
129 |
130 | export default FetchByIndices;
131 |
--------------------------------------------------------------------------------
/src/handlers/mediaById.js:
--------------------------------------------------------------------------------
1 | var FetchById = require('./fetchById.js');
2 |
3 | class MediaById extends FetchById {
4 |
5 | getIdQuery(id) {
6 | return this.wp.media().id(id);
7 | }
8 |
9 | getReturnPath(id, key) {
10 | return (typeof key !== 'undefined') ? ['mediaById', id, key] : ['mediaById', id];
11 | }
12 | }
13 |
14 | export default MediaById;
15 |
--------------------------------------------------------------------------------
/src/handlers/postsById.js:
--------------------------------------------------------------------------------
1 | var FetchById = require('./fetchById.js');
2 |
3 | class PostsById extends FetchById {
4 |
5 | getIdQuery(id) {
6 | return this.wp.posts().id(id);
7 | }
8 |
9 | getReturnPath(id, key) {
10 | return (typeof key !== 'undefined') ? ['postsById', id, key] : ['postsById', id];
11 | }
12 |
13 | getCachedPath(id) {
14 | return `postsById[${id}]`;
15 | }
16 |
17 | getReferenceKeys() {
18 | return {
19 | author: (id, value) => `authorsById[${value}]`,
20 | featured_media: (id, value) => `mediaById[${value}]`,
21 | terms: (id, value) => `termsByPost[${id}]`
22 | };
23 | }
24 | }
25 |
26 | export default PostsById;
27 |
--------------------------------------------------------------------------------
/src/handlers/postsByIndices.js:
--------------------------------------------------------------------------------
1 | var FetchByIndices = require('./FetchByIndices.js');
2 |
3 | class PostsByIndices extends FetchByIndices {
4 |
5 | getRootQuery() {
6 | return this.wp.posts();
7 | }
8 |
9 | getReferencePath(record) {
10 | return `postsById[${record.id}]`;
11 | }
12 |
13 | getReturnPath(index) {
14 | return (typeof index !== 'undefined') ? ['recentPosts', index] : ['recentPosts'];
15 | }
16 | }
17 |
18 | export default PostsByIndices;
19 |
--------------------------------------------------------------------------------
/src/handlers/postsByTerm.js:
--------------------------------------------------------------------------------
1 | var FetchByIndices = require('./FetchByIndices.js');
2 |
3 | class PostsByTerm extends FetchByIndices {
4 |
5 | constructor(shared, indices, filter, vocabulary, term) {
6 | super(shared, indices, filter);
7 | this.vocabulary = vocabulary;
8 | this.term = term;
9 | }
10 |
11 | getRootQuery() {
12 | return this.wp.posts().taxonomy(this.vocabulary, this.term);
13 | }
14 |
15 | getReferencePath(record) {
16 | return `postsById[${record.id}]`;
17 | }
18 |
19 | getReturnPath(index) {
20 | return (typeof index !== 'undefined')
21 | ? ['postsByTerm', this.vocabulary, this.term, index]
22 | : ['postsByTerm', this.vocabulary, this.term];
23 | }
24 | }
25 |
26 | export default PostsByTerm;
27 |
--------------------------------------------------------------------------------
/src/handlers/taxonomiesById.js:
--------------------------------------------------------------------------------
1 | var FetchById = require('./fetchById.js');
2 |
3 | class TaxonomiesById extends FetchById {
4 |
5 | getIdQuery(id) {
6 | return this.wp.taxonomies().taxonomy(id);
7 | }
8 |
9 | getReturnPath(id, key) {
10 | return (typeof key !== 'undefined')
11 | ? ['taxonomies', id, 'meta', key]
12 | : ['taxonomies', id, 'meta'];
13 | }
14 | }
15 |
16 | export default TaxonomiesById;
17 |
--------------------------------------------------------------------------------
/src/handlers/termsById.js:
--------------------------------------------------------------------------------
1 | var FetchById = require('./fetchById.js');
2 |
3 | class TermsById extends FetchById {
4 |
5 | constructor(shared, ids, keys, vocabulary) {
6 | super(shared, ids, keys);
7 | this.vocabulary = vocabulary;
8 | }
9 |
10 | getIdQuery(id) {
11 | return this.wp[this.vocabulary]().id(id);
12 | }
13 |
14 | getReturnPath(id, key) {
15 | return (typeof key !== 'undefined')
16 | ? ['termsById', this.vocabulary, id, key]
17 | : ['termsById', this.vocabulary, id];
18 | }
19 |
20 | getCachedPath(id) {
21 | return `termsById.${this.vocabulary}[${id}]`;
22 | }
23 |
24 | getReferenceKeys() {
25 | return {
26 | children: (id, value) => `taxonomies.${this.vocabulary}.termsByParentId[${id}]`
27 | };
28 | }
29 | }
30 |
31 | export default TermsById;
32 |
--------------------------------------------------------------------------------
/src/handlers/termsByIndices.js:
--------------------------------------------------------------------------------
1 | var FetchByIndices = require('./FetchByIndices.js');
2 |
3 | class TermsByIndices extends FetchByIndices {
4 |
5 | constructor(shared, indices, filter, vocabulary, parentId) {
6 | super(shared, indices, filter);
7 | this.vocabulary = vocabulary;
8 | this.parentId = parentId;
9 | }
10 |
11 | getRootQuery() {
12 | let query = this.wp[this.vocabulary]();
13 | if (this.parentId) {
14 | query = query.parent(this.parentId);
15 | }
16 | return query;
17 | }
18 |
19 | getReferencePath(record) {
20 | return `termsById.${this.vocabulary}[${record.id}]`;
21 | }
22 |
23 | getReturnPath(index) {
24 | let base = ['taxonomies', this.vocabulary, this.parentId ? 'termsByParentId' : 'terms'];
25 | if (this.parentId) {
26 | base.push(this.parentId);
27 | }
28 | return (typeof index !== 'undefined')
29 | ? base.concat([index])
30 | : base;
31 | }
32 | }
33 |
34 | export default TermsByIndices;
35 |
--------------------------------------------------------------------------------
/src/handlers/termsByPost.js:
--------------------------------------------------------------------------------
1 | var FetchByIndices = require('./FetchByIndices.js');
2 |
3 | class TermsByPost extends FetchByIndices {
4 |
5 | constructor(shared, indices, filter, postId, vocabulary) {
6 | super(shared, indices, filter);
7 | this.postId = postId;
8 | this.vocabulary = vocabulary;
9 | }
10 |
11 | getRootQuery() {
12 | return this.wp.taxonomies().collection(this.vocabulary).forPost(this.postId);
13 | }
14 |
15 | // pagination does not exist on post terms
16 | getPaging() {
17 | return false;
18 | }
19 |
20 | getReferencePath(record) {
21 | return `termsById.${this.vocabulary}[${record.id}]`;
22 | }
23 |
24 | getReturnPath(index) {
25 | return (typeof index !== 'undefined')
26 | ? ['termsByPost', this.postId, this.vocabulary, index]
27 | : ['termsByPost', this.postId, this.vocabulary];
28 | }
29 | }
30 |
31 | export default TermsByPost;
32 |
--------------------------------------------------------------------------------
/src/wordpressRouter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Router = require('falcor-router');
4 | var Promise = require('promise');
5 | var _ = require('lodash');
6 |
7 | // falcor basics
8 | var jsonGraph = require('falcor-json-graph');
9 | var $ref = jsonGraph.ref;
10 | var $error = jsonGraph.error;
11 |
12 | // wordpress client for API 2.0
13 | var WP = require('wordpress-rest-api');
14 |
15 | // handlers
16 | var PostsById = require('./handlers/postsById.js');
17 | var PostsByIndices = require('./handlers/postsByIndices.js');
18 | var PostsByTerm = require('./handlers/postsByTerm.js');
19 | var TermsById = require('./handlers/termsById.js');
20 | var TaxonomiesById = require('./handlers/taxonomiesById.js');
21 | var TermsByIndices = require('./handlers/termsByIndices.js');
22 | var TermsByPost = require('./handlers/termsByPost.js');
23 | var AuthorsById = require('./handlers/authorsById.js');
24 | var MediaById = require('./handlers/mediaById.js');
25 |
26 | // logging
27 | var bunyan = require('bunyan');
28 | var log = bunyan.createLogger({name: 'wordpressRouter'});
29 | log.level(process.env.NODE_ENV === 'production' ? 'fatal' : 'info');
30 |
31 | /*
32 | * Extend Falcor Router
33 | */
34 | class WordpressRouter extends
35 | Router.createClass([
36 | {
37 | route: 'postsById[{integers:postIds}][{keys:props}]',
38 | get: function (pathSet) {
39 | var handler = new PostsById(this, pathSet.postIds, pathSet.props);
40 | return handler.buildReturn();
41 | }
42 | },
43 |
44 | {
45 | route: 'postsByTerm[{keys:vocabularies}][{keys:terms}][{keys:indices}]',
46 | get: function (pathSet) {
47 | var promises = _.map(pathSet.vocabularies, (vocabulary) => {
48 | return _.map(pathSet.terms, (term) => {
49 | var handler = new PostsByTerm(
50 | this, pathSet.indices, {orderby: 'date'}, vocabulary, term
51 | );
52 | return handler.buildReturn();
53 | });
54 | });
55 | return Promise.all(_.flatten(promises)).then((records) => {
56 | return _.flatten(records);
57 | });
58 | }
59 | },
60 |
61 | {
62 | route: 'termsByPost[{integers:postIds}][{keys:vocabularies}][{keys:indices}]',
63 | get: function (pathSet) {
64 | var promises = [];
65 | _.forEach(pathSet.postIds, (postId) => {
66 | _.forEach(pathSet.vocabularies, (vocabulary) => {
67 | var handler = new TermsByPost(
68 | this, pathSet.indices, {}, postId, vocabulary
69 | );
70 | promises.push(handler.buildReturn());
71 | });
72 | });
73 | return Promise.all(promises).then((records) => {
74 | return _.flatten(records);
75 | });
76 | }
77 | },
78 |
79 | {
80 | route: 'taxonomies[{keys:vocabularies}].termsByParentId[{integers:parentIds}][{keys:indices}]',
81 | get: function (pathSet) {
82 | var promises = [];
83 | _.forEach(pathSet.vocabularies, (vocabulary) => {
84 | _.forEach(pathSet.parentIds, (parentId) => {
85 | var handler = new TermsByIndices(
86 | this, pathSet.indices, {orderby: 'date'}, vocabulary, parentId
87 | );
88 | promises.push(handler.buildReturn());
89 | });
90 | });
91 | return Promise.all(promises).then((records) => {
92 | return _.flatten(records);
93 | });
94 | }
95 | },
96 |
97 | {
98 | route: 'recentPosts[{keys:indices}]',
99 | get: function (pathSet) {
100 | var handler = new PostsByIndices(this, pathSet.indices, {orderby: 'date'});
101 | return handler.buildReturn();
102 | }
103 | },
104 |
105 | {
106 | route: 'taxonomies[{keys:vocabularies}].terms[{keys:indices}]',
107 | get: function (pathSet) {
108 | var promises = _.map(pathSet.vocabularies, (vocabulary) => {
109 | var handler = new TermsByIndices(
110 | this, pathSet.indices, null, vocabulary
111 | );
112 | return handler.buildReturn();
113 | });
114 | return Promise.all(promises).then((records) => {
115 | return _.flatten(records);
116 | });
117 | }
118 | },
119 |
120 | {
121 | route: 'taxonomies[{keys:vocabularies}].meta[{keys:props}]',
122 | get: function (pathSet) {
123 | var handler = new TaxonomiesById(this, pathSet.vocabularies, pathSet.props);
124 | return handler.buildReturn();
125 | }
126 | },
127 |
128 | {
129 | route: 'termsById[{keys:vocabularies}][{integers:categoryIds}][{keys:props}]',
130 | get: function (pathSet) {
131 | var promises = _.map(pathSet.vocabularies, (vocabulary) => {
132 | var handler = new TermsById(
133 | this, pathSet.categoryIds, pathSet.props, vocabulary
134 | );
135 | return handler.buildReturn();
136 | });
137 | return Promise.all(promises).then((records) => {
138 | return _.flatten(records);
139 | });
140 | }
141 | },
142 |
143 | {
144 | route: 'authorsById[{integers:userIds}][{keys:props}]',
145 | get: function (pathSet) {
146 | var handler = new AuthorsById(this, pathSet.userIds, pathSet.props);
147 | return handler.buildReturn();
148 | }
149 | },
150 |
151 | {
152 | route: 'mediaById[{integers:mediaIds}][{keys:props}]',
153 | get: function (pathSet) {
154 | var handler = new MediaById(this, pathSet.mediaIds, pathSet.props);
155 | return handler.buildReturn();
156 | }
157 | }
158 |
159 | ]) {
160 | constructor(endpoint, auth) {
161 | super();
162 | let options = {endpoint: endpoint};
163 | // auth object should have username, password fields
164 | if (typeof auth !== 'undefined') {
165 | _.merge(options, auth, {auth: true});
166 | }
167 | this.wp = new WP(options);
168 | this.log = log;
169 | // caching for rendundant data in a single flight
170 | this.cache = {};
171 | }
172 |
173 | cacheSet(identifier, value) {
174 | this.cache[identifier] = value;
175 | }
176 |
177 | cacheGet(identifier) {
178 | return this.cache[identifier];
179 | }
180 | }
181 |
182 | /*
183 | * Export generator for disposable instances
184 | */
185 |
186 | module.exports = function (endpoint, auth) {
187 | return new WordpressRouter(endpoint, auth);
188 | };
189 |
--------------------------------------------------------------------------------
/tests/fixtures/responses/postsByIdMultiple:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/posts/1",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b0800000000000003ad55d16adb3014fd1555cf49ec94650393a60c36d8de0a2bf4612a41b1af1dadb224a4eba6c1e4df77afdb642dddf29005f2a0d8f239e79e7baed44b53c9623a9295469085bccca71fc7f96c3ccd6ff34fc5e5acf83093cf2f974d8bffdcd0740cd3cb08ae8208b4966bc4900a95a9ac82d64f3661ac8399f8d8a8ec3a5c4de56e245b5f99da0cbbffcebbdf70943bd9ae613eb0d68f373eda8a14e3367039c127a47fd6b887e392985f65f94c65d35c65afb054c668062dc1bda9ef1bf38981ef828b29bd437064d19b5df3b0b8035bfa16047a31d7621da1be52afdc796d8c928bbb1bf1f9e6bbf8429e891f0621cd55a6171371bb3649d06febbb286a13130a2e6e22be5606858fa2020b08c2e048e01a9c48a8238a95f54d635c73413061a11c2b85a7126238aef49d8cb32ad01dae7d1c725783c68e12b36ca1325a16393bd9b6e4e4922ac02e51df7c00475d0854c7bb87094df9b09545ad6d8291ac7d6c35e7943e76958e9c8592a2ddf86880b07e4eefa99dbae125ad969c0c5af73281ade9592fb941c7b3421dfb95bc53d926a8ecf1928ca546244a8edc1164e9ad85128d77ff053760e995efa898d354f10890aa610458d8de744283760555a5571c6a8c1df97642d55d8278a83a42b0cf069f09fd2504e99af5f37141153c1221f93aa651401fa9e9a719b36f97ca223c1a464c03fc26141a51976b4edfa9e0438caf83a693702f9b7011623b20a27ef2ceb7a47d1fcb2d25f42cfdf813f38367a39eb27e20e4ba9794fd7311f2181da838f9ddcb8cf5d2e9968fdf4d20ae77d1e27b60f37c13f411ec8ef620b4c1d298d2c5c179dcddef76bf018bd61a649a060000"
10 | ],
11 | "headers": {
12 | "content-type": "application/json; charset=UTF-8",
13 | "content-length": "620",
14 | "connection": "close",
15 | "access-control-allow-headers": "Authorization",
16 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
17 | "allow": "GET",
18 | "content-encoding": "gzip",
19 | "date": "Sat, 11 Jun 2016 20:48:49 GMT",
20 | "link": " ; rel=\"alternate\"; type=text/html",
21 | "server": "nginx/1.4.6 (Ubuntu)",
22 | "x-batcache": "MISS",
23 | "x-cached": "MISS",
24 | "x-content-type-options": "nosniff",
25 | "x-ec2-instance-id": "i-f737987d",
26 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
27 | "vary": "Cookie",
28 | "x-cache": "Miss from cloudfront",
29 | "via": "1.1 3e4642ebc640ace400836140916c7de0.cloudfront.net (CloudFront)",
30 | "x-amz-cf-id": "X1rNg2i6HChBi1LKClOv8eRuW6EAW9UszzBTXkRBN_7R8pvj9BAL9Q=="
31 | }
32 | },
33 | {
34 | "scope": "https://demo.wp-api.org:443",
35 | "method": "GET",
36 | "path": "/wp-json/wp/v2/posts/100",
37 | "body": "",
38 | "status": 200,
39 | "response": [
40 | "1f8b0800000000000003c55adb721cb711fd15641ff2a499d5356531325d2a492e2915cba6652b95f2ba54e00cc8453437cd85a4a3d2bfe79c6e0083a5442751549507d3e4ee0cd0e83e7dfa7443ef37bede1cddb97dfbd6a6b6b3db1c6deedebef3a7e2f683e2f6c39feede3bba77fbe8fec38d7ef9e6bc9d6f7ce07ce142ef37a3eb6a373afcbed9cff3301dedb6bb6deddabebc1c0a3bf8b21fcf775b6eb2dbde7e80ff1eeeb6ee6a70b59f6d61a76969b1007e1babbd9f5d35f745dd37fdb8db6e3edcdab47dedcfbc2cfe6933e303bf6bead42ce730ef3fd815079f7f1be895a19f66fcd5f8eeed973f1976f173836d0edcf72c78c524af98d52b46bc429f547d37bb0e813978f9d1fecef1b3d92cb3b9e89b659811dbd65cb8c6cf06e76e7c654f7b83cf867eb4c676bef58f765bbcb3eb1e2d0d7f36fef864f16672b5f19d71d3ac3b2eadc186937bb72cddbc8c78090fe2f1dd565fd36ddd6c7c6d180cf38e8b58373833e247d3d8d90c637fe16bd85c9ad762119eeb75d96a7658d5f865745c01ebc0e6d27c7f76e62bef273c348e388d874d1758a0c763e97ca6eb3b83e5e3074bfbf1919ef4ad58450387c9b666015ad321709467fd64ec4267612b38077bcab2f410bd909e8d073e6dfaeaedbba59fddf1a3e1f83550ece8753b0d6eec2c0fa35eaf96f6dde24af374a97cbb4ca6410046df8b0df04aab67fea1b195c3196c0b0bab65f04c8bd99947d60844bede6d9e2ccd60cde4bb19beed8d43442618d7782c8fdfd463bb8dd98fee0c8f330925072f2f2fcbe776a9de9655dfeeb6962fd8b6c01a859bf13f3f21fd60b48753277e2416ba827ee2d7e57e6e9bdde67845e3305a37210a7e694bf39d3def3c4f2eafc12805179d6b8fcd637c7170063ac3b871ecc7f4c2e846bc267801bc10e2659a7bfe6dcb1b8ef337b7efdc58faeeac07cb6c8e797a9ccb022774926ecd0897e6a5dffb0668e6c299eb473bfbbec3f72f8838fd1a6e110c986e4160f02a60d50b002d6239322040c5d9726eb1d252dbe080678008305e2d930581adb8c499f6be42d6b9b19277b15f4b8c95e2157c4457c40d32279de0e421694089800c7c2811efa79b1cf2aadadbf6d48de7f08a441961f44dd36b78134c0a5fc76876ae7213fc86339d2e937aacf158a2d77c2fcdb3abca0dc0b1574c0b3c989b3485deb4a7a5f9d1213d6124fc42b8203b2b5f8320d67c8535927848032c399bbeedf07048d5c93c8ec48f25e1bbae3fc5b76ddf20e33cfe16688006e425f13c284f98e200838f6b3ff8a9f26a3a0f6442804d6baf7c7b90472f045e2d608be42372d6ed3ac00421212b8debc96a807dc4a16e72fe5f6cd59f4e7d17f0e88087a2f615ca5ae0d902640a947664024b72426244522c0349d6811e022c2297013138b6073344d7023da94406d0833222a34b75709264883f7dae0e779639e65248991c1a328412559a68a7eb1d6850d6102766a07c857a8024e86f72c2535fbd75dda4551e6b8249e266d96f423ebec62719e7c03591247f9ea5f0b0f8700d52b0ba8b4e2d951d910db18213a407d9c5d271f8492a60ea94da35d016cb540abb23d2586cad1c7268807986b3c10f008fa0be343fa0fcf4cabdceaa69825718096e4885162c4fcda25b615d595fcf66780279130124db027c28102170d7bdfd5cc3c5572e800877cdeb2aae48ecdf554fddd8f6f3ac694f54fb4208b408e59aa5a840cef982a5a38071c5dccfb685d74f5171906448e81a470c1528e24cfd1e61998aa28d78245bd2ff52f4a470269ad1928e07b0353982d093bab52a10e45d9917866f51fe40c4312b02236749189d2c9e8a7f289f9a2c62be154569a2ddee9359fbed685b1fd3f5eac053adef96495de5e0c7c2d6aa43511a134f440e5dcd5067d98a458045fe31335289ca5de5fc4938b2bab45203e0793055287f7662858a75c5740e84462a0dac9c844f69feaa3c0df081e96aac859450ed2220db133cf4fbb0d45e6b124c87020456236a27fc82674e10444a35143e6104682b0253513ca53360fd50d5f398bde8089d6bd0cc244773d18fa44529481d7434cc2a261ca9487fb8e05d7c81d314d03405e96e2e064523402a07439d463563aa8a400a94980b52984225ab9203b80092d2e9439ca6120f0cc7f891693748d8fd3d51bc310e907b083cfccf5a906f8117f1285f18e5e783e327aa8845edd1893e3e2f9f4c0b2238509a2479059a8d6155870a9c833b847c293ab3af848b19272f11d328419e828d42a500979c2175a406536f505f287d30e96190d65fc9bf3551789607eb5992f40f2a155fabbcc7cf970004ad4a1410732b9658783ea0387fed1998952507ffc9214280d2b2aa1b598333d0476247a4d35a517023727f289084a32b8ae347a7a3d96d7900df9ea30cce50bc2f5451a5353425a83e88d169ac72552c00dbf74d5dfa79b77d70fffed5fd7be84a01386c3cac9ee9635384f38830000671602b3997c40bf32e19cc6e02694e76cf088c5eca1f614115cd24049f74a0f80af83d787cb75533d064bdd6620309251d141ea325cc2a66870aeb608d767519d6d1a7fc90a145ba3f1287c152e74490f622dc3a543298415427fac8d381720018a426d6a7563a0c6f23f499e45ecb030c3db3153a176c13ce333b680f7838c86d9810a84d5c34e1d0b3b81ca766d1d1b101df081649c2a5457f9e0d5bb0955b95f90ef333f1281c106581919ca153350e49a9d23e1b54260cc894ae9a0c27488689da8aeded6903f605ede2cbd81c05e682e1f2f8a10a8fef4d1897a0bd5281262d0300a14944433b2c194587f4239087d253e0a983000586800049c709f25bbc987d7c4d34a54a073722856d02406902e5016fe870958872ba0a2a167a55ec056f6b520221e8744371c65c21ba97e813b9120f84c5a4748d6e0f4412614ac7095c7074e25569f90e3a8167742c5e41fee92c81ed5da8a06a2d7df554541a7328223828bd90555264a40b8c81fb4869a6f2cc1324e39232d5d14aec5cb4b4d0a8685c3cc30d256938be266c3325fe789d30e4e05fdbf364cd8dede273c89fa6d1c22cb615481d1411e89eb9d0cea85021247192ba1c569dc090796d053804c9aadc1032686bd01ceab0f83f65478fe14d6a2d4f986011c9b142292480924e75495e06919148b96966431f0b286b524caba0641d5bead2c074df5aec708a4c01afc0ef528a10791633511846c59af4f038419ca3acc8c7531604532a966418268dacc63240195062a397ab222010d98d56bfc74c8a122267b068522ca13cd74d02ea95c57863acb5a3eaabcaba0a64cb014dd85c85298453cfee32e84df53da202dd89d5d1dab1eb0e431fb1a534a0477ca593baa00b8162407c36a21daff750e8aab4da28a1c802c870ae8157622aafaecbc0fa23f6c7daf829fe044ad6c4be76f0b5a9f9a9bfc468e6d4ff1313e2b910ca2a284f01cf10a72238b2909cc6e99957ca43883f8c5a8d911cd1f1a2fa267e2573158bcee74711e03890d68cb449a430b44c79804fa89c0f07536afa738b16189d980cba75ee50409115c1f968bde2b0a490d6622d0f85b4e79a72b1b9d0524e1111b470184be92142876c72f5a7c3134934518c0c10742c5560a2042d1061da4aea62e94663bd2a19264becdc53d36a31e6d301109e77107ea16b898c2ee30ef334a674ecdf85f5638e46f09c643db3c4e01a5c52a3939a40195d4c9fece4fe8eb6a244a30585c41991b617d2df16b18a022b5a3311800c7dd27044162f04a3c091b419f823a4d155200b69d424a7a901516c41303a23174d08f4e92014ec9211219cade25b91094662dd612e898440eca60190100915a604fa443eee87f11c58b056f55a2d207a935e7fc5093b8c4db2fafba0a0b4d88107545e6aa8fbda886ff2171eb302a7a1ba4e42658c903f24553fa08654aa24c845c55569f7572ad4628a09f9e1f14fa8f9d04349279534b6402376435c3d90b049f4971bc53457a697d8e75fbd8e2319d1c9697696c6c3c9e0388a09dc21770fc800ee7dd02ca517be8f449ce420e99e8d1765164b616ec753111a31fd0ef4bf9c15cc2a751669884980942f0ec0f225c8a08732514664e94284eca4041d593e7ffb49bccc88070427e0dee7306ab1b7666495e857be40d9e56037c76a5a3fb5257779e5849b32502790aa5a22965978322fb5d16e2cb2bfcb362b4199a519d685f1082779ace6693344e05b6d1a740670cd4d308035200c1865a10c7578f967f29af60d69cdd85a260062a4112a1d87a739bba677b0d473449bea23e349140fce4ff3a75eb1275336b007a038e1ed4d9c84932ab5e812ebf9fb2fb143acdb2c035a9d549de5cf0148a106c7592fc786ab1c50e88658f1e290668fc3471787d09cffd5bd21871202c5dfb9266429c651097310a544e5ff752788ce45c998f6a42b40f3efeefdcc97bad9fbe58f7bdc82fae1cfbf22781c30301448c47d3fe21efed6e60cc358342bf59b1657e27673f4f02b5ef1b6b8159fdf4c68b39709f7cffde03adc460fbe3b5f3fac9a1e28c2c7985b576f7fdb1c9dd9667258b11f5bcb8b7bbc8e9ba9918f4042ba73dc3f3aacf6cb9d5f71016dcff92b7e7bc33b6efcfe7e33b9e60c9fbddff02af1f76fbd71b7ff0fccf876dbcb61b7bdb88b93a1204fbb2dfe61c1e60316ad307844fdc25ddbffb4a0ac858bd305c7f93cbb789d0fbbe43a9f8645cf6335879bb3bab6a7bc88c78c129efb8c732fb823e2b9c552647da32efe42ab07204cdfd0feafa3732109267816221317a62302ff79ae5943b6db8eee027a11634d39c7e57014611950f9a5dc25cbedb60fbf8afbd879b6d59e68ffdc63c892df0c16b3d0d54538c18c0b125973b6577dd7b7f0534c83df90115f24fa6b5a6511baf51ed995b6a497df20dbbed4964cdc6c33e61aee6a25afdf6f30b6e13f5eb91cb0db4760e63fc6b9d42ee5fde89a0f7886ea00ff4283ffc08619f0e1d70f1ffe05c7185ce321240000"
41 | ],
42 | "headers": {
43 | "content-type": "application/json; charset=UTF-8",
44 | "content-length": "3560",
45 | "connection": "close",
46 | "access-control-allow-headers": "Authorization",
47 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
48 | "allow": "GET",
49 | "content-encoding": "gzip",
50 | "date": "Sat, 11 Jun 2016 20:48:49 GMT",
51 | "link": " ; rel=\"alternate\"; type=text/html",
52 | "server": "nginx/1.4.6 (Ubuntu)",
53 | "x-batcache": "MISS",
54 | "x-cached": "MISS",
55 | "x-content-type-options": "nosniff",
56 | "x-ec2-instance-id": "i-f737987d",
57 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
58 | "vary": "Cookie",
59 | "x-cache": "Miss from cloudfront",
60 | "via": "1.1 c381fe6202a5a2a18615c3efcbdca28a.cloudfront.net (CloudFront)",
61 | "x-amz-cf-id": "RDj2GV5WOtH2XtVILixPwTKEdNjyd9B6cMhSwPKn9Ke5m3f1nNArtw=="
62 | }
63 | }
64 | ]
--------------------------------------------------------------------------------
/tests/fixtures/responses/postsByIdSingle:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/posts/1",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b0800000000000003ad55d16adb3014fd1555cf49ec94650393a60c36d8de0a2bf4612a41b1af1dadb224a4eba6c1e4df77afdb642dddf29005f2a0d8f239e79e7baed44b53c9623a9295469085bccca71fc7f96c3ccd6ff34fc5e5acf83093cf2f974d8bffdcd0740cd3cb08ae8208b4966bc4900a95a9ac82d64f3661ac8399f8d8a8ec3a5c4de56e245b5f99da0cbbffcebbdf70943bd9ae613eb0d68f373eda8a14e3367039c127a47fd6b887e392985f65f94c65d35c65afb054c668062dc1bda9ef1bf38981ef828b29bd437064d19b5df3b0b8035bfa16047a31d7621da1be52afdc796d8c928bbb1bf1f9e6bbf8429e891f0621cd55a6171371bb3649d06febbb286a13130a2e6e22be5606858fa2020b08c2e048e01a9c48a8238a95f54d635c73413061a11c2b85a7126238aef49d8cb32ad01dae7d1c725783c68e12b36ca1325a16393bd9b6e4e4922ac02e51df7c00475d0854c7bb87094df9b09545ad6d8291ac7d6c35e7943e76958e9c8592a2ddf86880b07e4eefa99dbae125ad969c0c5af73281ade9592fb941c7b3421dfb95bc53d926a8ecf1928ca546244a8edc1164e9ad85128d77ff053760e995efa898d354f10890aa610458d8de744283760555a5571c6a8c1df97642d55d8278a83a42b0cf069f09fd2504e99af5f37141153c1221f93aa651401fa9e9a719b36f97ca223c1a464c03fc26141a51976b4edfa9e0438caf83a693702f9b7011623b20a27ef2ceb7a47d1fcb2d25f42cfdf813f38367a39eb27e20e4ba9794fd7311f2181da838f9ddcb8cf5d2e9968fdf4d20ae77d1e27b60f37c13f411ec8ef620b4c1d298d2c5c179dcddef76bf018bd61a649a060000"
10 | ],
11 | "headers": {
12 | "content-type": "application/json; charset=UTF-8",
13 | "content-length": "620",
14 | "connection": "close",
15 | "access-control-allow-headers": "Authorization",
16 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
17 | "allow": "GET",
18 | "content-encoding": "gzip",
19 | "date": "Sat, 11 Jun 2016 18:44:57 GMT",
20 | "link": " ; rel=\"alternate\"; type=text/html",
21 | "server": "nginx/1.4.6 (Ubuntu)",
22 | "x-batcache": "HIT",
23 | "x-cached": "EXPIRED",
24 | "x-content-type-options": "nosniff",
25 | "x-ec2-instance-id": "i-f737987d",
26 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
27 | "vary": "Cookie",
28 | "x-cache": "Miss from cloudfront",
29 | "via": "1.1 b4462bd98dd9186cca8c54d37f70d629.cloudfront.net (CloudFront)",
30 | "x-amz-cf-id": "fsfzd1XTGJ8eNkmxQSUhvKg2QOBT5C-eTjqWgO3yIU4_2yC7d3GyBw=="
31 | }
32 | }
33 | ]
--------------------------------------------------------------------------------
/tests/fixtures/responses/postsByTermSlug:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/posts?filter%5Bcategories%5D=uncategorized&filter%5Borderby%5D=date&page=1&per_page=4",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b0800000000000003ed5d6b731bc795fd2b637ed84f064849a4126b1da618895e6b63c9a228c9b515ba5c436044ce1ac0c0c040a2e3f27fdf73cebdb7bb072229c796edec6eaa129a04667a6edfe7b98f1efded879d76baf3e0cec73bd3ba6f761eecdcddbb737fb47730bab3f762ef0f0fee1e3cd83fd8b12fbfb998f7375e70b1e1323fecac9ac5b45935f87de7b2ef97eb0767bb67bbd366de8ddf2e47f5b21d77ab8bb3dd3f2fff7467e7c78f77e6ddb47dddeaeaeb9f1b17dcfaecf56c73c1e735b359377adbad665350dc7fbfe47696ddbac75fb376f1eded24f1f967bb7b0767bb77f6ce768bb5ce76b95adbcfb0dc607f9ff379959ef7113733e9167db3008b06577dba3cfcaa994dba7953f55df5695d5dae9ad77f3a2bb85332e66ce7f0ab67d5d1b3c7d523f0ac3a6dfb66fde9d96e7d38ae5e5cb6eb0afffbbedbacaad7ed6add57dcdcb83a9eb67dd5adaa69336bfaa66afb8fabfeb25954ebbe5ef5d5f9acbbb86817171f6199e5e1d9829436579366b5bc9dd277c8f8a014d49bfeb25b49ef5e3775bf81c67c336fa66dbdf3608f9c9ccfc1c96fb0837eb386dcba65b3801496d8c73b1faefb76f2edf73b0f5ed7b375f3f1ceeb6e35afa9a7b87931ad57d4850954fba25bb50dd6fadb9daf21cefa82bfe2b76fa819f8fd879d75337b8dcf7ed8a1806ed71548ecbfd7dde26cf7edf26cf7cd5d301682584373767ec492936e366b267ddb2d7ed1725aab3eef36d8cccfa38a2600aa6402242c988ed59af979339dd6e754ea7eb501df7ec6ae37eb669576bd6a963363f0075add9560fd67d24f77811dbcc103c1d7114ca1ef5610facf634c88eb6c77d5bc69b9e25acbbf5d3ea8fbbe9e5c52fb7eeee252e33f2f6b78c2201bebf6cd6aae15fbfaaa5b7473d01e6af93d34f483c823ab79e2d9c73f40d7d303b9ef6fa0fb1fea8134a3f4286afec66dec879d453da7fb7dbbc4b3de512dc681b716097e5835b31f714ddfcc973398290207f5f1c7af7ffc11b42b34edc1236c05a7bd4f5edcbdf7e0dede83fd4f702fbfdc0a10c30bfeb1e09423c1de2767bbcdd5127ea9af47f57abd815e4cf1db6a",
10 | "7209c73ce9bbd1b49b752b44881faf8d65432a6e8865c38b3c96fd84a792693f3bc6fdf49d5d1ffb8e9d2b55e24a95b952892bb784c4cb3b87c77db5e9ab37dd6cb384936fe6d59b668630867dcfda09bc5e4585e85675552fda798bd8857bce169f6e66fc396b0f4f366db56ea655bba81a44423d7133af1083d7cd779bcd02210537e1425c7eb66bb7d9639bbe6aa71585517dc745ea66d954f05e88e63542eaaa7bd34e61bae3ea9528c2759d2d3be91bac5ab508565c01eb80e671f5e5ebd7eda445609e74ab1576d382a63758a0c365697fd5a25b54583e3ed8ccdfddd243443d52450297eb7a5e6d00a5d226b095e36e5dc187835978149883676a5972885c48d7c68611fb27df7eb7e9fae61030e415b4b821d7ebf5b2592d18759deb93cdfcbb4d33ae1e6d26ed7cb3ae6610c0aaed4403b832b73d3f9bd513c4ea0a96dd5793cdb2a559007000d3081e01d43cdccc9675b56e173d78db550d24b20671b316cbe337e3d8d94e89810410dfbe7d3bfebcde4cbe1dc3eb03eef0867a3ec21aa3a6c77fda35cc0f44b760ea9a1f89c266443ef1ebf1653f9f013b656d5caeea660d29b49bf9b87a525f2c5aee5cb78128532e32b73eac8ef0c5600f6446d5ac56c05471c3aa59e136e90bd40b22de2000f1ef7a7cc376be6a2e17cd6adc2e5e7780c03b87dc3df655434fc8247b34253cae9eb697ed0cdacc850bd6af6a62087cff981a675f832dd2816ab18160702bd4aa9302d690e58a028156bcde5cd4586933ad9d01c75011e8f864b32626ca7a893d5db613585db39ae85e3c6f4e1d1b8b2bf888ac8807144c3ac1cedd68e012a132e0a124dead6f62c8e9e4b206ea585d802b9232c4d812b163dbeb515293513b0d692e9a49b306dfb0a7f38dc1e06ad66289ceec1dd0174076093d6e4da7a51eb44d92426ed6e7e3ea7903f30491e00bd505d63969a77010d95e8934687830032c092c3d5fe06237d57575148e1f4b82778bee1cdfcebb192caec5df520db801dd24ce230b90a718e8e0d1b45db6eb496ba47343950bb89ad7572dd28382bd8fa55e73a82d8c8f9a931fb7809a4024f44aabbcb329947d854dddc4fcffac27dd3920abeb63037d184ddb09c29afbd9119c29b474414f50d339c130c2298edd494edd3db85a842f83c660db2d3c43b016da9342a42b3d5c467874f9ea464606f993e7c6f0a6a68d31373191d2384c64102552486a3b59dfc00d6a0d31b1e0da29e2018ca0bb89098f9028348bb5010f695d7ad828ff26e7d34ef149e173c09a70922f7b051e061fae41176cec2253c7e61d610d11c1a9a403eb62e8187e920298318579dc0479cf58de1d92c662397268d350e61ecc867f80f248ebc7d533849fce7c6f531b69d2571009df90022dbc3c318b3d0aeb6a7ddb5bc51de84e0890de16ca8710e782dbe6f6e7262edef2061ad16c71dd327f3af627934700bf5ddf9bd953abdb911ce8c8c33543d10836d7c20d2cfa11881bf55d5fcfc1f573441c18190c7a8a2d7a040a3d33be875aa6a058873ed25b92ff0a7a0a9cc9cd5848c70578347d04554f712b2310d8ddb834cacf10fee088c32adc231746184c16a7e20ff3a75521b1762e445905ddcdb556fbd9aa9eb761ae57034ecddbc5861e13ac6ac0c7513d351c8ad098fc44f8d04c8631ab9e300830c81fd122cd513557a5ffa43a32bacc1503c079782a0f7ff59a112ae24ab568e0d0e84add2b27e033aebe303f0de583a79b622d9884611729d92595877c5f6e90f42b2681742040e86a68ed1abfe09a130891500d814f1e01d88a8a695abc4e7bc0fa1ed54b993d5e5075b654b3801cb337dd8a6e51016981f408648dd6d8d228fdd13877f105763302a619d1ddf523e42bc44350526d0c719af52098940092bbc4129082142259831cd00b6852dabdcb693dc605cb43fc28b01b20ece53d21de9003e01e040ffe3316948fc08db89437acf4f3e0f0a12162a13d321161aef864bd8104978426095ec1cd86588da1526767879c2f4167f1957c31e5d44a622625",
11 | "c05378238f14f025af613a8ac1c41bc417e63e68f420c8e2afec2f1b0af77290f792a0bfa3547c6df01e3f9f422148557201615b1162c179d7e2f2b6637856861cfc5f9b7001a5650d373206174a1f8e1d924e6b05e086e43e1ac10857cd6874f8e9f9aa3adbe506daf905c2600f80fcd810555ac34c82e8833aba5e4dbc32281595825d76b3e9b8edcf760ff6f7aff6efa13e0985c38359cb7329779114613f0206d0416cb896cd25f042bb4b04339b8099d3bb170e8c5c2a2f6140156692834f3850bc82fe0e2e3fdb35329064bdb2600308a50c0a9791125a15adc380b55363595da1ebc8539e15daa2ec8f8ea3c25217d420cb45f8688f6420835a9ddc47690e8403d0416262bb2abb43bf1ba22f20770e0f20f4753d41e682c7f87e508a25fd81864182bb36b1688d4df762b9b2c2e348907147697069d1977dc5142cfb56f37c43fb4c7e140c085850c966c854934342aaa4af769489a857205d23194c9085096d457a7b3e83f785dbc59791ebb8e702e1ba7c88c2e3be356a3848af0ca029658042981191d005960cd0a17c04f0503905ae1a08c83d040048da8ec36fe6d6c7c5c75ba029453ab011265c270518570f8b22006ae47444a5bb72140bbc2a7ae1b7cd28a121c8743d38a3ae10eca5f609aec486b09842d7aa41991ddd0e0234bae3a45c6074f2ab4af90699c031198b5b607f564b607ae711d4a825af1e09a5d18642831de9b95529c8280b0cc1bd83345378e60e127109995a692532170b2d242a888b3ddc109296875bc0b640e247b9c2502a7f4ecf133537a68b9f03fecc66169845db08a6832002dcd38f2c331a1910929c14977dd5353c64195ba11cd264436e1019b035dc1ce2b0f89faca343f126a5962734b0d0e48850a612d09285e19252af609130b975cf843e02286352989523d98629f5b802e9edbcc613ce6129f02be0bb421124cf602684511958530e8f1d441d256b3eaeaae192c6a64b2a8629913559ba2a439598e895a8081a08eb46aadfa1264508517ab020294228f77513803aad51de584d2da3ea2693ba410d1a180999bdd991015300a78ed9a5e34de33da402dc89d591da31ebf6a28f681957708ff8ca2a758e0ba1c550f1be1276dccea1905559b43187a20560e15c03b7842967d615cafa1ccfc7daf8297e424bb2616f6d3c27352fbab728cd9cb77f4785b81fc9658d084f8b42863372249bc6ee6957e687207f109589918d5879d178135fa9ae5223f3792e008e0d59ccc8caa09d8d11c4e7a5804f889c87852923fdf31a293032317561adee8066ca64e4cc47ea15c5124b2d727818293d37938be4c24239418463612f4bd9263c43ae4af467c513199a102305041c4b14985c820508afb6d275317423b1ce4886c692ca0444125ca64699cf0a40b8be01f0f3ac253cbaca1d68ab7a708afc5d5e3f6c3494e784cb85372178d9529794e8a42450a50b7463874c178cfb2fa41563245a4048ac11597aa1fc76145174149e060228b44f094778f19174147aa434037fb8195db9b350a2269b260644b0055fac462e4c08edb34228bc4be108c16c03dfa699f0488c3bb425e8684dd9ad9750094128af12d81565b9df0b168c559d450b60d384d74f596107b109567fe9054b0b76f003062f4dd4dd147d72e4fee50d4790c036cb5546282f52d477ada12b3527c845c5aaf4f453036a6162727eb8fc1a34ef399432a984b1a51a910d717577c255727f25513473f3f4927df9d5ab28c90827a7da592a0f2782a314e3be43bd0758009f3d4896d20d5f86234e7090ee9e89176116436149c723018da4ede557da2b3cabe22c6c0c9500852f16c0caebe84187305125b2d410a17732071d5ebebcfb613433628332666cafbc28726b4ad61c7df61708bb2cec96ba9a6e4d69c95db69cd00085eb0454332c1161169c2c436dd08d452eef32cd4aaaccd00ceabc3cc24a1ea3797a1824f099250d5603d8621308600cf002a3162ab40e37bfa45fb376635a3352cba480286978a463f1b4f4aee91e2cf539a44df451f849040fd64fcbab4e99939937a807ec3e61f7262ae174951674a9ebe5fd4ff18488db0c03169d0c9d95d741913c0647ad974e3bc301535d97d5ad132ae021a495641fca00b65dd737645142aa784b9b90a1185ba59ac3514a2abf574f10998b3963d2935a80d5fbfa7ed587eaecfdeddf38f7d42efffd6b082f86856088378dea7cf2c79f3aab339975d022b4acff99a675f6f6fe35afa399940f337d02dd45452006429cb980041f7262670fb379efccecc404990f907da8f1262d77b6fbc91f7fadd92067d1ef351dc4c7ff66f341616bbfc684d0c10df341770e1edcd9bb6d3e282ef825f341708f23552947f805150b4d2cd4e7390f7ccf7450d0c0e0c351d86b0799e2229f0e7aef337ff16cd07b9f70e354ec11c194520ffc427e30b8d6e7b97e71db5cd081aad25e4ab5ec5279cb53554a411481a69ac0f89da19a35048ffccc2751cfc89527f689a3e802ecc3210b552f552d29cb5208b50052c4c6910c2977400cb4fec3b03c6d78795da6848f093f09728b55afcb049f6c56cbcbefada6e5f9d60854a662494a21aca0106936f1171344368583441087fa95100b871cbc2916d012ff45bb2c325ff22ab109134e83c9184b9995d3a9d1e38548e6d06414ca83aa8aa5b9282679489359b47a986780227f2df9ef2b059af61a4b01b4739719c998f5fe22d9cdea22298f8b4c27771d8938b935d65e8ff9a3603f360c89a61925e78f6a65cc257d04441aa4bd43784c9054e448156435cd0cd32ab18ec2825400ea121aaa61120d9ee90e5832907e14c853c5ff9844c018f03f95ac49716ec7b28c81aa95faae915e96fb896a0498763ed8a8d52c08c32172b204e226bf58f3b30f9933e5fe9ea345a79d09402215ec00bbad78325093171ac6e3ec8b3aa42985213f8f6489488cf8ec00e652a5bc3967bfecc4d85d4ed014c5157116b2c8d585ebec885305c7abe9bcf6c62d8a222cbc0e9e6e0692eb5998a688aa2c8bada9ca69c310457921598a0a20c692e8f4984aab7a47a3540d820661d346f223501e0dc1a92c60850d30e8598d690a0edc2522b241f111a9baa1b5e9313902879cc47362d2c212532195b45b742304d7f1a3f054485b53caf87290db3d75218a5cdc64c9177ec27f4e5132888a454a96a5fb50d9e1b5f00fb498544749df1629f7119502c6603fb9d1f0b09481ea3c74c96ae827e737284f598dc82b4f96585ae9bd4dca689371f4f6d07c50b195b34ba59c8f1a2e602f108122f36f90129f28a8303d35452db6e553a4770f8f6c3e91b682c225a40509d3e8929451d372db857d716614ade9ec8cb87792e0c1c90d22519ec4667381520f8d9bb2839ac881bc6879d8723310cc31d37cb3d2ad8e193ca21e552ef12a8a50502d1b67b0128539c2ec9eca7b543430cf92841fcf2caf3bc63641a1d5e1b00bf244e96d79d1231f5c7357b5554502df0821ca1bb03fab676e31037253a61f7eb2a87c2896b5838ad5d194f19ead8ff05868c1e5c19661ede9e5a0e0e0e804a459a312de35d19754ffcee169f8ff698b7927969d583d034be88dbdfc1465672bcd7174960ef5799ed3e4f5c163aa2df10ebc3aac348df104fd1ca779e62284a4b7648f5b737f52ce1993952c5c6d8d551f83387ab66872e7fabf1b5772165fe419619b45d110ab2ccb7bd0892bb8075203e1491bac263ab8809c614464854c257de92afe1ceabcf5b2cc2b38844a1c6a920e63bbae77e61212d54fac180b3c2a6626dd4ca444b9cd6abf853fc560c25f72afbc98a595058aec2de585d32b5a815e06767f16a3e2de0d8486598d5525451813fa8b666110781a7c104c2d9e2cedd08c28263421b4228e160d58454643e4259e00d9c603773fe6a3af8bb65fd48b0beb5f645d1b05554c793011e5616a145760820f65c5986eb29647599f0d682b292010c5c8294d1b0df9459a8da5ae8352fccfacad08942769002315a50bbbc808c21d39ad9dc159569f714146d685ae13ca84ddb19f8b32a7e2bd0ffd72f2ca27df684684fe68c10113637c",
12 | "da9437c54e951281cfcdcf725a9423ac260e5709ebc3d28f0fc60d1f07488d90495e5d271fa2a1a30da6aaa31bc9057d22701e124192e1eba1d7a49e73fe865025046288c57b2769264c6698a207128fe3c8ba88b30bc4e4b3593287eca3a462f23a593ff25dbc58c373f03d61d2f01791bd0c3a6254048c776a1200c821a29735d995b0386f5d5bd03a3d1a786f86e9478ef952d2129897def71d2306b88ba99a24c671750a378510207f079a927c4fe1af52cb3fb660b8c5710d1a93502da53b635aa00dcd85f698d70b36046190900668925a09ed082502f43b1b52fe6398435132a58dc3162b342dd43b659489e19a95c0de52c375ece32f3e1c6ea9b4fbd7a29528e86a6e2c4655c01ed9ef966a3f8b4336c137ecb7305d1b0e1d765273e7fdaf9b7e72e983b1b9ff3562cc886321a5a7416e10c3f170f2505dd36d8293247f3819e73b3b8f8566961e5511d7663174314876b10c2955cff7214690703e062302b05e8d08a8346437faecae0bd97d27cd234c12df806cb8f7385d84b6ac4f2db14ad1204246fbdbf624ab854cbd016e21498e1fae548a50383c4f488535f2d906650359e6ee34d1777f9c4e3311b9d8907e280f7ca33c786901bc6acb883cab16702c3c407824280eb01199295c0c8dc1c6e101b69113038131ad814962ea45435f60138f61c0ac64f345c84d8f12ee4aa620d465a79b687ed51719f7292349e007c13847dbc2dbd8aca93cbf8d0c014e3cf4ce4da97a098e14ec927195595ca1625120e03e737a2872b7a7eba56474fc3855b399f57f37357377c149018c0e74fe5f0ed8f8c8328298ce4ccdc3dd27ca20c788c1ee8af286e5b9c397198b2c91ba21eff4bef9bdc32776b02567765216b71e826f3adc132551f84681de2d84b01f7a94c9f3f2dd1328b38f0bd89530623bf942ef9ae776601636079d92a91376340932f17ff027013e40c3e43f2d2c67a752baa72818c000d3bd01f78763bf319b7bf7d032251e9733304774370897c720c622953863f5044f30a89b140a2c90e545267f855610a160515ee079a4c5249c3bb64283be91af232fd4c606999c449ecce0d931678cdb2f16b3e63526d8b114a7933fb3633c3613c610932c48d344b78f277f7270b5ff07bc42019e0b4fd47872c17ca6eb0829aae05204ac5c263e42064f035011bc945f044d2a6fc1d0601be44c79c9113e2bd0a6aa6b9edd15e1a9bc83ca607180e986a6004154ba22cbf591a661b2029b9372b6205901ea8ec2b26311190b08d2c7a671606461e527d0740887caaf5c103a1ee71eaec777a738938e91e8b6c120b8a289a78d112dd66edce14e65f6c299a9b09ce508e9807db6793859645cd835a2620a2848d2d3d9529db6b2aa25d3d2c1a8b4b092c0ac79047106ce57957aec3fa33feba60f38c013b5d6e9869bba0ed33ec71cda65b3ea3dcef33816eae431a9c901c3d812cf6b80f538c9e6d1cf916f783896e5e35a0c4867e7832308ed24361fd303a62f8825c0b43af65d560520b53ca796e7c2d77e86d26f884335c6169c6694fdce2d0c9bb1d3145c8852be71e55aaee890b42b918d8063e7f2cc0b14ac7c14e36c10aa4fa32b7986a15dc7d6bf74fd5a039b4a158261a2540143e48d081cc0624210e8873cb4e6e9dc371bcf0c2f981121e4f32aab4e8012d4d654f61b04435864406f55ea68c9a62dc531169fdfdace6639a47add7e18019fd7fda5d9c51075f8c022c8911bc5fe307b97020abb751ee834aebac06e85dd2d36c0222cee6a8224677b3065d7209aef434b260b79d048d270e67514bf5835f0813ed79c052c13aed5408442835589d2753e891413c0389a589e280c4dcf90a16cb998b4324df85bbef9bdc120c6ce6cc6dc8cb8002edcdced0161ef8f57fb7bc3808098ac08ee9a444fee5a6b9121b2a00cbbf224bd65168e83a353e24767734f0a52093fc8b34aae96583d23c7982305270c230cab3ccf62462c49c7cf4d38231030329866d0455c8699e0387800eb306dba1edb57cc951e29fe9913c89e28a9940c81009683d929548249e12ee394a77922a42d8e15e4373ce459e051098959088e88a9f1401678a55c479f518802f6659007cbbc3fe30e019b22d848b6426bceb945ce8320849ccb9a7f23ad6995571e1201e48297fc55ae81d608caf2810b7ec0d863af50c05fd959845620fa1b576c8bc59a4c18400b12026c468cc55279ef39d1cb150d918108788548cd223e2bfe965058344ea71f1ca0a6c9d8a839c09b3dd3d992e013e2807a34265e250f6cd978c6a28c86b99105464b24ddc780e85443d111023242028ac96fb1cafca46fdbcbc1c42f6096361e0c415696943874d198a27e715a20b1258a79103c000de199c16f01236339488402858623f8cb8fe047613c6839157fa1607acc5ab51f7bc7dd8d4189e87be039628ac5109d67c1534cb5f599915314f28031ca8d5275e374837800306187b24db3542f2d9cb3bbebd82def1ea6ee5664f8aa41b91e5d5fc71eeaff0ecedf16aac5308265fcf51365bc036b10441e15a526b5efb1432179b0c35ab4d0c39c69f18419b81fb906580f7ea0209a3ab4610a5e3ba03d94d832768835c890adeda5a4f1af9be5653d8b43009a0048780ab962d22344a26c457e9423b407f1d253c2104118afed5cc57c6e2683e702a3b3ac900ebc9c46601b9877c94cf8f41b14ce72cd34a06bed013e565c267bb265d18d0d076e8f6b65a1b8bcc6e370ac18b4a75ec1a3389b03a3f559066f9ad825de2ab87d5c9594089ea66101a8acc11e33acdf6c9c259d2823b84ac590c0e1f20cffc72749fed1f1d6fd9f3addeaafa7fb279a6d3df8d764ebaf35d96aacfdb073ad38d5fd1b4fb5eeff4a43adc69ddf69a4150fffad065addc07e8d71d6fbf76e9867ddfbe4c1febddbe659e3825f32cf3a4bd5f09120b2a7d1c28f3a13f89e79d6a08101e5c679d6b8c8e759dffbcc5f3ccffade27dc38cffa45e287672ed601313c4d9073db3cebddc3a74c2e12080628d3d018f31ea68c844e793a24a13c2d8ee49197e3fff6e22a141662a444b3463eebc19a32008ad16335274b407873c6ce003656041e22f4c77edcbdc07929570301c5c780eaca6e0cb5a4327354bbd40d894fe34c39f229df02603bde56f6dc5be44220c5c6ade96cb555f6c9e259b89987838de3c4fa8f39e587d6a4a7babc36268fc8caf452a454ee009c467fde6826054c63f85a29e3b07228968e71ea45c7c2edf2c1ae8b0e995a1296ad58f54bf9462ca5ac5d194a9172e44e670c6519eac7c4cf1638cf0dcecfeacbe6fb78f30f2a4148e555d2b5aeb715e6529d32801cb6efa54083df4a6ad501f4dd5853b868a97969443c0cc1a51e70ae709065306530bf98292973d81815b2ecd4aa34c4dda1f4984555115d42573a94c6b24de290b2f240255acc320589f1ba61356353352767ab51913e4a4350f684a23a95a631981f33e7d2cbf5401c0edddbc8aad4201e898fce8d4c95ef4b8d90ee441a1ef96f7627de03ce03213146a7372841e106a53a9803faf5d8f04d6f3063dd055ac5d71af1f597a226551fa1f54af8a464ac21e744ed5a653adabcc6db29509488ee200aa0a9ce3f4292940f29e0d5dcca7f46295be30b1522af8df2d550c5b00dd937544f02b6fa1845cff4fba67c6dff5057dbfbc77c02523ac81b69e34751316016a767f884b352b7cbfdc181cc57a91a132f2f436345658bc8538bfcaf38e298c6bc0e0eb389467b81c715c07c9fea055d5ee5d38b1ba94d46365daade4f94b34fa93774815925c448699519656e724178e648a4b9f050e97d79e5f568fc41e494343884dfa0cce5d7273eaa4d0bd5db07f10b0b7a7090fabbbcf6189fdb452a52955f71199bc5cd077d9dbae048ba3cf1ed3e9abb767440286150d532abb2fd9971c7081b08846ed89c0ef9934a85a7f1be14690f1b0810bae613ef0fe4fd981e1f6b2a2cb0109b5e69d90c0ea6bef407c943ab1441f532660f7b873e679dec026b72c222ed58bd49d4639361400a32d236b5f77344a1bd967716ea494d2ebf3a023da946914c9c5452ded1142cef28e29bb275ab1c881a562fd3a54946073c50ec864da659c19584b88ada0a8370877a6804574c81a683e48800c518949b2dcb05c31dda13b00708da5c6eb13808347bb9aef530e1cb8456a9132d1f21efe7156a6bcde7a6229e818d601ff89705ded789b8bbf787ab3bf7b7de9c750068c6d7ae6e39683a1d8625b600f1ab17680b716c99fcb3e8b747658e1274df13af2d4d15a5a4e51cf88d229f59651491096f922471e30983014327060762f6c57c131e545e487d52115b0ae151a8bce033cdd7442391aec2cbb1a119e5c551fb8a9dc0262cb293294299e5d55e762cc045fa3694d1656e730669361a9e2a4f3bbc578e070777aef6f7710214b5c7fc72b58f46e895d90bd7526bab389994a392eb7531e6996bfc604e7e198ff5baac8f9afcb2e012cab3f6ba0daa073b06d20f7f5332bcb0bdd882f0156e24dea442632820e1d170588196028ce29ed04fd013d117ac377bdb8af1a99afb97fafbf245c3e9be82045114c8440a625a07d14352a853a79b186eecf44036412a480638199029da699c966e962fa1292670e470d41937afcbf4856fda66888fa7c9c0b1bac308d66775b13b6a7badcbb87a69b62e57e20d62dcc41020ca7cba2cb53c249878042e121c8075240029fca4ed21f0e68e10160b7736e84421592b34dba6d48196d21b0d6112851fc4c1a698c24bba538affb9dee403a92b3e5e27d367f8c730f012f289a13612cbd7f3d4eb912277cc3832768cda8555e50ba81653c30ac2265c6823cd36e83279505a29ede1626936ba00b7e195d268295b8904c3f9d641993e65a87c9ecbddb01026270a269964dd5ea05c647d9a6d3598059cc05b3cd4f85a34a5d04f48f498c95db442520e9326c202bd40fb410e81079c34138c62b2f531a60d0370467aa0b0acc401493a1fc9ddc0c7a577c9d95b534134de3ca2ce6fb85224bc0f637c8637455048f1bd643a01500a681aa474960d44637a0a48e2de1af97e99d1690ab2f02e8fa7d7a9d4e925a787fccdc7f09ede683e72f08346b21def8227907120e8fa646761470838617285d500ad383c965f098d290ed6c449aa39358c875c7cbe0cfc49d503ef27a283884091df277f8c4ea45ece77dda6fed2b4f12a7104c84893d1bf2a30c728b4c2865a242dbc613cbd6f09bcf832dedfaf2c8479b3590d63b4474b746c80c94202a180317e8790e01f29469861bb2313da255a038fe4fec439dae68a8a1818a0d8728c5d145698d4d5c708d3a0c7755cf96283f77be14d997662835d3a9d5d00ef732b4f097de1fa6cc3051127b047471bd73d836337ffb1e971fe323fa6b076584ca0ce88b0663acc09a162663308c70345cf0b58eaf84e37f91461d26020ccec949377108ac5b142e2390823d0d2af0c7c37748e600a9ffbdc49925cb1fb5739a92c6f2e80037d02f243fc3b4c061573bdc9b21ea3cae05873ad45fe155326e6e0698e1a9a234318028bcd98e2815a639c45366646f2c179dc355eb40b59d3edc0ae5166901b83bb90457bf0bd1a9790c58d5bf5c502719037aa8898c53baa3156070c92670434c525e6baf00bd9ba1ebc86095acf8a06692252171c2879bf285f149f9ec3e3d3708e69fc94ef484d6789c0221d1755a9c09e49173d084322ea180fb5b4993540a1089319294de37d816606476f78ab329ef04fe6b1709f02e570684038ecc50affd442f7b628b4287e8dc2f15b982663712e0a532151590938ae64c9842c744dc11b0c1323c8c098e4c066b32622b4814f321d71d9144fbc2e3c8de347ff370ab898df211d26279fc4106a8811e4eb9ddd274cd72dc55744c4bdc331bbeaa98f266e7d0c31479a9962c89a5d7f7c418159c3596f9fa49364641654df8691ccff4854f083d4d384dd5d68d729798f5a232fcac92b6f57a2a885f897410c775250758d0c47b026817cc167e6b229af556eb134e63140400add0056fce745c89e043d3e53b2c595ccdd601356adb4b99fa47e20063115fe2c78c421c9c21559c02472f5e9919bdcf19788beeb6f5b53409b56e0",
13 | "093cfda3367a5d6acb51154ad554115e47228e41a37424d5dedb5ee2db28d2987ae22e74348cfb06dce277737d1e256f28ffa589f097b041b8f3805ee69e827d7852ca995f695c4cd8024577a894b2f6923ed365e9931db44ab7c71cf7e5fdc16bd00b075b4cd417f692ab71c0ac3eae06879aa965393c25b114bcc931f953be120054e0b9e531fc13b9c72818d82bf6053a8c838a675097443e78a06491536479c231c66c2c1696173f911e52e9a8e3562580e99697bc62f010e7c141be46df414c79cd97aa259a3473163bb8821e3ad0b57c62f92db28338f869b5b2403914380883472b2f3f8626586729a6118bea5b92206a597a354619904b3972d7e16ccb086a9a4ac78b670eca4f568a78e16fb630cd216740217e0ee289c947992e3780404d33bc75faf52ea65fefdcdf9a7edd3fa45f80a70b541a60a5684a197c844f926730dd4e69555834f9c8fd0c8be1a7f04af47c2031dc0907ca58a710db61b85b8c4ff08c3806e1128566fde339e5652f436acab88d15e5f7276c693457e923aff8dc3a16f5cfd215adfe3ff53fffd1f1a7fb77fff7ce3fddbff7af01a85f6b00ca79fb6127a0eedffbcd47a0eedffd9566a09c41bfd310149ffe5b4d4185997dd031a8afff075b433fe9947a0000"
14 | ],
15 | "headers": {
16 | "content-type": "application/json; charset=UTF-8",
17 | "content-length": "9933",
18 | "connection": "close",
19 | "access-control-allow-headers": "Authorization",
20 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
21 | "allow": "GET",
22 | "content-encoding": "gzip",
23 | "date": "Wed, 15 Jun 2016 04:06:04 GMT",
24 | "link": "; rel=\"next\"",
25 | "server": "nginx/1.4.6 (Ubuntu)",
26 | "x-batcache": "MISS",
27 | "x-cached": "EXPIRED",
28 | "x-content-type-options": "nosniff",
29 | "x-ec2-instance-id": "i-f737987d",
30 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
31 | "x-wp-total": "101",
32 | "x-wp-totalpages": "26",
33 | "vary": "Cookie",
34 | "x-cache": "Miss from cloudfront",
35 | "via": "1.1 9f21952d33d91266890f2ab34b849a9d.cloudfront.net (CloudFront)",
36 | "x-amz-cf-id": "ZqgbgoWPES25_xPTnaRYm0r-q2LAVDcZgRhmY04SXxdnq1aGUL2B7g=="
37 | }
38 | }
39 | ]
--------------------------------------------------------------------------------
/tests/fixtures/responses/recentPostsBasic:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/posts?filter%5Borderby%5D=date&page=1&per_page=4",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b0800000000000003ed5d6b731bc795fd2b637ed84f064849a4126b1da618895e6b63c9a228c9b515ba5c436044ce1ac0c0c040a2e3f27fdf73cebdb7bb072229c796edec6eaa129a04667a6edfe7b98f1efded879d76baf3e0cec73bd3ba6f761eecdcddbb737fb47730bab3f762ef0f0fee1e3cd83fd8b12fbfb998f7375e70b1e1323fecac9ac5b45935f87de7b2ef97eb0767bb67bbd366de8ddf2e47f5b21d77ab8bb3dd3f2fff7467e7c78f77e6ddb47dddeaeaeb9f1b17dcfaecf56c73c1e735b359377adbad665350dc7fbfe47696ddbac75fb376f1eded24f1f967bb7b0767bb77f6ce768bb5ce76b95adbcfb0dc607f9ff379959ef7113733e9167db3008b06577dba3cfcaa994dba7953f55df5695d5dae9ad77f3a2bb85332e66ce7f0ab67d5d1b3c7d523f0ac3a6dfb66fde9d96e7d38ae5e5cb6eb0afffbbedbacaad7ed6add57dcdcb83a9eb67dd5adaa69336bfaa66afb8fabfeb25954ebbe5ef5d5f9acbbb86817171f6199e5e1d9829436579366b5bc9dd277c8f8a014d49bfeb25b49ef5e3775bf81c67c336fa66dbdf3608f9c9ccfc1c96fb0837eb386dcba65b3801496d8c73b1faefb76f2edf73b0f5ed7b375f3f1ceeb6e35afa9a7b87931ad57d4850954fba25bb50dd6fadb9daf21cefa82bfe2b76fa819f8fd879d75337b8dcf7ed8a1806ed71548ecbfd7dde26cf7edf26cf7cd5d301682584373767ec492936e366b267ddb2d7ed1725aab3eef36d8cccfa38a2600aa6402242c988ed59af979339dd6e754ea7eb501df7ec6ae37eb669576bd6a963363f0075add9560fd67d24f77811dbcc103c1d7114ca1ef5610facf634c88eb6c77d5bc69b9e25acbbf5d3ea8fbbe9e5c52fb7eeee252e33f2f6b78c2201bebf6cd6aae15fbfaaa5b7473d01e6af93d34f483c823ab79e2d9c73f40d7d303b9ef6fa0fb1fea8134a3f4286afec66dec879d453da7fb7dbbc4b3de512dc681b716097e5835b31f714ddfcc973398290207f5f1c7af7ffc11b42b34edc1236c05a7bd4f5edcbdf7e0dede83fd4f702fbfdc0a10c30bfeb1e09423c1de2767bbcdd5127ea9af47f57abd815e4cf1db6a7209c73ce9bbd1b49b752b44881faf8d65432a6e8865c38b3c96fd84a792693f3bc6fdf49d5d1ffb8e9d2b55e24a95b952892bb784c4cb3b87c77db5e9ab37dd6cb384936fe6d59b668630867dcfda09bc5e4585e85675552fda798bd8857bce169f6e66fc396b0f4f366db56ea655bba81a44423d7133af1083d7cd779bcd02210537e1425c7eb66bb7d9639bbe6aa71585517dc745ea66d954f05e88e63542eaaa7bd34e61bae3ea9528c2759d2d3be91bac5ab508565c01eb80e671f5e5ebd7eda445609e74ab1576d382a63758a0c365697fd5a25b54583e3ed8ccdfddd243443d52450297eb7a5e6d00a5d226b095e36e5dc187835978149883676a5972885c48d7c68611fb27df7eb7e9fae61030e415b4b821d7ebf5b2592d18759deb93cdfcbb4d33ae1e6d26ed7cb3ae6610c0aaed4403b832b73d3f9bd513c4ea0a96dd5793cdb2a559007000d3081e01d43cdccc9675b56e173d78db550d24b20671b316cbe337e3d8d94e89810410dfbe7d3bfebcde4cbe1dc3eb03eef0867a3ec21aa3a6c77fda35cc0f44b760ea9a1f89c266443ef1ebf1653f9f013b656d5caeea660d29b49bf9b87a525f2c5aee5cb78128532e32b73eac8ef0c5600f6446d5ac56c05471c3aa59e136e90bd40b22de2000f1ef7a7cc376be6a2e17cd6adc2e5e7780c03b87dc3df655434fc8247b34253cae9eb697ed0cdacc850bd6af6a62087cff981a675f832dd2816ab18160702bd4aa9302d690e58a028156bcde5cd4586933ad9d01c75011e8f864b32626ca7a893d5db613585db39ae85e3c6f4e1d1b8b2bf888ac8807144c3ac1cedd68e012a132e0a124dead6f62c8e9e4b206ea585d802b9232c4d812b163dbeb515293513b0d692e9a49b306dfb0a7f38dc1e06ad66289ceec1dd0174076093d6e4da7a51eb44d92426ed6e7e3ea7903f30491e00bd505d63969a77010d95e8934687830032c092c3d5fe06237d57575148e1f4b82778bee1cdfcebb192caec5df520db801dd24ce230b90a718e8e0d1b45db6eb496ba47343950bb89ad7572dd28382bd8fa55e73a82d8c8f9a931fb7809a4024f44aabbcb329947d854dddc4fcffac27dd3920abeb63037d184ddb09c29afbd9119c29b474414f50d339c130c2298edd494edd3db85a842f83c660db2d3c43b016da9342a42b3d5c467874f9ea464606f993e7c6f0a6a68d31373191d2384c64102552486a3b59dfc00d6a0d31b1e0da29e2018ca0bb89098f9028348bb5010f695d7ad828ff26e7d34ef149e173c09a70922f7b051e061fae41176cec2253c7e61d610d11c1a9a403eb62e8187e920298318579dc0479cf58de1d92c662397268d350e61ecc867f80f248ebc7d533849fce7c6f531b69d2571009df90022dbc3c318b3d0aeb6a7ddb5bc51de84e0890de16ca8710e782dbe6f6e7262edef2061ad16c71dd327f3af627934700bf5ddf9bd953abdb911ce8c8c33543d10836d7c20d2cfa11881bf55d5fcfc1f573441c18190c7a8a2d7a040a3d33be875aa6a058873ed25b92ff0a7a0a9cc9cd5848c70578347d04554f712b2310d8ddb834cacf10fee088c32adc231746184c16a7e20ff3a75521b1762e445905ddcdb556fbd9aa9eb761ae57034ecddbc5861e13ac6ac0c7513d351c8ad098fc44f8d04c8631ab9e300830c81fd122cd513557a5ffa43a32bacc1503c079782a0f7ff59a112ae24ab568e0d0e84add2b27e033aebe303f0de583a79b622d9884611729d92595877c5f6e90f42b2681742040e86a68ed1abfe09a130891500d814f1e01d88a8a695abc4e7bc0fa1ed54b993d5e5075b654b3801cb337dd8a6e51016981f408648dd6d8d228fdd13877f105763302a619d1ddf523e42bc44350526d0c719af52098940092bbc4129082142259831cd00b6852dabdcb693dc605cb43fc28b01b20ece53d21de9003e01e040ffe3316948fc08db89437acf4f3e0f0a12162a13d321161aef864bd8104978426095ec1cd86588da1526767879c2f4167f1957c31e5d44a622625c05378238f14f025af613a8ac1c41bc417e63e68f420c8e2afec",
10 | "2f1b0af77290f792a0bfa3547c6df01e3f9f422148557201615b1162c179d7e2f2b6637856861cfc5f9b7001a5650d373206174a1f8e1d924e6b05e086e43e1ac10857cd6874f8e9f9aa3adbe506daf905c2600f80fcd810555ac34c82e8833aba5e4dbc32281595825d76b3e9b8edcf760ff6f7aff6efa13e0985c38359cb7329779114613f0206d0416cb896cd25f042bb4b04339b8099d3bb170e8c5c2a2f6140156692834f3850bc82fe0e2e3fdb35329064bdb2600308a50c0a9791125a15adc380b55363595da1ebc8539e15daa2ec8f8ea3c25217d420cb45f8688f6420835a9ddc47690e8403d0416262bb2abb43bf1ba22f20770e0f20f4753d41e682c7f87e508a25fd81864182bb36b1688d4df762b9b2c2e348907147697069d1977dc5142cfb56f37c43fb4c7e140c085850c966c854934342aaa4af769489a857205d23194c9085096d457a7b3e83f785dbc59791ebb8e702e1ba7c88c2e3be356a3848af0ca029658042981191d005960cd0a17c04f0503905ae1a08c83d040048da8ec36fe6d6c7c5c75ba029453ab011265c270518570f8b22006ae47444a5bb72140bbc2a7ae1b7cd28a121c8743d38a3ae10eca5f609aec486b09842d7aa41991ddd0e0234bae3a45c6074f2ab4af90699c031198b5b607f564b607ae711d4a825af1e09a5d18642831de9b95529c8280b0cc1bd83345378e60e127109995a692532170b2d242a888b3ddc109296875bc0b640e247b9c2502a7f4ecf133537a68b9f03fecc66169845db08a6832002dcd38f2c331a1910929c14977dd5353c64195ba11cd264436e1019b035dc1ce2b0f89faca343f126a5962734b0d0e48850a612d09285e19252af609130b975cf843e02286352989523d98629f5b802e9edbcc613ce6129f02be0bb421124cf602684511958530e8f1d441d256b3eaeaae192c6a64b2a8629913559ba2a439598e895a8081a08eb46aadfa1264508517ab020294228f77513803aad51de584d2da3ea2693ba410d1a180999bdd991015300a78ed9a5e34de33da402dc89d591da31ebf6a28f681957708ff8ca2a758e0ba1c550f1be1276dccea1905559b43187a20560e15c03b7842967d615cafa1ccfc7daf8297e424bb2616f6d3c27352fbab728cd9cb77f4785b81fc9658d084f8b42863372249bc6ee6957e687207f109589918d5879d178135fa9ae5223f3792e008e0d59ccc8caa09d8d11c4e7a5804f889c87852923fdf31a293032317561adee8066ca64e4cc47ea15c5124b2d727818293d37938be4c24239418463612f4bd9263c43ae4af467c513199a102305041c4b14985c820508afb6d275317423b1ce4886c692ca0444125ca64699cf0a40b8be01f0f3ac253cbaca1d68ab7a708afc5d5e3f6c3494e784cb85372178d9529794e8a42450a50b7463874c178cfb2fa41563245a4048ac11597aa1fc76145174149e060228b44f094778f19174147aa434037fb8195db9b350a2269b260644b0055fac462e4c08edb34228bc4be108c16c03dfa699f0488c3bb425e8684dd9ad9750094128af12d81565b9df0b168c559d450b60d384d74f596107b109567fe9054b0b76f003062f4dd4dd147d72e4fee50d4790c036cb5546282f52d477ada12b3527c845c5aaf4f453036a6162727eb8fc1a34ef399432a984b1a51a910d717577c255727f25513473f3f4927df9d5ab28c90827a7da592a0f2782a314e3be43bd0758009f3d4896d20d5f86234e7090ee9e89176116436149c723018da4ede557da2b3cabe22c6c0c9500852f16c0caebe84187305125b2d410a17732071d5ebebcfb613433628332666cafbc28726b4ad61c7df61708bb2cec96ba9a6e4d69c95db69cd00085eb0454332c1161169c2c436dd08d452eef32cd4aaaccd00ceabc3cc24a1ea3797a1824f099250d5603d8621308600cf002a3162ab40e37bfa45fb376635a3352cba480286978a463f1b4f4aee91e2cf539a44df451f849040fd64fcbab4e99939937a807ec3e61f7262ae174951674a9ebe5fd4ff18488db0c03169d0c9d95d741913c0647ad974e3bc301535d97d5ad132ae021a495641fca00b65dd737645142aa784b9b90a1185ba59ac3514a2abf574f10998b3963d2935a80d5fbfa7ed587eaecfdeddf38f7d42efffd6b082f86856088378dea7cf2c79f3aab339975d022b4acff99a675f6f6fe35afa399940f337d02dd45452006429cb980041f7262670fb379efccecc404990f907da8f1262d77b6fbc91f7fadd92067d1ef351dc4c7ff66f341616bbfc684d0c10df341770e1edcd9bb6d3e282ef825f341708f23552947f805150b4d2cd4e7390f7ccf7450d0c0e0c351d86b0799e2229f0e7aef337ff16cd07b9f70e354ec11c194520ffc427e30b8d6e7b97e71db5cd081aad25e4ab5ec5279cb53554a411481a69ac0f89da19a35048ffccc2751cfc89527f689a3e802ecc3210b552f552d29cb5208b50052c4c6910c2977400cb4fec3b03c6d78795da6848f093f09728b55afcb049f6c56cbcbefada6e5f9d60854a662494a21aca0106936f1171344368583441087fa95100b871cbc2916d012ff45bb2c325ff22ab109134e83c9184b9995d3a9d1e38548e6d06414ca83aa8aa5b9282679489359b47a986780227f2df9ef2b059af61a4b01b4739719c998f5fe22d9cdea22298f8b4c27771d8938b935d65e8ff9a3603f360c89a61925e78f6a65cc257d04441aa4bd43784c9054e448156435cd0cd32ab18ec2825400ea121aaa61120d9ee90e5832907e14c853c5ff9844c018f03f95ac49716ec7b28c81aa95faae915e96fb896a0498763ed8a8d52c08c32172b204e226bf58f3b30f9933e5fe9ea345a79d09402215ec00bbad78325093171ac6e3ec8b3aa42985213f8f6489488cf8ec00e652a5bc3967bfecc4d85d4ed014c5157116b2c8d585ebec885305c7abe9bcf6c62d8a222cbc0e9e6e0692eb5998a688aa2c8bada9ca69c310457921598a0a20c692e8f4984aab7a47a3540d820661d346f223501e0dc1a92c60850d30e8598d690a0edc2522b241f111a9baa1b5e9313902879cc47362d2c212532195b45b742304d7f1a3f054485b53caf87290db3d75218a5cdc64c9177ec27f4e5132888a454a96a5fb50d9e1b5f00fb498544749df1629f7119502c6603fb9d1f0b09481ea3c74c96ae827e737284f598dc82b4f96585ae9bd4dca689371f4f6d07c50b195b34ba59c8f1a2e602f108122f36f90129f28a8303d35452db6e553a4770f8f6c3e91b682c225a40509d3e8929451d372db857d716614ade9ec8cb87792e0c1c90d22519ec4667381520f8d9bb2839ac881bc6879d8723310cc31d37cb3d2ad8e193ca21e552ef12a8a50502d1b67b0128539c2ec9eca7b543430cf92841fcf2caf3bc63641a1d5e1b00bf244e96d79d1231f5c7357b5554502df0821ca1bb03fab676e31037253a61f7eb2a87c2896b5838ad5d194f19ead8ff05868c1e5c19661ede9e5a0e0e0e804a459a312de35d19754ffcee169f8ff698b7927969d583d034be88dbdfc1465672bcd7174960ef5799ed3e4f5c163aa2df10ebc3aac348df104fd1ca779e62284a4b7648f5b737f52ce1993952c5c6d8d551f83387ab66872e7fabf1b5772165fe419619b45d110ab2ccb7bd0892bb8075203e1491bac263ab8809c614464854c257de92afe1ceabcf5b2cc2b38844a1c6a920e63bbae77e61212d54fac180b3c2a6626dd4ca444b9cd6abf853fc560c25f72afbc98a595058aec2de585d32b5a815e06767f16a3e2de0d8486598d5525451813fa8b666110781a7c104c2d9e2cedd08c28263421b4228e160d58454643e4259e00d9c603773fe6a3af8bb65fd48b0beb5f645d1b05554c793011e5616a145760820f65c5986eb29647599f0d682b292010c5c8294d1b0df9459a8da5ae8352fccfacad08942769002315a50bbbc808c21d39ad9dc159569f714146d685ae13ca84ddb19f8b32a7e2bd0ffd72f2ca27df684684fe68c10113637cda9437c54e951281cfcdcf725a9423ac260e5709ebc3d28f0fc6",
11 | "0d1f07488d90495e5d271fa2a1a30da6aaa31bc9057d22701e124192e1eba1d7a49e73fe865025046288c57b2769264c6698a207128fe3c8ba88b30bc4e4b3593287eca3a462f23a593ff25dbc58c373f03d61d2f01791bd0c3a6254048c776a1200c821a29735d995b0386f5d5bd03a3d1a786f86e9478ef952d2129897def71d2306b88ba99a24c671750a378510207f079a927c4fe1af52cb3fb660b8c5710d1a93502da53b635aa00dcd85f698d70b36046190900668925a09ed082502f43b1b52fe6398435132a58dc3162b342dd43b659489e19a95c0de52c375ece32f3e1c6ea9b4fbd7a29528e86a6e2c4655c01ed9ef966a3f8b4336c137ecb7305d1b0e1d765273e7fdaf9b7e72e983b1b9ff3562cc886321a5a7416e10c3f170f2505dd36d8293247f3819e73b3b8f8566961e5511d7663174314876b10c2955cff7214690703e062302b05e8d08a8346437faecae0bd97d27cd234c12df806cb8f7385d84b6ac4f2db14ad1204246fbdbf624ab854cbd016e21498e1fae548a50383c4f488535f2d906650359e6ee34d1777f9c4e3311b9d8907e280f7ca33c786901bc6acb883cab16702c3c407824280eb01199295c0c8dc1c6e101b69113038131ad814962ea45435f60138f61c0ac64f345c84d8f12ee4aa620d465a79b687ed51719f7292349e007c13847dbc2dbd8aca93cbf8d0c014e3cf4ce4da97a098e14ec927195595ca1625120e03e737a2872b7a7eba56474fc3855b399f57f37357377c149018c0e74fe5f0ed8f8c8328298ce4ccdc3dd27ca20c788c1ee8af286e5b9c397198b2c91ba21eff4bef9bdc32776b02567765216b71e826f3adc132551f84681de2d84b01f7a94c9f3f2dd1328b38f0bd89530623bf942ef9ae776601636079d92a91376340932f17ff027013e40c3e43f2d2c67a752baa72818c000d3bd01f78763bf319b7bf7d032251e9733304774370897c720c622953863f5044f30a89b140a2c90e545267f855610a160515ee079a4c5249c3bb64283be91af232fd4c606999c449ecce0d931678cdb2f16b3e63526d8b114a7933fb3633c3613c610932c48d344b78f277f7270b5ff07bc42019e0b4fd47872c17ca6eb0829aae05204ac5c263e42064f035011bc945f044d2a6fc1d0601be44c79c9113e2bd0a6aa6b9edd15e1a9bc83ca607180e986a6004154ba22cbf591a661b2029b9372b6205901ea8ec2b26311190b08d2c7a671606461e527d0740887caaf5c103a1ee71eaec777a738938e91e8b6c120b8a289a78d112dd66edce14e65f6c299a9b09ce508e9807db6793859645cd835a2620a2848d2d3d9529db6b2aa25d3d2c1a8b4b092c0ac79047106ce57957aec3fa33feba60f38c013b5d6e9869bba0ed33ec71cda65b3ea3dcef33816eae431a9c901c3d812cf6b80f538c9e6d1cf916f783896e5e35a0c4867e7832308ed24361fd303a62f8825c0b43af65d560520b53ca796e7c2d77e86d26f884335c6169c6694fdce2d0c9bb1d3145c8852be71e55aaee890b42b918d8063e7f2cc0b14ac7c14e36c10aa4fa32b7986a15dc7d6bf74fd5a039b4a158261a2540143e48d081cc0624210e8873cb4e6e9dc371bcf0c2f981121e4f32aab4e8012d4d654f61b04435864406f55ea68c9a62dc531169fdfdace6639a47add7e18019fd7fda5d9c51075f8c022c8911bc5fe307b97020abb751ee834aebac06e85dd2d36c0222cee6a8224677b3065d7209aef434b260b79d048d270e67514bf5835f0813ed79c052c13aed5408442835589d2753e891413c0389a589e280c4dcf90a16cb998b4324df85bbef9bdc120c6ce6cc6dc8cb8002edcdced0161ef8f57fb7bc3808098ac08ee9a444fee5a6b9121b2a00cbbf224bd65168e83a353e24767734f0a52093fc8b34aae96583d23c7982305270c230cab3ccf62462c49c7cf4d38231030329866d0455c8699e0387800eb306dba1edb57cc951e29fe9913c89e28a9940c81009683d929548249e12ee394a77922a42d8e15e4373ce4",
12 | "59e051098959088e88a9f1401678a55c479f518802f6659007cbbc3fe30e019b22d848b6426bceb945ce8320849ccb9a7f23ad6995571e1201e48297fc55ae81d608caf2810b7ec0d863af50c05fd959845620fa1b576c8bc59a4c18400b12026c468cc55279ef39d1cb150d918108788548cd223e2bfe965058344ea71f1ca0a6c9d8a839c09b3dd3d992e013e2807a34265e250f6cd978c6a28c86b99105464b24ddc780e85443d111023242028ac96fb1cafca46fdbcbc1c42f6096361e0c415696943874d198a27e715a20b1258a79103c000de199c16f01236339488402858623f8cb8fe047613c6839157fa1607acc5ab51f7bc7dd8d4189e87be039628ac5109d67c1534cb5f599915314f28031ca8d5275e374837800306187b24db3542f2d9cb3bbebd82def1ea6ee5664f8aa41b91e5d5fc71eeaff0ecedf16aac5308265fcf51365bc036b10441e15a526b5efb1432179b0c35ab4d0c39c69f18419b81fb906580f7ea0209a3ab4610a5e3ba03d94d832768835c890adeda5a4f1af9be5653d8b43009a0048780ab962d22344a26c457e9423b407f1d253c2104118afed5cc57c6e2683e702a3b3ac900ebc9c46601b9877c94cf8f41b14ce72cd34a06bed013e565c267bb265d18d0d076e8f6b65a1b8bcc6e370ac18b4a75ec1a3389b03a3f559066f9ad825de2ab87d5c9594089ea66101a8acc11e33acdf6c9c259d2823b84ac590c0e1f20cffc72749fed1f1d6fd9f3addeaafa7fb279a6d3df8d764ebaf35d96aacfdb073ad38d5fd1b4fb5eeff4a43adc69ddf69a4150fffad065addc07e8d71d6fbf76e9867ddfbe4c1febddbe659e3825f32cf3a4bd5f09120b2a7d1c28f3a13f89e79d6a08101e5c679d6b8c8e759dffbcc5f3ccffade27dc38cffa45e287672ed601313c4d9073db3cebddc3a74c2e12080628d3d018f31ea68c844e793a24a13c2d8ee49197e3fff6e22a141662a444b3463eebc19a32008ad16335274b407873c6ce003656041e22f4c77edcbdc07929570301c5c780eaca6e0cb5a4327354bbd40d894fe34c39f229df02603bde56f6dc5be44220c5c6ade96cb555f6c9e259b89987838de3c4fa8f39e587d6a4a7babc36268fc8caf452a454ee009c467fde6826054c63f85a29e3b07228968e71ea45c7c2edf2c1ae8b0e995a1296ad58f54bf9462ca5ac5d194a9172e44e670c6519eac7c4cf1638cf0dcecfeacbe6fb78f30f2a4148e555d2b5aeb715e6529d32801cb6efa54083df4a6ad501f4dd5853b868a97969443c0cc1a51e70ae709065306530bf98292973d81815b2ecd4aa34c4dda1f4984555115d42573a94c6b24de290b2f240255acc320589f1ba61356353352767ab51913e4a4350f684a23a95a631981f33e7d2cbf5401c0edddbc8aad4201e898fce8d4c95ef4b8d90ee441a1ef96f7627de03ce03213146a7372841e106a53a9803faf5d8f04d6f3063dd055ac5d71af1f597a226551fa1f54af8a464ac21e744ed5a653adabcc6db29509488ee200aa0a9ce3f4292940f29e0d5dcca7f46295be30b1522af8df2d550c5b00dd937544f02b6fa1845cff4fba67c6dff5057dbfbc77c02523ac81b69e34751316016a767f884b352b7cbfdc181cc57a91a132f2f436345658bc8538bfcaf38e298c6bc0e0eb389467b81c715c07c9fea055d5ee5d38b1ba94d46365daade4f94b34fa93774815925c448699519656e724178e648a4b9f050e97d79e5f568fc41e494343884dfa0cce5d7273eaa4d0bd5db07f10b0b7a7090fabbbcf6189fdb452a52955f71199bc5cd077d9dbae048ba3cf1ed3e9abb767440286150d532abb2fd9971c7081b08846ed89c0ef9934a85a7f1be14690f1b0810bae613ef0fe4fd981e1f6b2a2cb0109b5e69d90c0ea6bef407c943ab1441f532660f7b873e679dec026b72c222ed58bd49d4639361400a32d236b5f77344a1bd967716ea494d2ebf3a023da946914c9c5452ded1142cef28e29bb275ab1c881a562fd3a54946073c50ec864da659c19584b88ada0a8370877a6804574c81a683e48800c518949b2dcb05c31dda13b00708da5c6eb13808347bb9aef530e1cb8456a9132d1f21efe7156a6bcde7a6229e818d601ff89705ded789b8bbf787ab3bf7b7de9c750068c6d7ae6e39683a1d8625b600f1ab17680b716c99fcb3e8b747658e1274df13af2d4d15a5a4e51cf88d229f59651491096f922471e30983014327060762f6c57c131e545e487d52115b0ae151a8bce033cdd7442391aec2cbb1a119e5c551fb8a9dc0262cb293294299e5d55e762cc045fa3694d1656e730669361a9e2a4f3bbc578e070777aef6f7710214b5c7fc72b58f46e895d90bd7526bab389994a392eb7531e6996bfc604e7e198ff5baac8f9a",
13 | "fcb2e012cab3f6ba0daa073b06d20f7f5332bcb0bdd882f0156e24dea442632820e1d170588196028ce29ed04fd013d117ac377bdb8af1a99afb97fafbf245c3e9be82045114c8440a625a07d14352a853a79b186eecf44036412a480638199029da699c966e962fa1292670e470d41937afcbf4856fda66888fa7c9c0b1bac308d66775b13b6a7badcbb87a69b62e57e20d62dcc41020ca7cba2cb53c249878042e121c8075240029fca4ed21f0e68e10160b7736e84421592b34dba6d48196d21b0d6112851fc4c1a698c24bba538affb9dee403a92b3e5e27d367f8c730f012f289a13612cbd7f3d4eb912277cc3832768cda8555e50ba81653c30ac2265c6823cd36e83279505a29ede1626936ba00b7e195d268295b8904c3f9d641993e65a87c9ecbddb01026270a269964dd5ea05c647d9a6d3598059cc05b3cd4f85a34a5d04f48f498c95db442520e9326c202bd40fb410e81079c34138c62b2f531a60d0370467aa0b0acc401493a1fc9ddc0c7a577c9d95b534134de3ca2ce6fb85224bc0f637c8637455048f1bd643a01500a681aa474960d44637a0a48e2de1af97e99d1690ab2f02e8fa7d7a9d4e925a787fccdc7f09ede683e72f08346b21def8227907120e8fa646761470838617285d500ad383c965f098d290ed6c449aa39358c875c7cbe0cfc49d503ef27a283884091df277f8c4ea45ece77dda6fed2b4f12a7104c84893d1bf2a30c728b4c2865a242dbc613cbd6f09bcf832dedfaf2c8479b3590d63b4474b746c80c94202a180317e8790e01f29469861bb2313da255a038fe4fec439dae68a8a1818a0d8728c5d145698d4d5c708d3a0c7755cf96283f77be14d997662835d3a9d5d00ef732b4f097de1fa6cc3051127b047471bd73d836337ffb1e971fe323fa6b076584ca0ce88b0663acc09a162663308c70345cf0b58eaf84e37f91461d26020ccec949377108ac5b142e2390823d0d2af0c7c37748e600a9ffbdc49925cb1fb5739a92c6f2e80037d02f243fc3b4c061573bdc9b21ea3cae05873ad45fe155326e6e0698e1a9a234318028bcd98e2815a639c45366646f2c179dc355eb40b59d3edc0ae5166901b83bb90457bf0bd1a9790c58d5bf5c502719037aa8898c53baa3156070c92670434c525e6baf00bd9ba1ebc86095acf8a06692252171c2879bf285f149f9ec3e3d3708e69fc94ef484d6789c0221d1755a9c09e49173d084322ea180fb5b4993540a1089319294de37d816606476f78ab329ef04fe6b1709f02e570684038ecc50affd442f7b628b4287e8dc2f15b982663712e0a532151590938ae64c9842c744dc11b0c1323c8c098e4c066b32622b4814f321d71d9144fbc2e3c8de347ff370ab898df211d26279fc4106a8811e4eb9ddd274cd72dc55744c4bdc331bbeaa98f266e7d0c31479a9962c89a5d7f7c418159c3596f9fa49364641654df8691ccff4854f083d4d384dd5d68d729798f5a232fcac92b6f57a2a885f897410c775250758d0c47b026817cc167e6b229af556eb134e63140400add0056fce745c89e043d3e53b2c595ccdd601356adb4b99fa47e20063115fe2c78c421c9c21559c02472f5e9919bdcf19788beeb6f5b53409b56e0093cfda3367a5d6acb51154ad554115e47228e41a37424d5dedb5ee2db28d2987ae22e74348cfb06dce277737d1e256f28ffa589f097b041b8f3805ee69e827d7852ca995f695c4cd8024577a894b2f6923ed365e9931db44ab7c71cf7e5fdc16bd00b075b4cd417f692ab71c0ac3eae06879aa965393c25b114bcc931f953be120054e0b9e531fc13b9c72818d82bf6053a8c838a675097443e78a06491536479c231c66c2c1696173f911e52e9a8e3562580e99697bc62f010e7c141be46df414c79cd97aa259a3473163bb8821e3ad0b57c62f92db28338f869b5b2403914380883472b2f3f8626586729a6118bea5b92206a597a354619904b3972d7e16ccb086a9a4ac78b670eca4f568a78e16fb630cd216740217e0ee289c947992e3780404d33bc75faf52ea65fefdcdf9a7edd3fa45f80a70b541a60a5684a197c844f926730dd4e69555834f9c8fd0c8be1a7f04af47c2031dc0907ca58a710db61b85b8c4ff08c3806e1128566fde339e5652f436acab88d15e5f7276c693457e923aff8dc3a16f5cfd215adfe3ff53fffd1f1a7fb77fff7ce3fddbff7af01a85f6b00ca79fb6127a0eedffbcd47a0eedffd9566a09c41bfd310149ffe5b4d4185997dd031a8afff075b433fe9947a0000"
14 | ],
15 | "headers": {
16 | "content-type": "application/json; charset=UTF-8",
17 | "transfer-encoding": "chunked",
18 | "connection": "close",
19 | "access-control-allow-headers": "Authorization",
20 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
21 | "allow": "GET",
22 | "content-encoding": "gzip",
23 | "date": "Sat, 11 Jun 2016 18:39:51 GMT",
24 | "link": "; rel=\"next\"",
25 | "server": "nginx/1.4.6 (Ubuntu)",
26 | "x-batcache": "HIT",
27 | "x-cached": "EXPIRED",
28 | "x-content-type-options": "nosniff",
29 | "x-ec2-instance-id": "i-f737987d",
30 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
31 | "x-wp-total": "101",
32 | "x-wp-totalpages": "26",
33 | "vary": "Cookie",
34 | "x-cache": "Miss from cloudfront",
35 | "via": "1.1 e9805f6e7e7fc960be065e8aee90e3c4.cloudfront.net (CloudFront)",
36 | "x-amz-cf-id": "EojUBXsPZ6gjQcG7hY6lrxhtifRqPJov4C-LJ7hf0y6SSSMkzmszVA=="
37 | }
38 | }
39 | ]
--------------------------------------------------------------------------------
/tests/fixtures/responses/taxonomiesMeta:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/taxonomies/category",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b08000000000000039d90c16ec4200c44ffc5e774917ae4dacf585615226e420bd802a7e92ae2df6b9aeda9b7deacc11edecc01c567040b2f5e70a11ab1c1042d6d8b6ae1d4eeaaccd8428d2c918a3ea82077d6557b05a626709b608d587d0d6b0c3e8195bae104af29960fdd3a20504a18cef3eb016bc537f55945b859679c9931d365e727cff142757146e7f746650cce7c3e3b23fe8b0ae501d8f5bb9d6d14cc03e15f768f6cbf7661fb893ecc1e85ecac29ff700ebefd243c2aa63e9ac0cc499b9acfd4fdd6fb373b384fdf56010000"
10 | ],
11 | "headers": {
12 | "content-type": "application/json; charset=UTF-8",
13 | "content-length": "211",
14 | "connection": "close",
15 | "access-control-allow-headers": "Authorization",
16 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
17 | "allow": "GET",
18 | "content-encoding": "gzip",
19 | "date": "Wed, 15 Jun 2016 03:14:57 GMT",
20 | "server": "nginx/1.4.6 (Ubuntu)",
21 | "x-batcache": "MISS",
22 | "x-cached": "MISS",
23 | "x-content-type-options": "nosniff",
24 | "x-ec2-instance-id": "i-f737987d",
25 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
26 | "vary": "Cookie",
27 | "x-cache": "Miss from cloudfront",
28 | "via": "1.1 b1e9642a58f783f714c47d1a096accf6.cloudfront.net (CloudFront)",
29 | "x-amz-cf-id": "bz5cnAhgVaMMo8KCzf7L-HfgmhbyUToKitnuP1no1x5zcrEGi7HrLQ=="
30 | }
31 | }
32 | ]
--------------------------------------------------------------------------------
/tests/fixtures/responses/taxonomyTermsByIndex:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "scope": "https://demo.wp-api.org:443",
4 | "method": "GET",
5 | "path": "/wp-json/wp/v2/categories?page=1&per_page=1",
6 | "body": "",
7 | "status": 200,
8 | "response": [
9 | "1f8b0800000000000003a552cb4ec33010fc973d87bae56809f1159ceaa832c992ba38f6ca0f4288f2efacd3b40255e2506ea3b1773c9ed9fd04a605b9aba0f1d925465bc62dc626184ac63b90001558e3de191d53a2289550a2c5de6f067ad064363e744a343a61e7c3a844762b365fd82ac1d34ef7c8d32f3f0f988e36774cffbacf74d29fdef97ee4a38b28b3a403167fdb0a0ec54d04394144fb06723fc1312083bffcb1d753f44e898194f878bc1a361895d8c15c9704acc5e6fce9ff6a2e82fad567b67c9fd61ac3e2ef9a43b13990241fd3218dc4a9de275e04e2f3a5278c4f6b0239f07b8be8dad9409cfd4dbaa5f5e1dcfb14d0cea535ecc9f20ef032a59071aee7b9fe06ae5ce1d25d020000"
10 | ],
11 | "headers": {
12 | "content-type": "application/json; charset=UTF-8",
13 | "content-length": "273",
14 | "connection": "close",
15 | "access-control-allow-headers": "Authorization",
16 | "access-control-expose-headers": "X-WP-Total, X-WP-TotalPages",
17 | "allow": "GET",
18 | "content-encoding": "gzip",
19 | "date": "Wed, 15 Jun 2016 03:30:48 GMT",
20 | "server": "nginx/1.4.6 (Ubuntu)",
21 | "x-batcache": "MISS",
22 | "x-cached": "MISS",
23 | "x-content-type-options": "nosniff",
24 | "x-ec2-instance-id": "i-f737987d",
25 | "x-powered-by": "PHP/7.0.4-6+deb.sury.org~trusty+3",
26 | "x-wp-total": "1",
27 | "x-wp-totalpages": "1",
28 | "vary": "Cookie",
29 | "x-cache": "Miss from cloudfront",
30 | "via": "1.1 522fd7e3012339aa909d37522f21bc35.cloudfront.net (CloudFront)",
31 | "x-amz-cf-id": "AfjNRWPyQM2wh937_mq-Hpaqq6QjgxKgTLlr3-nTMQ0xrNUuT47NTA=="
32 | }
33 | }
34 | ]
--------------------------------------------------------------------------------
/tests/wordpressRouter.js:
--------------------------------------------------------------------------------
1 | var chai = require('chai');
2 | var sinon = require('sinon');
3 | var sinonChai = require('sinon-chai');
4 | var expect = chai.expect;
5 | chai.use(sinonChai);
6 |
7 | var nock = require('nock');
8 | var nockBack = require('nock').back;
9 | nockBack.setMode('record');
10 | nockBack.fixtures = __dirname + '/fixtures/responses';
11 |
12 | var wordpressRouter = require('../lib/wordpressRouter');
13 | var falcor = require('falcor');
14 | var endpoint = 'https://demo.wp-api.org/wp-json';
15 |
16 |
17 | describe( 'wordpress router', function() {
18 |
19 | var router, model, info, error;
20 | var savedIds = {posts:[], termSlug:null};
21 |
22 | beforeEach(function() {
23 | router = new wordpressRouter(endpoint);
24 | info = sinon.spy();
25 | error = sinon.spy();
26 | router.log = {info: info, error: error};
27 | model = new falcor.Model({source: router});
28 | });
29 |
30 | it( 'imports correctly as a class', function() {
31 | expect(wordpressRouter).to.be.a( 'function' );
32 | expect(router).to.be.an( 'object' );
33 | });
34 |
35 | it( 'can be used as a model source', function() {
36 | expect(model).to.be.an( 'object' );
37 | });
38 |
39 | describe( 'recentPosts', function() {
40 |
41 | it( 'retrieves recents posts by indices', function(done) {
42 | nockBack('recentPostsBasic', function(nockDone) {
43 | model.get('recentPosts[0..3].id').subscribe( function(data) {
44 | check(done, function() {
45 |
46 | expect(error.notCalled).to.be.true;
47 | expect(data.json).to.have.key('recentPosts');
48 |
49 | ['0','1','2','3'].forEach(function (index) {
50 | expect(data.json.recentPosts).to.have.property(index);
51 | var post = data.json.recentPosts[index];
52 | expect(post).to.have.property('id');
53 | savedIds.posts.push(post.id);
54 | });
55 |
56 | nockDone();
57 | });
58 | });
59 | });
60 | });
61 |
62 | });
63 |
64 | describe( 'postsById', function() {
65 |
66 | it( 'requests a single post by id', function(done) {
67 | var postId = savedIds.posts[0];
68 |
69 | nockBack('postsByIdSingle', function(nockDone) {
70 | model.get('postsById[' + postId + '].id').subscribe( function(data) {
71 | check(done, function() {
72 |
73 | expect(error.notCalled).to.be.true;
74 |
75 | expect(data.json).to.have.key('postsById');
76 | expect(data.json.postsById).to.have.key('' + postId);
77 | expect(data.json.postsById[postId].id).to.equal(postId);
78 |
79 | nockDone();
80 | });
81 | });
82 | });
83 | });
84 |
85 | it( 'requests multiple posts by id with keyed properties', function(done) {
86 | var postIds = savedIds.posts.slice(0,2);
87 |
88 | nockBack('postsByIdMultiple', function(nockDone) {
89 | model.get('postsById[' + postIds.join(',') + ']["id","title","slug"]').subscribe( function(data) {
90 | check(done, function() {
91 |
92 | expect(error.notCalled).to.be.true;
93 |
94 | postIds.forEach(function (postId) {
95 | expect(data.json.postsById).to.have.property('' + postId);
96 | var post = data.json.postsById[postId];
97 | expect(post).to.have.keys('id','title','slug');
98 | expect(post.id).to.equal(postId);
99 | });
100 |
101 | nockDone();
102 | });
103 | });
104 | });
105 | });
106 |
107 | });
108 |
109 | describe( 'taxonomies', function() {
110 |
111 | it( 'fetches metadata for a taxonomy', function(done) {
112 | nockBack('taxonomiesMeta', function(nockDone) {
113 | model.get('taxonomies.category.meta["name","slug"]').subscribe( function(data) {
114 | check(done, function() {
115 |
116 | expect(error.notCalled).to.be.true;
117 | expect(data.json).to.deep.equal({
118 | "taxonomies": {
119 | "category": {
120 | "meta": {
121 | "name": "Categories",
122 | "slug": "category"
123 | }
124 | }
125 | }
126 | })
127 |
128 | nockDone();
129 | });
130 | });
131 | });
132 | });
133 |
134 | it( 'fetches terms for a taxonomy by index', function(done) {
135 | nockBack('taxonomyTermsByIndex', function(nockDone) {
136 | model.get('taxonomies.categories.terms[0]["name","slug"]').subscribe( function(data) {
137 | check(done, function() {
138 |
139 | expect(error.notCalled).to.be.true;
140 | expect(data.json).to.have.deep.property('taxonomies.categories.terms');
141 | expect(data.json.taxonomies.categories.terms[0]).to.have.keys('slug','name')
142 | savedIds.termSlug = data.json.taxonomies.categories.terms[0].slug;
143 |
144 | nockDone();
145 | });
146 | });
147 | });
148 | });
149 |
150 | it( 'fetches posts by a specified term slug', function(done) {
151 | nockBack('postsByTermSlug', function(nockDone) {
152 | var slug = savedIds.termSlug;
153 |
154 | model.get('postsByTerm.categories.' + slug + '[0..3]["title","id"]').subscribe( function(data) {
155 | check(done, function() {
156 |
157 | expect(error.notCalled).to.be.true;
158 | expect(data.json).to.have.deep.property('postsByTerm.categories.' + slug);
159 | var postList = data.json.postsByTerm.categories[slug];
160 |
161 | ['0','1','2','3'].forEach(function (index) {
162 | expect(postList).to.have.property(index);
163 | expect(postList[index]).to.have.keys('id','title');
164 | });
165 |
166 | nockDone();
167 | });
168 | });
169 | });
170 | });
171 |
172 |
173 |
174 |
175 | });
176 |
177 | describe( 'postsById', function() {
178 |
179 | it( 'requests a single post by id', function(done) {
180 | done();
181 | });
182 | });
183 |
184 | });
185 |
186 | function check( done, f ) {
187 | try {
188 | f();
189 | done();
190 | } catch( e ) {
191 | done( e );
192 | }
193 | }
194 |
--------------------------------------------------------------------------------