m3api-rest 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +51 -0
- package/README.md +170 -34
- package/index.js +674 -51
- package/package.json +1 -1
package/CHANGES.md
CHANGED
|
@@ -5,6 +5,57 @@ This file records the changes in each m3api-rest release.
|
|
|
5
5
|
The annotated tag (and GitLab release) for each version also lists the changes,
|
|
6
6
|
but this file may sometimes contain later improvements (e.g. typo fixes).
|
|
7
7
|
|
|
8
|
+
## v0.2.0 (2026-04-05)
|
|
9
|
+
|
|
10
|
+
- Major functionality update:
|
|
11
|
+
beyond `getJson()` and `postForJson()`,
|
|
12
|
+
m3api-rest now supports the following:
|
|
13
|
+
- request methods:
|
|
14
|
+
- GET
|
|
15
|
+
- POST
|
|
16
|
+
- PUT
|
|
17
|
+
- DELETE
|
|
18
|
+
- PATCH
|
|
19
|
+
- request body content types:
|
|
20
|
+
- `application/json`
|
|
21
|
+
- `application/x-www-form-urlencoded`
|
|
22
|
+
- `multipart/form-data`
|
|
23
|
+
- response body content types:
|
|
24
|
+
- `application/json`
|
|
25
|
+
- `text/plain`
|
|
26
|
+
- `text/html`
|
|
27
|
+
|
|
28
|
+
Yielding the following full list of request functions:
|
|
29
|
+
- `getJson()`
|
|
30
|
+
- `getText()`
|
|
31
|
+
- `getHtml()`
|
|
32
|
+
- `postForJson()`
|
|
33
|
+
- `postForText()`
|
|
34
|
+
- `postForHtml()`
|
|
35
|
+
- `putForJson()`
|
|
36
|
+
- `putForText()`
|
|
37
|
+
- `putForHtml()`
|
|
38
|
+
- `deleteForJson()`
|
|
39
|
+
- `deleteForText()`
|
|
40
|
+
- `deleteForHtml()`
|
|
41
|
+
- `patchForJson()`
|
|
42
|
+
- `patchForText()`
|
|
43
|
+
- `patchForHtml()`
|
|
44
|
+
- BREAKING CHANGE:
|
|
45
|
+
`getJson()` and `postForJson()` can now return `String` instances
|
|
46
|
+
in addition to objects and arrays,
|
|
47
|
+
if the server returns JSON-encoded strings.
|
|
48
|
+
(This is unlikely for MediaWiki core’s REST API endpoints,
|
|
49
|
+
but common in the Wikibase REST API.)
|
|
50
|
+
- BREAKING CHANGE:
|
|
51
|
+
The `body` property of the `RestApiServerError`,
|
|
52
|
+
`RestApiClientError` and `UnexpectedResponseStatus` classes
|
|
53
|
+
is now documented with the type `*` (“any”) rather than `string|Object`.
|
|
54
|
+
The previous type was incorrect – if the server response is JSON,
|
|
55
|
+
m3api-rest just decodes it for the error without checking if it’s an object or not.
|
|
56
|
+
(You almost certainly don’t need to care about this change,
|
|
57
|
+
but it’s technically breaking.)
|
|
58
|
+
|
|
8
59
|
## v0.1.1 (2026-04-05)
|
|
9
60
|
|
|
10
61
|
- Updated the library for the new network interface of m3api v1.1.0,
|
package/README.md
CHANGED
|
@@ -3,22 +3,14 @@
|
|
|
3
3
|
m3api-rest is an extension package for [m3api],
|
|
4
4
|
allowing you to interact with the MediaWiki REST API.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Usage examples
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
All functions start with the HTTP method name (in lowercase);
|
|
11
|
-
for GET functions, this is directly followed by the response type (e.g. `getJson`),
|
|
12
|
-
while other functions have the word “for” in between (e.g. `postForJson`)
|
|
13
|
-
to clarify that this is the response content type, not the request content type.
|
|
14
|
-
(The content type of the request body is specified by the type of the body passed into the function;
|
|
15
|
-
currently `postForJson` only supports `URLSearchParams` bodies,
|
|
16
|
-
but in future versions the same function will support multiple body types.)
|
|
8
|
+
Before digging into all the available features in m3api-rest,
|
|
9
|
+
let’s start with some examples for commonly used functions.
|
|
17
10
|
|
|
18
11
|
### `getJson`
|
|
19
12
|
|
|
20
13
|
Make a GET request for some JSON data.
|
|
21
|
-
Usage examples:
|
|
22
14
|
|
|
23
15
|
```js
|
|
24
16
|
import Session from 'm3api';
|
|
@@ -46,7 +38,23 @@ See also below for details on the different ways to specify parameters.
|
|
|
46
38
|
### `postForJson`
|
|
47
39
|
|
|
48
40
|
Make a POST request that will return some JSON data.
|
|
49
|
-
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const session = new Session( 'test.wikipedia.org', {}, {
|
|
44
|
+
userAgent: 'm3api-rest-README-example',
|
|
45
|
+
accessToken: ...,
|
|
46
|
+
} );
|
|
47
|
+
|
|
48
|
+
const title = 'Test page',
|
|
49
|
+
source = 'Test page contents',
|
|
50
|
+
comment = 'test edit';
|
|
51
|
+
const response = await postForJson( session, '/v1/page', {
|
|
52
|
+
title,
|
|
53
|
+
source,
|
|
54
|
+
comment,
|
|
55
|
+
} );
|
|
56
|
+
console.log( `Created new page with page ID ${ response.id }` );
|
|
57
|
+
```
|
|
50
58
|
|
|
51
59
|
```js
|
|
52
60
|
const wikitext = '== ==\nThis is <span id=id>bad</span> <span id=id>wikitext</span>.';
|
|
@@ -56,12 +64,112 @@ const lints = await postForJson( session, '/v1/transform/wikitext/to/lint', new
|
|
|
56
64
|
console.log( lints ); // [ { type: 'empty-heading', ... }, { type: 'duplicate-ids', ... } ]
|
|
57
65
|
```
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
### `putForJson`
|
|
68
|
+
|
|
69
|
+
Make a PUT request that will return some JSON data.
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
// session should still have an accessToken, like in the previous example
|
|
73
|
+
const title = 'Test page';
|
|
74
|
+
const page = await getJson( session, path`/v1/page/${ title }` );
|
|
75
|
+
const updatedPage = await putForJson( session, path`/v1/page/${ title }`, {
|
|
76
|
+
source: page.source.replace( /privledge/g, 'privilege' ), // example typo fix
|
|
77
|
+
comment: 'test edit',
|
|
78
|
+
content_model: page.content_model,
|
|
79
|
+
latest: page.latest,
|
|
80
|
+
} );
|
|
81
|
+
console.log( `Edited page with revision ID ${ updatedPage.latest.id }` );
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `getHtml`
|
|
85
|
+
|
|
86
|
+
Make a GET request that will return HTML.
|
|
87
|
+
The HTML is returned as a `String`;
|
|
88
|
+
if you want to turn it into a DOM, you will need to parse it yourself,
|
|
89
|
+
e.g. using a [`DOMParser`][] in the browser or [jsdom][] on Node.js.
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
const title = 'Douglas Adams';
|
|
93
|
+
const html = await getHtml( session, path`/v1/page/${ title }/html` );
|
|
94
|
+
const dom = new DOMParser().parseFromString( html, 'text/html' );
|
|
95
|
+
const rudimentaryLeadParagraph = dom.querySelector( 'p:not( .mw-empty-elt )' );
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `postForText`, `postForHtml`
|
|
99
|
+
|
|
100
|
+
Make GET requests that will return text or HTML, respectively.
|
|
101
|
+
As with `getHtml`, the result is returned as a `String`.
|
|
102
|
+
You can use these functions to convert between wikitext and HTML, for instance.
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const wikitext = "''Hello, world!''";
|
|
106
|
+
const html = await postForHtml( session, '/v1/transform/wikitext/to/html', {
|
|
107
|
+
wikitext,
|
|
108
|
+
} );
|
|
109
|
+
console.log( html.valueOf() );
|
|
110
|
+
// <!DOCTYPE html>...<i ...>Hello, world!</i>
|
|
111
|
+
const wikitext2 = await postForText( session, '/v1/transform/html/to/wikitext', {
|
|
112
|
+
html,
|
|
113
|
+
} );
|
|
114
|
+
console.log( wikitext2.valueOf() );
|
|
115
|
+
// ''Hello, world!''
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Request functions
|
|
63
119
|
|
|
64
|
-
|
|
120
|
+
m3api-rest supports the following:
|
|
121
|
+
|
|
122
|
+
- request methods:
|
|
123
|
+
- GET
|
|
124
|
+
- POST
|
|
125
|
+
- PUT
|
|
126
|
+
- DELETE
|
|
127
|
+
- PATCH
|
|
128
|
+
- request body content types:
|
|
129
|
+
- `application/json`
|
|
130
|
+
- `application/x-www-form-urlencoded`
|
|
131
|
+
- `multipart/form-data`
|
|
132
|
+
- response body content types:
|
|
133
|
+
- `application/json`
|
|
134
|
+
- `text/plain`
|
|
135
|
+
- `text/html`
|
|
136
|
+
|
|
137
|
+
### Request methods and response body content types
|
|
138
|
+
|
|
139
|
+
Each combination of request method and response body content type has a separate function,
|
|
140
|
+
whose name begins with the HTTP method name (in lowercase).
|
|
141
|
+
For GET functions, this is directly followed by the response type (e.g. `getJson`),
|
|
142
|
+
while other functions have the word “for” in between (e.g. `postForJson`)
|
|
143
|
+
to clarify that this is the response body content type, not the request body content type.
|
|
144
|
+
The response body content types are “json”, “text”, or “html”,
|
|
145
|
+
and included in the method name with an initial uppercase letter
|
|
146
|
+
(e.g. `getJson`, `postForText`, `postForHtml`).
|
|
147
|
+
Overall, the following functions are available:
|
|
148
|
+
|
|
149
|
+
- `getJson`
|
|
150
|
+
- `getText`
|
|
151
|
+
- `getHtml`
|
|
152
|
+
- `postForJson`
|
|
153
|
+
- `postForText`
|
|
154
|
+
- `postForHtml`
|
|
155
|
+
- `putForJson`
|
|
156
|
+
- `putForText`
|
|
157
|
+
- `putForHtml`
|
|
158
|
+
- `deleteForJson`
|
|
159
|
+
- `deleteForText`
|
|
160
|
+
- `deleteForHtml`
|
|
161
|
+
- `patchForJson`
|
|
162
|
+
- `patchForText`
|
|
163
|
+
- `patchForHtml`
|
|
164
|
+
|
|
165
|
+
### Request body content types
|
|
166
|
+
|
|
167
|
+
The request body type for non-GET request functions is determined
|
|
168
|
+
by the type of the object passed into the function,
|
|
169
|
+
i.e. the same function (e.g. `postForJson`) can send request bodies encoded in different ways.
|
|
170
|
+
For details, see the section on “body parameters” below.
|
|
171
|
+
|
|
172
|
+
### Specifying parameters
|
|
65
173
|
|
|
66
174
|
REST API endpoints have different kinds of parameters.
|
|
67
175
|
Many endpoints take parameters in the path, written like `/v1/page/{title}` (`title` is a parameter);
|
|
@@ -69,7 +177,7 @@ many endpoints take query parameters after the path, like `/v1/search/page?q=sea
|
|
|
69
177
|
and non-GET endpoints (POST etc.) take body parameters in several encodings.
|
|
70
178
|
m3api-rest supports several ways to specify these parameters.
|
|
71
179
|
|
|
72
|
-
|
|
180
|
+
#### Path parameters
|
|
73
181
|
|
|
74
182
|
Path parameters can be specified using a tagged template literal (string template)
|
|
75
183
|
using the `path` function,
|
|
@@ -98,7 +206,7 @@ const page = await getJson( session, '/v1/page/{title}', {
|
|
|
98
206
|
// makes a request to /v1/page/AC%2FDC?redirect=true
|
|
99
207
|
```
|
|
100
208
|
|
|
101
|
-
|
|
209
|
+
#### Query parameters
|
|
102
210
|
|
|
103
211
|
The GET request functions, e.g. `getJson`, take an object with query parameters after the path:
|
|
104
212
|
|
|
@@ -119,31 +227,57 @@ you should pass them into the `path` as an object:
|
|
|
119
227
|
|
|
120
228
|
```js
|
|
121
229
|
const params = { fakeQueryParam: 'abc' };
|
|
122
|
-
await postForJson( path`/v0/fake/endpoint?${ params }`,
|
|
230
|
+
await postForJson( path`/v0/fake/endpoint?${ params }`, {
|
|
123
231
|
fakeBodyParam: 'xyz',
|
|
124
|
-
} )
|
|
125
|
-
// makes a request to /v0/fake/endpoint?fakeQueryParam=abc with fakeBodyParam
|
|
232
|
+
} );
|
|
233
|
+
// makes a request to /v0/fake/endpoint?fakeQueryParam=abc with {"fakeBodyParam":"xyz"} in the body
|
|
126
234
|
```
|
|
127
235
|
|
|
128
236
|
This is also possible for GET requests, but you should probably prefer passing the query parameters separately there.
|
|
129
237
|
|
|
130
|
-
|
|
238
|
+
#### Body parameters
|
|
131
239
|
|
|
132
|
-
The non-GET request functions, e.g. `postForJson`, take a value for the body after the path.
|
|
133
|
-
The type of the value encodes the content type with which the body will be sent
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
(`FormData` for `multipart/form-data`, plain object for `application/json`)
|
|
138
|
-
will be added in a future version.
|
|
240
|
+
The non-GET request functions, e.g. `postForJson`, take a value for the request body after the path.
|
|
241
|
+
The type of the value encodes the content type with which the request body will be sent:
|
|
242
|
+
a plain object is sent as `application/json`;
|
|
243
|
+
a `URLSearchParams` instance is sent as `application/x-www-form-urlencoded`;
|
|
244
|
+
and a `FormData` instance is sent as `multipart/form-data`.
|
|
139
245
|
|
|
140
246
|
```js
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
247
|
+
const wikitext = "''Hello, world!''";
|
|
248
|
+
|
|
249
|
+
// send as application/json
|
|
250
|
+
const html = await postForHtml(
|
|
251
|
+
session,
|
|
252
|
+
'/v1/transform/wikitext/to/html',
|
|
253
|
+
{
|
|
254
|
+
wikitext,
|
|
255
|
+
},
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
// send as application/x-www-form-urlencoded
|
|
259
|
+
const html = await postForHtml(
|
|
260
|
+
session,
|
|
261
|
+
'/v1/transform/wikitext/to/html',
|
|
262
|
+
new URLSearchParams( {
|
|
263
|
+
wikitext,
|
|
264
|
+
} ),
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// send as multipart/form-data
|
|
268
|
+
const formData = new FormData();
|
|
269
|
+
formData.set( 'wikitext', wikitext );
|
|
270
|
+
const html = await postForHtml(
|
|
271
|
+
session,
|
|
272
|
+
'/v1/transform/wikitext/to/html',
|
|
273
|
+
formData,
|
|
274
|
+
);
|
|
145
275
|
```
|
|
146
276
|
|
|
277
|
+
Note that not all REST API endpoints accept all request body content types.
|
|
278
|
+
Generally speaking, JSON is your safest bet,
|
|
279
|
+
but you should consult the API endpoint’s documentation to see what request bodies it accepts.
|
|
280
|
+
|
|
147
281
|
As mentioned above, you can also specify path parameters here.
|
|
148
282
|
|
|
149
283
|
## License
|
|
@@ -153,4 +287,6 @@ By contributing to this software,
|
|
|
153
287
|
you agree to publish your contribution under the same license.
|
|
154
288
|
|
|
155
289
|
[m3api]: https://www.npmjs.com/package/m3api
|
|
290
|
+
[`DOMParser`]: https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
|
|
291
|
+
[jsdom]: https://www.npmjs.com/package/jsdom
|
|
156
292
|
[ISC License]: https://spdx.org/licenses/ISC.html
|
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export class RestApiServerError extends Error {
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @param {number} status The invalid status code received from the API.
|
|
8
|
-
* @param {
|
|
8
|
+
* @param {*} body The response body received from the API.
|
|
9
9
|
*/
|
|
10
10
|
constructor( status, body ) {
|
|
11
11
|
super( `REST API server error: ${ status }\n\n${ JSON.stringify( body ) }` );
|
|
@@ -27,9 +27,9 @@ export class RestApiServerError extends Error {
|
|
|
27
27
|
* The body of the response.
|
|
28
28
|
*
|
|
29
29
|
* Depending on the response’s content type,
|
|
30
|
-
* this may be a string or a JSON-decoded
|
|
30
|
+
* this may be a string or a JSON-decoded value.
|
|
31
31
|
*
|
|
32
|
-
* @member {
|
|
32
|
+
* @member {*}
|
|
33
33
|
*/
|
|
34
34
|
this.body = body;
|
|
35
35
|
}
|
|
@@ -43,7 +43,7 @@ export class RestApiClientError extends Error {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @param {number} status The invalid status code received from the API.
|
|
46
|
-
* @param {
|
|
46
|
+
* @param {*} body The response body received from the API.
|
|
47
47
|
*/
|
|
48
48
|
constructor( status, body ) {
|
|
49
49
|
super( `REST API client error: ${ status }\n\n${ JSON.stringify( body ) }` );
|
|
@@ -65,9 +65,9 @@ export class RestApiClientError extends Error {
|
|
|
65
65
|
* The body of the response.
|
|
66
66
|
*
|
|
67
67
|
* Depending on the response’s content type,
|
|
68
|
-
* this may be a string or a JSON-decoded
|
|
68
|
+
* this may be a string or a JSON-decoded value.
|
|
69
69
|
*
|
|
70
|
-
* @member {
|
|
70
|
+
* @member {*}
|
|
71
71
|
*/
|
|
72
72
|
this.body = body;
|
|
73
73
|
}
|
|
@@ -83,7 +83,7 @@ export class UnexpectedResponseStatus extends Error {
|
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* @param {number} status The unexpected status code received from the API.
|
|
86
|
-
* @param {
|
|
86
|
+
* @param {*} body The response body received from the API.
|
|
87
87
|
*/
|
|
88
88
|
constructor( status, body ) {
|
|
89
89
|
super( `Unexpected REST API response status: ${ status }\n\n${ JSON.stringify( body ) }` );
|
|
@@ -105,9 +105,9 @@ export class UnexpectedResponseStatus extends Error {
|
|
|
105
105
|
* The body of the response.
|
|
106
106
|
*
|
|
107
107
|
* Depending on the response’s content type,
|
|
108
|
-
* this may be a string or a JSON-decoded
|
|
108
|
+
* this may be a string or a JSON-decoded value.
|
|
109
109
|
*
|
|
110
|
-
* @member {
|
|
110
|
+
* @member {*}
|
|
111
111
|
*/
|
|
112
112
|
this.body = body;
|
|
113
113
|
}
|
|
@@ -292,6 +292,25 @@ export class InvalidPathParams extends Error {
|
|
|
292
292
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Get the MIME type (e.g. application/json) of the given response.
|
|
297
|
+
*
|
|
298
|
+
* @private
|
|
299
|
+
* @param {Response} response
|
|
300
|
+
* @return {string} The mime type part of the Content-Type response header,
|
|
301
|
+
* not including parameters like ;charset=utf-8
|
|
302
|
+
*/
|
|
303
|
+
function getResponseMimeType( response ) {
|
|
304
|
+
const contentType = response.headers.get( 'Content-Type' );
|
|
305
|
+
const [ mimeType ] = contentType.split( ';', 1 );
|
|
306
|
+
// this accepts some technically invalid Content-Type headers
|
|
307
|
+
// (we don’t check if the part before ; is a valid media-type,
|
|
308
|
+
// i.e. two tokens separated by a slash,
|
|
309
|
+
// cf. https://httpwg.org/specs/rfc9110.html#media.type)
|
|
310
|
+
// because there’s no reason to reject them
|
|
311
|
+
return mimeType;
|
|
312
|
+
}
|
|
313
|
+
|
|
295
314
|
/**
|
|
296
315
|
* Determine whether this response contains JSON
|
|
297
316
|
* according to its headers.
|
|
@@ -301,14 +320,37 @@ export class InvalidPathParams extends Error {
|
|
|
301
320
|
* @return {boolean}
|
|
302
321
|
*/
|
|
303
322
|
function isResponseJson( response ) {
|
|
304
|
-
const
|
|
305
|
-
const [ mimeType ] = contentType.split( ';', 1 ); // split off ;charset=utf-8 and suchlike
|
|
323
|
+
const mimeType = getResponseMimeType( response );
|
|
306
324
|
return mimeType === 'application/json' ||
|
|
307
325
|
( mimeType.startsWith( 'application/' ) && mimeType.endsWith( '+json' ) );
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Determine whether this response contains text
|
|
330
|
+
* (“plain text”, but in practice often wikitext) according to its headers.
|
|
331
|
+
*
|
|
332
|
+
* @private
|
|
333
|
+
* @param {Response} response
|
|
334
|
+
* @return {boolean}
|
|
335
|
+
*/
|
|
336
|
+
function isResponseText( response ) {
|
|
337
|
+
const mimeType = getResponseMimeType( response );
|
|
338
|
+
return mimeType === 'text/plain' ||
|
|
339
|
+
( mimeType.startsWith( 'text/' ) && mimeType.endsWith( '+plain' ) );
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Determine whether this response contains HTML
|
|
344
|
+
* according to its headers.
|
|
345
|
+
*
|
|
346
|
+
* @private
|
|
347
|
+
* @param {Response} response
|
|
348
|
+
* @return {boolean}
|
|
349
|
+
*/
|
|
350
|
+
function isResponseHtml( response ) {
|
|
351
|
+
const mimeType = getResponseMimeType( response );
|
|
352
|
+
return mimeType === 'text/html' ||
|
|
353
|
+
( mimeType.startsWith( 'text/' ) && mimeType.endsWith( '+html' ) );
|
|
312
354
|
}
|
|
313
355
|
|
|
314
356
|
/**
|
|
@@ -316,7 +358,7 @@ function isResponseJson( response ) {
|
|
|
316
358
|
*
|
|
317
359
|
* @private
|
|
318
360
|
* @param {Response} response
|
|
319
|
-
* @return {
|
|
361
|
+
* @return {*}
|
|
320
362
|
*/
|
|
321
363
|
async function getResponseBodyForError( response ) {
|
|
322
364
|
if ( isResponseJson( response ) ) {
|
|
@@ -350,7 +392,7 @@ const responseStatuses = new WeakMap();
|
|
|
350
392
|
/**
|
|
351
393
|
* Get the HTTP status code for this response.
|
|
352
394
|
*
|
|
353
|
-
* @param {Object|Array} response A response object returned by one of the request functions
|
|
395
|
+
* @param {Object|Array|String} response A response object returned by one of the request functions
|
|
354
396
|
* ({@link getJson} etc.). Note that it must be exactly the object returned by the function
|
|
355
397
|
* (compared by identity, i.e. `===`), not a serialization of it or anything similar.
|
|
356
398
|
* @return {number} The HTTP status code, i.e. an integer between 200 and 599.
|
|
@@ -369,17 +411,21 @@ export function getResponseStatus( response ) {
|
|
|
369
411
|
*
|
|
370
412
|
* @private
|
|
371
413
|
* @param {Response} response
|
|
372
|
-
* @return {Object|Array}
|
|
414
|
+
* @return {Object|Array|String}
|
|
373
415
|
*/
|
|
374
416
|
async function getResponseJson( response ) {
|
|
375
417
|
if ( isResponseJson( response ) ) {
|
|
376
418
|
const body = await response.json();
|
|
419
|
+
let bodyWithIdentity;
|
|
377
420
|
if ( typeof body === 'object' && body !== null ) {
|
|
378
|
-
|
|
379
|
-
|
|
421
|
+
bodyWithIdentity = body;
|
|
422
|
+
} else if ( typeof body === 'string' ) {
|
|
423
|
+
bodyWithIdentity = new String( body );
|
|
380
424
|
} else {
|
|
381
425
|
throw new InvalidResponseBody( body );
|
|
382
426
|
}
|
|
427
|
+
responseStatuses.set( bodyWithIdentity, response.status );
|
|
428
|
+
return bodyWithIdentity;
|
|
383
429
|
} else {
|
|
384
430
|
throw new IncompatibleResponseType(
|
|
385
431
|
'application/json',
|
|
@@ -389,6 +435,49 @@ async function getResponseJson( response ) {
|
|
|
389
435
|
}
|
|
390
436
|
}
|
|
391
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Get the body of the response and check that it’s valid text
|
|
440
|
+
* (“plain text”, but in practice often wikitext.)
|
|
441
|
+
*
|
|
442
|
+
* @private
|
|
443
|
+
* @param {Response} response
|
|
444
|
+
* @return {String}
|
|
445
|
+
*/
|
|
446
|
+
async function getResponseText( response ) {
|
|
447
|
+
if ( isResponseText( response ) ) {
|
|
448
|
+
const text = new String( await response.text() );
|
|
449
|
+
responseStatuses.set( text, response.status );
|
|
450
|
+
return text;
|
|
451
|
+
} else {
|
|
452
|
+
throw new IncompatibleResponseType(
|
|
453
|
+
'text/plain',
|
|
454
|
+
response.headers.get( 'Content-Type' ),
|
|
455
|
+
await getResponseBodyForError( response ),
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Get the body of the response and check that it’s valid HTML.
|
|
462
|
+
*
|
|
463
|
+
* @private
|
|
464
|
+
* @param {Response} response
|
|
465
|
+
* @return {String}
|
|
466
|
+
*/
|
|
467
|
+
async function getResponseHtml( response ) {
|
|
468
|
+
if ( isResponseHtml( response ) ) {
|
|
469
|
+
const html = new String( await response.text() );
|
|
470
|
+
responseStatuses.set( html, response.status );
|
|
471
|
+
return html;
|
|
472
|
+
} else {
|
|
473
|
+
throw new IncompatibleResponseType(
|
|
474
|
+
'text/html',
|
|
475
|
+
response.headers.get( 'Content-Type' ),
|
|
476
|
+
await getResponseBodyForError( response ),
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
392
481
|
/**
|
|
393
482
|
* Encode a path for a REST API endpoint.
|
|
394
483
|
*
|
|
@@ -439,7 +528,7 @@ export function path( strings, ...values ) {
|
|
|
439
528
|
*
|
|
440
529
|
* @private
|
|
441
530
|
* @param {string} path The path with optional `{param}` expressions.
|
|
442
|
-
* @param {Object|URLSearchParams} params The input params. Not modified.
|
|
531
|
+
* @param {Object|URLSearchParams|FormData} params The input params. Not modified.
|
|
443
532
|
* @return {Object} The potentially modified path and params.
|
|
444
533
|
*/
|
|
445
534
|
function substitutePathParams( path, params ) {
|
|
@@ -463,6 +552,38 @@ function substitutePathParams( path, params ) {
|
|
|
463
552
|
}
|
|
464
553
|
copiedParams.delete( paramName );
|
|
465
554
|
return encodeURIComponent( values[ 0 ] );
|
|
555
|
+
} else if ( params instanceof FormData ) {
|
|
556
|
+
if ( copiedParams === null ) {
|
|
557
|
+
copiedParams = new FormData();
|
|
558
|
+
for ( const [ name, value ] of params.entries() ) {
|
|
559
|
+
copiedParams.append( name, value );
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
const values = copiedParams.getAll( paramName );
|
|
563
|
+
if ( values.length !== 1 ) {
|
|
564
|
+
throw new InvalidPathParams(
|
|
565
|
+
values.length === 0 ?
|
|
566
|
+
`Unspecified path param ${ match }` :
|
|
567
|
+
`Ambiguous path param ${ match }`,
|
|
568
|
+
path,
|
|
569
|
+
paramName,
|
|
570
|
+
params,
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
copiedParams.delete( paramName );
|
|
574
|
+
const value = values[ 0 ];
|
|
575
|
+
if ( value instanceof Blob ) {
|
|
576
|
+
// in practice, value will almost always be a File here,
|
|
577
|
+
// as FormData will turn any Blob into a File (except on old Node versions),
|
|
578
|
+
// hence the unspecific “Blob or File” in the message
|
|
579
|
+
throw new InvalidPathParams(
|
|
580
|
+
`Path param ${ match } cannot be a Blob or File`,
|
|
581
|
+
path,
|
|
582
|
+
paramName,
|
|
583
|
+
params,
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
return encodeURIComponent( value );
|
|
466
587
|
} else {
|
|
467
588
|
if ( copiedParams === null ) {
|
|
468
589
|
copiedParams = { ...params };
|
|
@@ -484,6 +605,44 @@ function substitutePathParams( path, params ) {
|
|
|
484
605
|
return { path: substitutedPath, params: copiedParams || params };
|
|
485
606
|
}
|
|
486
607
|
|
|
608
|
+
/**
|
|
609
|
+
* Convenience function to add a request header to the given `fetch()` options.
|
|
610
|
+
*
|
|
611
|
+
* @private
|
|
612
|
+
* @param {RequestInit} fetchOptions
|
|
613
|
+
* @param {string} name
|
|
614
|
+
* @param {string} value
|
|
615
|
+
*/
|
|
616
|
+
function addHeaderToOptions( fetchOptions, name, value ) {
|
|
617
|
+
fetchOptions.headers = new Headers( fetchOptions.headers );
|
|
618
|
+
fetchOptions.headers.set( name, value );
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Prepare a GET request for the given parameters.
|
|
623
|
+
* Encodes the params into the URL and sets up request headers.
|
|
624
|
+
*
|
|
625
|
+
* @private
|
|
626
|
+
* @param {Session} session
|
|
627
|
+
* @param {string} path
|
|
628
|
+
* @param {Object} params
|
|
629
|
+
* @param {Options} options
|
|
630
|
+
* @return {Array} url and fetchOptions
|
|
631
|
+
*/
|
|
632
|
+
function prepareGetRequest( session, path, params, options ) {
|
|
633
|
+
( { path, params } = substitutePathParams( path, params ) );
|
|
634
|
+
const restUrl = session.apiUrl.replace( /api\.php$/, 'rest.php' );
|
|
635
|
+
const url = new URL( restUrl + path );
|
|
636
|
+
for ( const [ name, value ] of Object.entries( params || {} ) ) {
|
|
637
|
+
url.searchParams.append( name, value );
|
|
638
|
+
}
|
|
639
|
+
const fetchOptions = {
|
|
640
|
+
method: 'GET',
|
|
641
|
+
headers: session.getRequestHeaders( options ),
|
|
642
|
+
};
|
|
643
|
+
return [ url, fetchOptions ];
|
|
644
|
+
}
|
|
645
|
+
|
|
487
646
|
/**
|
|
488
647
|
* Make a GET request to a REST API endpoint and return the JSON-decoded body.
|
|
489
648
|
*
|
|
@@ -494,25 +653,129 @@ function substitutePathParams( path, params ) {
|
|
|
494
653
|
* @param {Object} [params] Parameters for the request URL.
|
|
495
654
|
* This may include both parameters for the path and query parameters.
|
|
496
655
|
* @param {Options} [options] Request options.
|
|
497
|
-
* @return {Object|Array} The body of the API response, JSON-decoded.
|
|
656
|
+
* @return {Object|Array|String} The body of the API response, JSON-decoded.
|
|
657
|
+
* If the API returned a string, then for technical reasons it will be returned
|
|
658
|
+
* as a `String` instance, not a primitive string value;
|
|
659
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
660
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
498
661
|
*/
|
|
499
662
|
export async function getJson( session, path, params, options = {} ) {
|
|
663
|
+
const [ url, fetchOptions ] = prepareGetRequest( session, path, params, options );
|
|
664
|
+
addHeaderToOptions( fetchOptions, 'accept', 'application/json' );
|
|
665
|
+
const response = await session.fetch( url, fetchOptions );
|
|
666
|
+
await checkResponseStatus( response );
|
|
667
|
+
return await getResponseJson( response );
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Make a GET request to a REST API endpoint and return the text body.
|
|
672
|
+
*
|
|
673
|
+
* @param {Session} session The m3api session to use for this request.
|
|
674
|
+
* @param {string} path The resource path.
|
|
675
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
676
|
+
* Use the {@link path} tag function to build the path.
|
|
677
|
+
* @param {Object} [params] Parameters for the request URL.
|
|
678
|
+
* This may include both parameters for the path and query parameters.
|
|
679
|
+
* @param {Options} [options] Request options.
|
|
680
|
+
* @return {String} The body of the API response.
|
|
681
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
682
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
683
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
684
|
+
*/
|
|
685
|
+
export async function getText( session, path, params, options = {} ) {
|
|
686
|
+
const [ url, fetchOptions ] = prepareGetRequest( session, path, params, options );
|
|
687
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/plain' );
|
|
688
|
+
const response = await session.fetch( url, fetchOptions );
|
|
689
|
+
await checkResponseStatus( response );
|
|
690
|
+
return await getResponseText( response );
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Make a GET request to a REST API endpoint and return the HTML body.
|
|
695
|
+
*
|
|
696
|
+
* @param {Session} session The m3api session to use for this request.
|
|
697
|
+
* @param {string} path The resource path, e.g. `/v1/page/{title}/html`.
|
|
698
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
699
|
+
* Use the {@link path} tag function to build the path.
|
|
700
|
+
* @param {Object} [params] Parameters for the request URL.
|
|
701
|
+
* This may include both parameters for the path and query parameters.
|
|
702
|
+
* @param {Options} [options] Request options.
|
|
703
|
+
* @return {String} The body of the API response.
|
|
704
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
705
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
706
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
707
|
+
*/
|
|
708
|
+
export async function getHtml( session, path, params, options = {} ) {
|
|
709
|
+
const [ url, fetchOptions ] = prepareGetRequest( session, path, params, options );
|
|
710
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/html' );
|
|
711
|
+
const response = await session.fetch( url, fetchOptions );
|
|
712
|
+
await checkResponseStatus( response );
|
|
713
|
+
return await getResponseHtml( response );
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Encode a body for the request to the server.
|
|
718
|
+
*
|
|
719
|
+
* @param {Object|URLSearchParams|FormData} body
|
|
720
|
+
* @return {RequestInit} To be mixed into the `fetch()` options.
|
|
721
|
+
*/
|
|
722
|
+
function encodeBody( body ) {
|
|
723
|
+
if ( body instanceof URLSearchParams || body instanceof FormData ) {
|
|
724
|
+
return { body };
|
|
725
|
+
} else {
|
|
726
|
+
return {
|
|
727
|
+
body: JSON.stringify( body ),
|
|
728
|
+
headers: {
|
|
729
|
+
'Content-Type': 'application/json',
|
|
730
|
+
},
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Prepare a non-GET request for the given parameters.
|
|
737
|
+
* Encodes the params into the URL and body and sets up request headers.
|
|
738
|
+
* The caller must set the specific method afterwards.
|
|
739
|
+
*
|
|
740
|
+
* @private
|
|
741
|
+
* @param {Session} session
|
|
742
|
+
* @param {string} path
|
|
743
|
+
* @param {Object} params
|
|
744
|
+
* @param {Options} options
|
|
745
|
+
* @return {Array} url and fetchOptions
|
|
746
|
+
*/
|
|
747
|
+
function prepareRequestWithBody( session, path, params, options ) {
|
|
500
748
|
( { path, params } = substitutePathParams( path, params ) );
|
|
501
749
|
const restUrl = session.apiUrl.replace( /api\.php$/, 'rest.php' );
|
|
502
750
|
const url = new URL( restUrl + path );
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const headers = {
|
|
507
|
-
accept: 'application/json',
|
|
508
|
-
...session.getRequestHeaders( options ),
|
|
751
|
+
const fetchOptions = {
|
|
752
|
+
method: '', // trigger a TypeError in fetch() if caller does not override method
|
|
753
|
+
...encodeBody( params ),
|
|
509
754
|
};
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
headers,
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
755
|
+
fetchOptions.headers = new Headers( fetchOptions.headers );
|
|
756
|
+
for ( const [ name, value ] of Object.entries( session.getRequestHeaders( options ) ) ) {
|
|
757
|
+
fetchOptions.headers.set( name, value );
|
|
758
|
+
}
|
|
759
|
+
return [ url, fetchOptions ];
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Prepare a POST request for the given parameters.
|
|
764
|
+
* Encodes the params into the URL and body and sets up request headers.
|
|
765
|
+
*
|
|
766
|
+
* @private
|
|
767
|
+
* @param {Session} session
|
|
768
|
+
* @param {string} path
|
|
769
|
+
* @param {Object} params
|
|
770
|
+
* @param {Options} options
|
|
771
|
+
* @return {Array} url and fetchOptions
|
|
772
|
+
*/
|
|
773
|
+
function preparePostRequest( session, path, params, options ) {
|
|
774
|
+
const [ url, fetchOptions ] = prepareRequestWithBody( session, path, params, options );
|
|
775
|
+
return [ url, {
|
|
776
|
+
...fetchOptions,
|
|
777
|
+
method: 'POST',
|
|
778
|
+
} ];
|
|
516
779
|
}
|
|
517
780
|
|
|
518
781
|
/**
|
|
@@ -522,27 +785,387 @@ export async function getJson( session, path, params, options = {} ) {
|
|
|
522
785
|
* @param {string} path The resource path, e.g. `/v1/page`.
|
|
523
786
|
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
524
787
|
* Use the {@link path} tag function to build the path.
|
|
525
|
-
* @param {URLSearchParams} params The request body.
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
788
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
789
|
+
* An Object will be sent using the `application/json` content type;
|
|
790
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
791
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
529
792
|
* You may also include parameters for the path here.
|
|
530
793
|
* @param {Options} [options] Request options.
|
|
531
|
-
* @return {Object|Array} The body of the API response, JSON-decoded.
|
|
794
|
+
* @return {Object|Array|String} The body of the API response, JSON-decoded.
|
|
795
|
+
* If the API returned a string, then for technical reasons it will be returned
|
|
796
|
+
* as a `String` instance, not a primitive string value;
|
|
797
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
798
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
532
799
|
*/
|
|
533
800
|
export async function postForJson( session, path, params, options = {} ) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
801
|
+
const [ url, fetchOptions ] = preparePostRequest( session, path, params, options );
|
|
802
|
+
// skip this for now due to T412610
|
|
803
|
+
// addHeaderToOptions( fetchOptions, 'accept', 'application/json' );
|
|
804
|
+
const response = await session.fetch( url, fetchOptions );
|
|
805
|
+
await checkResponseStatus( response );
|
|
806
|
+
return await getResponseJson( response );
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Make a POST request to a REST API endpoint and return the text body.
|
|
811
|
+
*
|
|
812
|
+
* @param {Session} session The m3api session to use for this request.
|
|
813
|
+
* @param {string} path The resource path, e.g. `/v1/transform/html/to/wikitext`.
|
|
814
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
815
|
+
* Use the {@link path} tag function to build the path.
|
|
816
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
817
|
+
* An Object will be sent using the `application/json` content type;
|
|
818
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
819
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
820
|
+
* You may also include parameters for the path here.
|
|
821
|
+
* @param {Options} [options] Request options.
|
|
822
|
+
* @return {String} The body of the API response.
|
|
823
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
824
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
825
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
826
|
+
*/
|
|
827
|
+
export async function postForText( session, path, params, options = {} ) {
|
|
828
|
+
const [ url, fetchOptions ] = preparePostRequest( session, path, params, options );
|
|
829
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/plain' );
|
|
830
|
+
const response = await session.fetch( url, fetchOptions );
|
|
831
|
+
await checkResponseStatus( response );
|
|
832
|
+
return await getResponseText( response );
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* Make a POST request to a REST API endpoint and return the HTML body.
|
|
837
|
+
*
|
|
838
|
+
* @param {Session} session The m3api session to use for this request.
|
|
839
|
+
* @param {string} path The resource path, e.g. `/v1/transform/wikitext/to/html`.
|
|
840
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
841
|
+
* Use the {@link path} tag function to build the path.
|
|
842
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
843
|
+
* An Object will be sent using the `application/json` content type;
|
|
844
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
845
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
846
|
+
* You may also include parameters for the path here.
|
|
847
|
+
* @param {Options} [options] Request options.
|
|
848
|
+
* @return {String} The body of the API response.
|
|
849
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
850
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
851
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
852
|
+
*/
|
|
853
|
+
export async function postForHtml( session, path, params, options = {} ) {
|
|
854
|
+
const [ url, fetchOptions ] = preparePostRequest( session, path, params, options );
|
|
855
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/html' );
|
|
856
|
+
const response = await session.fetch( url, fetchOptions );
|
|
857
|
+
await checkResponseStatus( response );
|
|
858
|
+
return await getResponseHtml( response );
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Prepare a PUT request for the given parameters.
|
|
863
|
+
* Encodes the params into the URL and body and sets up request headers.
|
|
864
|
+
*
|
|
865
|
+
* @private
|
|
866
|
+
* @param {Session} session
|
|
867
|
+
* @param {string} path
|
|
868
|
+
* @param {Object} params
|
|
869
|
+
* @param {Options} options
|
|
870
|
+
* @return {Array} url and fetchOptions
|
|
871
|
+
*/
|
|
872
|
+
function preparePutRequest( session, path, params, options ) {
|
|
873
|
+
const [ url, fetchOptions ] = prepareRequestWithBody( session, path, params, options );
|
|
874
|
+
return [ url, {
|
|
875
|
+
...fetchOptions,
|
|
876
|
+
method: 'PUT',
|
|
877
|
+
} ];
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Make a PUT request to a REST API endpoint and return the JSON-decoded body.
|
|
882
|
+
*
|
|
883
|
+
* @param {Session} session The m3api session to use for this request.
|
|
884
|
+
* @param {string} path The resource path, e.g. `/v1/page/{title}`.
|
|
885
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
886
|
+
* Use the {@link path} tag function to build the path.
|
|
887
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
888
|
+
* An Object will be sent using the `application/json` content type;
|
|
889
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
890
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
891
|
+
* You may also include parameters for the path here.
|
|
892
|
+
* Note that all known PUT endpoints only accept JSON bodies,
|
|
893
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
894
|
+
* @param {Options} [options] Request options.
|
|
895
|
+
* @return {Object|Array|String} The body of the API response, JSON-decoded.
|
|
896
|
+
* If the API returned a string, then for technical reasons it will be returned
|
|
897
|
+
* as a `String` instance, not a primitive string value;
|
|
898
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
899
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
900
|
+
*/
|
|
901
|
+
export async function putForJson( session, path, params, options = {} ) {
|
|
902
|
+
const [ url, fetchOptions ] = preparePutRequest( session, path, params, options );
|
|
903
|
+
addHeaderToOptions( fetchOptions, 'accept', 'application/json' );
|
|
904
|
+
const response = await session.fetch( url, fetchOptions );
|
|
905
|
+
await checkResponseStatus( response );
|
|
906
|
+
return await getResponseJson( response );
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Make a PUT request to a REST API endpoint and return the text body.
|
|
911
|
+
*
|
|
912
|
+
* @param {Session} session The m3api session to use for this request.
|
|
913
|
+
* @param {string} path The resource path.
|
|
914
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
915
|
+
* Use the {@link path} tag function to build the path.
|
|
916
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
917
|
+
* An Object will be sent using the `application/json` content type;
|
|
918
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
919
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
920
|
+
* You may also include parameters for the path here.
|
|
921
|
+
* Note that all known PUT endpoints only accept JSON bodies,
|
|
922
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
923
|
+
* @param {Options} [options] Request options.
|
|
924
|
+
* @return {String} The body of the API response.
|
|
925
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
926
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
927
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
928
|
+
*/
|
|
929
|
+
export async function putForText( session, path, params, options = {} ) {
|
|
930
|
+
const [ url, fetchOptions ] = preparePutRequest( session, path, params, options );
|
|
931
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/plain' );
|
|
932
|
+
const response = await session.fetch( url, fetchOptions );
|
|
933
|
+
await checkResponseStatus( response );
|
|
934
|
+
return await getResponseText( response );
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Make a PUT request to a REST API endpoint and return the HTML body.
|
|
939
|
+
*
|
|
940
|
+
* @param {Session} session The m3api session to use for this request.
|
|
941
|
+
* @param {string} path The resource path.
|
|
942
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
943
|
+
* Use the {@link path} tag function to build the path.
|
|
944
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
945
|
+
* An Object will be sent using the `application/json` content type;
|
|
946
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
947
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
948
|
+
* You may also include parameters for the path here.
|
|
949
|
+
* Note that all known PUT endpoints only accept JSON bodies,
|
|
950
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
951
|
+
* @param {Options} [options] Request options.
|
|
952
|
+
* @return {String} The body of the API response.
|
|
953
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
954
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
955
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
956
|
+
*/
|
|
957
|
+
export async function putForHtml( session, path, params, options = {} ) {
|
|
958
|
+
const [ url, fetchOptions ] = preparePutRequest( session, path, params, options );
|
|
959
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/html' );
|
|
960
|
+
const response = await session.fetch( url, fetchOptions );
|
|
961
|
+
await checkResponseStatus( response );
|
|
962
|
+
return await getResponseHtml( response );
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Prepare a DELETE request for the given parameters.
|
|
967
|
+
* Encodes the params into the URL and body and sets up request headers.
|
|
968
|
+
*
|
|
969
|
+
* @private
|
|
970
|
+
* @param {Session} session
|
|
971
|
+
* @param {string} path
|
|
972
|
+
* @param {Object} params
|
|
973
|
+
* @param {Options} options
|
|
974
|
+
* @return {Array} url and fetchOptions
|
|
975
|
+
*/
|
|
976
|
+
function prepareDeleteRequest( session, path, params, options ) {
|
|
977
|
+
const [ url, fetchOptions ] = prepareRequestWithBody( session, path, params, options );
|
|
978
|
+
return [ url, {
|
|
979
|
+
...fetchOptions,
|
|
980
|
+
method: 'DELETE',
|
|
981
|
+
} ];
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Make a DELETE request to a REST API endpoint and return the JSON-decoded body.
|
|
986
|
+
*
|
|
987
|
+
* @param {Session} session The m3api session to use for this request.
|
|
988
|
+
* @param {string} path The resource path, e.g. `/v1/page/{title}`.
|
|
989
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
990
|
+
* Use the {@link path} tag function to build the path.
|
|
991
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
992
|
+
* An Object will be sent using the `application/json` content type;
|
|
993
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
994
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
995
|
+
* You may also include parameters for the path here.
|
|
996
|
+
* Note that all known DELETE endpoints only accept JSON bodies,
|
|
997
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
998
|
+
* @param {Options} [options] Request options.
|
|
999
|
+
* @return {Object|Array|String} The body of the API response, JSON-decoded.
|
|
1000
|
+
* If the API returned a string, then for technical reasons it will be returned
|
|
1001
|
+
* as a `String` instance, not a primitive string value;
|
|
1002
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1003
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1004
|
+
*/
|
|
1005
|
+
export async function deleteForJson( session, path, params, options = {} ) {
|
|
1006
|
+
const [ url, fetchOptions ] = prepareDeleteRequest( session, path, params, options );
|
|
1007
|
+
addHeaderToOptions( fetchOptions, 'accept', 'application/json' );
|
|
1008
|
+
const response = await session.fetch( url, fetchOptions );
|
|
1009
|
+
await checkResponseStatus( response );
|
|
1010
|
+
return await getResponseJson( response );
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* Make a DELETE request to a REST API endpoint and return the text body.
|
|
1015
|
+
*
|
|
1016
|
+
* @param {Session} session The m3api session to use for this request.
|
|
1017
|
+
* @param {string} path The resource path.
|
|
1018
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
1019
|
+
* Use the {@link path} tag function to build the path.
|
|
1020
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
1021
|
+
* An Object will be sent using the `application/json` content type;
|
|
1022
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
1023
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
1024
|
+
* You may also include parameters for the path here.
|
|
1025
|
+
* Note that all known DELETE endpoints only accept JSON bodies,
|
|
1026
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
1027
|
+
* @param {Options} [options] Request options.
|
|
1028
|
+
* @return {String} The body of the API response.
|
|
1029
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
1030
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1031
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1032
|
+
*/
|
|
1033
|
+
export async function deleteForText( session, path, params, options = {} ) {
|
|
1034
|
+
const [ url, fetchOptions ] = prepareDeleteRequest( session, path, params, options );
|
|
1035
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/plain' );
|
|
1036
|
+
const response = await session.fetch( url, fetchOptions );
|
|
1037
|
+
await checkResponseStatus( response );
|
|
1038
|
+
return await getResponseText( response );
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Make a DELETE request to a REST API endpoint and return the HTML body.
|
|
1043
|
+
*
|
|
1044
|
+
* @param {Session} session The m3api session to use for this request.
|
|
1045
|
+
* @param {string} path The resource path.
|
|
1046
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
1047
|
+
* Use the {@link path} tag function to build the path.
|
|
1048
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
1049
|
+
* An Object will be sent using the `application/json` content type;
|
|
1050
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
1051
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
1052
|
+
* You may also include parameters for the path here.
|
|
1053
|
+
* Note that all known DELETE endpoints only accept JSON bodies,
|
|
1054
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
1055
|
+
* @param {Options} [options] Request options.
|
|
1056
|
+
* @return {String} The body of the API response.
|
|
1057
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
1058
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1059
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1060
|
+
*/
|
|
1061
|
+
export async function deleteForHtml( session, path, params, options = {} ) {
|
|
1062
|
+
const [ url, fetchOptions ] = prepareDeleteRequest( session, path, params, options );
|
|
1063
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/html' );
|
|
1064
|
+
const response = await session.fetch( url, fetchOptions );
|
|
1065
|
+
await checkResponseStatus( response );
|
|
1066
|
+
return await getResponseHtml( response );
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Prepare a PATCH request for the given parameters.
|
|
1071
|
+
* Encodes the params into the URL and body and sets up request headers.
|
|
1072
|
+
*
|
|
1073
|
+
* @private
|
|
1074
|
+
* @param {Session} session
|
|
1075
|
+
* @param {string} path
|
|
1076
|
+
* @param {Object} params
|
|
1077
|
+
* @param {Options} options
|
|
1078
|
+
* @return {Array} url and fetchOptions
|
|
1079
|
+
*/
|
|
1080
|
+
function preparePatchRequest( session, path, params, options ) {
|
|
1081
|
+
const [ url, fetchOptions ] = prepareRequestWithBody( session, path, params, options );
|
|
1082
|
+
return [ url, {
|
|
1083
|
+
...fetchOptions,
|
|
1084
|
+
method: 'PATCH',
|
|
1085
|
+
} ];
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Make a PATCH request to a REST API endpoint and return the JSON-decoded body.
|
|
1090
|
+
*
|
|
1091
|
+
* @param {Session} session The m3api session to use for this request.
|
|
1092
|
+
* @param {string} path The resource path, e.g. `/v1/page/{title}`.
|
|
1093
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
1094
|
+
* Use the {@link path} tag function to build the path.
|
|
1095
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
1096
|
+
* An Object will be sent using the `application/json` content type;
|
|
1097
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
1098
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
1099
|
+
* You may also include parameters for the path here.
|
|
1100
|
+
* Note that all known PATCH endpoints only accept JSON bodies,
|
|
1101
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
1102
|
+
* @param {Options} [options] Request options.
|
|
1103
|
+
* @return {Object|Array|String} The body of the API response, JSON-decoded.
|
|
1104
|
+
* If the API returned a string, then for technical reasons it will be returned
|
|
1105
|
+
* as a `String` instance, not a primitive string value;
|
|
1106
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1107
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1108
|
+
*/
|
|
1109
|
+
export async function patchForJson( session, path, params, options = {} ) {
|
|
1110
|
+
const [ url, fetchOptions ] = preparePatchRequest( session, path, params, options );
|
|
1111
|
+
addHeaderToOptions( fetchOptions, 'accept', 'application/json' );
|
|
1112
|
+
const response = await session.fetch( url, fetchOptions );
|
|
546
1113
|
await checkResponseStatus( response );
|
|
547
1114
|
return await getResponseJson( response );
|
|
548
1115
|
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Make a PATCH request to a REST API endpoint and return the text body.
|
|
1119
|
+
*
|
|
1120
|
+
* @param {Session} session The m3api session to use for this request.
|
|
1121
|
+
* @param {string} path The resource path.
|
|
1122
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
1123
|
+
* Use the {@link path} tag function to build the path.
|
|
1124
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
1125
|
+
* An Object will be sent using the `application/json` content type;
|
|
1126
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
1127
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
1128
|
+
* You may also include parameters for the path here.
|
|
1129
|
+
* Note that all known PATCH endpoints only accept JSON bodies,
|
|
1130
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
1131
|
+
* @param {Options} [options] Request options.
|
|
1132
|
+
* @return {String} The body of the API response.
|
|
1133
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
1134
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1135
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1136
|
+
*/
|
|
1137
|
+
export async function patchForText( session, path, params, options = {} ) {
|
|
1138
|
+
const [ url, fetchOptions ] = preparePatchRequest( session, path, params, options );
|
|
1139
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/plain' );
|
|
1140
|
+
const response = await session.fetch( url, fetchOptions );
|
|
1141
|
+
await checkResponseStatus( response );
|
|
1142
|
+
return await getResponseText( response );
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/**
|
|
1146
|
+
* Make a PATCH request to a REST API endpoint and return the HTML body.
|
|
1147
|
+
*
|
|
1148
|
+
* @param {Session} session The m3api session to use for this request.
|
|
1149
|
+
* @param {string} path The resource path.
|
|
1150
|
+
* Does not include the domain, script path, or `rest.php` endpoint.
|
|
1151
|
+
* Use the {@link path} tag function to build the path.
|
|
1152
|
+
* @param {Object|URLSearchParams|FormData} params The request body.
|
|
1153
|
+
* An Object will be sent using the `application/json` content type;
|
|
1154
|
+
* URLSearchParams will be sent using the `application/x-www-form-urlencoded` content type;
|
|
1155
|
+
* FormData will be sent using the `multipart/form-data` content type.
|
|
1156
|
+
* You may also include parameters for the path here.
|
|
1157
|
+
* Note that all known PATCH endpoints only accept JSON bodies,
|
|
1158
|
+
* so URLSearchParams or FormData params are unlikely to be useful.
|
|
1159
|
+
* @param {Options} [options] Request options.
|
|
1160
|
+
* @return {String} The body of the API response.
|
|
1161
|
+
* For technical reasons, this is a `String` instance, not a primitive string value;
|
|
1162
|
+
* you can mostly use it interchangeably with an ordinary string,
|
|
1163
|
+
* or turn it into one by calling its `.valueOf()` method.
|
|
1164
|
+
*/
|
|
1165
|
+
export async function patchForHtml( session, path, params, options = {} ) {
|
|
1166
|
+
const [ url, fetchOptions ] = preparePatchRequest( session, path, params, options );
|
|
1167
|
+
addHeaderToOptions( fetchOptions, 'accept', 'text/html' );
|
|
1168
|
+
const response = await session.fetch( url, fetchOptions );
|
|
1169
|
+
await checkResponseStatus( response );
|
|
1170
|
+
return await getResponseHtml( response );
|
|
1171
|
+
}
|