ghost 6.0.6 → 6.0.8
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/components/tryghost-i18n-6.0.8.tgz +0 -0
- package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +2 -2
- package/core/built/admin/assets/admin-x-activitypub/{index-BRzGrD-C.mjs → index-1EXYCtPI.mjs} +26876 -22657
- package/core/built/admin/assets/admin-x-activitypub/{index-Co80faUx.mjs → index-If44c6h0.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-B4W7CQcA.mjs → CodeEditorView-CzXlGImM.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
- package/core/built/admin/assets/admin-x-settings/{index-Bmm3Xeuw.mjs → index-BgCSf8S1.mjs} +4 -5
- package/core/built/admin/assets/admin-x-settings/{index-CuwMM9FM.mjs → index-D2pIApbM.mjs} +26 -11
- package/core/built/admin/assets/admin-x-settings/{index-jv9DN3ZO.mjs → index-RKA3H0Lh.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{modals-CUGEPPYA.mjs → modals-D0f6kxWg.mjs} +2 -2
- package/core/built/admin/assets/{chunk.524.56bb70d3e8660d34aef1.js → chunk.524.099dcd3975a0e60c5579.js} +6 -6
- package/core/built/admin/assets/{chunk.582.ae0341229e71a85d0b2d.js → chunk.582.6830378a89a17aeedd0b.js} +8 -8
- package/core/built/admin/assets/{ghost-2bcbd118a8ad45fed5401e84a7e87c9a.js → ghost-138bb4718f8b9d666bdd7a2b45330d58.js} +34 -33
- package/core/built/admin/assets/{ghost-2c537ee89c36199137eafc1768fd7de8.css → ghost-a7a53bf80dc45c37ae9c174a0d02a882.css} +1 -1
- package/core/built/admin/assets/{ghost-dark-ad23efc1d702e3643a8ee90d089df5d6.css → ghost-dark-6e0062029f988d8676e87f22d8e7f4a3.css} +1 -1
- package/core/built/admin/assets/posts/posts.js +83336 -82274
- package/core/built/admin/assets/stats/stats.js +26957 -26799
- package/core/built/admin/index.html +4 -4
- package/core/frontend/helpers/ghost_head.js +9 -9
- package/core/frontend/public/ghost-stats.min.js +3 -3
- package/core/frontend/public/member-attribution.min.js +1 -1
- package/core/frontend/src/ghost-stats/ghost-stats.js +18 -4
- package/core/frontend/src/member-attribution/member-attribution.js +28 -18
- package/core/frontend/src/utils/url-attribution.js +53 -40
- package/core/server/api/endpoints/utils/serializers/input/posts.js +7 -5
- package/core/server/data/tinybird/endpoints/api_top_utm_campaigns.pipe +31 -0
- package/core/server/data/tinybird/endpoints/api_top_utm_contents.pipe +31 -0
- package/core/server/data/tinybird/endpoints/api_top_utm_mediums.pipe +31 -0
- package/core/server/data/tinybird/endpoints/api_top_utm_sources.pipe +31 -0
- package/core/server/data/tinybird/endpoints/api_top_utm_terms.pipe +31 -0
- package/core/server/data/tinybird/tests/api_top_utm_campaigns.yaml +108 -0
- package/core/server/data/tinybird/tests/api_top_utm_contents.yaml +108 -0
- package/core/server/data/tinybird/tests/api_top_utm_mediums.yaml +108 -0
- package/core/server/data/tinybird/tests/api_top_utm_sources.yaml +108 -0
- package/core/server/data/tinybird/tests/api_top_utm_terms.yaml +108 -0
- package/core/server/services/lib/magic-link/MagicLink.js +17 -11
- package/core/server/services/members/MembersConfigProvider.js +11 -1
- package/core/server/services/members/SingleUseTokenProvider.js +159 -6
- package/core/server/services/members/api.js +1 -1
- package/core/server/services/members/emails/signin.js +9 -5
- package/core/server/services/members/members-api/controllers/RouterController.js +95 -19
- package/core/server/services/members/members-api/members-api.js +8 -4
- package/core/server/services/members/members-ssr.js +5 -3
- package/core/server/services/members/middleware.js +2 -2
- package/core/server/services/tinybird/TinybirdService.js +6 -1
- package/core/server/services/update-check/UpdateCheckService.js +1 -1
- package/core/server/web/members/app.js +12 -3
- package/core/shared/config/defaults.json +1 -1
- package/core/shared/labs.js +3 -1
- package/package.json +7 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +380 -104
- package/components/tryghost-i18n-6.0.6.tgz +0 -0
|
@@ -25,9 +25,31 @@ const messages = {
|
|
|
25
25
|
invalidType: 'Invalid checkout type.',
|
|
26
26
|
notConfigured: 'This site is not accepting payments at the moment.',
|
|
27
27
|
invalidNewsletters: 'Cannot subscribe to invalid newsletters {newsletters}',
|
|
28
|
-
archivedNewsletters: 'Cannot subscribe to archived newsletters {newsletters}'
|
|
28
|
+
archivedNewsletters: 'Cannot subscribe to archived newsletters {newsletters}',
|
|
29
|
+
otcNotSupported: 'OTC verification not supported.',
|
|
30
|
+
invalidCode: 'Invalid verification code.',
|
|
31
|
+
failedToVerifyCode: 'Failed to verify code, please try again.'
|
|
29
32
|
};
|
|
30
33
|
|
|
34
|
+
// helper utility for logic shared between sendMagicLink and verifyOTC
|
|
35
|
+
function extractRefererOrRedirect(req) {
|
|
36
|
+
const {autoRedirect, redirect} = req.body;
|
|
37
|
+
|
|
38
|
+
if (autoRedirect === false) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (redirect) {
|
|
43
|
+
try {
|
|
44
|
+
return new URL(redirect).href;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
logging.warn(e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return req.get('referer') || null;
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
module.exports = class RouterController {
|
|
32
54
|
/**
|
|
33
55
|
* RouterController
|
|
@@ -558,21 +580,10 @@ module.exports = class RouterController {
|
|
|
558
580
|
}
|
|
559
581
|
|
|
560
582
|
async sendMagicLink(req, res) {
|
|
561
|
-
const {email, honeypot
|
|
562
|
-
let {emailType
|
|
583
|
+
const {email, honeypot} = req.body;
|
|
584
|
+
let {emailType} = req.body;
|
|
563
585
|
|
|
564
|
-
|
|
565
|
-
if (autoRedirect === false){
|
|
566
|
-
referrer = null;
|
|
567
|
-
}
|
|
568
|
-
if (redirect) {
|
|
569
|
-
try {
|
|
570
|
-
// Validate URL
|
|
571
|
-
referrer = new URL(redirect).href;
|
|
572
|
-
} catch (e) {
|
|
573
|
-
logging.warn(e);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
586
|
+
const referrer = extractRefererOrRedirect(req);
|
|
576
587
|
|
|
577
588
|
if (!email) {
|
|
578
589
|
throw new errors.BadRequestError({
|
|
@@ -628,9 +639,9 @@ module.exports = class RouterController {
|
|
|
628
639
|
} else {
|
|
629
640
|
const signIn = await this._handleSignin(req, normalizedEmail, referrer);
|
|
630
641
|
|
|
631
|
-
if (this.labsService.isSet('membersSigninOTC') && signIn.
|
|
642
|
+
if (this.labsService.isSet('membersSigninOTC') && signIn.otcRef) {
|
|
632
643
|
res.writeHead(201, {'Content-Type': 'application/json'});
|
|
633
|
-
return res.end(JSON.stringify({otc_ref: signIn.
|
|
644
|
+
return res.end(JSON.stringify({otc_ref: signIn.otcRef}));
|
|
634
645
|
}
|
|
635
646
|
}
|
|
636
647
|
|
|
@@ -649,6 +660,71 @@ module.exports = class RouterController {
|
|
|
649
660
|
}
|
|
650
661
|
}
|
|
651
662
|
|
|
663
|
+
async verifyOTC(req, res) {
|
|
664
|
+
const {otc, otcRef} = req.body;
|
|
665
|
+
|
|
666
|
+
if (!otc || !otcRef) {
|
|
667
|
+
throw new errors.BadRequestError({
|
|
668
|
+
message: tpl(messages.badRequest),
|
|
669
|
+
context: 'otc and otcRef are required',
|
|
670
|
+
code: 'OTC_VERIFICATION_MISSING_PARAMS'
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const tokenProvider = this._magicLinkService.tokenProvider;
|
|
675
|
+
if (!tokenProvider || typeof tokenProvider.verifyOTC !== 'function') {
|
|
676
|
+
throw new errors.BadRequestError({
|
|
677
|
+
message: tpl(messages.otcNotSupported),
|
|
678
|
+
code: 'OTC_NOT_SUPPORTED'
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const isValidOTC = await tokenProvider.verifyOTC(otcRef, otc);
|
|
683
|
+
if (!isValidOTC) {
|
|
684
|
+
throw new errors.BadRequestError({
|
|
685
|
+
message: tpl(messages.invalidCode),
|
|
686
|
+
code: 'INVALID_OTC'
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const tokenValue = await tokenProvider.getTokenByRef(otcRef);
|
|
691
|
+
if (!tokenValue) {
|
|
692
|
+
throw new errors.BadRequestError({
|
|
693
|
+
message: tpl(messages.invalidCode),
|
|
694
|
+
code: 'INVALID_OTC_REF'
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const otcVerificationHash = await this._createHashFromOTCAndToken(otc, tokenValue);
|
|
699
|
+
if (!otcVerificationHash) {
|
|
700
|
+
throw new errors.BadRequestError({
|
|
701
|
+
message: tpl(messages.failedToVerifyCode),
|
|
702
|
+
code: 'OTC_VERIFICATION_FAILED'
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const referrer = extractRefererOrRedirect(req);
|
|
707
|
+
|
|
708
|
+
const redirectUrl = this._magicLinkService.getSigninURL(tokenValue, 'signin', referrer, otcVerificationHash);
|
|
709
|
+
if (!redirectUrl) {
|
|
710
|
+
throw new errors.BadRequestError({
|
|
711
|
+
message: tpl(messages.failedToVerifyCode),
|
|
712
|
+
code: 'OTC_VERIFICATION_FAILED'
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return res.json({redirectUrl});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
async _createHashFromOTCAndToken(otc, token) {
|
|
720
|
+
// timestamp for anti-replay protection (5 minute window)
|
|
721
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
722
|
+
|
|
723
|
+
const hash = this._magicLinkService.tokenProvider.createOTCVerificationHash(otc, token, timestamp);
|
|
724
|
+
|
|
725
|
+
return `${timestamp}:${hash}`;
|
|
726
|
+
}
|
|
727
|
+
|
|
652
728
|
async _handleSignup(req, normalizedEmail, referrer = null) {
|
|
653
729
|
if (!this._allowSelfSignup()) {
|
|
654
730
|
if (this._settingsCache.get('members_signup_access') === 'paid') {
|
|
@@ -684,11 +760,11 @@ module.exports = class RouterController {
|
|
|
684
760
|
}
|
|
685
761
|
|
|
686
762
|
async _handleSignin(req, normalizedEmail, referrer = null) {
|
|
687
|
-
const {emailType,
|
|
763
|
+
const {emailType, includeOTC: reqIncludeOTC} = req.body;
|
|
688
764
|
|
|
689
765
|
let includeOTC = false;
|
|
690
766
|
|
|
691
|
-
if (this.labsService.isSet('membersSigninOTC') && (
|
|
767
|
+
if (this.labsService.isSet('membersSigninOTC') && (reqIncludeOTC === true || reqIncludeOTC === 'true')) {
|
|
692
768
|
includeOTC = true;
|
|
693
769
|
}
|
|
694
770
|
|
|
@@ -235,12 +235,12 @@ module.exports = function MembersAPI({
|
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
async function getTokenDataFromMagicLinkToken(token) {
|
|
239
|
-
return await magicLinkService.getDataFromToken(token);
|
|
238
|
+
async function getTokenDataFromMagicLinkToken(token, otcVerification) {
|
|
239
|
+
return await magicLinkService.getDataFromToken(token, otcVerification);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
async function getMemberDataFromMagicLinkToken(token) {
|
|
243
|
-
const {email, labels = [], name = '', oldEmail, newsletters, attribution, reqIp, type} = await getTokenDataFromMagicLinkToken(token);
|
|
242
|
+
async function getMemberDataFromMagicLinkToken(token, otcVerification) {
|
|
243
|
+
const {email, labels = [], name = '', oldEmail, newsletters, attribution, reqIp, type} = await getTokenDataFromMagicLinkToken(token, otcVerification);
|
|
244
244
|
if (!email) {
|
|
245
245
|
return null;
|
|
246
246
|
}
|
|
@@ -340,6 +340,10 @@ module.exports = function MembersAPI({
|
|
|
340
340
|
body.json(),
|
|
341
341
|
forwardError((req, res) => routerController.sendMagicLink(req, res))
|
|
342
342
|
),
|
|
343
|
+
verifyOTC: Router().use(
|
|
344
|
+
body.json(),
|
|
345
|
+
forwardError((req, res) => routerController.verifyOTC(req, res))
|
|
346
|
+
),
|
|
343
347
|
createCheckoutSession: Router().use(
|
|
344
348
|
body.json(),
|
|
345
349
|
forwardError((req, res) => routerController.createCheckoutSession(req, res))
|
|
@@ -156,12 +156,13 @@ class MembersSSR {
|
|
|
156
156
|
* @method _getMemberDataFromToken
|
|
157
157
|
*
|
|
158
158
|
* @param {JWT} token
|
|
159
|
+
* @param {string} [otcVerification]
|
|
159
160
|
*
|
|
160
161
|
* @returns {Promise<Member>} member
|
|
161
162
|
*/
|
|
162
|
-
async _getMemberDataFromToken(token) {
|
|
163
|
+
async _getMemberDataFromToken(token, otcVerification) {
|
|
163
164
|
const api = await this._getMembersApi();
|
|
164
|
-
return api.getMemberDataFromMagicLinkToken(token);
|
|
165
|
+
return api.getMemberDataFromMagicLinkToken(token, otcVerification);
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
/**
|
|
@@ -234,7 +235,8 @@ class MembersSSR {
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
const token = Array.isArray(query.token) ? query.token[0] : query.token;
|
|
237
|
-
const
|
|
238
|
+
const otcVerification = Array.isArray(query.otc_verification) ? query.otc_verification[0] : query.otc_verification;
|
|
239
|
+
const member = await this._getMemberDataFromToken(token, otcVerification);
|
|
238
240
|
|
|
239
241
|
if (!member) {
|
|
240
242
|
// The member doesn't exist any longer (could be a sign in token for a member that was deleted)
|
|
@@ -332,8 +332,8 @@ const createSessionFromMagicLink = async function createSessionFromMagicLink(req
|
|
|
332
332
|
// req.query is a plain object, copy it to a URLSearchParams object so we can call toString()
|
|
333
333
|
const searchParams = new URLSearchParams('');
|
|
334
334
|
Object.keys(req.query).forEach((param) => {
|
|
335
|
-
// don't copy the "token" or "
|
|
336
|
-
if (param !== 'token' && param !== 'r') {
|
|
335
|
+
// don't copy the "token", "r", or "otc_verification" params
|
|
336
|
+
if (param !== 'token' && param !== 'r' && param !== 'otc_verification') {
|
|
337
337
|
searchParams.set(param, req.query[param]);
|
|
338
338
|
}
|
|
339
339
|
});
|
|
@@ -53,7 +53,12 @@ const TINYBIRD_PIPES = [
|
|
|
53
53
|
'api_top_locations',
|
|
54
54
|
'api_top_os',
|
|
55
55
|
'api_top_pages',
|
|
56
|
-
'api_top_sources'
|
|
56
|
+
'api_top_sources',
|
|
57
|
+
'api_top_utm_sources',
|
|
58
|
+
'api_top_utm_mediums',
|
|
59
|
+
'api_top_utm_campaigns',
|
|
60
|
+
'api_top_utm_contents',
|
|
61
|
+
'api_top_utm_terms'
|
|
57
62
|
];
|
|
58
63
|
|
|
59
64
|
/**
|
|
@@ -189,7 +189,7 @@ class UpdateCheckService {
|
|
|
189
189
|
|
|
190
190
|
try {
|
|
191
191
|
const response = await this.request(checkEndpoint, reqObj);
|
|
192
|
-
return response.body;
|
|
192
|
+
return JSON.parse(response.body);
|
|
193
193
|
} catch (err) {
|
|
194
194
|
// CASE: no notifications available, ignore
|
|
195
195
|
if (err.statusCode === 404) {
|
|
@@ -41,7 +41,7 @@ module.exports = function setupMembersApp() {
|
|
|
41
41
|
// We don't want to add global bodyParser middleware as that interferes with stripe webhook requests on - `/webhooks`.
|
|
42
42
|
|
|
43
43
|
// Manage newsletter subscription via unsubscribe link - these should be authenticated by uuid and hashed key
|
|
44
|
-
membersApp.get('/api/member/newsletters',
|
|
44
|
+
membersApp.get('/api/member/newsletters',
|
|
45
45
|
middleware.authMemberByUuid,
|
|
46
46
|
middleware.getMemberNewsletters
|
|
47
47
|
);
|
|
@@ -59,7 +59,7 @@ module.exports = function setupMembersApp() {
|
|
|
59
59
|
} else {
|
|
60
60
|
membersApp.get('/api/member', middleware.getMemberData);
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
membersApp.put('/api/member', bodyParser.json({limit: '50mb'}), middleware.updateMemberData);
|
|
64
64
|
membersApp.post('/api/member/email', bodyParser.json({limit: '50mb'}), (req, res, next) => membersService.api.middleware.updateEmailAddress(req, res, next));
|
|
65
65
|
|
|
@@ -72,7 +72,6 @@ module.exports = function setupMembersApp() {
|
|
|
72
72
|
|
|
73
73
|
membersApp.get('/api/integrity-token', middleware.createIntegrityToken);
|
|
74
74
|
|
|
75
|
-
// NOTE: this is wrapped in a function to ensure we always go via the getter
|
|
76
75
|
membersApp.post(
|
|
77
76
|
'/api/send-magic-link',
|
|
78
77
|
bodyParser.json(),
|
|
@@ -81,10 +80,20 @@ module.exports = function setupMembersApp() {
|
|
|
81
80
|
shared.middleware.brute.membersAuthEnumeration,
|
|
82
81
|
// Prevent brute forcing passwords for the same email address
|
|
83
82
|
shared.middleware.brute.membersAuth,
|
|
83
|
+
// NOTE: this is wrapped in a function to ensure we always go via the getter
|
|
84
84
|
function lazySendMagicLinkMw(req, res, next) {
|
|
85
85
|
return membersService.api.middleware.sendMagicLink(req, res, next);
|
|
86
86
|
}
|
|
87
87
|
);
|
|
88
|
+
membersApp.post(
|
|
89
|
+
'/api/verify-otc',
|
|
90
|
+
bodyParser.json(),
|
|
91
|
+
middleware.verifyIntegrityToken,
|
|
92
|
+
// NOTE: this is wrapped in a function to ensure we always go via the getter
|
|
93
|
+
function lazyVerifyOTCMw(req, res, next) {
|
|
94
|
+
return membersService.api.middleware.verifyOTC(req, res, next);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
88
97
|
membersApp.post('/api/create-stripe-checkout-session', function lazyCreateCheckoutSessionMw(req, res, next) {
|
|
89
98
|
return membersService.api.middleware.createCheckoutSession(req, res, next);
|
|
90
99
|
});
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
},
|
|
213
213
|
"portal": {
|
|
214
214
|
"url": "https://cdn.jsdelivr.net/ghost/portal@~{version}/umd/portal.min.js",
|
|
215
|
-
"version": "2.
|
|
215
|
+
"version": "2.53"
|
|
216
216
|
},
|
|
217
217
|
"sodoSearch": {
|
|
218
218
|
"url": "https://cdn.jsdelivr.net/ghost/sodo-search@~{version}/umd/sodo-search.min.js",
|
package/core/shared/labs.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ghost",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.8",
|
|
4
4
|
"description": "The professional publishing platform",
|
|
5
5
|
"author": "Ghost Foundation",
|
|
6
6
|
"homepage": "https://ghost.org",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"@tryghost/helpers": "1.1.97",
|
|
87
87
|
"@tryghost/html-to-plaintext": "1.0.4",
|
|
88
88
|
"@tryghost/http-cache-utils": "0.1.20",
|
|
89
|
-
"@tryghost/i18n": "file:components/tryghost-i18n-6.0.
|
|
89
|
+
"@tryghost/i18n": "file:components/tryghost-i18n-6.0.8.tgz",
|
|
90
90
|
"@tryghost/image-transform": "1.4.6",
|
|
91
91
|
"@tryghost/job-manager": "1.0.3",
|
|
92
92
|
"@tryghost/kg-card-factory": "5.1.2",
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
"heic-convert": "2.1.0",
|
|
167
167
|
"html-to-text": "5.1.1",
|
|
168
168
|
"html5parser": "2.0.2",
|
|
169
|
-
"human-number": "2.0.
|
|
169
|
+
"human-number": "2.0.6",
|
|
170
170
|
"iconv-lite": "0.6.3",
|
|
171
171
|
"image-size": "1.2.1",
|
|
172
172
|
"intl": "1.2.5",
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
"knex-migrator": "5.3.2",
|
|
182
182
|
"leaky-bucket": "2.2.0",
|
|
183
183
|
"lodash": "4.17.21",
|
|
184
|
-
"luxon": "3.7.
|
|
184
|
+
"luxon": "3.7.2",
|
|
185
185
|
"mailgun.js": "10.4.0",
|
|
186
186
|
"metascraper": "5.45.15",
|
|
187
187
|
"metascraper-author": "5.45.10",
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
"@types/bookshelf": "1.2.9",
|
|
233
233
|
"@types/common-tags": "1.8.4",
|
|
234
234
|
"@types/jsonwebtoken": "9.0.10",
|
|
235
|
-
"@types/node": "22.18.
|
|
235
|
+
"@types/node": "22.18.3",
|
|
236
236
|
"@types/node-jose": "1.1.13",
|
|
237
237
|
"@types/nodemailer": "6.4.19",
|
|
238
238
|
"@types/sinon": "17.0.4",
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
"inquirer": "8.2.7",
|
|
251
251
|
"jwk-to-pem": "2.0.7",
|
|
252
252
|
"jwks-rsa": "3.2.0",
|
|
253
|
-
"mocha": "11.7.
|
|
253
|
+
"mocha": "11.7.2",
|
|
254
254
|
"mocha-slow-test-reporter": "0.1.2",
|
|
255
255
|
"mock-knex": "TryGhost/mock-knex#68948e11b0ea4fe63456098dfdc169bea7f62009",
|
|
256
256
|
"nock": "13.5.6",
|
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
"jackspeak": "2.3.6",
|
|
274
274
|
"moment": "2.24.0",
|
|
275
275
|
"moment-timezone": "0.5.45",
|
|
276
|
-
"@tryghost/i18n": "file:components/tryghost-i18n-6.0.
|
|
276
|
+
"@tryghost/i18n": "file:components/tryghost-i18n-6.0.8.tgz"
|
|
277
277
|
},
|
|
278
278
|
"nx": {
|
|
279
279
|
"targets": {
|