ghost 5.8.3 → 5.9.2

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.
Files changed (113) hide show
  1. package/components/tryghost-adapter-manager-0.0.0.tgz +0 -0
  2. package/components/tryghost-api-framework-0.0.0.tgz +0 -0
  3. package/components/tryghost-bootstrap-socket-0.0.0.tgz +0 -0
  4. package/components/tryghost-custom-theme-settings-service-0.0.0.tgz +0 -0
  5. package/components/tryghost-email-analytics-provider-mailgun-0.0.0.tgz +0 -0
  6. package/components/tryghost-email-analytics-service-0.0.0.tgz +0 -0
  7. package/components/tryghost-job-manager-0.0.0.tgz +0 -0
  8. package/components/tryghost-mailgun-client-0.0.0.tgz +0 -0
  9. package/components/tryghost-member-analytics-service-0.0.0.tgz +0 -0
  10. package/components/tryghost-members-api-0.0.0.tgz +0 -0
  11. package/components/tryghost-members-importer-0.0.0.tgz +0 -0
  12. package/components/tryghost-members-offers-0.0.0.tgz +0 -0
  13. package/components/tryghost-members-payments-0.0.0.tgz +0 -0
  14. package/components/tryghost-members-ssr-0.0.0.tgz +0 -0
  15. package/components/tryghost-members-stripe-service-0.0.0.tgz +0 -0
  16. package/components/tryghost-minifier-0.0.0.tgz +0 -0
  17. package/components/tryghost-mw-cache-control-0.0.0.tgz +0 -0
  18. package/components/tryghost-mw-error-handler-0.0.0.tgz +0 -0
  19. package/components/tryghost-oembed-service-0.0.0.tgz +0 -0
  20. package/components/tryghost-package-json-0.0.0.tgz +0 -0
  21. package/components/tryghost-session-service-0.0.0.tgz +0 -0
  22. package/components/tryghost-settings-path-manager-0.0.0.tgz +0 -0
  23. package/components/tryghost-update-check-service-0.0.0.tgz +0 -0
  24. package/content/themes/casper/README.md +1 -1
  25. package/content/themes/casper/assets/built/portal.min.js +3 -0
  26. package/content/themes/casper/assets/built/screen.css +1 -1
  27. package/content/themes/casper/assets/built/screen.css.map +1 -1
  28. package/content/themes/casper/assets/css/screen.css +119 -37
  29. package/content/themes/casper/package.json +3 -3
  30. package/content/themes/casper/partials/post-card.hbs +3 -1
  31. package/content/themes/casper/post.hbs +7 -7
  32. package/content/themes/casper/yarn.lock +69 -68
  33. package/core/boot.js +2 -0
  34. package/core/built/admin/assets/{chunk.143.cf66fd97f99af03c697f.js → chunk.143.4e4590d80452422483d8.js} +5 -5
  35. package/core/built/admin/assets/{chunk.178.e95388dfcc564cdb1ecc.js → chunk.178.16d88956c09eb76205e0.js} +4 -4
  36. package/core/built/admin/assets/{chunk.351.cbc224ca65c14ef5322d.js → chunk.351.73f27952f867334a8228.js} +3 -3
  37. package/core/built/admin/assets/{chunk.351.cbc224ca65c14ef5322d.js.LICENSE.txt → chunk.351.73f27952f867334a8228.js.LICENSE.txt} +0 -0
  38. package/core/built/admin/assets/{ghost-b469423d0fbe5e40af17b560f7e3cead.css → ghost-0319628ec5dcb83e6968e99eaa629a75.css} +1 -1
  39. package/core/built/admin/assets/{ghost-dark-bcb6f4517a2dfe23a0a280632bfca00c.css → ghost-dark-eada0a988277e84b4c8ead995f912044.css} +1 -1
  40. package/core/built/admin/assets/{ghost-f1d63ad9698b7d38261df6384513c952.js → ghost-f144e03b578116a5d0ed41bceaf2bab8.js} +90 -88
  41. package/core/built/admin/index.html +5 -5
  42. package/core/frontend/helpers/comment_count.js +1 -15
  43. package/core/frontend/helpers/comments.js +4 -16
  44. package/core/frontend/helpers/ghost_head.js +1 -1
  45. package/core/frontend/services/routing/controllers/unsubscribe.js +3 -0
  46. package/core/server/api/endpoints/comments-members.js +23 -1
  47. package/core/server/api/endpoints/index.js +52 -52
  48. package/core/server/api/endpoints/oembed.js +1 -1
  49. package/core/server/api/endpoints/utils/serializers/input/comments.js +18 -0
  50. package/core/server/api/endpoints/utils/serializers/input/db.js +1 -1
  51. package/core/server/api/endpoints/utils/serializers/input/index.js +4 -0
  52. package/core/server/api/endpoints/utils/serializers/input/integrations.js +2 -2
  53. package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-filter-type-group-mapper.js +0 -0
  54. package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-key-group-mapper.js +0 -0
  55. package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-key-type-mapper.js +0 -0
  56. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +12 -12
  57. package/core/server/api/endpoints/utils/serializers/output/tiers.js +1 -1
  58. package/core/server/api/index.js +0 -2
  59. package/core/server/data/importer/importers/data/settings.js +2 -2
  60. package/core/server/data/migrations/versions/5.9/2022-08-09-08-32-added-new-integration-type.js +24 -0
  61. package/core/server/data/schema/clients/mysql.js +0 -15
  62. package/core/server/data/schema/commands.js +0 -9
  63. package/core/server/data/schema/fixtures/fixtures.json +1 -1
  64. package/core/server/data/schema/schema.js +3 -3
  65. package/core/server/models/base/plugins/user-type.js +1 -9
  66. package/core/server/models/comment.js +96 -15
  67. package/core/server/models/label.js +14 -0
  68. package/core/server/models/newsletter.js +21 -0
  69. package/core/server/models/tag.js +20 -0
  70. package/core/server/models/user.js +20 -0
  71. package/core/server/services/auth/api-key/admin.js +1 -5
  72. package/core/server/services/auth/api-key/content.js +1 -5
  73. package/core/server/services/bulk-email/bulk-email-processor.js +19 -12
  74. package/core/server/services/bulk-email/index.js +1 -17
  75. package/core/server/services/comments/controller.js +9 -0
  76. package/core/server/services/comments/email-templates/new-comment-reply.hbs +3 -3
  77. package/core/server/services/comments/email-templates/new-comment-reply.txt.js +1 -1
  78. package/core/server/services/comments/email-templates/new-comment.hbs +2 -2
  79. package/core/server/services/comments/email-templates/report.hbs +2 -2
  80. package/core/server/services/comments/emails.js +2 -1
  81. package/core/server/services/comments/service.js +16 -3
  82. package/core/server/services/mega/post-email-serializer.js +11 -6
  83. package/core/server/services/permissions/can-this.js +154 -161
  84. package/core/server/services/permissions/parse-context.js +1 -8
  85. package/core/server/services/webhooks/serialize.js +3 -3
  86. package/core/server/web/api/endpoints/admin/routes.js +1 -1
  87. package/core/server/web/api/endpoints/content/routes.js +1 -1
  88. package/core/server/web/comments/routes.js +2 -1
  89. package/core/server/web/shared/middleware/index.js +1 -1
  90. package/core/shared/config/defaults.json +2 -2
  91. package/core/shared/labs.js +0 -1
  92. package/package.json +34 -37
  93. package/yarn.lock +272 -245
  94. package/core/server/api/README.md +0 -130
  95. package/core/server/api/shared/frame.js +0 -95
  96. package/core/server/api/shared/headers.js +0 -152
  97. package/core/server/api/shared/http.js +0 -127
  98. package/core/server/api/shared/index.js +0 -25
  99. package/core/server/api/shared/pipeline.js +0 -259
  100. package/core/server/api/shared/serializers/handle.js +0 -140
  101. package/core/server/api/shared/serializers/index.js +0 -13
  102. package/core/server/api/shared/serializers/input/all.js +0 -41
  103. package/core/server/api/shared/serializers/input/index.js +0 -5
  104. package/core/server/api/shared/serializers/output/index.js +0 -1
  105. package/core/server/api/shared/utils/index.js +0 -5
  106. package/core/server/api/shared/utils/options.js +0 -23
  107. package/core/server/api/shared/validators/handle.js +0 -68
  108. package/core/server/api/shared/validators/index.js +0 -9
  109. package/core/server/api/shared/validators/input/all.js +0 -213
  110. package/core/server/api/shared/validators/input/index.js +0 -5
  111. package/core/server/services/bulk-email/mailgun.js +0 -122
  112. package/core/server/services/oembed.js +0 -346
  113. package/core/server/web/shared/middleware/cache-control.js +0 -43
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.8%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
11
+ <meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.9%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22moment%22%3A%7B%22includeTimezone%22%3A%22all%22%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -37,7 +37,7 @@
37
37
  </style>
38
38
 
39
39
  <link integrity="" rel="stylesheet" href="assets/vendor-bc9d2c9e5c8a33f0c92e81189d48e04c.css">
40
- <link integrity="" rel="stylesheet" href="assets/ghost-b469423d0fbe5e40af17b560f7e3cead.css" title="light">
40
+ <link integrity="" rel="stylesheet" href="assets/ghost-0319628ec5dcb83e6968e99eaa629a75.css" title="light">
41
41
 
42
42
 
43
43
  </head>
@@ -54,8 +54,8 @@
54
54
  <div id="ember-basic-dropdown-wormhole"></div>
55
55
 
56
56
  <script src="assets/vendor-516c9e43b4aeb92079dc1ab92c9ce492.js"></script>
57
- <script src="assets/chunk.351.cbc224ca65c14ef5322d.js"></script>
58
- <script src="assets/chunk.143.cf66fd97f99af03c697f.js"></script>
59
- <script src="assets/ghost-f1d63ad9698b7d38261df6384513c952.js"></script>
57
+ <script src="assets/chunk.351.73f27952f867334a8228.js"></script>
58
+ <script src="assets/chunk.143.4e4590d80452422483d8.js"></script>
59
+ <script src="assets/ghost-f144e03b578116a5d0ed41bceaf2bab8.js"></script>
60
60
  </body>
61
61
  </html>
@@ -1,8 +1,7 @@
1
1
  const {SafeString} = require('../services/handlebars');
2
- const {labs} = require('../services/proxy');
3
2
  const {html} = require('common-tags');
4
3
 
5
- function commentCount(options) {
4
+ module.exports = function commentCount(options) {
6
5
  const empty = options.hash.empty === undefined ? '' : options.hash.empty;
7
6
  const singular = options.hash.singular === undefined ? 'comment' : options.hash.singular;
8
7
  const plural = options.hash.plural === undefined ? 'comments' : options.hash.plural;
@@ -21,17 +20,4 @@ function commentCount(options) {
21
20
  >
22
21
  </script>
23
22
  `);
24
- }
25
-
26
- module.exports = function commentsLabsWrapper() {
27
- const self = this;
28
- const args = arguments;
29
-
30
- return labs.enabledHelper({
31
- flagKey: 'comments',
32
- flagName: 'Comments',
33
- helperName: 'comment_count'
34
- }, () => {
35
- return commentCount.apply(self, args);
36
- });
37
23
  };
@@ -1,8 +1,8 @@
1
1
  const {SafeString} = require('../services/handlebars');
2
- const {urlUtils, getFrontendKey, labs, settingsCache} = require('../services/proxy');
2
+ const {urlUtils, getFrontendKey, settingsCache} = require('../services/proxy');
3
3
  const {getFrontendAppConfig, getDataAttributes} = require('../utils/frontend-apps');
4
4
 
5
- async function comments(options) {
5
+ module.exports = async function comments(options) {
6
6
  // todo: For now check on the comment id to exclude normal pages (we probably have a better way to do this)
7
7
 
8
8
  const commentId = this.comment_id;
@@ -66,7 +66,8 @@ async function comments(options) {
66
66
  'avatar-saturation': avatarSaturation,
67
67
  'accent-color': accentColor,
68
68
  'app-version': appVersion,
69
- 'comments-enabled': commentsEnabled
69
+ 'comments-enabled': commentsEnabled,
70
+ publication: settingsCache.get('title')
70
71
  };
71
72
 
72
73
  const dataAttributes = getDataAttributes(data);
@@ -74,19 +75,6 @@ async function comments(options) {
74
75
  return new SafeString(`
75
76
  <script defer src="${scriptUrl}" ${dataAttributes} crossorigin="anonymous"></script>
76
77
  `);
77
- }
78
-
79
- module.exports = async function commentsLabsWrapper() {
80
- const self = this;
81
- const args = arguments;
82
-
83
- return labs.enabledHelper({
84
- flagKey: 'comments',
85
- flagName: 'Comments',
86
- helperName: 'comments'
87
- }, () => {
88
- return comments.apply(self, args);
89
- });
90
78
  };
91
79
 
92
80
  module.exports.async = true;
@@ -229,7 +229,7 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam
229
229
  head.push(`<link rel="stylesheet" type="text/css" href="${getAssetUrl('public/cards.min.css')}">`);
230
230
  }
231
231
 
232
- if (labs.isSet('comments') && settingsCache.get('enable_comments') !== 'off') {
232
+ if (settingsCache.get('enable_comments') !== 'off') {
233
233
  head.push(`<script defer src="${getAssetUrl('public/comment-counts.min.js')}" data-ghost-comments-counts-api="${urlUtils.getSiteUrl(true)}members/api/comments/counts/"></script>`);
234
234
  }
235
235
 
@@ -18,6 +18,9 @@ module.exports = async function unsubscribeController(req, res) {
18
18
  if (query.newsletter) {
19
19
  redirectUrl.searchParams.append('newsletter', query.newsletter);
20
20
  }
21
+ if (query.comments) {
22
+ redirectUrl.searchParams.append('comments', query.comments);
23
+ }
21
24
  redirectUrl.searchParams.append('action', 'unsubscribe');
22
25
 
23
26
  return res.redirect(302, redirectUrl.href);
@@ -3,7 +3,7 @@ const tpl = require('@tryghost/tpl');
3
3
  const errors = require('@tryghost/errors');
4
4
  const models = require('../../models');
5
5
  const commentsService = require('../../services/comments');
6
- const ALLOWED_INCLUDES = ['post', 'member', 'likes', 'replies', 'parent'];
6
+ const ALLOWED_INCLUDES = ['member', 'replies', 'replies.member', 'replies.count.likes', 'replies.liked', 'count.replies', 'count.likes', 'liked', 'post', 'parent'];
7
7
  const UNSAFE_ATTRS = ['status'];
8
8
 
9
9
  const messages = {
@@ -37,6 +37,28 @@ module.exports = {
37
37
  }
38
38
  },
39
39
 
40
+ replies: {
41
+ options: [
42
+ 'include',
43
+ 'page',
44
+ 'limit',
45
+ 'fields',
46
+ 'filter',
47
+ 'order',
48
+ 'debug',
49
+ 'id'
50
+ ],
51
+ validation: {
52
+ options: {
53
+ include: ALLOWED_INCLUDES
54
+ }
55
+ },
56
+ permissions: 'browse',
57
+ query(frame) {
58
+ return commentsService.controller.replies(frame);
59
+ }
60
+ },
61
+
40
62
  read: {
41
63
  options: [
42
64
  'include'
@@ -1,4 +1,4 @@
1
- const shared = require('../shared');
1
+ const apiFramework = require('@tryghost/api-framework');
2
2
  const localUtils = require('./utils');
3
3
 
4
4
  // ESLint Override Notice
@@ -9,19 +9,19 @@ const localUtils = require('./utils');
9
9
 
10
10
  module.exports = {
11
11
  get authentication() {
12
- return shared.pipeline(require('./authentication'), localUtils);
12
+ return apiFramework.pipeline(require('./authentication'), localUtils);
13
13
  },
14
14
 
15
15
  get db() {
16
- return shared.pipeline(require('./db'), localUtils);
16
+ return apiFramework.pipeline(require('./db'), localUtils);
17
17
  },
18
18
 
19
19
  get identities() {
20
- return shared.pipeline(require('./identities'), localUtils);
20
+ return apiFramework.pipeline(require('./identities'), localUtils);
21
21
  },
22
22
 
23
23
  get integrations() {
24
- return shared.pipeline(require('./integrations'), localUtils);
24
+ return apiFramework.pipeline(require('./integrations'), localUtils);
25
25
  },
26
26
 
27
27
  // @TODO: transform
@@ -30,147 +30,147 @@ module.exports = {
30
30
  },
31
31
 
32
32
  get schedules() {
33
- return shared.pipeline(require('./schedules'), localUtils);
33
+ return apiFramework.pipeline(require('./schedules'), localUtils);
34
34
  },
35
35
 
36
36
  get pages() {
37
- return shared.pipeline(require('./pages'), localUtils);
37
+ return apiFramework.pipeline(require('./pages'), localUtils);
38
38
  },
39
39
 
40
40
  get redirects() {
41
- return shared.pipeline(require('./redirects'), localUtils);
41
+ return apiFramework.pipeline(require('./redirects'), localUtils);
42
42
  },
43
43
 
44
44
  get roles() {
45
- return shared.pipeline(require('./roles'), localUtils);
45
+ return apiFramework.pipeline(require('./roles'), localUtils);
46
46
  },
47
47
 
48
48
  get slugs() {
49
- return shared.pipeline(require('./slugs'), localUtils);
49
+ return apiFramework.pipeline(require('./slugs'), localUtils);
50
50
  },
51
51
 
52
52
  get webhooks() {
53
- return shared.pipeline(require('./webhooks'), localUtils);
53
+ return apiFramework.pipeline(require('./webhooks'), localUtils);
54
54
  },
55
55
 
56
56
  get posts() {
57
- return shared.pipeline(require('./posts'), localUtils);
57
+ return apiFramework.pipeline(require('./posts'), localUtils);
58
58
  },
59
59
 
60
60
  get invites() {
61
- return shared.pipeline(require('./invites'), localUtils);
61
+ return apiFramework.pipeline(require('./invites'), localUtils);
62
62
  },
63
63
 
64
64
  get mail() {
65
- return shared.pipeline(require('./mail'), localUtils);
65
+ return apiFramework.pipeline(require('./mail'), localUtils);
66
66
  },
67
67
 
68
68
  get notifications() {
69
- return shared.pipeline(require('./notifications'), localUtils);
69
+ return apiFramework.pipeline(require('./notifications'), localUtils);
70
70
  },
71
71
 
72
72
  get settings() {
73
- return shared.pipeline(require('./settings'), localUtils);
73
+ return apiFramework.pipeline(require('./settings'), localUtils);
74
74
  },
75
75
 
76
76
  get membersStripeConnect() {
77
- return shared.pipeline(require('./members-stripe-connect'), localUtils);
77
+ return apiFramework.pipeline(require('./members-stripe-connect'), localUtils);
78
78
  },
79
79
 
80
80
  get members() {
81
- return shared.pipeline(require('./members'), localUtils);
81
+ return apiFramework.pipeline(require('./members'), localUtils);
82
82
  },
83
83
 
84
84
  get offers() {
85
- return shared.pipeline(require('./offers'), localUtils);
85
+ return apiFramework.pipeline(require('./offers'), localUtils);
86
86
  },
87
87
 
88
88
  get tiers() {
89
- return shared.pipeline(require('./tiers'), localUtils);
89
+ return apiFramework.pipeline(require('./tiers'), localUtils);
90
90
  },
91
91
 
92
92
  get memberSigninUrls() {
93
- return shared.pipeline(require('./member-signin-urls.js'), localUtils);
93
+ return apiFramework.pipeline(require('./member-signin-urls.js'), localUtils);
94
94
  },
95
95
 
96
96
  get labels() {
97
- return shared.pipeline(require('./labels'), localUtils);
97
+ return apiFramework.pipeline(require('./labels'), localUtils);
98
98
  },
99
99
 
100
100
  get images() {
101
- return shared.pipeline(require('./images'), localUtils);
101
+ return apiFramework.pipeline(require('./images'), localUtils);
102
102
  },
103
103
 
104
104
  get media() {
105
- return shared.pipeline(require('./media'), localUtils);
105
+ return apiFramework.pipeline(require('./media'), localUtils);
106
106
  },
107
107
 
108
108
  get files() {
109
- return shared.pipeline(require('./files'), localUtils);
109
+ return apiFramework.pipeline(require('./files'), localUtils);
110
110
  },
111
111
 
112
112
  get tags() {
113
- return shared.pipeline(require('./tags'), localUtils);
113
+ return apiFramework.pipeline(require('./tags'), localUtils);
114
114
  },
115
115
 
116
116
  get users() {
117
- return shared.pipeline(require('./users'), localUtils);
117
+ return apiFramework.pipeline(require('./users'), localUtils);
118
118
  },
119
119
 
120
120
  get previews() {
121
- return shared.pipeline(require('./previews'), localUtils);
121
+ return apiFramework.pipeline(require('./previews'), localUtils);
122
122
  },
123
123
 
124
124
  get emailPost() {
125
- return shared.pipeline(require('./email-post'), localUtils);
125
+ return apiFramework.pipeline(require('./email-post'), localUtils);
126
126
  },
127
127
 
128
128
  get oembed() {
129
- return shared.pipeline(require('./oembed'), localUtils);
129
+ return apiFramework.pipeline(require('./oembed'), localUtils);
130
130
  },
131
131
 
132
132
  get slack() {
133
- return shared.pipeline(require('./slack'), localUtils);
133
+ return apiFramework.pipeline(require('./slack'), localUtils);
134
134
  },
135
135
 
136
136
  get config() {
137
- return shared.pipeline(require('./config'), localUtils);
137
+ return apiFramework.pipeline(require('./config'), localUtils);
138
138
  },
139
139
 
140
140
  get explore() {
141
- return shared.pipeline(require('./explore'), localUtils);
141
+ return apiFramework.pipeline(require('./explore'), localUtils);
142
142
  },
143
143
 
144
144
  get themes() {
145
- return shared.pipeline(require('./themes'), localUtils);
145
+ return apiFramework.pipeline(require('./themes'), localUtils);
146
146
  },
147
147
 
148
148
  get actions() {
149
- return shared.pipeline(require('./actions'), localUtils);
149
+ return apiFramework.pipeline(require('./actions'), localUtils);
150
150
  },
151
151
 
152
152
  get email_previews() {
153
- return shared.pipeline(require('./email-previews'), localUtils);
153
+ return apiFramework.pipeline(require('./email-previews'), localUtils);
154
154
  },
155
155
 
156
156
  get emails() {
157
- return shared.pipeline(require('./emails'), localUtils);
157
+ return apiFramework.pipeline(require('./emails'), localUtils);
158
158
  },
159
159
 
160
160
  get site() {
161
- return shared.pipeline(require('./site'), localUtils);
161
+ return apiFramework.pipeline(require('./site'), localUtils);
162
162
  },
163
163
 
164
164
  get snippets() {
165
- return shared.pipeline(require('./snippets'), localUtils);
165
+ return apiFramework.pipeline(require('./snippets'), localUtils);
166
166
  },
167
167
 
168
168
  get stats() {
169
- return shared.pipeline(require('./stats'), localUtils);
169
+ return apiFramework.pipeline(require('./stats'), localUtils);
170
170
  },
171
171
 
172
172
  get customThemeSettings() {
173
- return shared.pipeline(require('./custom-theme-settings'), localUtils);
173
+ return apiFramework.pipeline(require('./custom-theme-settings'), localUtils);
174
174
  },
175
175
 
176
176
  get serializers() {
@@ -178,11 +178,11 @@ module.exports = {
178
178
  },
179
179
 
180
180
  get newsletters() {
181
- return shared.pipeline(require('./newsletters'), localUtils);
181
+ return apiFramework.pipeline(require('./newsletters'), localUtils);
182
182
  },
183
183
 
184
184
  get comments() {
185
- return shared.pipeline(require('./comments'), localUtils);
185
+ return apiFramework.pipeline(require('./comments'), localUtils);
186
186
  },
187
187
 
188
188
  /**
@@ -194,38 +194,38 @@ module.exports = {
194
194
  * `api.admin` soon. Need to figure out how serializers & validation works then.
195
195
  */
196
196
  get pagesPublic() {
197
- return shared.pipeline(require('./pages-public'), localUtils, 'content');
197
+ return apiFramework.pipeline(require('./pages-public'), localUtils, 'content');
198
198
  },
199
199
 
200
200
  get tagsPublic() {
201
- return shared.pipeline(require('./tags-public'), localUtils, 'content');
201
+ return apiFramework.pipeline(require('./tags-public'), localUtils, 'content');
202
202
  },
203
203
 
204
204
  get publicSettings() {
205
- return shared.pipeline(require('./settings-public'), localUtils, 'content');
205
+ return apiFramework.pipeline(require('./settings-public'), localUtils, 'content');
206
206
  },
207
207
 
208
208
  get postsPublic() {
209
- return shared.pipeline(require('./posts-public'), localUtils, 'content');
209
+ return apiFramework.pipeline(require('./posts-public'), localUtils, 'content');
210
210
  },
211
211
 
212
212
  get authorsPublic() {
213
- return shared.pipeline(require('./authors-public'), localUtils, 'content');
213
+ return apiFramework.pipeline(require('./authors-public'), localUtils, 'content');
214
214
  },
215
215
 
216
216
  get tiersPublic() {
217
- return shared.pipeline(require('./tiers-public'), localUtils, 'content');
217
+ return apiFramework.pipeline(require('./tiers-public'), localUtils, 'content');
218
218
  },
219
219
 
220
220
  get newslettersPublic() {
221
- return shared.pipeline(require('./newsletters-public'), localUtils, 'content');
221
+ return apiFramework.pipeline(require('./newsletters-public'), localUtils, 'content');
222
222
  },
223
223
 
224
224
  get offersPublic() {
225
- return shared.pipeline(require('./offers-public'), localUtils, 'content');
225
+ return apiFramework.pipeline(require('./offers-public'), localUtils, 'content');
226
226
  },
227
227
 
228
228
  get commentsMembers() {
229
- return shared.pipeline(require('./comments-members'), localUtils, 'members');
229
+ return apiFramework.pipeline(require('./comments-members'), localUtils, 'members');
230
230
  }
231
231
  };
@@ -1,7 +1,7 @@
1
1
  const config = require('../../../shared/config');
2
2
  const externalRequest = require('../../lib/request-external');
3
3
 
4
- const OEmbed = require('../../services/oembed');
4
+ const OEmbed = require('@tryghost/oembed-service');
5
5
  const oembed = new OEmbed({config, externalRequest});
6
6
 
7
7
  const NFT = require('../../services/nft-oembed');
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ all(_apiConfig, frame) {
3
+ if (!frame.options.withRelated || frame.options.withRelated.length === 0) {
4
+ return;
5
+ }
6
+
7
+ // Map the 'liked' relation to 'count.liked'
8
+ frame.options.withRelated = frame.options.withRelated.map((relation) => {
9
+ if (relation === 'liked') {
10
+ return 'count.liked';
11
+ }
12
+ if (relation === 'replies.liked') {
13
+ return 'replies.count.liked';
14
+ }
15
+ return relation;
16
+ });
17
+ }
18
+ };
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:db');
3
- const optionsUtil = require('../../../../shared/utils/options');
3
+ const optionsUtil = require('@tryghost/api-framework').utils.options;
4
4
 
5
5
  const INTERNAL_OPTIONS = ['transacting', 'forUpdate'];
6
6
 
@@ -45,5 +45,9 @@ module.exports = {
45
45
 
46
46
  get webhooks() {
47
47
  return require('./webhooks');
48
+ },
49
+
50
+ get comments() {
51
+ return require('./comments');
48
52
  }
49
53
  };
@@ -3,9 +3,9 @@ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:input:
3
3
 
4
4
  function setDefaultFilter(frame) {
5
5
  if (frame.options.filter) {
6
- frame.options.filter = `(${frame.options.filter})+type:[custom,builtin]`;
6
+ frame.options.filter = `(${frame.options.filter})+type:[custom,builtin,core]`;
7
7
  } else {
8
- frame.options.filter = 'type:[custom,builtin]';
8
+ frame.options.filter = 'type:[custom,builtin,core]';
9
9
  }
10
10
  }
11
11
 
@@ -25,6 +25,11 @@ const postFields = [
25
25
  'url'
26
26
  ];
27
27
 
28
+ const countFields = [
29
+ 'replies',
30
+ 'likes'
31
+ ];
32
+
28
33
  const commentMapper = (model, frame) => {
29
34
  const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
30
35
 
@@ -36,12 +41,6 @@ const commentMapper = (model, frame) => {
36
41
  response.member = null;
37
42
  }
38
43
 
39
- if (jsonModel.likes) {
40
- response.likes_count = jsonModel.likes.length;
41
- } else {
42
- response.likes_count = 0;
43
- }
44
-
45
44
  if (jsonModel.replies) {
46
45
  response.replies = jsonModel.replies.map(reply => commentMapper(reply, frame));
47
46
  }
@@ -56,11 +55,12 @@ const commentMapper = (model, frame) => {
56
55
  response.post = _.pick(jsonModel.post, postFields);
57
56
  }
58
57
 
59
- // todo
60
- response.liked = false;
61
- if (jsonModel.likes && frame.original.context.member && frame.original.context.member.id) {
62
- const id = frame.original.context.member.id;
63
- response.liked = !!jsonModel.likes.find(l => l.member_id === id);
58
+ if (jsonModel.count && jsonModel.count.liked !== undefined) {
59
+ response.liked = jsonModel.count.liked > 0;
60
+ }
61
+
62
+ if (jsonModel.count) {
63
+ response.count = _.pick(jsonModel.count, countFields);
64
64
  }
65
65
 
66
66
  if (utils.isMembersAPI(frame)) {
@@ -68,7 +68,7 @@ const commentMapper = (model, frame) => {
68
68
  response.html = null;
69
69
  }
70
70
  }
71
-
71
+
72
72
  return response;
73
73
  };
74
74
 
@@ -3,7 +3,7 @@ const debug = require('@tryghost/debug')('api:endpoints:utils:serializers:output
3
3
 
4
4
  const allowedIncludes = ['monthly_price', 'yearly_price'];
5
5
  const localUtils = require('../../index');
6
- const utils = require('../../../../shared/utils');
6
+ const {utils} = require('@tryghost/api-framework');
7
7
  const labs = require('../../../../../../shared/labs');
8
8
 
9
9
  module.exports = {
@@ -1,3 +1 @@
1
1
  module.exports.endpoints = require('./endpoints');
2
-
3
- module.exports.shared = require('./shared');
@@ -5,8 +5,8 @@ const _ = require('lodash');
5
5
  const BaseImporter = require('./base');
6
6
  const models = require('../../../../models');
7
7
  const defaultSettings = require('../../../schema').defaultSettings;
8
- const keyGroupMapper = require('../../../../api/shared/serializers/input/utils/settings-key-group-mapper');
9
- const keyTypeMapper = require('../../../../api/shared/serializers/input/utils/settings-key-type-mapper');
8
+ const keyGroupMapper = require('../../../../api/endpoints/utils/serializers/input/utils/settings-key-group-mapper');
9
+ const keyTypeMapper = require('../../../../api/endpoints/utils/serializers/input/utils/settings-key-type-mapper');
10
10
  const {WRITABLE_KEYS_ALLOWLIST} = require('../../../../../shared/labs');
11
11
 
12
12
  const labsDefaults = JSON.parse(defaultSettings.labs.labs.defaultValue);
@@ -0,0 +1,24 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {createTransactionalMigration} = require('../../utils');
3
+
4
+ module.exports = createTransactionalMigration(
5
+ async function up(knex) {
6
+ logging.info('Changing Ghost Explore Integration to type "core"');
7
+ await knex('integrations')
8
+ .where({
9
+ name: 'Ghost Explore',
10
+ slug: 'ghost-explore'
11
+ })
12
+ .update('type', 'core');
13
+ },
14
+ async function down(knex) {
15
+ logging.info('Changing Ghost Explore Integration to type "builtin"');
16
+
17
+ await knex('integrations')
18
+ .where({
19
+ name: 'Ghost Explore',
20
+ slug: 'ghost-explore'
21
+ })
22
+ .update('type', 'builtin');
23
+ }
24
+ );
@@ -27,22 +27,7 @@ const getColumns = function getColumns(table, transaction) {
27
27
  });
28
28
  };
29
29
 
30
- // This function changes the type of posts.html and posts.markdown columns to mediumtext. Due to
31
- // a wrong datatype in schema.js some installations using mysql could have been created using the
32
- // data type text instead of mediumtext.
33
- // For details see: https://github.com/TryGhost/Ghost/issues/1947
34
- const checkPostTable = function checkPostTable(transaction = db.knex) {
35
- return transaction.raw('SHOW FIELDS FROM posts where Field ="html" OR Field = "markdown"').then(function (response) {
36
- return _.flatten(_.map(response[0], function (entry) {
37
- if (entry.Type.toLowerCase() !== 'mediumtext') {
38
- return (transaction || db.knex).raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT');
39
- }
40
- }));
41
- });
42
- };
43
-
44
30
  module.exports = {
45
- checkPostTable: checkPostTable,
46
31
  getTables: getTables,
47
32
  getIndexes: getIndexes,
48
33
  getColumns: getColumns
@@ -411,14 +411,6 @@ function getColumns(table, transaction = db.knex) {
411
411
  return Promise.reject(tpl(messages.noSupportForDatabase, {client: client}));
412
412
  }
413
413
 
414
- function checkTables(transaction = db.knex) {
415
- const client = transaction.client.config.client;
416
-
417
- if (DatabaseInfo.isMySQL(transaction)) {
418
- return clients[client].checkPostTable();
419
- }
420
- }
421
-
422
414
  function createColumnMigration(...migrations) {
423
415
  async function runColumnMigration(conn, migration) {
424
416
  const {
@@ -449,7 +441,6 @@ function createColumnMigration(...migrations) {
449
441
  }
450
442
 
451
443
  module.exports = {
452
- checkTables: checkTables,
453
444
  createTable: createTable,
454
445
  deleteTable: deleteTable,
455
446
  getTables: getTables,