@tryghost/admin-api 1.5.0 → 1.8.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/lib/index.js +66 -32
- package/lib/token.js +9 -2
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ const FormData = require('form-data');
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const token = require('./token');
|
|
5
5
|
|
|
6
|
-
const supportedVersions = ['v2', 'v3', 'v4', 'canary'];
|
|
6
|
+
const supportedVersions = ['v2', 'v3', 'v4', 'v5', 'canary'];
|
|
7
7
|
const packageName = '@tryghost/admin-api';
|
|
8
8
|
|
|
9
9
|
module.exports = function GhostAdminAPI(options) {
|
|
@@ -44,10 +44,7 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
if (!config.version) {
|
|
48
|
-
throw new Error(`${packageName} Config Missing: 'version' is required. E.g. ${supportedVersions.join(',')}`);
|
|
49
|
-
}
|
|
50
|
-
if (!supportedVersions.includes(config.version)) {
|
|
47
|
+
if (config.version && !supportedVersions.includes(config.version)) {
|
|
51
48
|
throw new Error(`${packageName} Config Invalid: 'version' ${config.version} is not supported`);
|
|
52
49
|
}
|
|
53
50
|
if (!config.url) {
|
|
@@ -69,6 +66,11 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
69
66
|
throw new Error(`${packageName} Config Invalid: 'key' ${config.key} must have the following format {A}:{B}, where A is 24 hex characters and B is 64 hex characters`);
|
|
70
67
|
}
|
|
71
68
|
|
|
69
|
+
if (config.version === 'v5') {
|
|
70
|
+
// NOTE: the version parameter is supported but not necessary for non-versioned API, starting with Ghost v5
|
|
71
|
+
delete config.version;
|
|
72
|
+
}
|
|
73
|
+
|
|
72
74
|
const resources = [
|
|
73
75
|
// @NOTE: stable
|
|
74
76
|
'posts',
|
|
@@ -202,29 +204,52 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
202
204
|
if (data.file) {
|
|
203
205
|
formData = new FormData();
|
|
204
206
|
formData.append('file', fs.createReadStream(data.file));
|
|
207
|
+
// NOTE: this default "image" doesn't work for all upload endpoints. Should be moved from here and required as
|
|
208
|
+
// an explicit method parameter. Leaving it here for now as I'm focusing on a different problem.
|
|
205
209
|
formData.append('purpose', data.purpose || 'image');
|
|
206
210
|
|
|
207
211
|
if (data.ref) {
|
|
208
212
|
formData.append('ref', data.ref);
|
|
209
213
|
}
|
|
210
214
|
|
|
215
|
+
if (data.thumbnail) {
|
|
216
|
+
formData.append('thumbnail', fs.createReadStream(data.thumbnail));
|
|
217
|
+
}
|
|
218
|
+
|
|
211
219
|
return formData;
|
|
212
220
|
}
|
|
213
221
|
}
|
|
214
222
|
|
|
215
223
|
api.images = {
|
|
216
224
|
upload(data) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (!isValidUpload(data)) {
|
|
222
|
-
return Promise.reject(new Error('Must be of FormData or include path'));
|
|
223
|
-
}
|
|
225
|
+
return makeUploadRequest('images', data, endpointFor('images/upload'));
|
|
226
|
+
}
|
|
227
|
+
};
|
|
224
228
|
|
|
225
|
-
|
|
229
|
+
api.media = {
|
|
230
|
+
/**
|
|
231
|
+
*
|
|
232
|
+
* @param {Object} data
|
|
233
|
+
* @param {String} data.file - file path to a media file
|
|
234
|
+
* @param {String} [data.thumbnail] - file path to a thumbnail file
|
|
235
|
+
* @param {String} [data.purpose]
|
|
236
|
+
* @returns Promise<Object>
|
|
237
|
+
*/
|
|
238
|
+
upload(data) {
|
|
239
|
+
return makeUploadRequest('media', data, endpointFor('media/upload'));
|
|
240
|
+
}
|
|
241
|
+
};
|
|
226
242
|
|
|
227
|
-
|
|
243
|
+
api.files = {
|
|
244
|
+
/**
|
|
245
|
+
*
|
|
246
|
+
* @param {Object} data
|
|
247
|
+
* @param {String} data.file - file path to a media file
|
|
248
|
+
* @param {String} [data.ref] - reference field returned in the response
|
|
249
|
+
* @returns Promise<Object>
|
|
250
|
+
*/
|
|
251
|
+
upload(data) {
|
|
252
|
+
return makeUploadRequest('files', data, endpointFor('files/upload'));
|
|
228
253
|
}
|
|
229
254
|
};
|
|
230
255
|
|
|
@@ -242,17 +267,7 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
242
267
|
|
|
243
268
|
api.themes = {
|
|
244
269
|
upload(data) {
|
|
245
|
-
|
|
246
|
-
return Promise.reject(new Error('Missing data'));
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (!isValidUpload(data)) {
|
|
250
|
-
return Promise.reject(new Error('Must be of FormData or include path'));
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
let formData = getFormData(data);
|
|
254
|
-
|
|
255
|
-
return makeUploadRequest('themes', formData, endpointFor('themes/upload'));
|
|
270
|
+
return makeUploadRequest('themes', data, endpointFor('themes/upload'));
|
|
256
271
|
},
|
|
257
272
|
activate(name) {
|
|
258
273
|
if (!name) {
|
|
@@ -266,14 +281,24 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
266
281
|
return api;
|
|
267
282
|
|
|
268
283
|
function makeUploadRequest(resourceType, data, endpoint) {
|
|
284
|
+
if (!data) {
|
|
285
|
+
return Promise.reject(new Error('Missing data'));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!isValidUpload(data)) {
|
|
289
|
+
return Promise.reject(new Error('Must be of FormData or include path'));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
let formData = getFormData(data);
|
|
293
|
+
|
|
269
294
|
const headers = {
|
|
270
|
-
'Content-Type': `multipart/form-data; boundary=${
|
|
295
|
+
'Content-Type': `multipart/form-data; boundary=${formData._boundary}`
|
|
271
296
|
};
|
|
272
297
|
|
|
273
298
|
return makeApiRequest({
|
|
274
299
|
endpoint: endpoint,
|
|
275
300
|
method: 'POST',
|
|
276
|
-
body:
|
|
301
|
+
body: formData,
|
|
277
302
|
headers
|
|
278
303
|
}).then((apiData) => {
|
|
279
304
|
if (!Array.isArray(apiData[resourceType])) {
|
|
@@ -308,7 +333,10 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
308
333
|
|
|
309
334
|
function endpointFor(resource, {id, slug, email} = {}) {
|
|
310
335
|
const {ghostPath, version} = config;
|
|
311
|
-
|
|
336
|
+
|
|
337
|
+
let endpoint = version
|
|
338
|
+
? `/${ghostPath}/api/${version}/admin/${resource}/`
|
|
339
|
+
: `/${ghostPath}/api/admin/${resource}/`;
|
|
312
340
|
|
|
313
341
|
if (id) {
|
|
314
342
|
endpoint = `${endpoint}${id}/`;
|
|
@@ -325,9 +353,15 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
325
353
|
const {url: apiUrl, key, version, makeRequest} = config;
|
|
326
354
|
const url = `${apiUrl}${endpoint}`;
|
|
327
355
|
|
|
328
|
-
|
|
329
|
-
Authorization: `Ghost ${token(
|
|
330
|
-
}
|
|
356
|
+
const ghostHeaders = {
|
|
357
|
+
Authorization: `Ghost ${token(key, version)}`
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
if (!version || ['v4', 'canary'].includes(version)) {
|
|
361
|
+
ghostHeaders['Accept-Version'] = version || 'v5';
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
headers = Object.assign({}, headers, ghostHeaders);
|
|
331
365
|
|
|
332
366
|
return makeRequest({
|
|
333
367
|
url,
|
|
@@ -339,7 +373,7 @@ module.exports = function GhostAdminAPI(options) {
|
|
|
339
373
|
/**
|
|
340
374
|
* @NOTE:
|
|
341
375
|
*
|
|
342
|
-
* If you are overriding `makeRequest`, we can't
|
|
376
|
+
* If you are overriding `makeRequest`, we can't garante that the returned format is the same, but
|
|
343
377
|
* we try to detect & return a proper error instance.
|
|
344
378
|
*/
|
|
345
379
|
if (err.response && err.response.data && err.response.data.errors) {
|
package/lib/token.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
const jwt = require('jsonwebtoken');
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {String} key - API key to sign JWT with
|
|
6
|
+
* @param {String} version - API version to use as a part of audience
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
module.exports = function token(key, version) {
|
|
4
10
|
const [id, secret] = key.split(':');
|
|
11
|
+
const audience = version ? `/${version}/admin/` : '/admin/';
|
|
5
12
|
|
|
6
13
|
return jwt.sign({}, Buffer.from(secret, 'hex'), { // eslint-disable-line no-undef
|
|
7
14
|
keyid: id,
|
|
8
15
|
algorithm: 'HS256',
|
|
9
16
|
expiresIn: '5m',
|
|
10
|
-
audience
|
|
17
|
+
audience
|
|
11
18
|
});
|
|
12
19
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tryghost/admin-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"repository": "https://github.com/TryGhost/SDK/tree/master/packages/admin-api",
|
|
5
5
|
"author": "Ghost Foundation",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
15
|
"dev": "echo \"Implement me!\"",
|
|
16
|
-
"test": "NODE_ENV=testing c8 --reporter text --reporter cobertura mocha './test/**/*.test.js'",
|
|
16
|
+
"test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'",
|
|
17
17
|
"lint": "eslint . --ext .js --cache",
|
|
18
18
|
"posttest": "yarn lint"
|
|
19
19
|
},
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"form-data": "^4.0.0",
|
|
32
32
|
"jsonwebtoken": "^8.4.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "36ffe70168eb2ad3eaefa0dc63a35697b284c9e7"
|
|
35
35
|
}
|