@tryghost/admin-api 1.6.0 → 1.8.1

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 CHANGED
@@ -3,9 +3,18 @@ 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
+ /**
10
+ *
11
+ * @param {Object} options
12
+ * @param {String} options.url
13
+ * @param {String} [options.ghostPath]
14
+ * @param {String} [options.version]
15
+ * @param {Function} [options.makeRequest]
16
+ * @param {String} [options.host] Deprecated
17
+ */
9
18
  module.exports = function GhostAdminAPI(options) {
10
19
  if (this instanceof GhostAdminAPI) {
11
20
  return GhostAdminAPI(options);
@@ -35,7 +44,12 @@ module.exports = function GhostAdminAPI(options) {
35
44
 
36
45
  const config = Object.assign({}, defaultConfig, options);
37
46
 
38
- // new GhostAdminAPI({host: '...'}) is deprecated
47
+ //
48
+ /**
49
+ * host parameter is deprecated
50
+ * @deprecated use "url" instead
51
+ * @example new GhostAdminAPI({host: '...'})
52
+ */
39
53
  if (config.host) {
40
54
  // eslint-disable-next-line
41
55
  console.warn(`${packageName}: The 'host' parameter is deprecated, please use 'url' instead`);
@@ -44,10 +58,7 @@ module.exports = function GhostAdminAPI(options) {
44
58
  }
45
59
  }
46
60
 
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)) {
61
+ if (config.version && !supportedVersions.includes(config.version)) {
51
62
  throw new Error(`${packageName} Config Invalid: 'version' ${config.version} is not supported`);
52
63
  }
53
64
  if (!config.url) {
@@ -69,6 +80,11 @@ module.exports = function GhostAdminAPI(options) {
69
80
  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
81
  }
71
82
 
83
+ if (config.version === 'v5') {
84
+ // NOTE: the version parameter is supported but not necessary for non-versioned API, starting with Ghost v5
85
+ delete config.version;
86
+ }
87
+
72
88
  const resources = [
73
89
  // @NOTE: stable
74
90
  'posts',
@@ -202,29 +218,52 @@ module.exports = function GhostAdminAPI(options) {
202
218
  if (data.file) {
203
219
  formData = new FormData();
204
220
  formData.append('file', fs.createReadStream(data.file));
221
+ // NOTE: this default "image" doesn't work for all upload endpoints. Should be moved from here and required as
222
+ // an explicit method parameter. Leaving it here for now as I'm focusing on a different problem.
205
223
  formData.append('purpose', data.purpose || 'image');
206
224
 
207
225
  if (data.ref) {
208
226
  formData.append('ref', data.ref);
209
227
  }
210
228
 
229
+ if (data.thumbnail) {
230
+ formData.append('thumbnail', fs.createReadStream(data.thumbnail));
231
+ }
232
+
211
233
  return formData;
212
234
  }
213
235
  }
214
236
 
215
237
  api.images = {
216
238
  upload(data) {
217
- if (!data) {
218
- return Promise.reject(new Error('Missing data'));
219
- }
220
-
221
- if (!isValidUpload(data)) {
222
- return Promise.reject(new Error('Must be of FormData or include path'));
223
- }
239
+ return makeUploadRequest('images', data, endpointFor('images/upload'));
240
+ }
241
+ };
224
242
 
225
- let formData = getFormData(data);
243
+ api.media = {
244
+ /**
245
+ *
246
+ * @param {Object} data
247
+ * @param {String} data.file - file path to a media file
248
+ * @param {String} [data.thumbnail] - file path to a thumbnail file
249
+ * @param {String} [data.purpose]
250
+ * @returns Promise<Object>
251
+ */
252
+ upload(data) {
253
+ return makeUploadRequest('media', data, endpointFor('media/upload'));
254
+ }
255
+ };
226
256
 
227
- return makeUploadRequest('images', formData, endpointFor('images/upload'));
257
+ api.files = {
258
+ /**
259
+ *
260
+ * @param {Object} data
261
+ * @param {String} data.file - file path to a media file
262
+ * @param {String} [data.ref] - reference field returned in the response
263
+ * @returns Promise<Object>
264
+ */
265
+ upload(data) {
266
+ return makeUploadRequest('files', data, endpointFor('files/upload'));
228
267
  }
229
268
  };
230
269
 
@@ -242,17 +281,7 @@ module.exports = function GhostAdminAPI(options) {
242
281
 
243
282
  api.themes = {
244
283
  upload(data) {
245
- if (!data) {
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'));
284
+ return makeUploadRequest('themes', data, endpointFor('themes/upload'));
256
285
  },
257
286
  activate(name) {
258
287
  if (!name) {
@@ -266,14 +295,24 @@ module.exports = function GhostAdminAPI(options) {
266
295
  return api;
267
296
 
268
297
  function makeUploadRequest(resourceType, data, endpoint) {
298
+ if (!data) {
299
+ return Promise.reject(new Error('Missing data'));
300
+ }
301
+
302
+ if (!isValidUpload(data)) {
303
+ return Promise.reject(new Error('Must be of FormData or include path'));
304
+ }
305
+
306
+ let formData = getFormData(data);
307
+
269
308
  const headers = {
270
- 'Content-Type': `multipart/form-data; boundary=${data._boundary}`
309
+ 'Content-Type': `multipart/form-data; boundary=${formData._boundary}`
271
310
  };
272
311
 
273
312
  return makeApiRequest({
274
313
  endpoint: endpoint,
275
314
  method: 'POST',
276
- body: data,
315
+ body: formData,
277
316
  headers
278
317
  }).then((apiData) => {
279
318
  if (!Array.isArray(apiData[resourceType])) {
@@ -308,7 +347,10 @@ module.exports = function GhostAdminAPI(options) {
308
347
 
309
348
  function endpointFor(resource, {id, slug, email} = {}) {
310
349
  const {ghostPath, version} = config;
311
- let endpoint = `/${ghostPath}/api/${version}/admin/${resource}/`;
350
+
351
+ let endpoint = version
352
+ ? `/${ghostPath}/api/${version}/admin/${resource}/`
353
+ : `/${ghostPath}/api/admin/${resource}/`;
312
354
 
313
355
  if (id) {
314
356
  endpoint = `${endpoint}${id}/`;
@@ -325,9 +367,15 @@ module.exports = function GhostAdminAPI(options) {
325
367
  const {url: apiUrl, key, version, makeRequest} = config;
326
368
  const url = `${apiUrl}${endpoint}`;
327
369
 
328
- headers = Object.assign({}, headers, {
329
- Authorization: `Ghost ${token(version, key)}`
330
- });
370
+ const ghostHeaders = {
371
+ Authorization: `Ghost ${token(key, version)}`
372
+ };
373
+
374
+ if (!version || ['v4', 'canary'].includes(version)) {
375
+ ghostHeaders['Accept-Version'] = version || 'v5';
376
+ }
377
+
378
+ headers = Object.assign({}, headers, ghostHeaders);
331
379
 
332
380
  return makeRequest({
333
381
  url,
@@ -339,7 +387,7 @@ module.exports = function GhostAdminAPI(options) {
339
387
  /**
340
388
  * @NOTE:
341
389
  *
342
- * If you are overriding `makeRequest`, we can't garantee that the returned format is the same, but
390
+ * If you are overriding `makeRequest`, we can't garante that the returned format is the same, but
343
391
  * we try to detect & return a proper error instance.
344
392
  */
345
393
  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
- module.exports = function token(version, key) {
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: `/${version}/admin/`
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.6.0",
3
+ "version": "1.8.1",
4
4
  "repository": "https://github.com/TryGhost/SDK/tree/master/packages/admin-api",
5
5
  "author": "Ghost Foundation",
6
6
  "license": "MIT",
@@ -31,5 +31,5 @@
31
31
  "form-data": "^4.0.0",
32
32
  "jsonwebtoken": "^8.4.0"
33
33
  },
34
- "gitHead": "f8813610f5ba4eed4fbcbd025eddf78795fd8aab"
34
+ "gitHead": "dbf4ab41a6964422987a68c4327336692a54527f"
35
35
  }