ghost 4.23.0 → 4.24.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 (48) hide show
  1. package/core/app.js +12 -1
  2. package/core/boot.js +31 -17
  3. package/core/bridge.js +10 -10
  4. package/core/built/assets/{ghost-dark-42cf6e0c730578940ec069bda45aea41.css → ghost-dark-e7b57ab951512c5719aee89b16b9a448.css} +1 -1
  5. package/core/built/assets/{ghost.min-fcf6a0738421f86c47c55f20d00c5ba9.css → ghost.min-7f3603dbeb5ebf0ec09e207ae82fb4e3.css} +1 -1
  6. package/core/built/assets/{ghost.min-cccc107e881b74c7aaf1a73e1e5e0dee.js → ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js} +84 -84
  7. package/core/built/assets/{vendor.min-c9002845b6c30ac978abdadde9f33d7c.js → vendor.min-1a84ac3ef74edf31c6e86810b45221cc.js} +148 -75
  8. package/core/frontend/services/card-assets/index.js +0 -12
  9. package/core/frontend/services/card-assets/service.js +22 -21
  10. package/core/frontend/src/cards/css/bookmark.css +7 -0
  11. package/core/frontend/src/cards/css/callout.css +1 -2
  12. package/core/frontend/src/cards/css/gallery.css +13 -3
  13. package/core/frontend/src/cards/css/toggle.css +20 -9
  14. package/core/frontend/web/middleware/serve-public-file.js +25 -8
  15. package/core/frontend/web/site.js +0 -3
  16. package/core/server/services/email-analytics/jobs/index.js +1 -1
  17. package/core/server/services/mega/template.js +5 -1
  18. package/core/server/services/redirects/api.js +18 -23
  19. package/core/server/services/redirects/index.js +18 -10
  20. package/core/server/services/redirects/utils.js +14 -0
  21. package/core/server/services/redirects/validation.js +10 -0
  22. package/core/server/services/route-settings/index.js +40 -17
  23. package/core/server/services/route-settings/route-settings.js +127 -114
  24. package/core/server/services/route-settings/settings-loader.js +14 -32
  25. package/core/server/services/themes/activation-bridge.js +3 -3
  26. package/core/server/services/url/LocalFileCache.js +75 -0
  27. package/core/server/services/url/UrlService.js +15 -47
  28. package/core/server/services/url/index.js +17 -4
  29. package/core/server/web/admin/app.js +2 -5
  30. package/core/server/web/admin/controller.js +35 -12
  31. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  32. package/core/server/web/admin/views/default-prod.html +4 -4
  33. package/core/server/web/admin/views/default.html +4 -4
  34. package/core/server/web/api/canary/admin/app.js +0 -3
  35. package/core/server/web/api/canary/content/app.js +0 -3
  36. package/core/server/web/api/v2/admin/app.js +0 -3
  37. package/core/server/web/api/v2/content/app.js +0 -3
  38. package/core/server/web/api/v3/admin/app.js +0 -3
  39. package/core/server/web/api/v3/content/app.js +0 -3
  40. package/core/server/web/members/app.js +0 -3
  41. package/core/server/web/oauth/app.js +0 -4
  42. package/core/server/web/parent/app.js +17 -8
  43. package/core/server/web/shared/middleware/error-handler.js +70 -53
  44. package/core/server/web/shared/middleware/index.js +0 -4
  45. package/core/shared/labs.js +7 -2
  46. package/package.json +19 -18
  47. package/yarn.lock +267 -107
  48. package/core/server/web/shared/middleware/maintenance.js +0 -25
package/core/app.js CHANGED
@@ -1,14 +1,25 @@
1
1
  const sentry = require('./shared/sentry');
2
2
  const express = require('./shared/express');
3
+ const config = require('./shared/config');
4
+ const urlService = require('./server/services/url');
3
5
 
4
6
  const fs = require('fs');
5
7
  const path = require('path');
6
8
 
9
+ const isMaintenanceModeEnabled = (req) => {
10
+ if (req.app.get('maintenance') || config.get('maintenance').enabled || !urlService.hasFinished()) {
11
+ return true;
12
+ }
13
+
14
+ return false;
15
+ };
16
+
7
17
  // We never want middleware functions to be anonymous
8
18
  const maintenanceMiddleware = (req, res, next) => {
9
- if (!req.app.get('maintenance')) {
19
+ if (!isMaintenanceModeEnabled(req)) {
10
20
  return next();
11
21
  }
22
+
12
23
  res.set({
13
24
  'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
14
25
  });
package/core/boot.js CHANGED
@@ -69,8 +69,9 @@ async function initDatabase({config, logging}) {
69
69
  * @param {object} options.ghostServer
70
70
  * @param {object} options.config
71
71
  * @param {object} options.bootLogger
72
+ * @param {boolean} options.frontend
72
73
  */
73
- async function initCore({ghostServer, config, bootLogger}) {
74
+ async function initCore({ghostServer, config, bootLogger, frontend}) {
74
75
  debug('Begin: initCore');
75
76
 
76
77
  // URL Utils is a bit slow, put it here so the timing is visible separate from models
@@ -95,12 +96,13 @@ async function initCore({ghostServer, config, bootLogger}) {
95
96
  debug('Begin: Url Service');
96
97
  const urlService = require('./server/services/url');
97
98
  // Note: there is no await here, we do not wait for the url service to finish
98
- // We can return, but the site will remain in (the shared, not global) maintenance mode until this finishes
99
- // This is managed on request: https://github.com/TryGhost/Ghost/blob/main/core/server/web/shared/middleware/maintenance.js#L13
99
+ // We can return, but the site will remain in maintenance mode until this finishes
100
+ // This is managed on request: https://github.com/TryGhost/Ghost/blob/main/core/app.js#L10
100
101
  urlService.init({
101
102
  onFinished: () => {
102
103
  bootLogger.log('URL Service Ready');
103
- }
104
+ },
105
+ urlCache: !frontend // hacky parameter to make the cache initialization kick in as we can't initialize labs before the boot
104
106
  });
105
107
  debug('End: Url Service');
106
108
 
@@ -129,6 +131,11 @@ async function initServicesForFrontend() {
129
131
  await routeSettings.init();
130
132
  debug('End: Routing Settings');
131
133
 
134
+ debug('Begin: Redirects');
135
+ const customRedirects = require('./server/services/redirects');
136
+ await customRedirects.init(),
137
+ debug('End: Redirects');
138
+
132
139
  debug('Begin: Themes');
133
140
  // customThemSettingsService.api must be initialized before any theme activation occurs
134
141
  const customThemeSettingsService = require('./server/services/custom-theme-settings');
@@ -149,9 +156,6 @@ async function initFrontend() {
149
156
  const helperService = require('./frontend/services/helpers');
150
157
  await helperService.init();
151
158
 
152
- const cardAssetService = require('./frontend/services/card-assets');
153
- await cardAssetService.init();
154
-
155
159
  debug('End: initFrontend');
156
160
  }
157
161
 
@@ -159,10 +163,13 @@ async function initFrontend() {
159
163
  * At the moment we load our express apps all in one go, they require themselves and are co-located
160
164
  * What we want is to be able to optionally load various components and mount them
161
165
  * So eventually this function should go away
166
+ * @param {Object} options
167
+ * @param {Boolean} options.backend
168
+ * @param {Boolean} options.frontend
162
169
  */
163
- async function initExpressApps() {
170
+ async function initExpressApps(options) {
164
171
  debug('Begin: initExpressApps');
165
- const parentApp = require('./server/web/parent/app')();
172
+ const parentApp = require('./server/web/parent/app')(options);
166
173
  debug('End: initExpressApps');
167
174
  return parentApp;
168
175
  }
@@ -178,6 +185,7 @@ async function initDynamicRouting() {
178
185
  const routing = require('./frontend/services/routing');
179
186
  const routeSettingsService = require('./server/services/route-settings');
180
187
  const bridge = require('./bridge');
188
+ bridge.init();
181
189
 
182
190
  // We pass the frontend API version + the dynamic routes here, so that the frontend services are slightly less tightly-coupled
183
191
  const apiVersion = bridge.getFrontendApiVersion();
@@ -219,7 +227,6 @@ async function initServices({config}) {
219
227
  const appService = require('./frontend/services/apps');
220
228
  const limits = require('./server/services/limits');
221
229
  const scheduling = require('./server/adapters/scheduling');
222
- const customRedirects = require('./server/services/redirects');
223
230
 
224
231
  const urlUtils = require('./shared/url-utils');
225
232
 
@@ -233,7 +240,6 @@ async function initServices({config}) {
233
240
  await offers.init();
234
241
 
235
242
  await Promise.all([
236
- customRedirects.init(),
237
243
  members.init(),
238
244
  permissions.init(),
239
245
  xmlrpc.listen(),
@@ -271,7 +277,7 @@ async function initBackgroundServices({config}) {
271
277
  themeService.loadInactiveThemes();
272
278
 
273
279
  // we don't want to kick off background services that will interfere with tests
274
- if (process.env.NODE_ENV.match(/^testing/)) {
280
+ if (process.env.NODE_ENV.startsWith('test')) {
275
281
  return;
276
282
  }
277
283
 
@@ -297,7 +303,7 @@ async function initBackgroundServices({config}) {
297
303
 
298
304
  * @returns {Promise<object>} ghostServer
299
305
  */
300
- async function bootGhost() {
306
+ async function bootGhost({backend = true, frontend = true} = {}) {
301
307
  // Metrics
302
308
  const startTime = Date.now();
303
309
  debug('Begin Boot');
@@ -346,6 +352,7 @@ async function bootGhost() {
346
352
  // Step 2 - Start server with minimal app in global maintenance mode
347
353
  debug('Begin: load server + minimal app');
348
354
  const rootApp = require('./app');
355
+
349
356
  const GhostServer = require('./server/ghost-server');
350
357
  ghostServer = new GhostServer({url: config.getSiteUrl()});
351
358
  await ghostServer.start(rootApp);
@@ -360,11 +367,18 @@ async function bootGhost() {
360
367
 
361
368
  // Step 4 - Load Ghost with all its services
362
369
  debug('Begin: Load Ghost Services & Apps');
363
- await initCore({ghostServer, config, bootLogger});
370
+ await initCore({ghostServer, config, bootLogger, frontend});
364
371
  await initServicesForFrontend();
365
- await initFrontend();
366
- const ghostApp = await initExpressApps();
367
- await initDynamicRouting();
372
+
373
+ if (frontend) {
374
+ await initFrontend();
375
+ }
376
+ const ghostApp = await initExpressApps({frontend, backend});
377
+
378
+ if (frontend) {
379
+ await initDynamicRouting();
380
+ }
381
+
368
382
  await initServices({config});
369
383
  debug('End: Load Ghost Services & Apps');
370
384
 
package/core/bridge.js CHANGED
@@ -16,6 +16,7 @@ const config = require('./shared/config');
16
16
  const logging = require('@tryghost/logging');
17
17
  const tpl = require('@tryghost/tpl');
18
18
  const themeEngine = require('./frontend/services/theme-engine');
19
+ const cardAssetService = require('./frontend/services/card-assets');
19
20
  const routerManager = require('./frontend/services/routing').routerManager;
20
21
  const settingsCache = require('./shared/settings-cache');
21
22
 
@@ -27,7 +28,7 @@ const messages = {
27
28
  };
28
29
 
29
30
  class Bridge {
30
- constructor() {
31
+ init() {
31
32
  /**
32
33
  * When locale changes, we reload theme translations
33
34
  * @deprecated: the term "lang" was deprecated in favor of "locale" publicly in 4.0
@@ -49,7 +50,7 @@ class Bridge {
49
50
  return themeEngine.getActive();
50
51
  }
51
52
 
52
- activateTheme(loadedTheme, checkedTheme) {
53
+ async activateTheme(loadedTheme, checkedTheme) {
53
54
  let settings = {
54
55
  locale: settingsCache.get('lang')
55
56
  };
@@ -67,8 +68,12 @@ class Bridge {
67
68
 
68
69
  if (previousGhostAPI !== undefined && (previousGhostAPI !== currentGhostAPI)) {
69
70
  events.emit('services.themes.api.changed');
70
- this.reloadFrontend();
71
+ await this.reloadFrontend();
71
72
  }
73
+
74
+ const cardAssetConfig = this.getCardAssetConfig();
75
+ debug('reload card assets config', cardAssetConfig);
76
+ await cardAssetService.load(cardAssetConfig);
72
77
  } catch (err) {
73
78
  logging.error(new errors.InternalServerError({
74
79
  message: tpl(messages.activateFailed, {theme: loadedTheme.name}),
@@ -93,17 +98,12 @@ class Bridge {
93
98
  }
94
99
  }
95
100
 
96
- reloadFrontend() {
101
+ async reloadFrontend() {
97
102
  const apiVersion = this.getFrontendApiVersion();
98
- const cardAssetConfig = this.getCardAssetConfig();
99
-
100
- debug('reload card assets config', cardAssetConfig);
101
- const cardAssetService = require('./frontend/services/card-assets');
102
- cardAssetService.load(cardAssetConfig);
103
103
 
104
104
  debug('reload frontend', apiVersion);
105
105
  const siteApp = require('./frontend/web/site');
106
- siteApp.reload({apiVersion});
106
+ await siteApp.reload({apiVersion});
107
107
  }
108
108
  }
109
109