@tryghost/admin-api 1.8.1 → 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,16 +3,39 @@ 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
+
9
31
  /**
10
32
  *
11
33
  * @param {Object} options
12
34
  * @param {String} options.url
13
35
  * @param {String} [options.ghostPath]
14
- * @param {String} [options.version]
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
15
37
  * @param {Function} [options.makeRequest]
38
+ * @param {Function} [options.generateToken]
16
39
  * @param {String} [options.host] Deprecated
17
40
  */
18
41
  module.exports = function GhostAdminAPI(options) {
@@ -22,6 +45,8 @@ module.exports = function GhostAdminAPI(options) {
22
45
 
23
46
  const defaultConfig = {
24
47
  ghostPath: 'ghost',
48
+ generateToken: token,
49
+ sendAcceptVersionHeader: true,
25
50
  makeRequest({url, method, data, params = {}, headers = {}}) {
26
51
  return axios({
27
52
  url,
@@ -58,9 +83,36 @@ module.exports = function GhostAdminAPI(options) {
58
83
  }
59
84
  }
60
85
 
61
- if (config.version && !supportedVersions.includes(config.version)) {
86
+ if (config.version === undefined) {
87
+ throw new Error(`${packageName} Config Missing: 'version' is required. E.g. ${supportedVersions.join(',')}`);
88
+ }
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+/))) {
62
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
+ }
63
114
  }
115
+
64
116
  if (!config.url) {
65
117
  throw new Error(`${packageName} Config Missing: 'url' is required. E.g. 'https://site.com'`);
66
118
  }
@@ -80,19 +132,12 @@ module.exports = function GhostAdminAPI(options) {
80
132
  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`);
81
133
  }
82
134
 
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
-
88
135
  const resources = [
89
- // @NOTE: stable
90
136
  'posts',
91
137
  'pages',
92
138
  'tags',
93
139
  'webhooks',
94
140
  'members',
95
- // @NOTE: experimental
96
141
  'users'
97
142
  ];
98
143
 
@@ -348,9 +393,8 @@ module.exports = function GhostAdminAPI(options) {
348
393
  function endpointFor(resource, {id, slug, email} = {}) {
349
394
  const {ghostPath, version} = config;
350
395
 
351
- let endpoint = version
352
- ? `/${ghostPath}/api/${version}/admin/${resource}/`
353
- : `/${ghostPath}/api/admin/${resource}/`;
396
+ const apiPrefix = resolveAPIPrefix(version);
397
+ let endpoint = `/${ghostPath}/api${apiPrefix}${resource}/`;
354
398
 
355
399
  if (id) {
356
400
  endpoint = `${endpoint}${id}/`;
@@ -367,12 +411,16 @@ module.exports = function GhostAdminAPI(options) {
367
411
  const {url: apiUrl, key, version, makeRequest} = config;
368
412
  const url = `${apiUrl}${endpoint}`;
369
413
 
414
+ let authorizationHeader;
415
+ const audience = resolveAPIPrefix(version);
416
+ authorizationHeader = `Ghost ${config.generateToken(key, audience)}`;
417
+
370
418
  const ghostHeaders = {
371
- Authorization: `Ghost ${token(key, version)}`
419
+ Authorization: authorizationHeader
372
420
  };
373
421
 
374
- if (!version || ['v4', 'canary'].includes(version)) {
375
- ghostHeaders['Accept-Version'] = version || 'v5';
422
+ if (config.acceptVersionHeader) {
423
+ ghostHeaders['Accept-Version'] = config.acceptVersionHeader;
376
424
  }
377
425
 
378
426
  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.1",
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": "dbf4ab41a6964422987a68c4327336692a54527f"
34
+ "gitHead": "b4c9597d781809903118a07e5fba16a106ec6053"
35
35
  }