@tryghost/admin-api 1.7.0 → 1.9.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,9 +3,41 @@ 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
+ // NOTE: bump this default when Ghost v5 is released
7
+ const defaultAcceptVersionHeader = 'v4.0';
8
+ const supportedVersions = ['v2', 'v3', 'v4', 'v5', 'canary'];
7
9
  const packageName = '@tryghost/admin-api';
8
10
 
11
+ /**
12
+ * This method can go away in favor of only sending 'Accept-Version` headers
13
+ * once the Ghost API removes a concept of version from it's URLS (with Ghost v5)
14
+ *
15
+ * @param {string} [version] version in `v{major}` format
16
+ * @returns {string}
17
+ */
18
+ const resolveAPIPrefix = (version) => {
19
+ let prefix;
20
+
21
+ // NOTE: the "version.match(/^v5\.\d+/)" expression should be changed to "version.match(/^v\d+\.\d+/)" once Ghost v5 is out
22
+ if (version === 'v5' || version === undefined || version.match(/^v5\.\d+/)) {
23
+ prefix = `/admin/`;
24
+ } else {
25
+ prefix = `/${version}/admin/`;
26
+ }
27
+
28
+ return prefix;
29
+ };
30
+
31
+ /**
32
+ *
33
+ * @param {Object} options
34
+ * @param {String} options.url
35
+ * @param {String} [options.ghostPath]
36
+ * @param {String|Boolean} [options.version] - a version string like v3.2, v4.1, v5.8 or boolean 'false' value identifying no Accept-Version header
37
+ * @param {Function} [options.makeRequest]
38
+ * @param {Function} [options.generateToken]
39
+ * @param {String} [options.host] Deprecated
40
+ */
9
41
  module.exports = function GhostAdminAPI(options) {
10
42
  if (this instanceof GhostAdminAPI) {
11
43
  return GhostAdminAPI(options);
@@ -13,6 +45,8 @@ module.exports = function GhostAdminAPI(options) {
13
45
 
14
46
  const defaultConfig = {
15
47
  ghostPath: 'ghost',
48
+ generateToken: token,
49
+ sendAcceptVersionHeader: true,
16
50
  makeRequest({url, method, data, params = {}, headers = {}}) {
17
51
  return axios({
18
52
  url,
@@ -35,7 +69,12 @@ module.exports = function GhostAdminAPI(options) {
35
69
 
36
70
  const config = Object.assign({}, defaultConfig, options);
37
71
 
38
- // new GhostAdminAPI({host: '...'}) is deprecated
72
+ //
73
+ /**
74
+ * host parameter is deprecated
75
+ * @deprecated use "url" instead
76
+ * @example new GhostAdminAPI({host: '...'})
77
+ */
39
78
  if (config.host) {
40
79
  // eslint-disable-next-line
41
80
  console.warn(`${packageName}: The 'host' parameter is deprecated, please use 'url' instead`);
@@ -44,12 +83,36 @@ module.exports = function GhostAdminAPI(options) {
44
83
  }
45
84
  }
46
85
 
47
- if (!config.version) {
86
+ if (config.version === undefined) {
48
87
  throw new Error(`${packageName} Config Missing: 'version' is required. E.g. ${supportedVersions.join(',')}`);
49
88
  }
50
- if (!supportedVersions.includes(config.version)) {
89
+
90
+ if (typeof config.version === 'boolean') {
91
+ config.sendAcceptVersionHeader = config.version;
92
+
93
+ if (config.version === true) {
94
+ config.acceptVersionHeader = defaultAcceptVersionHeader;
95
+ }
96
+ config.version = undefined;
97
+ } else if (!supportedVersions.includes(config.version) && !(config.version.match(/^v\d+\.\d+/))) {
51
98
  throw new Error(`${packageName} Config Invalid: 'version' ${config.version} is not supported`);
99
+ } else if (supportedVersions.includes(config.version) || config.version.match(/^v\d+\.\d+/)) {
100
+ if (config.version === 'canary') {
101
+ // eslint-disable-next-line
102
+ console.warn(`${packageName}: The 'version' parameter has a deprecated format 'canary', please use 'v{major}.{minor}' format instead`);
103
+
104
+ config.acceptVersionHeader = defaultAcceptVersionHeader;
105
+ } else if (config.version.match(/^v\d+$/)) {
106
+ // eslint-disable-next-line
107
+ console.warn(`${packageName}: The 'version' parameter has a deprecated format 'v{major}', please use 'v{major}.{minor}' format instead`);
108
+
109
+ // CASE: all the v1, v2, v4 ... strings should be normalized to fit 'v{major}.{minor}' format
110
+ config.acceptVersionHeader = `${config.version}.0`;
111
+ } else {
112
+ config.acceptVersionHeader = config.version;
113
+ }
52
114
  }
115
+
53
116
  if (!config.url) {
54
117
  throw new Error(`${packageName} Config Missing: 'url' is required. E.g. 'https://site.com'`);
55
118
  }
@@ -70,13 +133,11 @@ module.exports = function GhostAdminAPI(options) {
70
133
  }
71
134
 
72
135
  const resources = [
73
- // @NOTE: stable
74
136
  'posts',
75
137
  'pages',
76
138
  'tags',
77
139
  'webhooks',
78
140
  'members',
79
- // @NOTE: experimental
80
141
  'users'
81
142
  ];
82
143
 
@@ -331,7 +392,9 @@ module.exports = function GhostAdminAPI(options) {
331
392
 
332
393
  function endpointFor(resource, {id, slug, email} = {}) {
333
394
  const {ghostPath, version} = config;
334
- let endpoint = `/${ghostPath}/api/${version}/admin/${resource}/`;
395
+
396
+ const apiPrefix = resolveAPIPrefix(version);
397
+ let endpoint = `/${ghostPath}/api${apiPrefix}${resource}/`;
335
398
 
336
399
  if (id) {
337
400
  endpoint = `${endpoint}${id}/`;
@@ -348,9 +411,19 @@ module.exports = function GhostAdminAPI(options) {
348
411
  const {url: apiUrl, key, version, makeRequest} = config;
349
412
  const url = `${apiUrl}${endpoint}`;
350
413
 
351
- headers = Object.assign({}, headers, {
352
- Authorization: `Ghost ${token(version, key)}`
353
- });
414
+ let authorizationHeader;
415
+ const audience = resolveAPIPrefix(version);
416
+ authorizationHeader = `Ghost ${config.generateToken(key, audience)}`;
417
+
418
+ const ghostHeaders = {
419
+ Authorization: authorizationHeader
420
+ };
421
+
422
+ if (config.acceptVersionHeader) {
423
+ ghostHeaders['Accept-Version'] = config.acceptVersionHeader;
424
+ }
425
+
426
+ headers = Object.assign({}, headers, ghostHeaders);
354
427
 
355
428
  return makeRequest({
356
429
  url,
@@ -362,7 +435,7 @@ module.exports = function GhostAdminAPI(options) {
362
435
  /**
363
436
  * @NOTE:
364
437
  *
365
- * If you are overriding `makeRequest`, we can't garantee that the returned format is the same, but
438
+ * If you are overriding `makeRequest`, we can't garante that the returned format is the same, but
366
439
  * we try to detect & return a proper error instance.
367
440
  */
368
441
  if (err.response && err.response.data && err.response.data.errors) {
package/lib/token.js CHANGED
@@ -1,12 +1,18 @@
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} audience - token audience
7
+ * @returns
8
+ */
9
+ module.exports = function token(key, audience) {
4
10
  const [id, secret] = key.split(':');
5
11
 
6
12
  return jwt.sign({}, Buffer.from(secret, 'hex'), { // eslint-disable-line no-undef
7
13
  keyid: id,
8
14
  algorithm: 'HS256',
9
15
  expiresIn: '5m',
10
- audience: `/${version}/admin/`
16
+ audience
11
17
  });
12
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/admin-api",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
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": "bb3a33a1ff85c0d3efb2972e8d6dd72df458c271"
34
+ "gitHead": "b4c9597d781809903118a07e5fba16a106ec6053"
35
35
  }