@tryghost/admin-api 1.8.0 → 1.9.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,41 @@ const FormData = require('form-data');
3
3
  const fs = require('fs');
4
4
  const token = require('./token');
5
5
 
6
+ // NOTE: bump this default when Ghost v5 is released
7
+ const defaultAcceptVersionHeader = 'v4.0';
6
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 value identifying presence of 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,7 @@ module.exports = function GhostAdminAPI(options) {
13
45
 
14
46
  const defaultConfig = {
15
47
  ghostPath: 'ghost',
48
+ generateToken: token,
16
49
  makeRequest({url, method, data, params = {}, headers = {}}) {
17
50
  return axios({
18
51
  url,
@@ -35,7 +68,12 @@ module.exports = function GhostAdminAPI(options) {
35
68
 
36
69
  const config = Object.assign({}, defaultConfig, options);
37
70
 
38
- // new GhostAdminAPI({host: '...'}) is deprecated
71
+ //
72
+ /**
73
+ * host parameter is deprecated
74
+ * @deprecated use "url" instead
75
+ * @example new GhostAdminAPI({host: '...'})
76
+ */
39
77
  if (config.host) {
40
78
  // eslint-disable-next-line
41
79
  console.warn(`${packageName}: The 'host' parameter is deprecated, please use 'url' instead`);
@@ -44,9 +82,34 @@ module.exports = function GhostAdminAPI(options) {
44
82
  }
45
83
  }
46
84
 
47
- if (config.version && !supportedVersions.includes(config.version)) {
85
+ if (config.version === undefined) {
86
+ throw new Error(`${packageName} Config Missing: 'version' is required. E.g. ${supportedVersions.join(',')}`);
87
+ }
88
+
89
+ if (typeof config.version === 'boolean') {
90
+ if (config.version === true) {
91
+ config.acceptVersionHeader = defaultAcceptVersionHeader;
92
+ }
93
+ config.version = undefined;
94
+ } else if (!supportedVersions.includes(config.version) && !(config.version.match(/^v\d+\.\d+/))) {
48
95
  throw new Error(`${packageName} Config Invalid: 'version' ${config.version} is not supported`);
96
+ } else if (supportedVersions.includes(config.version) || config.version.match(/^v\d+\.\d+/)) {
97
+ if (config.version === 'canary') {
98
+ // eslint-disable-next-line
99
+ console.warn(`${packageName}: The 'version' parameter has a deprecated format 'canary', please use 'v{major}.{minor}' format instead`);
100
+
101
+ config.acceptVersionHeader = defaultAcceptVersionHeader;
102
+ } else if (config.version.match(/^v\d+$/)) {
103
+ // eslint-disable-next-line
104
+ console.warn(`${packageName}: The 'version' parameter has a deprecated format 'v{major}', please use 'v{major}.{minor}' format instead`);
105
+
106
+ // CASE: all the v1, v2, v4 ... strings should be normalized to fit 'v{major}.{minor}' format
107
+ config.acceptVersionHeader = `${config.version}.0`;
108
+ } else {
109
+ config.acceptVersionHeader = config.version;
110
+ }
49
111
  }
112
+
50
113
  if (!config.url) {
51
114
  throw new Error(`${packageName} Config Missing: 'url' is required. E.g. 'https://site.com'`);
52
115
  }
@@ -66,19 +129,12 @@ module.exports = function GhostAdminAPI(options) {
66
129
  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`);
67
130
  }
68
131
 
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
-
74
132
  const resources = [
75
- // @NOTE: stable
76
133
  'posts',
77
134
  'pages',
78
135
  'tags',
79
136
  'webhooks',
80
137
  'members',
81
- // @NOTE: experimental
82
138
  'users'
83
139
  ];
84
140
 
@@ -334,9 +390,8 @@ module.exports = function GhostAdminAPI(options) {
334
390
  function endpointFor(resource, {id, slug, email} = {}) {
335
391
  const {ghostPath, version} = config;
336
392
 
337
- let endpoint = version
338
- ? `/${ghostPath}/api/${version}/admin/${resource}/`
339
- : `/${ghostPath}/api/admin/${resource}/`;
393
+ const apiPrefix = resolveAPIPrefix(version);
394
+ let endpoint = `/${ghostPath}/api${apiPrefix}${resource}/`;
340
395
 
341
396
  if (id) {
342
397
  endpoint = `${endpoint}${id}/`;
@@ -353,12 +408,16 @@ module.exports = function GhostAdminAPI(options) {
353
408
  const {url: apiUrl, key, version, makeRequest} = config;
354
409
  const url = `${apiUrl}${endpoint}`;
355
410
 
411
+ let authorizationHeader;
412
+ const audience = resolveAPIPrefix(version);
413
+ authorizationHeader = `Ghost ${config.generateToken(key, audience)}`;
414
+
356
415
  const ghostHeaders = {
357
- Authorization: `Ghost ${token(key, version)}`
416
+ Authorization: authorizationHeader
358
417
  };
359
418
 
360
- if (!version || ['v4', 'canary'].includes(version)) {
361
- ghostHeaders['Accept-Version'] = version || 'v5';
419
+ if (config.acceptVersionHeader) {
420
+ ghostHeaders['Accept-Version'] = config.acceptVersionHeader;
362
421
  }
363
422
 
364
423
  headers = Object.assign({}, headers, ghostHeaders);
package/lib/token.js CHANGED
@@ -3,12 +3,11 @@ const jwt = require('jsonwebtoken');
3
3
  /**
4
4
  *
5
5
  * @param {String} key - API key to sign JWT with
6
- * @param {String} version - API version to use as a part of audience
6
+ * @param {String} audience - token audience
7
7
  * @returns
8
8
  */
9
- module.exports = function token(key, version) {
9
+ module.exports = function token(key, audience) {
10
10
  const [id, secret] = key.split(':');
11
- const audience = version ? `/${version}/admin/` : '/admin/';
12
11
 
13
12
  return jwt.sign({}, Buffer.from(secret, 'hex'), { // eslint-disable-line no-undef
14
13
  keyid: id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/admin-api",
3
- "version": "1.8.0",
3
+ "version": "1.9.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": "36ffe70168eb2ad3eaefa0dc63a35697b284c9e7"
34
+ "gitHead": "3633e6e946c394c73e53b496477543e98e301aa4"
35
35
  }