ghost 4.41.3 → 4.43.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.
Files changed (147) hide show
  1. package/content/themes/casper/package.json +2 -3
  2. package/content/themes/casper/partials/post-card.hbs +1 -1
  3. package/core/built/assets/ghost-dark-1933079797e24ccb8839657020830be5.css +1 -0
  4. package/core/built/assets/{ghost.min-1abf114ca26a71e8e1f09054f3592614.js → ghost.min-2a278873d60d6a13a4c05a396e5bed5e.js} +533 -398
  5. package/core/built/assets/ghost.min-38f3c38c0c6a1864f57079b068a0b0ce.css +1 -0
  6. package/core/built/assets/{vendor.min-9094db77ba3190cb10876f8e42e1d90d.js → vendor.min-21f79c68a284acb1b70039f3f63e5507.js} +68 -68
  7. package/core/built/assets/{vendor.min-2c8ad32b7960bb605ebc20097fee5ebd.css → vendor.min-ba66b98f7c24fa40e061c7ffc94f4e23.css} +214 -0
  8. package/core/frontend/apps/amp/lib/helpers/amp_analytics.js +1 -1
  9. package/core/frontend/apps/amp/lib/helpers/amp_components.js +1 -1
  10. package/core/frontend/apps/amp/lib/helpers/amp_content.js +1 -1
  11. package/core/frontend/apps/amp/lib/helpers/amp_style.js +1 -1
  12. package/core/frontend/apps/amp/lib/router.js +6 -5
  13. package/core/frontend/apps/private-blogging/lib/helpers/input_password.js +1 -1
  14. package/core/frontend/apps/private-blogging/lib/router.js +2 -2
  15. package/core/frontend/helpers/asset.js +1 -1
  16. package/core/frontend/helpers/author.js +1 -1
  17. package/core/frontend/helpers/authors.js +1 -1
  18. package/core/frontend/helpers/body_class.js +1 -1
  19. package/core/frontend/helpers/cancel_link.js +1 -1
  20. package/core/frontend/helpers/concat.js +1 -1
  21. package/core/frontend/helpers/content.js +1 -1
  22. package/core/frontend/helpers/date.js +1 -1
  23. package/core/frontend/helpers/encode.js +1 -1
  24. package/core/frontend/helpers/excerpt.js +1 -1
  25. package/core/frontend/helpers/facebook_url.js +1 -1
  26. package/core/frontend/helpers/foreach.js +2 -2
  27. package/core/frontend/helpers/get.js +1 -1
  28. package/core/frontend/helpers/ghost_foot.js +1 -1
  29. package/core/frontend/helpers/ghost_head.js +1 -1
  30. package/core/frontend/helpers/lang.js +1 -1
  31. package/core/frontend/helpers/link.js +1 -1
  32. package/core/frontend/helpers/link_class.js +1 -1
  33. package/core/frontend/helpers/match.js +1 -1
  34. package/core/frontend/helpers/navigation.js +1 -1
  35. package/core/frontend/helpers/pagination.js +1 -1
  36. package/core/frontend/helpers/plural.js +1 -1
  37. package/core/frontend/helpers/post_class.js +1 -1
  38. package/core/frontend/helpers/prev_post.js +6 -5
  39. package/core/frontend/helpers/price.js +1 -0
  40. package/core/frontend/helpers/products.js +1 -1
  41. package/core/frontend/helpers/reading_time.js +2 -2
  42. package/core/frontend/helpers/t.js +1 -1
  43. package/core/frontend/helpers/tags.js +1 -1
  44. package/core/frontend/helpers/tiers.js +1 -1
  45. package/core/frontend/helpers/title.js +1 -1
  46. package/core/frontend/helpers/twitter_url.js +1 -1
  47. package/core/frontend/helpers/url.js +1 -1
  48. package/core/frontend/meta/url.js +4 -4
  49. package/core/{server/data/schema → frontend/services/data}/checks.js +4 -4
  50. package/core/frontend/services/{routing/helpers → data}/entry-lookup.js +3 -3
  51. package/core/frontend/services/{routing/helpers → data}/fetch-data.js +3 -3
  52. package/core/frontend/services/data/index.js +5 -0
  53. package/core/frontend/services/{rendering.js → handlebars.js} +2 -1
  54. package/core/frontend/services/helpers/handlebars.js +1 -1
  55. package/core/frontend/services/proxy.js +2 -4
  56. package/core/frontend/services/{routing/helpers → rendering}/context.js +0 -0
  57. package/core/frontend/services/{routing/helpers → rendering}/error.js +0 -0
  58. package/core/frontend/services/{routing/helpers → rendering}/format-response.js +1 -1
  59. package/core/frontend/services/{routing/helpers → rendering}/index.js +0 -8
  60. package/core/frontend/services/{routing/helpers → rendering}/render-entries.js +1 -1
  61. package/core/frontend/services/{routing/helpers → rendering}/render-entry.js +1 -1
  62. package/core/frontend/services/{routing/helpers → rendering}/renderer.js +1 -1
  63. package/core/frontend/services/{routing/helpers → rendering}/secure.js +0 -0
  64. package/core/frontend/services/{routing/helpers → rendering}/templates.js +2 -2
  65. package/core/frontend/services/routing/CollectionRouter.js +1 -1
  66. package/core/frontend/services/routing/controllers/channel.js +9 -9
  67. package/core/frontend/services/routing/controllers/collection.js +9 -9
  68. package/core/frontend/services/routing/controllers/email-post.js +5 -6
  69. package/core/frontend/services/routing/controllers/entry.js +6 -6
  70. package/core/frontend/services/routing/controllers/preview.js +5 -6
  71. package/core/frontend/services/routing/controllers/rss.js +4 -3
  72. package/core/frontend/services/routing/controllers/static.js +5 -5
  73. package/core/frontend/services/routing/controllers/unsubscribe.js +2 -2
  74. package/core/frontend/services/routing/index.js +0 -4
  75. package/core/frontend/web/middleware/error-handler.js +2 -2
  76. package/core/server/api/canary/email-preview.js +2 -1
  77. package/core/server/api/canary/{email.js → emails.js} +0 -0
  78. package/core/server/api/canary/index.js +9 -1
  79. package/core/server/api/canary/members.js +0 -45
  80. package/core/server/api/canary/newsletters.js +45 -0
  81. package/core/server/api/canary/stats.js +23 -0
  82. package/core/server/api/canary/utils/serializers/output/email-previews.js +7 -0
  83. package/core/server/api/canary/utils/serializers/output/index.js +2 -22
  84. package/core/server/api/canary/utils/serializers/output/mappers/index.js +1 -0
  85. package/core/server/api/canary/utils/serializers/output/mappers/snippets.js +36 -0
  86. package/core/server/api/canary/utils/serializers/output/members.js +5 -2
  87. package/core/server/api/canary/utils/serializers/output/oembed.js +2 -2
  88. package/core/server/api/canary/utils/serializers/output/redirects.js +2 -2
  89. package/core/server/api/canary/utils/serializers/output/schedules.js +2 -2
  90. package/core/server/api/canary/utils/serializers/output/slack.js +2 -2
  91. package/core/server/api/canary/utils/serializers/output/themes.js +2 -2
  92. package/core/server/api/canary/utils/serializers/output/users.js +0 -23
  93. package/core/server/api/canary/utils/validators/input/index.js +6 -0
  94. package/core/server/api/shared/http.js +52 -51
  95. package/core/server/api/shared/serializers/handle.js +25 -26
  96. package/core/server/data/exporter/table-lists.js +2 -0
  97. package/core/server/data/migrations/utils.js +34 -2
  98. package/core/server/data/migrations/versions/4.42/2022-03-21-17-17-add.js +25 -0
  99. package/core/server/data/migrations/versions/4.42/2022-03-30-15-44-add-newsletter-permissions.js +28 -0
  100. package/core/server/data/migrations/versions/4.43/2022-03-28-19-26-recreate-newsletter-table.js +29 -0
  101. package/core/server/data/migrations/versions/4.43/2022-03-29-14-45-add-members-newsletters-table.js +7 -0
  102. package/core/server/data/migrations/versions/4.43/2022-04-01-10-13-add-post-newsletter-relation.js +108 -0
  103. package/core/server/data/migrations/versions/4.43/2022-04-06-09-47-add-type-column-to-paid-subscription-events.js +7 -0
  104. package/core/server/data/migrations/versions/4.43/2022-04-06-14-56-add-email-newsletter-relation.js +8 -0
  105. package/core/server/data/migrations/versions/4.43/2022-04-08-10-45-add-subscription-id-to-mrr-events.js +7 -0
  106. package/core/server/data/schema/commands.js +19 -14
  107. package/core/server/data/schema/index.js +0 -1
  108. package/core/server/data/schema/schema.js +36 -0
  109. package/core/server/models/base/bookshelf.js +1 -1
  110. package/core/server/models/base/plugins/crud.js +8 -0
  111. package/core/server/models/member.js +18 -1
  112. package/core/server/models/newsletter.js +43 -0
  113. package/core/server/models/post.js +4 -1
  114. package/core/server/services/auth/setup.js +4 -1
  115. package/core/server/services/mega/template.js +25 -13
  116. package/core/server/services/members/api.js +3 -1
  117. package/core/server/services/members/middleware.js +13 -3
  118. package/core/server/services/members/service.js +2 -1
  119. package/core/server/services/members/utils.js +13 -1
  120. package/core/server/services/newsletters/index.js +10 -0
  121. package/core/server/services/newsletters/service.js +24 -0
  122. package/core/server/services/slack.js +11 -3
  123. package/core/server/services/stats/index.js +1 -0
  124. package/core/server/services/stats/lib/members-stats-service.js +161 -0
  125. package/core/server/services/stats/lib/mrr-stats-service.js +154 -0
  126. package/core/server/services/stats/service.js +8 -0
  127. package/core/server/services/stripe/service.js +1 -0
  128. package/core/server/services/webhooks/webhooks-service.js +3 -1
  129. package/core/server/web/admin/views/default-prod.html +5 -5
  130. package/core/server/web/admin/views/default.html +5 -5
  131. package/core/server/web/api/canary/admin/routes.js +9 -2
  132. package/core/shared/config/defaults.json +2 -2
  133. package/core/shared/config/env/config.development.json +26 -0
  134. package/core/shared/config/env/config.production.json +21 -0
  135. package/core/shared/config/env/config.testing-mysql.json +59 -0
  136. package/core/shared/config/env/config.testing.json +58 -0
  137. package/package.json +50 -50
  138. package/yarn.lock +700 -769
  139. package/content/themes/casper/assets/css/csscomb.json +0 -240
  140. package/core/built/assets/ghost-dark-146c4c688b47d45c4aa018ee0f79cebc.css +0 -1
  141. package/core/built/assets/ghost.min-a73b150c7eecc4641d377cc73fb5eecd.css +0 -1
  142. package/core/server/api/canary/utils/serializers/output/email-preview.js +0 -10
  143. package/core/server/api/canary/utils/serializers/output/emails.js +0 -22
  144. package/core/server/api/canary/utils/serializers/output/identities.js +0 -7
  145. package/core/server/api/canary/utils/serializers/output/member-signin-urls.js +0 -7
  146. package/core/server/api/canary/utils/serializers/output/snippets.js +0 -107
  147. package/core/server/api/canary/utils/serializers/output/webhooks.js +0 -15
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // Overrides the standard behaviour of `{[title}}` to ensure the content is correctly escaped
5
5
 
6
- const {SafeString, escapeExpression} = require('../services/rendering');
6
+ const {SafeString, escapeExpression} = require('../services/handlebars');
7
7
 
8
8
  module.exports = function title() {
9
9
  return new SafeString(escapeExpression(this.title || ''));
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // Output a url for a twitter username
5
5
  const {socialUrls} = require('../services/proxy');
6
- const {localUtils} = require('../services/rendering');
6
+ const {localUtils} = require('../services/handlebars');
7
7
 
8
8
  // We use the name twitter_url to match the helper for consistency:
9
9
  module.exports = function twitter_url(username, options) { // eslint-disable-line camelcase
@@ -5,7 +5,7 @@
5
5
  // `absolute` flag outputs absolute URL, else URL is relative
6
6
 
7
7
  const {metaData} = require('../services/proxy');
8
- const {SafeString} = require('../services/rendering');
8
+ const {SafeString} = require('../services/handlebars');
9
9
  const logging = require('@tryghost/logging');
10
10
  const sentry = require('../../shared/sentry');
11
11
  const errors = require('@tryghost/errors');
@@ -1,6 +1,6 @@
1
- const schema = require('../../server/data/schema').checks;
2
1
  const urlUtils = require('../../shared/url-utils');
3
2
  const urlService = require('../../server/services/url');
3
+ const {checks} = require('../services/data');
4
4
 
5
5
  // This cleans the url from any `/amp` postfixes, so we'll never
6
6
  // output a url with `/amp` in the end, except for the needed `amphtml`
@@ -13,7 +13,7 @@ function sanitizeAmpUrl(url) {
13
13
  }
14
14
 
15
15
  function getUrl(data, absolute) {
16
- if (schema.isPost(data)) {
16
+ if (checks.isPost(data)) {
17
17
  /**
18
18
  * @NOTE
19
19
  *
@@ -33,11 +33,11 @@ function getUrl(data, absolute) {
33
33
  return urlService.getUrlByResourceId(data.id, {secure: data.secure, absolute: absolute, withSubdirectory: true});
34
34
  }
35
35
 
36
- if (schema.isTag(data) || schema.isUser(data)) {
36
+ if (checks.isTag(data) || checks.isUser(data)) {
37
37
  return urlService.getUrlByResourceId(data.id, {secure: data.secure, absolute: absolute, withSubdirectory: true});
38
38
  }
39
39
 
40
- if (schema.isNav(data)) {
40
+ if (checks.isNav(data)) {
41
41
  return urlUtils.urlFor('nav', {nav: data, secure: data.secure}, absolute);
42
42
  }
43
43
 
@@ -19,8 +19,8 @@ function isNav(jsonData) {
19
19
  }
20
20
 
21
21
  module.exports = {
22
- isPost: isPost,
23
- isTag: isTag,
24
- isUser: isUser,
25
- isNav: isNav
22
+ isPost,
23
+ isTag,
24
+ isUser,
25
+ isNav
26
26
  };
@@ -1,11 +1,11 @@
1
1
  const _ = require('lodash');
2
2
  const Promise = require('bluebird');
3
3
  const url = require('url');
4
- const debug = require('@tryghost/debug')('services:routing:helpers:entry-lookup');
4
+ const debug = require('@tryghost/debug')('services:data:entry-lookup');
5
5
  const routeMatch = require('path-match')();
6
6
 
7
7
  /**
8
- * @description Query API for a single entry/resource.
8
+ * Query API for a single entry/resource.
9
9
  * @param {String} postUrl
10
10
  * @param {Object} routerOptions
11
11
  * @param {Object} locals
@@ -14,7 +14,7 @@ const routeMatch = require('path-match')();
14
14
  function entryLookup(postUrl, routerOptions, locals) {
15
15
  debug(postUrl);
16
16
 
17
- const api = require('../../proxy').api[locals.apiVersion];
17
+ const api = require('../proxy').api[locals.apiVersion];
18
18
  const targetPath = url.parse(postUrl).path;
19
19
  const permalinks = routerOptions.permalinks;
20
20
  let isEditURL = false;
@@ -34,7 +34,7 @@ const defaultPostQuery = _.cloneDeep(queryDefaults);
34
34
  defaultPostQuery.options = defaultQueryOptions.options;
35
35
 
36
36
  /**
37
- * @description Process query request.
37
+ * Process query request.
38
38
  *
39
39
  * Takes a 'query' object, ensures that type, resource and options are set
40
40
  * Replaces occurrences of `%s` in options with slugParam
@@ -45,7 +45,7 @@ defaultPostQuery.options = defaultQueryOptions.options;
45
45
  * @returns {Promise}
46
46
  */
47
47
  function processQuery(query, slugParam, locals) {
48
- const api = require('../../proxy').api[locals.apiVersion];
48
+ const api = require('../proxy').api[locals.apiVersion];
49
49
 
50
50
  query = _.cloneDeep(query);
51
51
 
@@ -62,7 +62,7 @@ function processQuery(query, slugParam, locals) {
62
62
  }
63
63
 
64
64
  /**
65
- * @description Fetch data from API helper for controllers.
65
+ * Fetch data from API helper for controllers.
66
66
  *
67
67
  * Calls out to get posts per page, builds the final posts query & builds any additional queries
68
68
  * Wraps the queries using Promise.props to ensure it gets named responses
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ checks: require('./checks'),
3
+ entryLookup: require('./entry-lookup'),
4
+ fetchData: require('./fetch-data')
5
+ };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This is a loose concept of a frontend rendering framework
2
+ * This is a loose concept of a frontend handlebars toolkit
3
3
  * Note: everything here gets deep-required from the theme-engine
4
4
  * This indicates that the theme engine is a set of services, rather than a single service
5
5
  * and could do with a further refactor.
@@ -17,6 +17,7 @@ module.exports = {
17
17
  templates: require('./theme-engine/handlebars/template'),
18
18
 
19
19
  // Theme i18n
20
+ // @TODO: this should live somewhere else...
20
21
  themeI18n: require('./theme-engine/i18n'),
21
22
 
22
23
  // TODO: these need a more sensible home
@@ -2,7 +2,7 @@ const Promise = require('bluebird');
2
2
  const errors = require('@tryghost/errors');
3
3
  const logging = require('@tryghost/logging');
4
4
 
5
- const {hbs} = require('../rendering');
5
+ const {hbs} = require('../handlebars');
6
6
 
7
7
  // Register an async handlebars helper for a given handlebars instance
8
8
  function asyncHelperWrapper(hbsInstance, name, fn) {
@@ -2,8 +2,8 @@
2
2
  const settingsCache = require('../../shared/settings-cache');
3
3
  const config = require('../../shared/config');
4
4
 
5
- // Require from the rendering framework
6
- const {SafeString} = require('./rendering');
5
+ // Require from the handlebars framework
6
+ const {SafeString} = require('./handlebars');
7
7
 
8
8
  module.exports = {
9
9
  /**
@@ -22,8 +22,6 @@ module.exports = {
22
22
  }
23
23
  });
24
24
  },
25
- // This is used to decide e.g. if a JSON object is a Post, Page, Tag etc
26
- checks: require('../../server/data/schema').checks,
27
25
 
28
26
  /**
29
27
  * Section three: Core API
@@ -1,5 +1,5 @@
1
1
  const _ = require('lodash');
2
- const {prepareContextResource} = require('../../proxy');
2
+ const {prepareContextResource} = require('../proxy');
3
3
 
4
4
  /**
5
5
  * @description Formats API response into handlebars/theme format.
@@ -1,12 +1,4 @@
1
1
  module.exports = {
2
- get entryLookup() {
3
- return require('./entry-lookup');
4
- },
5
-
6
- get fetchData() {
7
- return require('./fetch-data');
8
- },
9
-
10
2
  get renderEntries() {
11
3
  return require('./render-entries');
12
4
  },
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('services:routing:helpers:render-entries');
1
+ const debug = require('@tryghost/debug')('services:routing:renderer:render-entries');
2
2
  const formatResponse = require('./format-response');
3
3
  const renderer = require('./renderer');
4
4
 
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('services:routing:helpers:render-post');
1
+ const debug = require('@tryghost/debug')('services:routing:renderer:render-post');
2
2
  const formatResponse = require('./format-response');
3
3
  const renderer = require('./renderer');
4
4
  /**
@@ -1,4 +1,4 @@
1
- const debug = require('@tryghost/debug')('services:routing:helpers:renderer');
1
+ const debug = require('@tryghost/debug')('services:routing:renderer:renderer');
2
2
  const setContext = require('./context');
3
3
  const templates = require('./templates');
4
4
 
@@ -6,8 +6,8 @@ const _ = require('lodash');
6
6
 
7
7
  const path = require('path');
8
8
  const url = require('url');
9
- const config = require('../../../../shared/config');
10
- const themeEngine = require('../../theme-engine');
9
+ const config = require('../../../shared/config');
10
+ const themeEngine = require('../theme-engine');
11
11
  const _private = {};
12
12
 
13
13
  /**
@@ -30,7 +30,7 @@ class CollectionRouter extends ParentRouter {
30
30
  value: object.permalink
31
31
  };
32
32
 
33
- // @NOTE: see helpers/templates - we use unshift to prepend the templates
33
+ // @NOTE: see renderer/templates - we use unshift to prepend the templates
34
34
  this.templates = (object.templates || []).reverse();
35
35
 
36
36
  this.filter = object.filter;
@@ -4,7 +4,8 @@ const tpl = require('@tryghost/tpl');
4
4
  const errors = require('@tryghost/errors');
5
5
  const security = require('@tryghost/security');
6
6
  const themeEngine = require('../../theme-engine');
7
- const helpers = require('../helpers');
7
+ const dataService = require('../../data');
8
+ const renderer = require('../../rendering');
8
9
 
9
10
  const messages = {
10
11
  pageNotFound: 'Page not found.'
@@ -50,7 +51,7 @@ module.exports = function channelController(req, res, next) {
50
51
  }
51
52
  }
52
53
 
53
- return helpers.fetchData(pathOptions, res.routerOptions, res.locals)
54
+ return dataService.fetchData(pathOptions, res.routerOptions, res.locals)
54
55
  .then(function handleResult(result) {
55
56
  // CASE: requested page is greater than number of pages we have
56
57
  if (pathOptions.page > result.meta.pagination.pages) {
@@ -60,16 +61,15 @@ module.exports = function channelController(req, res, next) {
60
61
  }
61
62
 
62
63
  // Format data 1
63
- // @TODO: See helpers/secure for explanation.
64
- helpers.secure(req, result.posts);
64
+ // @TODO: See renderer/secure for explanation.
65
+ renderer.secure(req, result.posts);
65
66
 
66
- // @TODO: See helpers/secure for explanation.
67
+ // @TODO: See renderer/secure for explanation.
67
68
  _.each(result.data, function (data) {
68
- helpers.secure(req, data);
69
+ renderer.secure(req, data);
69
70
  });
70
71
 
71
- const renderer = helpers.renderEntries(req, res);
72
- return renderer(result);
72
+ return renderer.renderEntries(req, res)(result);
73
73
  })
74
- .catch(helpers.handleError(next));
74
+ .catch(renderer.handleError(next));
75
75
  };
@@ -5,7 +5,8 @@ const errors = require('@tryghost/errors');
5
5
  const security = require('@tryghost/security');
6
6
  const {routerManager} = require('../');
7
7
  const themeEngine = require('../../theme-engine');
8
- const helpers = require('../helpers');
8
+ const renderer = require('../../rendering');
9
+ const dataService = require('../../data');
9
10
 
10
11
  const messages = {
11
12
  pageNotFound: 'Page not found.'
@@ -49,7 +50,7 @@ module.exports = function collectionController(req, res, next) {
49
50
  }
50
51
 
51
52
  debug('fetching data');
52
- return helpers.fetchData(pathOptions, res.routerOptions, res.locals)
53
+ return dataService.fetchData(pathOptions, res.routerOptions, res.locals)
53
54
  .then(function handleResult(result) {
54
55
  // CASE: requested page is greater than number of pages we have
55
56
  if (pathOptions.page > result.meta.pagination.pages) {
@@ -80,16 +81,15 @@ module.exports = function collectionController(req, res, next) {
80
81
  });
81
82
 
82
83
  // Format data 1
83
- // @TODO: See helpers/secure for explanation.
84
- helpers.secure(req, result.posts);
84
+ // @TODO: See renderer/secure for explanation.
85
+ renderer.secure(req, result.posts);
85
86
 
86
- // @TODO: See helpers/secure for explanation.
87
+ // @TODO: See renderer/secure for explanation.
87
88
  _.each(result.data, function (data) {
88
- helpers.secure(req, data);
89
+ renderer.secure(req, data);
89
90
  });
90
91
 
91
- const renderer = helpers.renderEntries(req, res);
92
- return renderer(result);
92
+ return renderer.renderEntries(req, res)(result);
93
93
  })
94
- .catch(helpers.handleError(next));
94
+ .catch(renderer.handleError(next));
95
95
  };
@@ -2,7 +2,7 @@ const debug = require('@tryghost/debug')('services:routing:controllers:emailpost
2
2
  const config = require('../../../../shared/config');
3
3
  const {routerManager} = require('../');
4
4
  const urlUtils = require('../../../../shared/url-utils');
5
- const helpers = require('../helpers');
5
+ const renderer = require('../../rendering');
6
6
 
7
7
  /**
8
8
  * @description Email Post Controller.
@@ -55,11 +55,10 @@ module.exports = function emailPostController(req, res, next) {
55
55
  post.access = !!post.html;
56
56
  }
57
57
 
58
- // @TODO: See helpers/secure
59
- helpers.secure(req, post);
58
+ // @TODO: See renderer/secure
59
+ renderer.secure(req, post);
60
60
 
61
- const renderer = helpers.renderEntry(req, res);
62
- return renderer(post);
61
+ return renderer.renderEntry(req, res)(post);
63
62
  })
64
- .catch(helpers.handleError(next));
63
+ .catch(renderer.handleError(next));
65
64
  };
@@ -3,7 +3,8 @@ const url = require('url');
3
3
  const config = require('../../../../shared/config');
4
4
  const {routerManager} = require('../');
5
5
  const urlUtils = require('../../../../shared/url-utils');
6
- const helpers = require('../helpers');
6
+ const dataService = require('../../data');
7
+ const renderer = require('../../rendering');
7
8
 
8
9
  /**
9
10
  * @description Entry controller.
@@ -15,7 +16,7 @@ const helpers = require('../helpers');
15
16
  module.exports = function entryController(req, res, next) {
16
17
  debug('entryController', res.routerOptions);
17
18
 
18
- return helpers.entryLookup(req.path, res.routerOptions, res.locals)
19
+ return dataService.entryLookup(req.path, res.routerOptions, res.locals)
19
20
  .then(function then(lookup) {
20
21
  // Format data 1
21
22
  const entry = lookup ? lookup.entry : false;
@@ -83,10 +84,9 @@ module.exports = function entryController(req, res, next) {
83
84
  }));
84
85
  }
85
86
 
86
- helpers.secure(req, entry);
87
+ renderer.secure(req, entry);
87
88
 
88
- const renderer = helpers.renderEntry(req, res);
89
- return renderer(entry);
89
+ return renderer.renderEntry(req, res)(entry);
90
90
  })
91
- .catch(helpers.handleError(next));
91
+ .catch(renderer.handleError(next));
92
92
  };
@@ -2,7 +2,7 @@ const debug = require('@tryghost/debug')('services:routing:controllers:preview')
2
2
  const config = require('../../../../shared/config');
3
3
  const {routerManager} = require('../');
4
4
  const urlUtils = require('../../../../shared/url-utils');
5
- const helpers = require('../helpers');
5
+ const renderer = require('../../rendering');
6
6
 
7
7
  /**
8
8
  * @description Preview Controller.
@@ -57,11 +57,10 @@ module.exports = function previewController(req, res, next) {
57
57
  post.access = !!post.html;
58
58
  }
59
59
 
60
- // @TODO: See helpers/secure
61
- helpers.secure(req, post);
60
+ // @TODO: See renderer/secure
61
+ renderer.secure(req, post);
62
62
 
63
- const renderer = helpers.renderEntry(req, res);
64
- return renderer(post);
63
+ return renderer.renderEntry(req, res)(post);
65
64
  })
66
- .catch(helpers.handleError(next));
65
+ .catch(renderer.handleError(next));
67
66
  };
@@ -4,7 +4,8 @@ const url = require('url');
4
4
  const security = require('@tryghost/security');
5
5
  const settingsCache = require('../../../../shared/settings-cache');
6
6
  const rssService = require('../../rss');
7
- const helpers = require('../helpers');
7
+ const renderer = require('../../rendering');
8
+ const dataService = require('../../data');
8
9
 
9
10
  // @TODO: is this really correct? Should we be using meta data title?
10
11
  function getTitle(relatedData) {
@@ -35,7 +36,7 @@ module.exports = function rssController(req, res, next) {
35
36
  // @TODO: This belongs to the rss service O_o
36
37
  const baseUrl = url.parse(req.originalUrl).pathname;
37
38
 
38
- helpers.fetchData(pathOptions, res.routerOptions, res.locals)
39
+ dataService.fetchData(pathOptions, res.routerOptions, res.locals)
39
40
  .then(function formatResult(result) {
40
41
  const response = _.pick(result, ['posts', 'meta']);
41
42
 
@@ -47,5 +48,5 @@ module.exports = function rssController(req, res, next) {
47
48
  .then(function (data) {
48
49
  return rssService.render(res, baseUrl, data);
49
50
  })
50
- .catch(helpers.handleError(next));
51
+ .catch(renderer.handleError(next));
51
52
  };
@@ -1,7 +1,7 @@
1
1
  const _ = require('lodash');
2
2
  const Promise = require('bluebird');
3
3
  const debug = require('@tryghost/debug')('services:routing:controllers:static');
4
- const helpers = require('../helpers');
4
+ const renderer = require('../../rendering');
5
5
 
6
6
  function processQuery(query, locals) {
7
7
  const api = require('../../proxy').api[locals.apiVersion];
@@ -60,12 +60,12 @@ module.exports = function staticController(req, res, next) {
60
60
  });
61
61
  }
62
62
 
63
- // @TODO: See helpers/secure for more context.
63
+ // @TODO: See renderer/secure for more context.
64
64
  _.each(response.data, function (data) {
65
- helpers.secure(req, data);
65
+ renderer.secure(req, data);
66
66
  });
67
67
 
68
- helpers.renderer(req, res, helpers.formatResponse.entries(response));
68
+ renderer.renderer(req, res, renderer.formatResponse.entries(response));
69
69
  })
70
- .catch(helpers.handleError(next));
70
+ .catch(renderer.handleError(next));
71
71
  };
@@ -1,7 +1,7 @@
1
1
  const debug = require('@tryghost/debug')('services:routing:controllers:unsubscribe');
2
2
  const path = require('path');
3
3
  const megaService = require('../../../../server/services/mega');
4
- const helpers = require('../../../services/routing/helpers');
4
+ const renderer = require('../../rendering');
5
5
 
6
6
  module.exports = async function unsubscribeController(req, res) {
7
7
  debug('unsubscribeController');
@@ -22,5 +22,5 @@ module.exports = async function unsubscribeController(req, res) {
22
22
  defaultTemplate: path.resolve(__dirname, '../../../views/', templateName)
23
23
  };
24
24
 
25
- return helpers.renderer(req, res, data);
25
+ return renderer.renderer(req, res, data);
26
26
  };
@@ -7,9 +7,5 @@ module.exports = {
7
7
 
8
8
  get registry() {
9
9
  return registry;
10
- },
11
-
12
- get helpers() {
13
- return require('./helpers');
14
10
  }
15
11
  };
@@ -4,7 +4,7 @@ const tpl = require('@tryghost/tpl');
4
4
  const sentry = require('../../../shared/sentry');
5
5
 
6
6
  const config = require('../../../shared/config');
7
- const helpers = require('../../services/routing/helpers');
7
+ const renderer = require('../../services/rendering');
8
8
 
9
9
  // @TODO: make this properly shared code
10
10
  const {prepareError, prepareStack} = require('@tryghost/mw-error-handler');
@@ -55,7 +55,7 @@ const themeErrorRenderer = (err, req, res, next) => {
55
55
 
56
56
  // Template
57
57
  // @TODO: very dirty !!!!!!
58
- helpers.templates.setTemplate(req, res);
58
+ renderer.templates.setTemplate(req, res);
59
59
 
60
60
  // It can be that something went wrong with the theme or otherwise loading handlebars
61
61
  // This ensures that no matter what res.render will work here
@@ -12,7 +12,8 @@ const emailPreview = new mega.EmailPreview({
12
12
  });
13
13
 
14
14
  module.exports = {
15
- docName: 'email_preview',
15
+ // @TODO make the route match the resource name in 5.0
16
+ docName: 'email_previews',
16
17
 
17
18
  read: {
18
19
  options: [
File without changes
@@ -158,7 +158,7 @@ module.exports = {
158
158
  },
159
159
 
160
160
  get emails() {
161
- return shared.pipeline(require('./email'), localUtils);
161
+ return shared.pipeline(require('./emails'), localUtils);
162
162
  },
163
163
 
164
164
  get site() {
@@ -169,6 +169,10 @@ module.exports = {
169
169
  return shared.pipeline(require('./snippets'), localUtils);
170
170
  },
171
171
 
172
+ get stats() {
173
+ return shared.pipeline(require('./stats'), localUtils);
174
+ },
175
+
172
176
  get customThemeSettings() {
173
177
  return shared.pipeline(require('./custom-theme-settings'), localUtils);
174
178
  },
@@ -177,6 +181,10 @@ module.exports = {
177
181
  return require('./utils/serializers');
178
182
  },
179
183
 
184
+ get newsletters() {
185
+ return shared.pipeline(require('./newsletters'), localUtils);
186
+ },
187
+
180
188
  /**
181
189
  * Content API Controllers
182
190
  *
@@ -452,51 +452,6 @@ module.exports = {
452
452
  };
453
453
  }
454
454
  },
455
- subscriberStats: {
456
- permissions: {
457
- method: 'browse'
458
- },
459
- async query() {
460
- const statsData = await membersService.api.events.getSubscriptions();
461
- const totalSubscriptions = (_.last(statsData) && _.last(statsData).subscribed) || 0;
462
- statsData.forEach((d) => {
463
- d.date = moment(d.date).format('YYYY-MM-DD');
464
- });
465
- return {
466
- resource: 'subscribers',
467
- total: totalSubscriptions,
468
- data: statsData.map((d) => {
469
- return Object.assign({}, {
470
- date: moment(d.date).format('YYYY-MM-DD'),
471
- value: d.subscribed
472
- });
473
- })
474
- };
475
- }
476
- },
477
- grossVolumeStats: {
478
- permissions: {
479
- method: 'browse'
480
- },
481
- async query() {
482
- const volumeData = await membersService.api.events.getVolume();
483
- const volumeStats = Object.keys(volumeData).map((curr) => {
484
- return {
485
- currency: curr,
486
- data: volumeData[curr].map((d) => {
487
- return Object.assign({}, {
488
- date: moment(d.date).format('YYYY-MM-DD'),
489
- value: d.volume
490
- });
491
- })
492
- };
493
- });
494
- return {
495
- resource: 'gross-volume',
496
- data: volumeStats
497
- };
498
- }
499
- },
500
455
 
501
456
  activityFeed: {
502
457
  options: [