@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 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
- 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
- }
225
+ return makeUploadRequest('images', data, endpointFor('images/upload'));
226
+ }
227
+ };
224
228
 
225
- let formData = getFormData(data);
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
- return makeUploadRequest('images', formData, endpointFor('images/upload'));
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
- 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'));
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=${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: data,
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
- let endpoint = `/${ghostPath}/api/${version}/admin/${resource}/`;
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
- headers = Object.assign({}, headers, {
329
- Authorization: `Ghost ${token(version, key)}`
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 garantee that the returned format is the same, but
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
- 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.5.0",
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": "d82e1de0669479d003f17dab743c173290de524f"
34
+ "gitHead": "36ffe70168eb2ad3eaefa0dc63a35697b284c9e7"
35
35
  }