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.
- package/core/app.js +12 -1
- package/core/boot.js +31 -17
- package/core/bridge.js +10 -10
- package/core/built/assets/{ghost-dark-42cf6e0c730578940ec069bda45aea41.css → ghost-dark-e7b57ab951512c5719aee89b16b9a448.css} +1 -1
- package/core/built/assets/{ghost.min-fcf6a0738421f86c47c55f20d00c5ba9.css → ghost.min-7f3603dbeb5ebf0ec09e207ae82fb4e3.css} +1 -1
- package/core/built/assets/{ghost.min-cccc107e881b74c7aaf1a73e1e5e0dee.js → ghost.min-d5595f9c71ebc534ccf9ac78483d357c.js} +84 -84
- package/core/built/assets/{vendor.min-c9002845b6c30ac978abdadde9f33d7c.js → vendor.min-1a84ac3ef74edf31c6e86810b45221cc.js} +148 -75
- package/core/frontend/services/card-assets/index.js +0 -12
- package/core/frontend/services/card-assets/service.js +22 -21
- package/core/frontend/src/cards/css/bookmark.css +7 -0
- package/core/frontend/src/cards/css/callout.css +1 -2
- package/core/frontend/src/cards/css/gallery.css +13 -3
- package/core/frontend/src/cards/css/toggle.css +20 -9
- package/core/frontend/web/middleware/serve-public-file.js +25 -8
- package/core/frontend/web/site.js +0 -3
- package/core/server/services/email-analytics/jobs/index.js +1 -1
- package/core/server/services/mega/template.js +5 -1
- package/core/server/services/redirects/api.js +18 -23
- package/core/server/services/redirects/index.js +18 -10
- package/core/server/services/redirects/utils.js +14 -0
- package/core/server/services/redirects/validation.js +10 -0
- package/core/server/services/route-settings/index.js +40 -17
- package/core/server/services/route-settings/route-settings.js +127 -114
- package/core/server/services/route-settings/settings-loader.js +14 -32
- package/core/server/services/themes/activation-bridge.js +3 -3
- package/core/server/services/url/LocalFileCache.js +75 -0
- package/core/server/services/url/UrlService.js +15 -47
- package/core/server/services/url/index.js +17 -4
- package/core/server/web/admin/app.js +2 -5
- package/core/server/web/admin/controller.js +35 -12
- package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/canary/admin/app.js +0 -3
- package/core/server/web/api/canary/content/app.js +0 -3
- package/core/server/web/api/v2/admin/app.js +0 -3
- package/core/server/web/api/v2/content/app.js +0 -3
- package/core/server/web/api/v3/admin/app.js +0 -3
- package/core/server/web/api/v3/content/app.js +0 -3
- package/core/server/web/members/app.js +0 -3
- package/core/server/web/oauth/app.js +0 -4
- package/core/server/web/parent/app.js +17 -8
- package/core/server/web/shared/middleware/error-handler.js +70 -53
- package/core/server/web/shared/middleware/index.js +0 -4
- package/core/shared/labs.js +7 -2
- package/package.json +19 -18
- package/yarn.lock +267 -107
- 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
|
|
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
|
|
99
|
-
// This is managed on request: https://github.com/TryGhost/Ghost/blob/main/core/
|
|
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.
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
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
|
|