,
+ ) => {
+ const rows = await subscriptionRowsFor(email);
+ const before = await knex()('members_stripe_customers_subscriptions')
+ .whereIn(
+ 'id',
+ rows.map((row: { id: string }) => row.id),
+ )
+ .select('id', 'offer_id', 'discount_start', 'discount_end');
+
+ try {
+ await knex()('members_stripe_customers_subscriptions')
+ .whereIn(
+ 'id',
+ rows.map((row: { id: string }) => row.id),
+ )
+ .update({ offer_id: offer.id, ...window });
+
+ await membersAgent.loginAs(email);
+ const request = membersAgent.get('/api/member/').expectStatus(200);
+ if (snapshot) {
+ request.matchHeaderSnapshot({ etag: anyEtag }).matchBodySnapshot(snapshot);
+ }
+ const { body } = await request;
+ await check(body);
+ } finally {
+ for (const row of before) {
+ await knex()('members_stripe_customers_subscriptions').where('id', row.id).update({
+ offer_id: row.offer_id,
+ discount_start: row.discount_start,
+ discount_end: row.discount_end,
+ });
+ }
+ }
+ };
+
+ it('takes a percentage off while the discount is running', async function () {
+ const offer = await createOffer({ type: 'percent', amount: 10, duration: 'forever' });
+
+ await withOffer(
+ 'paid@test.com',
+ offer,
+ { discount_start: new Date(Date.now() - DAY), discount_end: null },
+ (body) => {
+ const [subscription] = body.subscriptions;
+ assert.ok(subscription.offer, 'the subscription carries the offer it was given');
+ assert.equal(subscription.offer.id, offer.id);
+ assert.ok(subscription.next_payment.discount, 'the discount is found');
+ assert.equal(subscription.next_payment.discount.offer_id, offer.id);
+ assert.equal(subscription.next_payment.discount.type, 'percent');
+ assert.equal(
+ subscription.next_payment.amount,
+ Math.round(subscription.next_payment.original_amount * 0.9),
+ );
+ // Only present on a Stripe-backed subscription, and only once a
+ // discount window exists on the row.
+ assert.ok(subscription.discount_start, 'the window start reaches the member');
+ },
+ { ...memberMatcher(1), subscriptions: [discountedSubscriptionMatcher] },
+ );
+ });
+
+ it('takes a fixed amount off while the discount is running', async function () {
+ const offer = await createOffer({
+ type: 'fixed',
+ amount: 100,
+ currency: 'gbp',
+ duration: 'forever',
+ });
+
+ await withOffer(
+ 'paid@test.com',
+ offer,
+ { discount_start: new Date(Date.now() - DAY), discount_end: null },
+ (body) => {
+ const [subscription] = body.subscriptions;
+ assert.equal(subscription.next_payment.discount.type, 'fixed');
+ assert.equal(
+ subscription.next_payment.amount,
+ subscription.next_payment.original_amount - 100,
+ );
+ },
+ );
+ });
+
+ it('charges the full amount once the discount has run out', async function () {
+ const offer = await createOffer({ duration: 'repeating', duration_in_months: 3 });
+
+ await withOffer(
+ 'paid@test.com',
+ offer,
+ {
+ discount_start: new Date(Date.now() - 90 * DAY),
+ discount_end: new Date(Date.now() - DAY),
+ },
+ (body) => {
+ const [subscription] = body.subscriptions;
+ // The offer is still attached and still reported. What changed is that
+ // it no longer bears on what is owed next, which is a different fact
+ // and is why both are in the response.
+ assert.ok(subscription.offer, 'the offer is still named');
+ assert.equal(subscription.next_payment.discount, null);
+ assert.equal(
+ subscription.next_payment.amount,
+ subscription.next_payment.original_amount,
+ );
+ },
+ );
+ });
+
+ it('charges the full amount for a free-trial offer', async function () {
+ const offer = await createOffer({ type: 'trial', amount: 14, duration: 'trial' });
+
+ await withOffer(
+ 'paid@test.com',
+ offer,
+ { discount_start: new Date(Date.now() - DAY), discount_end: null },
+ (body) => {
+ const [subscription] = body.subscriptions;
+ // A trial offer changes when the next payment falls, not what it is.
+ assert.equal(subscription.next_payment.discount, null);
+ assert.equal(
+ subscription.next_payment.amount,
+ subscription.next_payment.original_amount,
+ );
+ },
+ );
+ });
+ });
+
+ it('includes a newsletter the publisher has archived', async function () {
+ // Archived newsletters are excluded from what a publisher offers, but a
+ // member already on one keeps receiving it, so it stays in their list.
+ // Pinned because nothing said either way, and the write path depends on it:
+ // a client round-tripping this list must not unsubscribe them.
+ const archived = await models.Base.knex('newsletters')
+ .where('status', 'archived')
+ .select('id');
+ assert.ok(archived.length > 0, 'the site has an archived newsletter to test with');
+
+ await membersAgent.loginAs('vip@test.com');
+
+ const { body } = await membersAgent.get('/api/member/').expectStatus(200);
+ const ids = body.newsletters.map((newsletter: { id: string }) => newsletter.id);
+
+ // The point of the case, rather than the list merely being non-empty: one of
+ // the newsletters a member is told they receive is one the publisher has
+ // stopped offering.
+ assert.ok(
+ archived.some((newsletter: { id: string }) => ids.includes(newsletter.id)),
+ 'an archived newsletter is still listed for the member',
+ );
+ });
+
+ it('projects a comped member with a synthesized subscription', async function () {
+ await membersAgent.loginAs(COMPED_EMAIL);
+
+ await membersAgent
+ .get('/api/member/')
+ .expectStatus(200)
+ .matchHeaderSnapshot({ etag: anyEtag })
+ .matchBodySnapshot({
+ ...memberMatcher(0),
+ subscriptions: [compedSubscriptionMatcher],
+ })
+ .expect(({ body }: { body: any }) => {
+ // A comped member has no Stripe subscription. The one here is built
+ // from the member's products, so it is the clearest evidence that the
+ // assembly ran rather than the row being passed through.
+ assert.equal(body.status, 'comped');
+ assert.equal(body.subscriptions.length, 1);
+ assert.equal(body.subscriptions[0].plan.nickname, 'Complimentary');
+ assert.equal(body.subscriptions[0].id, '');
+ });
+ });
+ });
+
+ describe('write', function () {
+ it('applies only the fields a member may change about themselves', async function () {
+ await membersAgent.loginAs(WRITABLE_EMAIL);
+ const before = await models.Member.findOne({ email: WRITABLE_EMAIL }, { require: true });
+
+ await membersAgent
+ .put('/api/member/')
+ .body({
+ name: 'Renamed',
+ expertise: 'Head of Testing',
+ // Everything below is outside the write projection. Each is dropped
+ // rather than refused, so the rest of the body still applies —
+ // `email` is the precedent: it is readable, ignored on write, and
+ // changed through a dedicated endpoint that verifies by magic link.
+ email: 'somebody-else@example.com',
+ status: 'comped',
+ labels: [{ name: 'VIP' }],
+ uuid: '00000000-0000-0000-0000-000000000000',
+ created_at: '2000-01-01T00:00:00.000Z',
+ })
+ .expectStatus(200)
+ .expect(({ body }: { body: any }) => {
+ assert.equal(body.name, 'Renamed');
+ assert.equal(body.expertise, 'Head of Testing');
+ assert.equal(body.email, WRITABLE_EMAIL);
+ assert.equal(body.status, 'free');
+ assert.equal(body.uuid, before.get('uuid'));
+ });
+
+ const after = await models.Member.findOne({ email: WRITABLE_EMAIL }, { require: true });
+ assert.equal(after.get('name'), 'Renamed');
+ assert.equal(after.get('status'), 'free');
+ assert.equal(after.get('uuid'), before.get('uuid'));
+ assert.equal((await after.related('labels').fetch()).length, 0);
+ });
+
+ it('trims the whitespace around an expertise', async function () {
+ await membersAgent.loginAs(WRITABLE_EMAIL);
+
+ const { body } = await membersAgent
+ .put('/api/member/')
+ .body({ expertise: ' Head of Testing ' })
+ .expectStatus(200);
+
+ // Trimmed on the way in rather than on the way out, so what is stored is
+ // what every other reader of this member sees too.
+ assert.equal(body.expertise, 'Head of Testing');
+ });
+
+ it('sets the newsletters a member asked for, and says so back', async function () {
+ await membersAgent.loginAs(WRITABLE_EMAIL);
+ const active = await models.Base.knex('newsletters')
+ .where('status', 'active')
+ .orderBy('sort_order', 'asc')
+ .select('id', 'name');
+ assert.ok(active.length > 0, 'the site offers a newsletter to subscribe to');
+
+ const { body } = await membersAgent
+ .put('/api/member/')
+ .body({ newsletters: [{ id: active[0].id }] })
+ .expectStatus(200);
+
+ // The response is the member re-read, not the request echoed, so this is
+ // also what says the write reached the join table rather than being dropped.
+ assert.deepEqual(
+ body.newsletters.map((newsletter: { id: string }) => newsletter.id),
+ [active[0].id],
+ );
+ });
+
+ it('unsubscribes and resubscribes a member through the one flag', async function () {
+ await membersAgent.loginAs(WRITABLE_EMAIL);
+
+ const { body: off } = await membersAgent
+ .put('/api/member/')
+ .body({ subscribed: false })
+ .expectStatus(200);
+ assert.deepEqual(off.newsletters, [], 'false detaches every newsletter');
+
+ const { body: on } = await membersAgent
+ .put('/api/member/')
+ .body({ subscribed: true })
+ .expectStatus(200);
+
+ // `subscribed` is older than newsletters being a list, and it still has to
+ // mean something. With none attached it re-subscribes the member to the
+ // ones a publisher puts new signups on, which is not the same as restoring
+ // what they had before, so the set is named rather than counted.
+ const onSignup = await models.Base.knex('newsletters')
+ .where({ status: 'active', subscribe_on_signup: true, visibility: 'members' })
+ .orderBy('sort_order', 'asc')
+ .select('id');
+
+ assert.deepEqual(
+ on.newsletters.map((newsletter: { id: string }) => newsletter.id).sort(),
+ onSignup.map((newsletter: { id: string }) => newsletter.id).sort(),
+ );
+ });
+ });
+});
diff --git a/ghost/core/test/e2e-api/members/middleware.test.js b/ghost/core/test/e2e-api/members/middleware.test.js
index b18e580fcb6..34d7d9f8516 100644
--- a/ghost/core/test/e2e-api/members/middleware.test.js
+++ b/ghost/core/test/e2e-api/members/middleware.test.js
@@ -160,6 +160,82 @@ describe('Comments API', function () {
assert.equal(member.get('expertise'), 'Head of Testing');
});
+ describe('and subscribed to a newsletter the publisher has archived', function () {
+ let archived;
+ let active;
+ let name;
+
+ beforeEach(async function () {
+ name = member.get('name');
+ archived = await models.Newsletter.add(
+ {
+ name: 'Archived for resubscribe test',
+ status: 'archived',
+ visibility: 'members',
+ subscribe_on_signup: false,
+ sort_order: 100,
+ },
+ { context: { internal: true } },
+ );
+
+ const before = await models.Member.findOne(
+ { id: member.id },
+ { require: true, withRelated: ['newsletters'] },
+ );
+ active = before.related('newsletters').models.map((n) => ({ id: n.id }));
+ assert.ok(active.length > 0, 'the member starts with an active newsletter');
+
+ await models.Member.edit(
+ {
+ newsletters: [...active, { id: archived.id }],
+ },
+ { id: member.id, context: { internal: true } },
+ );
+ });
+
+ afterEach(async function () {
+ await models.Member.edit(
+ { name, newsletters: active },
+ { id: member.id, context: { internal: true } },
+ );
+ await models.Newsletter.destroy({ id: archived.id, context: { internal: true } });
+ member = await models.Member.findOne({ id: member.id }, { require: true });
+ });
+
+ it('can still resubscribe', async function () {
+ await membersAgent.put(`/api/member/`).body({ subscribed: true }).expectStatus(200);
+
+ const after = await models.Member.findOne(
+ { id: member.id },
+ { require: true, withRelated: ['newsletters'] },
+ );
+ const ids = after.related('newsletters').models.map((n) => n.id);
+
+ assert.ok(ids.includes(archived.id), 'the archived newsletter is kept');
+ for (const { id } of active) {
+ assert.ok(ids.includes(id), 'the active newsletters are kept');
+ }
+ });
+
+ it('keeps the archived newsletter when changing something unrelated', async function () {
+ await membersAgent
+ .put(`/api/member/`)
+ .body({ name: 'Renamed with an archived newsletter' })
+ .expectStatus(200);
+
+ const after = await models.Member.findOne(
+ { id: member.id },
+ { require: true, withRelated: ['newsletters'] },
+ );
+ const ids = after.related('newsletters').models.map((n) => n.id);
+
+ assert.ok(ids.includes(archived.id), 'the archived newsletter is kept');
+ for (const { id } of active) {
+ assert.ok(ids.includes(id), 'the active newsletters are kept');
+ }
+ });
+ });
+
it('trims whitespace from expertise', async function () {
await membersAgent
.put(`/api/member/`)
diff --git a/ghost/core/test/e2e-frontend/members.test.js b/ghost/core/test/e2e-frontend/members.test.js
index 92fba189ed9..b2a739eb127 100644
--- a/ghost/core/test/e2e-frontend/members.test.js
+++ b/ghost/core/test/e2e-frontend/members.test.js
@@ -972,6 +972,67 @@ describe('Front-end members behavior', function () {
);
});
+ // @member is narrowed from the same member payload the members API
+ // narrows separately, through its own allowlist and its own code. Pinning
+ // it here is what makes a change to the assembly behind both of them
+ // visible when it reaches one surface and not the other. The theme's own
+ // narrowing is not under test: what a theme may see is a versioned part
+ // of Ghost's theme API and is asserted, not derived.
+ it('exposes a fixed set of member fields to a theme', async function () {
+ const res = await request.get('/free-to-see/').expect(200);
+
+ const keysOf = (className) => {
+ const match = res.text.match(new RegExp(`([^<]*)
`));
+ assertExists(match, `theme rendered ${className}`);
+ return new Set(match[1].trim().split(/\s+/).filter(Boolean));
+ };
+
+ assert.deepEqual(
+ keysOf('gh-test-member-keys'),
+ new Set([
+ 'uuid',
+ 'email',
+ 'name',
+ 'firstname',
+ 'avatar_image',
+ 'subscriptions',
+ 'paid',
+ 'status',
+ ]),
+ );
+
+ assert.deepEqual(
+ keysOf('gh-test-member-subscription-keys'),
+ new Set([
+ 'id',
+ 'customer',
+ 'status',
+ 'start_date',
+ 'default_payment_card_last4',
+ 'cancel_at_period_end',
+ 'cancellation_reason',
+ 'current_period_end',
+ 'plan',
+ 'price',
+ 'tier',
+ 'trial_start_at',
+ 'trial_end_at',
+ 'discount_start',
+ 'discount_end',
+ 'offer',
+ 'offer_redemptions',
+ 'next_payment',
+ 'attribution',
+ ]),
+ );
+
+ // The one @member value the theme's own narrowing rewrites: it
+ // substitutes `****` when Stripe reports no card. Pinned to the digits
+ // this member actually has, so a card that is there still reaches the
+ // theme rather than the placeholder standing in for it.
+ assert.match(res.text, /4242<\/p>/);
+ });
+
it('can read public post content', async function () {
await request.get('/free-to-see/').expect(200).expect(assertContentIsPresent);
});
diff --git a/ghost/core/test/unit/server/adapters/jobs/in-memory-jobs-backend.test.ts b/ghost/core/test/unit/server/adapters/jobs/in-memory-jobs-backend.test.ts
index 119359a9879..694ce643c0a 100644
--- a/ghost/core/test/unit/server/adapters/jobs/in-memory-jobs-backend.test.ts
+++ b/ghost/core/test/unit/server/adapters/jobs/in-memory-jobs-backend.test.ts
@@ -14,20 +14,53 @@ describe('InMemoryJobsBackend', function () {
assert.deepEqual(backend.requiredFns, ['start', 'enqueue', 'scheduleRecurring', 'shutdown']);
});
- it('buffers envelopes enqueued before start, then delivers on start', async function () {
- const received: JobEnvelope[] = [];
+ // Boot starts the jobs service before the web app is mounted or any
+ // recurring job is scheduled, so a pre-start enqueue or schedule is a
+ // boot-ordering bug.
+ it('throws on an enqueue before start instead of silently losing the job', function () {
const backend = new InMemoryJobsBackend();
+ assert.throws(
+ () => backend.enqueue({ type: 'early', payload: '{}' }),
+ /before the jobs backend is started/,
+ );
+ });
- backend.enqueue({ type: 'buffered', payload: '{"n":1}' });
+ // A silently accepted pre-start schedule would throw from enqueue inside
+ // the timer callback later - an uncaughtException - so it must fail at the
+ // registration site instead.
+ it('throws on a recurring schedule before start instead of arming a delayed crash', function () {
+ const backend = new InMemoryJobsBackend();
+ assert.throws(
+ () => backend.scheduleRecurring({ type: 'early', payload: '{}' }, { cron: '0 0 3 * * *' }),
+ /before the jobs backend is started/,
+ );
+ });
- backend.start({
- processor: async (env) => {
- received.push(env);
- },
- });
- await backend.shutdown({ timeoutMs: 1000 });
+ it('rejects an invalid declared queue concurrency at start instead of silently ignoring it', function () {
+ const backend = new InMemoryJobsBackend();
+ const processor = async () => {};
+ assert.throws(
+ () => backend.start({ processor, queues: { slow: { concurrency: 0 } } }),
+ /declared queue "slow"/,
+ );
+ assert.throws(
+ () => backend.start({ processor, queues: { slow: { concurrency: NaN } } }),
+ /declared queue "slow"/,
+ );
+ });
- assert.deepEqual(received, [{ type: 'buffered', payload: '{"n":1}' }]);
+ it('stays un-started when start rejects a declaration, so no work is accepted', function () {
+ const backend = new InMemoryJobsBackend();
+ assert.throws(() =>
+ backend.start({
+ processor: async () => {},
+ queues: { ok: { concurrency: 1 }, bad: { concurrency: 0 } },
+ }),
+ );
+ assert.throws(
+ () => backend.enqueue({ type: 'early', payload: '{}' }),
+ /before the jobs backend is started/,
+ );
});
it('caps concurrent deliveries at the default concurrency', async function () {
@@ -223,6 +256,82 @@ describe('InMemoryJobsBackend', function () {
assert.deepEqual(received, ['fresh'], 'a re-boot starts new work despite prior hung handlers');
});
+ describe('queue routing', function () {
+ // Tracks per-lane concurrency by tagging each envelope with its lane.
+ function makeLaneTracker() {
+ const running = new Map();
+ const max = new Map();
+ const release: Array<() => void> = [];
+ const processor = async (env: JobEnvelope) => {
+ const lane = JSON.parse(env.payload).lane as string;
+ running.set(lane, (running.get(lane) ?? 0) + 1);
+ max.set(lane, Math.max(max.get(lane) ?? 0, running.get(lane)!));
+ await new Promise((resolve) => {
+ release.push(resolve);
+ });
+ running.set(lane, running.get(lane)! - 1);
+ };
+ return { max, release, processor };
+ }
+
+ async function drainAndShutdown(
+ backend: InMemoryJobsBackend,
+ release: Array<() => void>,
+ ): Promise {
+ release.forEach((resolve) => resolve());
+ const releaser = setInterval(() => release.forEach((resolve) => resolve()), 5);
+ await backend.shutdown({ timeoutMs: 2000 });
+ clearInterval(releaser);
+ }
+
+ it('runs a declared queue at its own concurrency without occupying the default lane', async function () {
+ const { max, release, processor } = makeLaneTracker();
+ const backend = new InMemoryJobsBackend();
+
+ backend.start({ processor, queues: { webmentions: { concurrency: 1 } } });
+
+ for (let i = 0; i < 4; i = i + 1) {
+ backend.enqueue(
+ { type: 'webmention', payload: '{"lane":"webmentions"}' },
+ { queue: 'webmentions' },
+ );
+ backend.enqueue({ type: 'work', payload: '{"lane":"default"}' });
+ }
+ await new Promise((resolve) => {
+ setTimeout(resolve, 20);
+ });
+
+ assert.equal(max.get('webmentions'), 1, 'the declared queue runs serially');
+ assert.equal(max.get('default'), 3, 'a busy declared queue does not occupy default workers');
+
+ await drainAndShutdown(backend, release);
+ });
+
+ it('drains in-flight work on every lane at shutdown', async function () {
+ const completed: string[] = [];
+ const backend = new InMemoryJobsBackend();
+
+ backend.start({
+ processor: async (env) => {
+ await new Promise((resolve) => {
+ setTimeout(resolve, 20);
+ });
+ completed.push(env.type);
+ },
+ queues: { webmentions: { concurrency: 1 } },
+ });
+
+ backend.enqueue({ type: 'webmention', payload: '{}' }, { queue: 'webmentions' });
+ backend.enqueue({ type: 'work', payload: '{}' });
+ await new Promise((resolve) => {
+ setTimeout(resolve, 5);
+ });
+ await backend.shutdown({ timeoutMs: 2000 });
+
+ assert.deepEqual(completed.sort(), ['webmention', 'work']);
+ });
+ });
+
describe('recurring schedules', function () {
let clock: { tickAsync(ms: number): Promise; restore(): void } | undefined;
diff --git a/ghost/core/test/unit/server/services/gifts/gift-service-interface.test.ts b/ghost/core/test/unit/server/services/gifts/gift-service-interface.test.ts
index a54ed0b59fa..34c12b55837 100644
--- a/ghost/core/test/unit/server/services/gifts/gift-service-interface.test.ts
+++ b/ghost/core/test/unit/server/services/gifts/gift-service-interface.test.ts
@@ -20,11 +20,7 @@ describe('GiftService interface', function () {
sinon.restore();
});
- function createService({
- customizationEnabled = false,
- portalPlans = ['monthly', 'yearly'],
- timezone = 'Etc/UTC',
- } = {}) {
+ function createService({ portalPlans = ['monthly', 'yearly'], timezone = 'Etc/UTC' } = {}) {
const tier = {
id: {
toHexString: () => 'tier_1',
@@ -85,9 +81,6 @@ describe('GiftService interface', function () {
staffServiceEmails: {},
giftReminderScheduler: {},
checkoutAdapter,
- labsService: {
- isSet: sinon.stub().withArgs('giftSubCustomization').returns(customizationEnabled),
- },
settingsCache: {
get: settingsGet,
},
@@ -108,7 +101,6 @@ describe('GiftService interface', function () {
const result = await service.startCheckout({
tierId: 'tier_1',
cadence: 'year',
- duration: 1,
successUrl: 'https://example.com/',
cancelUrl: 'https://example.com/cancel/',
buyer: {
@@ -142,14 +134,12 @@ describe('GiftService interface', function () {
assert.equal(successUrl.searchParams.get('gift_token'), createdGift.token);
assert.equal(successUrl.searchParams.get('gift_tier'), 'tier_1');
assert.equal(successUrl.searchParams.get('gift_cadence'), 'year');
- assert.equal(successUrl.searchParams.get('gift_duration'), null);
+ assert.equal(successUrl.searchParams.get('gift_duration'), '12');
assert.equal(successUrl.searchParams.get('gift_delivery'), 'link');
});
it('validates email delivery and keeps recipient PII out of Stripe metadata', async function () {
- const { service, checkoutAdapter, giftRepository, giftDeliveryService } = createService({
- customizationEnabled: true,
- });
+ const { service, checkoutAdapter, giftRepository, giftDeliveryService } = createService();
await service.startCheckout({
tierId: 'tier_1',
@@ -190,7 +180,6 @@ describe('GiftService interface', function () {
it('stores a scheduled email delivery as 09:00 in the publication timezone', async function () {
const clock = sinon.useFakeTimers(new Date('2026-08-18T12:00:00.000Z'));
const { service, checkoutAdapter, giftRepository, giftDeliveryService } = createService({
- customizationEnabled: true,
timezone: 'America/Los_Angeles',
});
@@ -230,7 +219,7 @@ describe('GiftService interface', function () {
it('rejects delivery dates beyond the next publication-calendar year', async function () {
const clock = sinon.useFakeTimers(new Date('2026-08-18T12:00:00.000Z'));
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
+ const { service, checkoutAdapter } = createService();
await assert.rejects(
() =>
@@ -258,7 +247,7 @@ describe('GiftService interface', function () {
it('accepts delivery exactly 365 publication-calendar days ahead', async function () {
const clock = sinon.useFakeTimers(new Date('2026-08-18T12:00:00.000Z'));
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
+ const { service, checkoutAdapter } = createService();
await service.startCheckout({
tierId: 'tier_1',
@@ -281,7 +270,7 @@ describe('GiftService interface', function () {
});
it('prefers the checkout buyer name over the authenticated member name', async function () {
- const { service, giftRepository } = createService({ customizationEnabled: true });
+ const { service, giftRepository } = createService();
await service.startCheckout({
tierId: 'tier_1',
@@ -339,7 +328,7 @@ describe('GiftService interface', function () {
for (const { name, overrides, expected } of invalidCheckouts) {
it(`rejects ${name}`, async function () {
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
+ const { service, checkoutAdapter } = createService();
await assert.rejects(
() =>
@@ -363,7 +352,7 @@ describe('GiftService interface', function () {
}
it('keeps link gifts anonymous when buyer name is omitted', async function () {
- const { service, giftRepository } = createService({ customizationEnabled: true });
+ const { service, giftRepository } = createService();
await service.startCheckout({
tierId: 'tier_1',
@@ -387,45 +376,9 @@ describe('GiftService interface', function () {
assert.equal(gift.personalMessage, null);
});
- it('keeps omitted and explicit link delivery compatible while the flag is disabled', async function () {
- const { service, checkoutAdapter } = createService();
- const base = {
- tierId: 'tier_1',
- cadence: 'year',
- successUrl: 'https://example.com/',
- buyer: {
- memberId: null,
- email: 'buyer@example.com',
- name: null,
- isAuthenticated: false,
- },
- };
-
- await service.startCheckout(base);
- await service.startCheckout({ ...base, deliveryMethod: 'link' });
- await assert.rejects(
- () =>
- service.startCheckout({
- ...base,
- deliveryMethod: 'email',
- recipientEmail: 'recipient@example.com',
- }),
- { context: 'Gift email delivery is not available' },
- );
- await assert.rejects(
- () =>
- service.startCheckout({
- ...base,
- buyerName: 'Buyer',
- }),
- { context: 'Gift email delivery is not available' },
- );
- assert.equal(checkoutAdapter.createSession.callCount, 2);
- });
-
for (const duration of [3, 6]) {
it(`owns the customized ${duration}-month checkout decision`, async function () {
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
+ const { service, checkoutAdapter } = createService();
await service.startCheckout({
tierId: 'tier_1',
@@ -450,34 +403,9 @@ describe('GiftService interface', function () {
});
}
- it('ignores customized duration input while the flag is disabled', async function () {
+ it('keeps cadence-only clients compatible', async function () {
const { service, checkoutAdapter } = createService();
- await service.startCheckout({
- tierId: 'tier_1',
- cadence: 'year',
- duration: 3,
- successUrl: 'https://example.com/',
- buyer: {
- memberId: null,
- email: 'buyer@example.com',
- name: null,
- isAuthenticated: false,
- },
- });
-
- const plan = checkoutAdapter.createSession.firstCall.firstArg;
- const successUrl = new URL(plan.successUrl);
-
- assert.equal(plan.cadence, 'year');
- assert.equal(plan.duration, 1);
- assert.equal(plan.amount, 12000);
- assert.equal(successUrl.searchParams.get('gift_duration'), null);
- });
-
- it('keeps cadence-only clients compatible while customization is enabled', async function () {
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
-
await service.startCheckout({
tierId: 'tier_1',
cadence: 'year',
@@ -501,7 +429,6 @@ describe('GiftService interface', function () {
it('enforces the Portal plan gate for explicit customized durations', async function () {
const { service, checkoutAdapter } = createService({
- customizationEnabled: true,
portalPlans: ['yearly'],
});
@@ -525,7 +452,7 @@ describe('GiftService interface', function () {
});
it('rejects unsupported or conflicting customized durations', async function () {
- const { service, checkoutAdapter } = createService({ customizationEnabled: true });
+ const { service, checkoutAdapter } = createService();
const buyer = {
memberId: null,
email: 'buyer@example.com',
diff --git a/ghost/core/test/unit/server/services/gifts/gift-service.test.ts b/ghost/core/test/unit/server/services/gifts/gift-service.test.ts
index f48472391ba..f8f4ecd3b4c 100644
--- a/ghost/core/test/unit/server/services/gifts/gift-service.test.ts
+++ b/ghost/core/test/unit/server/services/gifts/gift-service.test.ts
@@ -260,9 +260,6 @@ describe('GiftService', function () {
staffServiceEmails,
giftReminderScheduler,
checkoutAdapter,
- labsService: {
- isSet: sinon.stub().returns(false),
- },
settingsCache: {
get: settingsCacheGet,
},
diff --git a/ghost/core/test/unit/server/services/jobs-service/jobs-service.test.ts b/ghost/core/test/unit/server/services/jobs-service/jobs-service.test.ts
index 55221fdfd3e..75bd8d877f5 100644
--- a/ghost/core/test/unit/server/services/jobs-service/jobs-service.test.ts
+++ b/ghost/core/test/unit/server/services/jobs-service/jobs-service.test.ts
@@ -3,6 +3,7 @@ import { describe, it, beforeEach } from 'vitest';
import type {
JobsBackendBase,
JobEnvelope,
+ JobRouting,
JobsStartOptions,
JobProcessor,
RecurringSchedule,
@@ -12,26 +13,33 @@ import {
JobsService,
JobsLogger,
JobsErrorReporter,
+ JobHandlingOptions,
} from '../../../../../core/server/services/jobs-service/jobs-service';
import { Job } from '../../../../../core/server/services/jobs-service/job';
class FakeBackend implements JobsBackendBase {
readonly requiredFns = ['start', 'enqueue', 'scheduleRecurring', 'shutdown'] as const;
processor: JobProcessor | null = null;
- enqueued: JobEnvelope[] = [];
- recurring: { envelope: JobEnvelope; schedule: RecurringSchedule }[] = [];
+ startOptions: JobsStartOptions | null = null;
+ enqueued: { envelope: JobEnvelope; routing?: JobRouting }[] = [];
+ recurring: { envelope: JobEnvelope; schedule: RecurringSchedule; routing?: JobRouting }[] = [];
shutdownCalls: (JobsShutdownOptions | undefined)[] = [];
start(options: JobsStartOptions): void {
this.processor = options.processor;
+ this.startOptions = options;
}
- enqueue(envelope: JobEnvelope): void {
- this.enqueued.push(envelope);
+ enqueue(envelope: JobEnvelope, routing?: JobRouting): void {
+ this.enqueued.push({ envelope, routing });
}
- scheduleRecurring(envelope: JobEnvelope, schedule: RecurringSchedule): void {
- this.recurring.push({ envelope, schedule });
+ scheduleRecurring(
+ envelope: JobEnvelope,
+ schedule: RecurringSchedule,
+ routing?: JobRouting,
+ ): void {
+ this.recurring.push({ envelope, schedule, routing });
}
shutdown(options?: JobsShutdownOptions): void {
@@ -40,7 +48,7 @@ class FakeBackend implements JobsBackendBase {
async deliver(index = 0): Promise {
assert.ok(this.processor, 'processor must be wired via start()');
- await this.processor!(this.enqueued[index]!);
+ await this.processor!(this.enqueued[index]!.envelope);
}
}
@@ -106,6 +114,71 @@ describe('JobsService', function () {
service.handle(GreetJob, async () => {});
assert.throws(() => service.handle(GreetJob, async () => {}), /already registered/);
});
+
+ it('rejects an invalid concurrency at registration', function () {
+ const service = makeService();
+ assert.throws(
+ () => service.handle(GreetJob, async () => {}, { queue: 'slow', concurrency: 0 }),
+ /Invalid concurrency/,
+ );
+ assert.throws(
+ () => service.handle(GreetJob, async () => {}, { queue: 'slow', concurrency: 1.5 }),
+ /Invalid concurrency/,
+ );
+ assert.throws(
+ () =>
+ service.handle(GreetJob, async () => {}, {
+ queue: 'slow',
+ } as unknown as JobHandlingOptions),
+ /Invalid concurrency/,
+ );
+ });
+
+ it('rejects an invalid or missing queue name at registration', function () {
+ const service = makeService();
+ assert.throws(
+ () => service.handle(GreetJob, async () => {}, { queue: '', concurrency: 1 }),
+ /Invalid queue/,
+ );
+ assert.throws(
+ () =>
+ service.handle(GreetJob, async () => {}, {
+ concurrency: 1,
+ } as unknown as JobHandlingOptions),
+ /Invalid queue/,
+ );
+ });
+
+ it('reserves the "default" queue name for the shared lane', function () {
+ const service = makeService();
+ assert.throws(
+ () => service.handle(GreetJob, async () => {}, { queue: 'default', concurrency: 1 }),
+ /reserved for the shared lane/,
+ );
+ });
+
+ it('rejects conflicting concurrency declarations for one queue', function () {
+ const service = makeService();
+ class OtherJob extends Job {
+ static type = 'other';
+ }
+ service.handle(GreetJob, async () => {}, { queue: 'slow', concurrency: 1 });
+ assert.throws(
+ () => service.handle(OtherJob, async () => {}, { queue: 'slow', concurrency: 2 }),
+ /Conflicting concurrency for queue "slow"/,
+ );
+ });
+
+ it('lets a second type join a queue by declaring the same concurrency', function () {
+ const service = makeService();
+ class OtherJob extends Job {
+ static type = 'other';
+ }
+ service.handle(GreetJob, async () => {}, { queue: 'slow', concurrency: 1 });
+ assert.doesNotThrow(() =>
+ service.handle(OtherJob, async () => {}, { queue: 'slow', concurrency: 1 }),
+ );
+ });
});
describe('dispatch', function () {
@@ -114,7 +187,7 @@ describe('JobsService', function () {
await service.dispatch(new GreetJob({ name: 'Ada' }));
assert.equal(backend.enqueued.length, 1);
- const envelope = backend.enqueued[0]!;
+ const envelope = backend.enqueued[0]!.envelope;
assert.equal(envelope.type, 'greet');
assert.equal(typeof envelope.payload, 'string');
assert.deepEqual(JSON.parse(envelope.payload), { name: 'Ada' });
@@ -144,6 +217,57 @@ describe('JobsService', function () {
});
});
+ describe('queue routing', function () {
+ it('routes a dispatched job to its handler-declared queue', async function () {
+ const service = makeService();
+ service.handle(GreetJob, async () => {}, { queue: 'greetings', concurrency: 2 });
+
+ await service.dispatch(new GreetJob({ name: 'Ada' }));
+
+ assert.deepEqual(backend.enqueued[0]!.routing, { queue: 'greetings' });
+ });
+
+ it('routing stays out of the envelope: no extra envelope fields from queue config', async function () {
+ const service = makeService();
+ service.handle(GreetJob, async () => {}, { queue: 'greetings', concurrency: 2 });
+
+ await service.dispatch(new GreetJob({ name: 'Ada' }));
+
+ assert.deepEqual(Object.keys(backend.enqueued[0]!.envelope).sort(), ['payload', 'type']);
+ });
+
+ it('dispatches with no routing when the type declares no queue', async function () {
+ const service = makeService();
+ service.handle(GreetJob, async () => {});
+
+ await service.dispatch(new GreetJob({ name: 'Ada' }));
+
+ assert.equal(backend.enqueued[0]!.routing, undefined);
+ });
+
+ it('hands declared queues to the backend on start', async function () {
+ const service = makeService();
+ class OtherJob extends Job {
+ static type = 'other';
+ }
+ service.handle(GreetJob, async () => {}, { queue: 'webmentions', concurrency: 1 });
+ service.handle(OtherJob, async () => {}, { queue: 'webmentions', concurrency: 1 });
+
+ await service.start();
+
+ assert.deepEqual(backend.startOptions!.queues, { webmentions: { concurrency: 1 } });
+ });
+
+ it('routes recurring schedules through the same queue mapping', async function () {
+ const service = makeService();
+ service.handle(GreetJob, async () => {}, { queue: 'greetings', concurrency: 2 });
+
+ await service.scheduleRecurring(new GreetJob({ name: 'cron' }), { cron: '0 0 3 * * *' });
+
+ assert.deepEqual(backend.recurring[0]!.routing, { queue: 'greetings' });
+ });
+ });
+
describe('delivery error handling', function () {
it('captures handler errors with job context and rethrows so the backend sees a failed delivery', async function () {
const { sentry, captured } = makeSentry();
diff --git a/ghost/core/test/unit/server/services/jobs-service/register-job-handlers.test.ts b/ghost/core/test/unit/server/services/jobs-service/register-job-handlers.test.ts
index b0d734fefbb..3864779a4b9 100644
--- a/ghost/core/test/unit/server/services/jobs-service/register-job-handlers.test.ts
+++ b/ghost/core/test/unit/server/services/jobs-service/register-job-handlers.test.ts
@@ -20,12 +20,16 @@ describe('register-job-handlers', function () {
// Handlers are looked up by their job type rather than registration order,
// so adding a handler does not silently shift which one a test exercises.
- function handlerFor(type: string) {
+ function registrationFor(type: string) {
const call = jobsService.handle
.getCalls()
.find((c) => (c.args[0] as { type?: string }).type === type);
assert.ok(call, `a handler is registered for ${type}`);
- return call!.args[1] as (job: unknown) => Promise;
+ return call!;
+ }
+
+ function handlerFor(type: string) {
+ return registrationFor(type).args[1] as (job: unknown) => Promise;
}
beforeEach(function () {
@@ -135,4 +139,13 @@ describe('register-job-handlers', function () {
assert.ok(mentionsController.processWebmention.calledOnceWithExactly(job));
});
+
+ // Guards the webmention isolation itself: dropping the options object in a
+ // refactor would silently move webmentions back onto the shared queue while
+ // every handler-behavior test still passes.
+ it('registers process-webmention on the dedicated webmentions queue', function () {
+ const registration = registrationFor('process-webmention');
+
+ assert.deepEqual(registration.args[2], { queue: 'webmentions', concurrency: 3 });
+ });
});
diff --git a/ghost/core/test/unit/server/services/members/members-api/controllers/router-controller.test.js b/ghost/core/test/unit/server/services/members/members-api/controllers/router-controller.test.js
index 1bdb3685aaa..a22a0ffb5f4 100644
--- a/ghost/core/test/unit/server/services/members/members-api/controllers/router-controller.test.js
+++ b/ghost/core/test/unit/server/services/members/members-api/controllers/router-controller.test.js
@@ -84,7 +84,7 @@ describe('RouterController', function () {
configured: true,
};
labsService = {
- isSet: sinon.stub().callsFake((flag) => flag !== 'giftSubCustomization'),
+ isSet: sinon.stub().returns(true),
};
settingsCache = {
get: sinon.stub().withArgs('all_blocked_email_domains').returns(['spam.xyz']),
diff --git a/ghost/core/test/utils/fixtures/themes/members-test-theme/post.hbs b/ghost/core/test/utils/fixtures/themes/members-test-theme/post.hbs
index 9b09e7f537e..798fa7357f2 100644
--- a/ghost/core/test/utils/fixtures/themes/members-test-theme/post.hbs
+++ b/ghost/core/test/utils/fixtures/themes/members-test-theme/post.hbs
@@ -16,6 +16,17 @@
state (a gift read stays anonymous even when the content is unlocked). --}}
{{#if @member}}member{{else}}anonymous{{/if}}
+ {{!-- Dumps the shape of @member, not its values, so a test can pin
+ exactly which member fields a theme can see. @member is narrowed by
+ its own allowlist from the same member payload the members API
+ narrows separately; this is what shows a change behind the two of
+ them reaching one surface and not the other. --}}
+ {{#each @member}}{{@key}} {{/each}}
+ {{#each @member.subscriptions}}
+ {{#each this}}{{@key}} {{/each}}
+ {{default_payment_card_last4}}
+ {{/each}}
+
{{content}}
diff --git a/koenig/koenig-lexical/package.json b/koenig/koenig-lexical/package.json
index c6494332a7a..239d9917b07 100644
--- a/koenig/koenig-lexical/package.json
+++ b/koenig/koenig-lexical/package.json
@@ -21,7 +21,8 @@
".": {
"import": "./dist/koenig-lexical.js",
"require": "./dist/koenig-lexical.umd.js"
- }
+ },
+ "./style.css": "./dist/style.css"
},
"scripts": {
"dev": "concurrently \"vite --host --force\" \"pnpm build --watch --emptyOutDir=false\" \"pnpm preview -l silent --host\" \"pnpm --filter @tryghost/kg-default-nodes dev\" \"pnpm --filter @tryghost/kg-default-transforms dev\"",
diff --git a/nx.json b/nx.json
index 3cbf4c61317..3a4b4acd8ca 100644
--- a/nx.json
+++ b/nx.json
@@ -42,6 +42,10 @@
"dependsOn": ["build"],
"inputs": ["default", "^default", { "runtime": "node -v" }]
},
+ "test:types": {
+ "cache": true,
+ "dependsOn": ["^build"]
+ },
"test:ci:*": {
"cache": true,
"inputs": ["default", "^default"]
diff --git a/package.json b/package.json
index 340cbd8558d..87280488ace 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"format:check": "oxfmt --check",
"check": "pnpm format:check && pnpm lint && pnpm test",
"test": "pnpm nx run-many -t test --exclude @tryghost/e2e --exclude ghost-admin",
+ "test:types": "pnpm nx run-many -t test:types",
"test:unit": "pnpm nx run-many -t test:unit",
"test:watch": "vitest",
"test:e2e": "pnpm --filter @tryghost/e2e test",
diff --git a/packages/adapters/jobs-base/README.md b/packages/adapters/jobs-base/README.md
index 052c37dd837..e59a8217150 100644
--- a/packages/adapters/jobs-base/README.md
+++ b/packages/adapters/jobs-base/README.md
@@ -12,11 +12,29 @@ in-memory one with no call-site change.
A backend extends `JobsBackendBase` and implements four methods:
-- `start({processor})` - wire the single delivery callback and begin accepting work.
-- `enqueue(envelope)` - accept an envelope for delivery. Resolves on **acceptance**, not completion.
-- `scheduleRecurring(envelope, {cron})` - register the recurring schedule for the envelope's type. The first registration per type wins; a later call for an already-scheduled type is ignored.
+- `start({processor, queues})` - wire the single delivery callback and begin accepting work. `queues` is the desired state declared by registered handlers (`{name: {concurrency}}`).
+- `enqueue(envelope, {queue})` - accept an envelope for delivery. Resolves on **acceptance**, not completion.
+- `scheduleRecurring(envelope, {cron}, {queue})` - register the recurring schedule for the envelope's type. The first registration per type wins; a later call for an already-scheduled type is ignored.
- `shutdown({timeoutMs})` - stop accepting work and drain in-flight work within a bounded time.
+### Queues
+
+A queue is a routing/QoS lane, and routing metadata only - **delivery always
+routes by the envelope's `type`, never by queue**, so a job is processable
+whichever queue it arrives on and a deploy can move a type between queues while
+older work is still in flight. Renaming or removing a queue is therefore a
+parallel change: keep consuming the old name until it has drained, then drop it.
+
+The declared queues are desired state, not a command. A backend enforces a
+queue's `concurrency` as strictly as it can - per process for the in-memory
+backend, globally where a durable backend supports it. Weaker enforcement is
+acceptable; silently ignoring a declaration is not: a backend that cannot
+satisfy a declared queue's constraints - whatever that means for its
+implementation - must fail loudly at `start()`. An envelope routed to a queue
+no handler declared must still be delivered, never dropped. The queue name
+`default` names the shared lane for envelopes with no routing and cannot be
+declared.
+
### Delivery outcome
The backend delivers an envelope by calling `processor(envelope)` and awaiting the
diff --git a/packages/adapters/jobs-base/src/base.ts b/packages/adapters/jobs-base/src/base.ts
index c33dd8a501c..b73e3cbcd92 100644
--- a/packages/adapters/jobs-base/src/base.ts
+++ b/packages/adapters/jobs-base/src/base.ts
@@ -3,10 +3,30 @@ export interface JobEnvelope {
payload: string;
}
+// Routing is metadata about where a job runs, never what runs it: delivery
+// must always be keyed on the envelope's type, so a job is processable
+// whichever queue it arrives on (deploys can move types between queues while
+// older envelopes are still in flight).
+export interface JobRouting {
+ queue?: string;
+}
+
+// A queue declared in code (via handler registration) is desired state: the
+// backend enforces its concurrency as strictly as it can - per process for an
+// in-memory backend, globally where a durable backend supports it. Weaker
+// enforcement is acceptable; silently ignoring a declaration is not.
+export interface QueueDeclaration {
+ concurrency?: number;
+}
+
export type JobProcessor = (envelope: JobEnvelope) => Promise;
export interface JobsStartOptions {
processor: JobProcessor;
+ // Queues declared by registered handlers. A backend that cannot satisfy a
+ // declared queue's constraints - whatever that means for its implementation -
+ // must fail loudly here rather than silently dropping the declaration.
+ queues?: Record;
}
export interface RecurringSchedule {
@@ -29,11 +49,12 @@ export abstract class JobsBackendBase {
abstract start(options: JobsStartOptions): void | Promise;
- abstract enqueue(envelope: JobEnvelope): void | Promise;
+ abstract enqueue(envelope: JobEnvelope, routing?: JobRouting): void | Promise;
abstract scheduleRecurring(
envelope: JobEnvelope,
schedule: RecurringSchedule,
+ routing?: JobRouting,
): void | Promise;
abstract shutdown(options?: JobsShutdownOptions): void | Promise;
diff --git a/packages/adapters/jobs-base/src/contract-test-suite.ts b/packages/adapters/jobs-base/src/contract-test-suite.ts
index c0156876885..4590245c880 100644
--- a/packages/adapters/jobs-base/src/contract-test-suite.ts
+++ b/packages/adapters/jobs-base/src/contract-test-suite.ts
@@ -110,6 +110,40 @@ export function runJobsBackendContractTests(
assert.equal(raced, 'shutdown');
});
+ // Queue routing is metadata: a backend may isolate queues or run one
+ // lane, but a routed envelope must always be delivered, and unknown
+ // routing must never lose work.
+ it('delivers an envelope enqueued with queue routing', async function () {
+ const received: JobEnvelope[] = [];
+ const backend = makeBackend();
+ await backend.start({
+ processor: async (env) => {
+ received.push(env);
+ },
+ queues: { isolated: { concurrency: 1 } },
+ });
+
+ await backend.enqueue(envelope, { queue: 'isolated' });
+ await backend.shutdown({ timeoutMs: 1000 });
+
+ assert.deepEqual(received, [envelope]);
+ });
+
+ it('delivers an envelope routed to a queue no handler declared', async function () {
+ const received: JobEnvelope[] = [];
+ const backend = makeBackend();
+ await backend.start({
+ processor: async (env) => {
+ received.push(env);
+ },
+ });
+
+ await backend.enqueue(envelope, { queue: 'undeclared' });
+ await backend.shutdown({ timeoutMs: 1000 });
+
+ assert.deepEqual(received, [envelope]);
+ });
+
it('tolerates start after a prior shutdown', async function () {
const received: JobEnvelope[] = [];
const backend = makeBackend();
diff --git a/packages/i18n/locales/af/portal.json b/packages/i18n/locales/af/portal.json
index 615baae95c8..29e67f11784 100644
--- a/packages/i18n/locales/af/portal.json
+++ b/packages/i18n/locales/af/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Aanbevelings",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Hernu teen {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "U het suksesvol aangemeld.",
"You've successfully subscribed to {siteTitle}": "Jy het suksesvol ingeteken op {siteTitle}",
"Your account": "U rekening",
diff --git a/packages/i18n/locales/ar/portal.json b/packages/i18n/locales/ar/portal.json
index 92ea2bbec7c..4d8bcf4d239 100644
--- a/packages/i18n/locales/ar/portal.json
+++ b/packages/i18n/locales/ar/portal.json
@@ -218,7 +218,6 @@
"Recipient's name": "",
"Recommendations": "التوصيات",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} سيتم التجديد بسعر ",
"Resume subscription": "",
@@ -339,8 +338,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": ".تم تسجيل الدخول بنجاح",
"You've successfully subscribed to {siteTitle}": "تم الاشتراك بنجاح في {siteTitle}",
"Your account": "حسابك",
diff --git a/packages/i18n/locales/bg/portal.json b/packages/i18n/locales/bg/portal.json
index 491c64369c9..c3362835a40 100644
--- a/packages/i18n/locales/bg/portal.json
+++ b/packages/i18n/locales/bg/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Препоръки",
"Redeem your gift": "",
- "Redeem your membership": "Активирайте абонамента си",
"Redeeming...": "Активиране...",
"Renews at {price}.": "Подновяване за {price}.",
"Resume subscription": "Възобнови абонамента",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Получихте абонамент като подарък",
- "You've been gifted a membership to {siteTitle}": "Получихте подарък - абонамент за {siteTitle}",
"You've successfully signed in.": "Влязохте успешно.",
"You've successfully subscribed to {siteTitle}": "Успешно се абонирахте за {siteTitle}",
"Your account": "Вашият профил",
diff --git a/packages/i18n/locales/bn/portal.json b/packages/i18n/locales/bn/portal.json
index 54e63962e15..9dd7eb2a220 100644
--- a/packages/i18n/locales/bn/portal.json
+++ b/packages/i18n/locales/bn/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "প্রস্তাবনা",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} এ নবায়ন হবে।",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "আপনি সফলভাবে সাইন ইন করেছেন।",
"You've successfully subscribed to {siteTitle}": "আপনি সফলভাবে সাবস্ক্রাইব করেছেন {siteTitle}",
"Your account": "আপনার অ্যাকাউন্ট",
diff --git a/packages/i18n/locales/bs/portal.json b/packages/i18n/locales/bs/portal.json
index 954bc27a71b..07639100294 100644
--- a/packages/i18n/locales/bs/portal.json
+++ b/packages/i18n/locales/bs/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Preporuke",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Obnavlja se po cijeni od {price}.",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Uspješna prijava.",
"You've successfully subscribed to {siteTitle}": "Uspješna pretplata na {siteTitle}",
"Your account": "Tvoj račun",
diff --git a/packages/i18n/locales/ca/portal.json b/packages/i18n/locales/ca/portal.json
index dad06273025..876bf55568a 100644
--- a/packages/i18n/locales/ca/portal.json
+++ b/packages/i18n/locales/ca/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Recomanacions",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Es renova a {price}",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Has iniciat la sessió correctament.",
"You've successfully subscribed to {siteTitle}": "T'has subscrit correctament a {siteTitle}",
"Your account": "El teu compte",
diff --git a/packages/i18n/locales/context.json b/packages/i18n/locales/context.json
index 763216ef77c..223a36a3d4e 100644
--- a/packages/i18n/locales/context.json
+++ b/packages/i18n/locales/context.json
@@ -272,7 +272,6 @@
"Redeem your gift": "CTA button label in the recipient gift email and on the Portal gift redemption page when the recipient is signed out",
"Redeem your gift subscription": "Fallback link text shown on the gift preview page when JavaScript is disabled, used to redeem a gift subscription",
"Redeem your gift:": "Call to action before the redemption link in the plain-text gift delivery email",
- "Redeem your membership": "CTA button label on the Portal gift redemption page",
"Redeeming...": "Loading state button label on the Portal gift redemption page",
"Remove dislike": "Accessible label for the icon-only dislike button on a comment, used when the comment has already been disliked by the current user (clicking removes the dislike)",
"Remove like": "Accessible label for the icon-only like button on a comment, used when the comment has already been liked by the current user (clicking removes the like)",
@@ -474,7 +473,6 @@
"You've been gifted a {duration}-month {tierName} membership_other": "Plural monthly gift introduction shown in Portal when the buyer and publication names are unavailable. wraps the complete duration; {duration} is the number of months and {tierName} is the membership tier.",
"You've been gifted a {duration}-year {tierName} membership": "Yearly gift introduction shown in Portal when the buyer and publication names are unavailable. wraps the complete duration; {duration} is the number of years and {tierName} is the membership tier.",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "Yearly gift introduction shown in Portal when the buyer name is unavailable. wraps the complete duration; {duration} is the number of years, {tierName} is the membership tier, and {siteTitle} is the publication name.",
- "You've been gifted a membership": "Subtitle on the Portal gift redemption page when the publication has no title configured (fallback)",
"You've been gifted a membership to {siteTitle}": "Subtitle on the Portal gift redemption page, and the hidden preheader text of the gift delivery email. {siteTitle} is the publication name (e.g. 'The Daily').",
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}": "Title shown in the gift link social preview for monthly gifts when the buyer name is unavailable. {duration} is the number of months, {tierName} is the membership tier, and {siteTitle} is the publication name.",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "Title shown in the gift link social preview for yearly gifts when the buyer name is unavailable. {duration} is the number of years, {tierName} is the membership tier, and {siteTitle} is the publication name.",
diff --git a/packages/i18n/locales/cs/portal.json b/packages/i18n/locales/cs/portal.json
index 30f8081dafb..d7480106fd2 100644
--- a/packages/i18n/locales/cs/portal.json
+++ b/packages/i18n/locales/cs/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Doporučení",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Obnovuje se za {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Úspěšně jste se přihlásili.",
"You've successfully subscribed to {siteTitle}": "Úspěšně jste se přihlásili k odběru {siteTitle}",
"Your account": "Váš účet",
diff --git a/packages/i18n/locales/da/portal.json b/packages/i18n/locales/da/portal.json
index 5ead1ae89f0..6b000d120a8 100644
--- a/packages/i18n/locales/da/portal.json
+++ b/packages/i18n/locales/da/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Anbefalinger",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Bliver fornyet til {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Du er nu logget ind.",
"You've successfully subscribed to {siteTitle}": "Du er nu tilmeldt til {siteTitle}",
"Your account": "Din konto",
diff --git a/packages/i18n/locales/de-CH/portal.json b/packages/i18n/locales/de-CH/portal.json
index 951a84c5424..f33002e3f88 100644
--- a/packages/i18n/locales/de-CH/portal.json
+++ b/packages/i18n/locales/de-CH/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Empfehlungen",
"Redeem your gift": "",
- "Redeem your membership": "Abonnement einlösen",
"Redeeming...": "Wird eingelöst...",
"Renews at {price}.": "Wird verlängert zum Preis von {price}.",
"Resume subscription": "Abo wieder aktivieren",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Sie haben ein Abonnement geschenkt erhalten",
- "You've been gifted a membership to {siteTitle}": "Sie haben ein Abonnement für {siteTitle} geschenkt erhalten",
"You've successfully signed in.": "Sie haben sich erfolgreich angemeldet.",
"You've successfully subscribed to {siteTitle}": "Sie haben sich erfolgreich abonniert bei {siteTitle}",
"Your account": "Ihr Konto",
diff --git a/packages/i18n/locales/de/portal.json b/packages/i18n/locales/de/portal.json
index 3de14f9b7a0..070bb4003fb 100644
--- a/packages/i18n/locales/de/portal.json
+++ b/packages/i18n/locales/de/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Empfehlungen",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Wird zum Preis von {price} verlängert.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Du hast dich erfolgreich angemeldet.",
"You've successfully subscribed to {siteTitle}": "Du hast dich erfolgreich angemeldet bei {siteTitle}",
"Your account": "Dein Konto",
diff --git a/packages/i18n/locales/el/portal.json b/packages/i18n/locales/el/portal.json
index fd2fca1c7a2..aaa96a00a4e 100644
--- a/packages/i18n/locales/el/portal.json
+++ b/packages/i18n/locales/el/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Συστάσεις",
"Redeem your gift": "",
- "Redeem your membership": "Εξαργύρωση της συνδρομής σας",
"Redeeming...": "Εξαργύρωση...",
"Renews at {price}.": "Ανανεώνεται στην τιμή {price}.",
"Resume subscription": "Επανέναρξη συνδρομής",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Σας χαρίστηκε μια συνδρομή",
- "You've been gifted a membership to {siteTitle}": "Σας χαρίστηκε μια συνδρομή στο {siteTitle}",
"You've successfully signed in.": "Έχετε συνδεθεί επιτυχώς.",
"You've successfully subscribed to {siteTitle}": "Έχετε εγγραφεί επιτυχώς στο {siteTitle}",
"Your account": "Ο λογαριασμός σας",
diff --git a/packages/i18n/locales/en/portal.json b/packages/i18n/locales/en/portal.json
index fd7ca766373..8d04282d40f 100644
--- a/packages/i18n/locales/en/portal.json
+++ b/packages/i18n/locales/en/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "",
diff --git a/packages/i18n/locales/eo/portal.json b/packages/i18n/locales/eo/portal.json
index 6f0208dbdf9..26e696082d7 100644
--- a/packages/i18n/locales/eo/portal.json
+++ b/packages/i18n/locales/eo/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Via konto",
diff --git a/packages/i18n/locales/es/portal.json b/packages/i18n/locales/es/portal.json
index 7e86cd1d1eb..efdbf300e69 100644
--- a/packages/i18n/locales/es/portal.json
+++ b/packages/i18n/locales/es/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Recomendaciones",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Se renueva a {price}.",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Has iniciado sesión correctamente.",
"You've successfully subscribed to {siteTitle}": "Te has suscrito correctamente a {siteTitle}",
"Your account": "Tu cuenta",
diff --git a/packages/i18n/locales/et/portal.json b/packages/i18n/locales/et/portal.json
index 5957362547f..a85633c465e 100644
--- a/packages/i18n/locales/et/portal.json
+++ b/packages/i18n/locales/et/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Soovitused",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Uueneb hinnaga {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Olete edukalt sisse loginud.",
"You've successfully subscribed to {siteTitle}": "Olete edukalt tellinud {siteTitle}",
"Your account": "Teie konto",
diff --git a/packages/i18n/locales/eu/portal.json b/packages/i18n/locales/eu/portal.json
index 604e84cec80..ea41c144465 100644
--- a/packages/i18n/locales/eu/portal.json
+++ b/packages/i18n/locales/eu/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Gomendioak",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price}(r)en truke berrituko da.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Saioa hasi duzu.",
"You've successfully subscribed to {siteTitle}": "Honakora harpidetu zara: {siteTitle}",
"Your account": "Zure kontua",
diff --git a/packages/i18n/locales/fa/portal.json b/packages/i18n/locales/fa/portal.json
index 2d8a17c83d4..360c51e0fba 100644
--- a/packages/i18n/locales/fa/portal.json
+++ b/packages/i18n/locales/fa/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "پیشنهادها",
"Redeem your gift": "",
- "Redeem your membership": "اشتراک خود را فعال کنید",
"Redeeming...": "در حال فعال\u200cسازی...",
"Renews at {price}.": "با قیمت {price} تمدید می\u200cشود.",
"Resume subscription": "ازسرگیری اشتراک",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "به شما یک اشتراک هدیه داده شده است",
- "You've been gifted a membership to {siteTitle}": "به شما یک اشتراک در {siteTitle} هدیه داده شده است",
"You've successfully signed in.": "با موفقیت وارد شدید.",
"You've successfully subscribed to {siteTitle}": "با موفقیت در {siteTitle} مشترک شدید",
"Your account": "حساب کاربری شما",
diff --git a/packages/i18n/locales/fi/portal.json b/packages/i18n/locales/fi/portal.json
index f3894731ab9..a9837c61c29 100644
--- a/packages/i18n/locales/fi/portal.json
+++ b/packages/i18n/locales/fi/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Suositukset",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Tilaus uusiutuu hinnalla {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Olet kirjautunut sisään onnistuneesti",
"You've successfully subscribed to {siteTitle}": "Tilaus onnistui: {siteTitle}",
"Your account": "Tilisi",
diff --git a/packages/i18n/locales/fr/portal.json b/packages/i18n/locales/fr/portal.json
index 78f1dc0e27a..1284eeb15cb 100644
--- a/packages/i18n/locales/fr/portal.json
+++ b/packages/i18n/locales/fr/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Suggestions",
"Redeem your gift": "",
- "Redeem your membership": "Activer votre abonnement",
"Redeeming...": "Activation...",
"Renews at {price}.": "Renouvellement pour {price}.",
"Resume subscription": "Réactiver l’abonnement",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Un abonnement vous a été offert",
- "You've been gifted a membership to {siteTitle}": "Un abonnement à {siteTitle} vous a été offert",
"You've successfully signed in.": "Vous vous êtes connecté avec succès.",
"You've successfully subscribed to {siteTitle}": "Vous vous êtes abonné à {siteTitle}",
"Your account": "Votre compte",
diff --git a/packages/i18n/locales/gd/portal.json b/packages/i18n/locales/gd/portal.json
index 057319a585c..66185f5e904 100644
--- a/packages/i18n/locales/gd/portal.json
+++ b/packages/i18n/locales/gd/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Mòlaidhean",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Prìs ath-nuadhachaidh: {price}",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Chlàraich thu a-steach gu soirbheachail.",
"You've successfully subscribed to {siteTitle}": "Fo-sgrìobh thu gu soirbheachail gu {siteTitle}",
"Your account": "An cunntas agad",
diff --git a/packages/i18n/locales/he/portal.json b/packages/i18n/locales/he/portal.json
index 8468f1ddd86..483b1ba7d1d 100644
--- a/packages/i18n/locales/he/portal.json
+++ b/packages/i18n/locales/he/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "המלצות",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "מתחדש ב {price}.",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "נכנסתם בהצלחה.",
"You've successfully subscribed to {siteTitle}": "נרשמתם בהצלחה ל {siteTitle}",
"Your account": "החשבון שלך",
diff --git a/packages/i18n/locales/hi/portal.json b/packages/i18n/locales/hi/portal.json
index 120183debd7..74e68d91f74 100644
--- a/packages/i18n/locales/hi/portal.json
+++ b/packages/i18n/locales/hi/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "सिफारिशें",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} पर नवीनीकृत होता है।",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "आपने सफलतापूर्वक साइन इन कर लिया है।",
"You've successfully subscribed to {siteTitle}": "आपने सफलतापूर्वक सदस्यता ली है {siteTitle}",
"Your account": "आपका खाता",
diff --git a/packages/i18n/locales/hr/portal.json b/packages/i18n/locales/hr/portal.json
index 9d32858e583..b40e049e078 100644
--- a/packages/i18n/locales/hr/portal.json
+++ b/packages/i18n/locales/hr/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Preporuke",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Obnovi po cijeni {price}",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Uspješno ste prijavljeni.",
"You've successfully subscribed to {siteTitle}": "Uspješno ste pretplaćeni na {siteTitle}",
"Your account": "Vaš korisnički račun",
diff --git a/packages/i18n/locales/hu/portal.json b/packages/i18n/locales/hu/portal.json
index a44b3c78a9d..bc5d547fa11 100644
--- a/packages/i18n/locales/hu/portal.json
+++ b/packages/i18n/locales/hu/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Ajánlott oldalak",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Megújul {price} áron",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Sikeresen bejelentkeztél.",
"You've successfully subscribed to {siteTitle}": "Sikeresen bejelentkeztél ide: {siteTitle}",
"Your account": "Fiókod",
diff --git a/packages/i18n/locales/id/portal.json b/packages/i18n/locales/id/portal.json
index 43e6df1f103..88a154d9018 100644
--- a/packages/i18n/locales/id/portal.json
+++ b/packages/i18n/locales/id/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "Rekomendasi",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Perpanjang dengan harga {price}",
"Resume subscription": "",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Anda telah berhasil masuk.",
"You've successfully subscribed to {siteTitle}": "Anda telah berhasil berlangganan ke {siteTitle}",
"Your account": "Akun Anda",
diff --git a/packages/i18n/locales/is/portal.json b/packages/i18n/locales/is/portal.json
index ee5eb50ef11..9d84c1ac741 100644
--- a/packages/i18n/locales/is/portal.json
+++ b/packages/i18n/locales/is/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Endurnýjast á verðinu {price}",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Þér tókst að skrá þig inn",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Aðgangurinn þinn",
diff --git a/packages/i18n/locales/it/portal.json b/packages/i18n/locales/it/portal.json
index 41c862eef44..802c147b374 100644
--- a/packages/i18n/locales/it/portal.json
+++ b/packages/i18n/locales/it/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Consigliati",
"Redeem your gift": "",
- "Redeem your membership": "Riscatta il tuo abbonamento",
"Redeeming...": "Riscatto in corso...",
"Renews at {price}.": "Rinnova a {price}.",
"Resume subscription": "Riprendi abbonamento",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Hai ricevuto un abbonamento in regalo",
- "You've been gifted a membership to {siteTitle}": "Hai ricevuto un abbonamento in regalo a {siteTitle}",
"You've successfully signed in.": "Accesso effettuato.",
"You've successfully subscribed to {siteTitle}": "Iscrizione effettuata a {siteTitle}",
"Your account": "Il tuo account",
diff --git a/packages/i18n/locales/ja/portal.json b/packages/i18n/locales/ja/portal.json
index f186dcc9abc..867e3391e6a 100644
--- a/packages/i18n/locales/ja/portal.json
+++ b/packages/i18n/locales/ja/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "おすすめ",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price}で更新されます。",
"Resume subscription": "",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "ログインに成功しました",
"You've successfully subscribed to {siteTitle}": "の購読に成功しました {siteTitle}",
"Your account": "あなたのアカウント",
diff --git a/packages/i18n/locales/ko/portal.json b/packages/i18n/locales/ko/portal.json
index 7a55d4bcf50..465eee61d52 100644
--- a/packages/i18n/locales/ko/portal.json
+++ b/packages/i18n/locales/ko/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "추천",
"Redeem your gift": "",
- "Redeem your membership": "멤버십 사용하기",
"Redeeming...": "사용 중...",
"Renews at {price}.": "{price}에 갱신돼요.",
"Resume subscription": "구독 재개",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "멤버십을 선물받으셨어요",
- "You've been gifted a membership to {siteTitle}": "{siteTitle}의 멤버십을 선물받으셨어요",
"You've successfully signed in.": "성공적으로 로그인되었어요.",
"You've successfully subscribed to {siteTitle}": "성공적으로 구독하셨어요: {siteTitle}",
"Your account": "계정",
diff --git a/packages/i18n/locales/kz/portal.json b/packages/i18n/locales/kz/portal.json
index 6e777594e14..0247d0add41 100644
--- a/packages/i18n/locales/kz/portal.json
+++ b/packages/i18n/locales/kz/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Ұсыныстар",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} бағасымен жаңартылады.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Кіру сәтті орындалды.",
"You've successfully subscribed to {siteTitle}": "Жазылым сәтті орындалды {siteTitle}",
"Your account": "Сіздің аккаунт",
diff --git a/packages/i18n/locales/lt/portal.json b/packages/i18n/locales/lt/portal.json
index 71a2f8bc865..8c6b1f2724d 100644
--- a/packages/i18n/locales/lt/portal.json
+++ b/packages/i18n/locales/lt/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Rekomendacijos",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Atsinaujins už",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Sėkmingai prisijungėte.",
"You've successfully subscribed to {siteTitle}": "Sėkmingai užsiprenumeravote {siteTitle}",
"Your account": "Jūsų paskyra",
diff --git a/packages/i18n/locales/lv/portal.json b/packages/i18n/locales/lv/portal.json
index a3218c21e7a..5a1be84e03f 100644
--- a/packages/i18n/locales/lv/portal.json
+++ b/packages/i18n/locales/lv/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Ieteikumi",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Atjauno par {price}",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Jūs esat veiksmīgi pierakstījies.",
"You've successfully subscribed to {siteTitle}": "Jūs esat veiksmīgi abonējis {siteTitle}",
"Your account": "Jūsu konts",
diff --git a/packages/i18n/locales/mk/portal.json b/packages/i18n/locales/mk/portal.json
index e55b58484bf..9a6b58ae170 100644
--- a/packages/i18n/locales/mk/portal.json
+++ b/packages/i18n/locales/mk/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Препораки",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Обновувањето е {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Успешно се најавивте.",
"You've successfully subscribed to {siteTitle}": "Успешно се претплативте на {siteTitle}",
"Your account": "Вашата сметка",
diff --git a/packages/i18n/locales/mn/portal.json b/packages/i18n/locales/mn/portal.json
index e31898fa373..d23769a1d18 100644
--- a/packages/i18n/locales/mn/portal.json
+++ b/packages/i18n/locales/mn/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Санал болгох",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price}-д шинэчлэгдэнэ.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Та амжилттай нэвтэрлээ.",
"You've successfully subscribed to {siteTitle}": "Таны захиалга амжилттай үүслээ. {siteTitle}",
"Your account": "Таны бүртгэл",
diff --git a/packages/i18n/locales/ms/portal.json b/packages/i18n/locales/ms/portal.json
index dd240ce1785..ffbfa9301a7 100644
--- a/packages/i18n/locales/ms/portal.json
+++ b/packages/i18n/locales/ms/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Perbaharui pada {price}.",
"Resume subscription": "",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Anda telah berjaya log masuk.",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Akaun anda",
diff --git a/packages/i18n/locales/nb/portal.json b/packages/i18n/locales/nb/portal.json
index 49eaf44479c..b99b21de670 100644
--- a/packages/i18n/locales/nb/portal.json
+++ b/packages/i18n/locales/nb/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Anbefalinger",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Fornyes til {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Du har logget på.",
"You've successfully subscribed to {siteTitle}": "Du har meldt deg på {siteTitle}",
"Your account": "Din konto",
diff --git a/packages/i18n/locales/ne/portal.json b/packages/i18n/locales/ne/portal.json
index 781971e978b..a89c05cf0a4 100644
--- a/packages/i18n/locales/ne/portal.json
+++ b/packages/i18n/locales/ne/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "",
diff --git a/packages/i18n/locales/nl/portal.json b/packages/i18n/locales/nl/portal.json
index 140c352b99c..f4f6ce6af7d 100644
--- a/packages/i18n/locales/nl/portal.json
+++ b/packages/i18n/locales/nl/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Aanbevelingen",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Verlengt met {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Je bent succesvol ingelogd.",
"You've successfully subscribed to {siteTitle}": "Je bent succesvol geabonneerd op {siteTitle}",
"Your account": "Jouw account",
diff --git a/packages/i18n/locales/nn/portal.json b/packages/i18n/locales/nn/portal.json
index 12ff00e0ad7..dece9f735b1 100644
--- a/packages/i18n/locales/nn/portal.json
+++ b/packages/i18n/locales/nn/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Forynast til {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Vellykka innlogging.",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Din brukar",
diff --git a/packages/i18n/locales/pa/portal.json b/packages/i18n/locales/pa/portal.json
index bb89187ac71..d6daa1b3254 100644
--- a/packages/i18n/locales/pa/portal.json
+++ b/packages/i18n/locales/pa/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "ਸਿਫ਼ਾਰਸ਼ਾਂ",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} 'ਤੇ ਨਵਿਆਇਆ ਜਾਵੇਗਾ।",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "ਤੁਸੀਂ ਸਫਲਤਾਪੂਰਵਕ ਸਾਈਨ ਇਨ ਕਰ ਲਿਆ ਹੈ।",
"You've successfully subscribed to {siteTitle}": "ਤੁਸੀਂ ਸਫਲਤਾਪੂਰਵਕ ਸਦੱਸਤਾ ਲਈ ਹੈ: {siteTitle}",
"Your account": "ਤੁਹਾਡਾ ਖਾਤਾ",
diff --git a/packages/i18n/locales/pl/portal.json b/packages/i18n/locales/pl/portal.json
index fc6549c5779..767051c790b 100644
--- a/packages/i18n/locales/pl/portal.json
+++ b/packages/i18n/locales/pl/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Rekomendacje",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Odnowi się w cenie {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Logowanie powiodło się.",
"You've successfully subscribed to {siteTitle}": "Pomyślnie zasubskrybowano {siteTitle}",
"Your account": "Twoje konto",
diff --git a/packages/i18n/locales/pt-BR/portal.json b/packages/i18n/locales/pt-BR/portal.json
index 719001509e0..5d08707fec7 100644
--- a/packages/i18n/locales/pt-BR/portal.json
+++ b/packages/i18n/locales/pt-BR/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Recomendações",
"Redeem your gift": "",
- "Redeem your membership": "Resgatar sua assinatura",
"Redeeming...": "Resgatando...",
"Renews at {price}.": "Renova por {price}",
"Resume subscription": "Retomar assinatura",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Você recebeu uma assinatura de presente",
- "You've been gifted a membership to {siteTitle}": "Você recebeu uma assinatura de presente para {siteTitle}",
"You've successfully signed in.": "Você entrou com sucesso.",
"You've successfully subscribed to {siteTitle}": "Você se inscreveu com sucesso {siteTitle}",
"Your account": "Sua conta",
diff --git a/packages/i18n/locales/pt/portal.json b/packages/i18n/locales/pt/portal.json
index 6196082466c..c31d9d915e5 100644
--- a/packages/i18n/locales/pt/portal.json
+++ b/packages/i18n/locales/pt/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Recomendações",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Renove por {price}",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Registou-se com sucesso.",
"You've successfully subscribed to {siteTitle}": "Subscreveu com sucesso {siteTitle}",
"Your account": "A sua conta",
diff --git a/packages/i18n/locales/ro/portal.json b/packages/i18n/locales/ro/portal.json
index a7981023536..a0a764550af 100644
--- a/packages/i18n/locales/ro/portal.json
+++ b/packages/i18n/locales/ro/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Recomandări",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Se reînnoiește la {price}.",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Te-ai autentificat cu succes.",
"You've successfully subscribed to {siteTitle}": "Te-ai abonat cu succes la {siteTitle}",
"Your account": "Contul tău",
diff --git a/packages/i18n/locales/ru/portal.json b/packages/i18n/locales/ru/portal.json
index d9ba623ba3c..244edd0b5c3 100644
--- a/packages/i18n/locales/ru/portal.json
+++ b/packages/i18n/locales/ru/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Рекомендации",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Продление за {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Вы успешно вошли.",
"You've successfully subscribed to {siteTitle}": "Вы успешно подписались на {siteTitle}",
"Your account": "Ваш аккаунт",
diff --git a/packages/i18n/locales/si/portal.json b/packages/i18n/locales/si/portal.json
index 273e00a3453..a84da6cc2df 100644
--- a/packages/i18n/locales/si/portal.json
+++ b/packages/i18n/locales/si/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "නිර්දේශි\u200bත",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price} ක මුදලකට renew වනු ඇත.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "ඔබ සාර්ථකව sign in වන ලදී.",
"You've successfully subscribed to {siteTitle}": "ඔබ සාර්ථකව subscribe ක\u200bර ඇත {siteTitle}",
"Your account": "ඔබගේ ගිණුම",
diff --git a/packages/i18n/locales/sk/portal.json b/packages/i18n/locales/sk/portal.json
index 7e4c4deb07e..accaac8ac6f 100644
--- a/packages/i18n/locales/sk/portal.json
+++ b/packages/i18n/locales/sk/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Odporúčania",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Obnoviť za {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Úspešne ste sa prihlásili",
"You've successfully subscribed to {siteTitle}": "Úspešne ste sa prihlásili na odber pre {siteTitle}",
"Your account": "Váš účet",
diff --git a/packages/i18n/locales/sl/portal.json b/packages/i18n/locales/sl/portal.json
index 50688ba9cf8..1641fecd208 100644
--- a/packages/i18n/locales/sl/portal.json
+++ b/packages/i18n/locales/sl/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Priporočila",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Obnovi se za {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Uspešno ste se prijavili.",
"You've successfully subscribed to {siteTitle}": "Uspešno ste se naročili na {siteTitle}",
"Your account": "Vaš račun",
diff --git a/packages/i18n/locales/sq/portal.json b/packages/i18n/locales/sq/portal.json
index e5487bcb7d1..e9aba84ce69 100644
--- a/packages/i18n/locales/sq/portal.json
+++ b/packages/i18n/locales/sq/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Rinovohet per {price} ",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Ju jeni identifikuar me sukses.",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Llogaria juar",
diff --git a/packages/i18n/locales/sr-Cyrl/portal.json b/packages/i18n/locales/sr-Cyrl/portal.json
index 6e35adb41b1..78af6f94435 100644
--- a/packages/i18n/locales/sr-Cyrl/portal.json
+++ b/packages/i18n/locales/sr-Cyrl/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Препоруке",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Обнавља се по цени од {price}.",
"Resume subscription": "",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Успешно сте се пријавили.",
"You've successfully subscribed to {siteTitle}": "Успешно сте се претплатили на {siteTitle}",
"Your account": "Ваш налог",
diff --git a/packages/i18n/locales/sr/portal.json b/packages/i18n/locales/sr/portal.json
index ae54fce7ba2..3d6efd4c3eb 100644
--- a/packages/i18n/locales/sr/portal.json
+++ b/packages/i18n/locales/sr/portal.json
@@ -215,7 +215,6 @@
"Recipient's name": "",
"Recommendations": "Preporuke",
"Redeem your gift": "",
- "Redeem your membership": "Preuzmite svoje članstvo",
"Redeeming...": "Preuzimanje...",
"Renews at {price}.": "Obnavlja se po ceni od {price}.",
"Resume subscription": "Ponovo aktivirajte pretplatu",
@@ -330,8 +329,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Dobili ste članstvo na poklon",
- "You've been gifted a membership to {siteTitle}": "Dobili ste na poklon članstvo za {siteTitle}",
"You've successfully signed in.": "Uspešno ste se prijavili.",
"You've successfully subscribed to {siteTitle}": "Uspešno ste se pretplatili na {siteTitle}",
"Your account": "Vaš nalog",
diff --git a/packages/i18n/locales/sv/portal.json b/packages/i18n/locales/sv/portal.json
index 1efdd9758cc..70829d37ceb 100644
--- a/packages/i18n/locales/sv/portal.json
+++ b/packages/i18n/locales/sv/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Rekommendationer",
"Redeem your gift": "",
- "Redeem your membership": "Lös in din prenumeration",
"Redeeming...": "Löser in...",
"Renews at {price}.": "Förnyas till priset {price}.",
"Resume subscription": "Återuppta prenumeration",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Du har fått en gåvoprenumeration",
- "You've been gifted a membership to {siteTitle}": "Du har fått en gåvoprenumeration på {siteTitle}",
"You've successfully signed in.": "Du är nu inloggad.",
"You've successfully subscribed to {siteTitle}": "Du är nu anmäld till {siteTitle}",
"Your account": "Ditt konto",
diff --git a/packages/i18n/locales/sw/portal.json b/packages/i18n/locales/sw/portal.json
index a0bb2ec36d9..85a298141b7 100644
--- a/packages/i18n/locales/sw/portal.json
+++ b/packages/i18n/locales/sw/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Mapendekezo",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Inajirudia kwa bei ya {price}.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Umeingia kwa mafanikio.",
"You've successfully subscribed to {siteTitle}": "Umejiunga kwa mafanikio na {siteTitle}",
"Your account": "Akaunti yako",
diff --git a/packages/i18n/locales/ta/portal.json b/packages/i18n/locales/ta/portal.json
index 8e077e35739..87db61d8da4 100644
--- a/packages/i18n/locales/ta/portal.json
+++ b/packages/i18n/locales/ta/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "பரிந்துரைகள்",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "{price}க்கு புதுப்பிக்கப்படுகிறது.",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "நீங்கள் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள்.",
"You've successfully subscribed to {siteTitle}": "நீங்கள் வெற்றிகரமாக சந்தா செய்துள்ளீர்கள் {siteTitle}",
"Your account": "உங்கள் கணக்கு",
diff --git a/packages/i18n/locales/th/portal.json b/packages/i18n/locales/th/portal.json
index 5213b416c9f..72cfc22cfda 100644
--- a/packages/i18n/locales/th/portal.json
+++ b/packages/i18n/locales/th/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "รายการแนะนำ",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "ต่ออายุที่ {price}",
"Resume subscription": "",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "คุณลงชื่อเข้าใช้สำเร็จแล้ว",
"You've successfully subscribed to {siteTitle}": "คุณรับสมัครข้อมูลสำเร็จแล้ว {siteTitle}",
"Your account": "บัญชีของคุณ",
diff --git a/packages/i18n/locales/tr/portal.json b/packages/i18n/locales/tr/portal.json
index c76df755fb5..b6575e0023c 100644
--- a/packages/i18n/locales/tr/portal.json
+++ b/packages/i18n/locales/tr/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "Tavsiyeler",
"Redeem your gift": "",
- "Redeem your membership": "Üyeliğinizi kullanın",
"Redeeming...": "Kullanıma sunuluyor...",
"Renews at {price}.": "{price} karşılığında yenilenir.",
"Resume subscription": "Aboneliği devam ettir",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Sana bir üyelik hediye edildi.",
- "You've been gifted a membership to {siteTitle}": "{siteTitle} için sana bir üyelik hediye edildi.",
"You've successfully signed in.": "Başarıyla oturum açtınız.",
"You've successfully subscribed to {siteTitle}": "Başarıyla abone oldunuz {siteTitle}",
"Your account": "Hesabın",
diff --git a/packages/i18n/locales/uk/portal.json b/packages/i18n/locales/uk/portal.json
index f61b8ea0f5b..07916f88c8a 100644
--- a/packages/i18n/locales/uk/portal.json
+++ b/packages/i18n/locales/uk/portal.json
@@ -216,7 +216,6 @@
"Recipient's name": "",
"Recommendations": "Рекомендації",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "Поновлення за {price}.",
"Resume subscription": "",
@@ -333,8 +332,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "Ви успішно увійшли.",
"You've successfully subscribed to {siteTitle}": "Ви успішно підписалися на {siteTitle}",
"Your account": "Ваш обліковий запис",
diff --git a/packages/i18n/locales/ur/portal.json b/packages/i18n/locales/ur/portal.json
index 86de26869b6..c72d526e4d3 100644
--- a/packages/i18n/locales/ur/portal.json
+++ b/packages/i18n/locales/ur/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "نیا کرتا ہے {price} پر۔",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "آپ نے کامیابی سے سائن ان کیا ہے۔",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "آپ کا اکاؤنٹ",
diff --git a/packages/i18n/locales/uz/portal.json b/packages/i18n/locales/uz/portal.json
index 92a67bef285..4cce979dd78 100644
--- a/packages/i18n/locales/uz/portal.json
+++ b/packages/i18n/locales/uz/portal.json
@@ -214,7 +214,6 @@
"Recipient's name": "",
"Recommendations": "",
"Redeem your gift": "",
- "Redeem your membership": "",
"Redeeming...": "",
"Renews at {price}.": "",
"Resume subscription": "",
@@ -327,8 +326,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "",
- "You've been gifted a membership to {siteTitle}": "",
"You've successfully signed in.": "",
"You've successfully subscribed to {siteTitle}": "",
"Your account": "Sizning hisobingiz",
diff --git a/packages/i18n/locales/vi/portal.json b/packages/i18n/locales/vi/portal.json
index b767d766999..78694922551 100644
--- a/packages/i18n/locales/vi/portal.json
+++ b/packages/i18n/locales/vi/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "Đề xuất",
"Redeem your gift": "",
- "Redeem your membership": "Đổi gói thành viên của bạn",
"Redeeming...": "Đang đổi...",
"Renews at {price}.": "Phí gia hạn {price}.",
"Resume subscription": "Tiếp tục gói",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "Bạn vừa được tặng một gói thành viên",
- "You've been gifted a membership to {siteTitle}": "Bạn vừa được tặng một gói thành viên trên {siteTitle}",
"You've successfully signed in.": "Bạn đã đăng nhập thành công.",
"You've successfully subscribed to {siteTitle}": "Bạn đã đăng ký thành công {siteTitle}",
"Your account": "Tài khoản của bạn",
diff --git a/packages/i18n/locales/zh-Hant/portal.json b/packages/i18n/locales/zh-Hant/portal.json
index b55617199c7..218c2126654 100644
--- a/packages/i18n/locales/zh-Hant/portal.json
+++ b/packages/i18n/locales/zh-Hant/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "所有推薦",
"Redeem your gift": "",
- "Redeem your membership": "兌換您的會員資格",
"Redeeming...": "正在兌換...",
"Renews at {price}.": "以 {price} 的價格續費。",
"Resume subscription": "恢復訂閱",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "您收到了一份會員資格禮物",
- "You've been gifted a membership to {siteTitle}": "您收到了一份 {siteTitle} 的會員資格禮物",
"You've successfully signed in.": "您已成功登入。",
"You've successfully subscribed to {siteTitle}": "您已經成功訂閱 {siteTitle}",
"Your account": "您的帳號",
diff --git a/packages/i18n/locales/zh/portal.json b/packages/i18n/locales/zh/portal.json
index f9f6bb2f2c8..05e30b700ad 100644
--- a/packages/i18n/locales/zh/portal.json
+++ b/packages/i18n/locales/zh/portal.json
@@ -213,7 +213,6 @@
"Recipient's name": "",
"Recommendations": "推荐",
"Redeem your gift": "",
- "Redeem your membership": "兑换您的会员资格",
"Redeeming...": "正在兑换...",
"Renews at {price}.": "以{price}的价格续费。",
"Resume subscription": "恢复订阅",
@@ -324,8 +323,6 @@
"You've been gifted a {duration}-month {tierName} membership to {siteTitle}_other": "",
"You've been gifted a {duration}-year {tierName} membership": "",
"You've been gifted a {duration}-year {tierName} membership to {siteTitle}": "",
- "You've been gifted a membership": "有人赠送了您会员资格",
- "You've been gifted a membership to {siteTitle}": "有人赠送了您 {siteTitle} 的会员资格",
"You've successfully signed in.": "您已成功登录。",
"You've successfully subscribed to {siteTitle}": "您已成功订阅 {siteTitle}",
"Your account": "您的账户",
diff --git a/packages/testing/test-data/src/selectors/editor.ts b/packages/testing/test-data/src/selectors/editor.ts
new file mode 100644
index 00000000000..2ab51e02b84
--- /dev/null
+++ b/packages/testing/test-data/src/selectors/editor.ts
@@ -0,0 +1,18 @@
+/**
+ * Editor selector strings, consumed by the admin screen helpers and the e2e
+ * page objects. Source of truth: apps/admin/src/editor.
+ */
+
+// testids
+export const postEditor = 'post-editor';
+export const editorTitleInput = 'editor-title-input';
+export const editorExcerptInput = 'editor-excerpt-input';
+export const editorBody = 'editor-body';
+export const editorSecondaryInstance = 'editor-secondary-instance';
+export const editorWordCount = 'editor-word-count';
+export const editorLoadError = 'editor-load-error';
+export const tkIndicator = 'tk-indicator';
+
+// accessible names
+export const postsBackLink = 'Posts';
+export const pagesBackLink = 'Pages';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8c2e92539c7..eb830aaa62a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -252,8 +252,8 @@ catalogs:
specifier: 14.3.1
version: 14.3.1
'@tryghost/api-framework':
- specifier: 3.3.9
- version: 3.3.9
+ specifier: 3.3.12
+ version: 3.3.12
'@tryghost/brute-knex':
specifier: 3.2.2
version: 3.2.2
@@ -264,11 +264,11 @@ catalogs:
specifier: 1.0.11
version: 1.0.11
'@tryghost/debug':
- specifier: 2.3.9
- version: 2.3.9
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/domain-events':
- specifier: 3.3.10
- version: 3.3.10
+ specifier: 3.3.13
+ version: 3.3.13
'@tryghost/helpers':
specifier: 1.1.106
version: 1.1.106
@@ -276,8 +276,8 @@ catalogs:
specifier: 1.5.6
version: 1.5.6
'@tryghost/metrics':
- specifier: 3.5.0
- version: 3.5.0
+ specifier: 3.5.3
+ version: 3.5.3
'@tryghost/mg-clean-html':
specifier: 0.12.6
version: 0.12.6
@@ -285,8 +285,8 @@ catalogs:
specifier: 0.11.2
version: 0.11.2
'@tryghost/request':
- specifier: 4.0.3
- version: 4.0.3
+ specifier: 4.0.5
+ version: 4.0.5
'@tryghost/string':
specifier: 0.3.5
version: 0.3.5
@@ -294,11 +294,11 @@ catalogs:
specifier: 1.0.0
version: 1.0.0
'@tryghost/tpl':
- specifier: 2.3.9
- version: 2.3.9
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/validator':
- specifier: 3.2.10
- version: 3.2.10
+ specifier: 3.2.12
+ version: 3.2.12
'@types/express':
specifier: 4.17.25
version: 4.17.25
@@ -629,8 +629,8 @@ catalogs:
overrides:
cron-validate: 1.4.5
knex-migrator>knex: 2.4.2
- '@tryghost/errors': 3.3.9
- '@tryghost/logging': 5.4.0
+ '@tryghost/errors': 3.3.12
+ '@tryghost/logging': 5.4.3
'@tryghost/nql': 0.13.4
'@tryghost/nql-lang': 0.7.0
jackspeak: 4.2.3
@@ -1278,7 +1278,7 @@ importers:
version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
react:
specifier: catalog:react17
version: 17.0.2
@@ -1769,7 +1769,7 @@ importers:
dependencies:
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
devDependencies:
'@doist/react-interpolate':
specifier: 2.2.4
@@ -2047,7 +2047,7 @@ importers:
dependencies:
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
react:
specifier: 'catalog:'
version: 18.3.1
@@ -2117,7 +2117,7 @@ importers:
dependencies:
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
'@tryghost/i18n':
specifier: workspace:*
version: link:../../packages/i18n
@@ -2264,10 +2264,10 @@ importers:
version: link:../packages/custom-field-types
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
'@tryghost/logging':
- specifier: 5.4.0
- version: 5.4.0(supports-color@10.2.2)
+ specifier: 5.4.3
+ version: 5.4.3(supports-color@10.2.2)
'@tryghost/test-data':
specifier: workspace:*
version: link:../packages/testing/test-data
@@ -2369,10 +2369,10 @@ importers:
version: link:../../packages/admin-api-schema
'@tryghost/api-framework':
specifier: 'catalog:'
- version: 3.3.9(supports-color@10.2.2)
+ version: 3.3.12(supports-color@10.2.2)
'@tryghost/bookshelf-plugins':
- specifier: 2.3.8
- version: 2.3.8(supports-color@10.2.2)
+ specifier: 2.3.12
+ version: 2.3.12(supports-color@10.2.2)
'@tryghost/brute-knex':
specifier: 'catalog:'
version: 3.2.2(better-sqlite3@12.11.1)(express@4.22.2(supports-color@10.2.2))(mysql2@3.22.5(@types/node@22.20.1))(supports-color@10.2.2)
@@ -2392,20 +2392,20 @@ importers:
specifier: 'catalog:'
version: 1.0.11
'@tryghost/database-info':
- specifier: 2.3.2
- version: 2.3.2
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
'@tryghost/domain-events':
specifier: 'catalog:'
- version: 3.3.10(supports-color@10.2.2)
+ version: 3.3.13(supports-color@10.2.2)
'@tryghost/email-mock-receiver':
- specifier: 2.1.0
- version: 2.1.0
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/errors':
- specifier: 3.3.9
- version: 3.3.9
+ specifier: 3.3.12
+ version: 3.3.12
'@tryghost/helpers':
specifier: 'catalog:'
version: 1.1.106
@@ -2446,11 +2446,11 @@ importers:
specifier: 'catalog:'
version: 1.5.6
'@tryghost/logging':
- specifier: 5.4.0
- version: 5.4.0(supports-color@10.2.2)
+ specifier: 5.4.3
+ version: 5.4.3(supports-color@10.2.2)
'@tryghost/metrics':
specifier: 'catalog:'
- version: 3.5.0(supports-color@10.2.2)
+ version: 3.5.3(supports-color@10.2.2)
'@tryghost/mg-clean-html':
specifier: 'catalog:'
version: 0.12.6(encoding@0.1.13)
@@ -2467,8 +2467,8 @@ importers:
specifier: 1.0.6
version: 1.0.6
'@tryghost/nodemailer':
- specifier: 2.3.1
- version: 2.3.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)
+ specifier: 2.3.12
+ version: 2.3.12(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)
'@tryghost/nql':
specifier: 0.13.4
version: 0.13.4(supports-color@10.2.2)
@@ -2482,8 +2482,8 @@ importers:
specifier: workspace:*
version: link:../../packages/parse-email-address
'@tryghost/pretty-cli':
- specifier: 3.3.2
- version: 3.3.2
+ specifier: 3.3.12
+ version: 3.3.12
'@tryghost/prometheus-metrics':
specifier: 1.0.8
version: 1.0.8(supports-color@10.2.2)
@@ -2492,10 +2492,10 @@ importers:
version: 0.1.21
'@tryghost/request':
specifier: 'catalog:'
- version: 4.0.3
+ version: 4.0.5
'@tryghost/root-utils':
- specifier: 2.3.2
- version: 2.3.2
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/security':
specifier: 1.0.6
version: 1.0.6
@@ -2507,19 +2507,19 @@ importers:
version: 0.3.5
'@tryghost/tpl':
specifier: 'catalog:'
- version: 2.3.9
+ version: 2.3.12
'@tryghost/url-utils':
specifier: 5.2.6
version: 5.2.6
'@tryghost/validator':
specifier: 'catalog:'
- version: 3.2.10
+ version: 3.2.12
'@tryghost/version':
- specifier: 2.3.2
- version: 2.3.2
+ specifier: 2.3.12
+ version: 2.3.12
'@tryghost/zip':
- specifier: 3.5.1
- version: 3.5.1(supports-color@10.2.2)
+ specifier: 3.5.11
+ version: 3.5.11(supports-color@10.2.2)
'@x402/core':
specifier: 'catalog:'
version: 2.12.0
@@ -2846,11 +2846,11 @@ importers:
specifier: workspace:*
version: link:../../configs/eslint
'@tryghost/express-test':
- specifier: 2.1.0
- version: 2.1.0(express@4.22.2(supports-color@10.2.2))(supports-color@10.2.2)
+ specifier: 2.3.12
+ version: 2.3.12(express@4.22.2(supports-color@10.2.2))(supports-color@10.2.2)
'@tryghost/webhook-mock-receiver':
- specifier: 2.1.0
- version: 2.1.0
+ specifier: 2.3.12
+ version: 2.3.12
'@types/bookshelf':
specifier: 1.2.9
version: 1.2.9(mysql2@3.22.5(@types/node@22.20.1))(supports-color@10.2.2)
@@ -4001,8 +4001,8 @@ importers:
packages/adapters/scheduling-base:
dependencies:
'@tryghost/logging':
- specifier: 5.4.0
- version: 5.4.0(supports-color@10.2.2)
+ specifier: 5.4.3
+ version: 5.4.3(supports-color@10.2.2)
devDependencies:
'@internal/cfg-eslint':
specifier: 'workspace:'
@@ -4041,8 +4041,8 @@ importers:
packages/adapters/sso-base:
dependencies:
'@tryghost/errors':
- specifier: 3.3.9
- version: 3.3.9
+ specifier: 3.3.12
+ version: 3.3.12
devDependencies:
'@internal/cfg-eslint':
specifier: workspace:*
@@ -4115,8 +4115,8 @@ importers:
packages/admin-api-schema:
dependencies:
'@tryghost/errors':
- specifier: 3.3.9
- version: 3.3.9
+ specifier: 3.3.12
+ version: 3.3.12
ajv:
specifier: 'catalog:'
version: 8.20.0
@@ -4224,7 +4224,7 @@ importers:
dependencies:
'@tryghost/debug':
specifier: 'catalog:'
- version: 2.3.9(supports-color@10.2.2)
+ version: 2.3.12(supports-color@10.2.2)
i18next:
specifier: 23.16.8
version: 23.16.8
@@ -4411,19 +4411,6 @@ packages:
resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==}
engines: {node: ^22.13.0 || >=24.0.0}
- '@aws-crypto/sha256-browser@5.2.0':
- resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
-
- '@aws-crypto/sha256-js@5.2.0':
- resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==}
- engines: {node: '>=16.0.0'}
-
- '@aws-crypto/supports-web-crypto@5.2.0':
- resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==}
-
- '@aws-crypto/util@5.2.0':
- resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
-
'@aws-sdk/checksums@3.1000.12':
resolution: {integrity: sha512-RgNDWfhNRIlNEzePIRrYTNi/6q+wwRMMapojn8YVzw4ZcJRa/gxVMtUbeZARR1gmopuv6oIhMbY7J66qIQ0ynw==}
engines: {node: '>=20.0.0'}
@@ -4432,46 +4419,82 @@ packages:
resolution: {integrity: sha512-di9U/7Po7qlVYb2dq58ULsbBAE1pBIk53rux+50LQCvH1X+/l1Ys+BIk/QLBtdaK1nADk0xRNEBbA1QWVnMccw==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/client-sesv2@3.1073.0':
- resolution: {integrity: sha512-+9OG/NMj/5OFL0ygVFEbh/CF1ENdGLSuYR3upvYJ4entG3dcAwBzgxRl81EAXt7yI0nK6IqBy7H6QuNoAs3Aew==}
+ '@aws-sdk/client-sesv2@3.1121.0':
+ resolution: {integrity: sha512-Vk7tHo7TPBlR5MmvpfR4XXNL5uld/5uWHNBceUArtQrzhwNaxt/5ANp45JETZfLH9VDoaX3bTmoHeSMOWc0Ldg==}
engines: {node: '>=20.0.0'}
'@aws-sdk/core@3.974.27':
resolution: {integrity: sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/core@3.977.9':
+ resolution: {integrity: sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-env@3.972.53':
resolution: {integrity: sha512-+KDA3uc/HZ1vIneGu5QMQb0gAXDYrm2vOE60+BJ7lS0YinMQ5i2oV4PR1A16XkF6K1IbSwjEHd1hQIIgMsK48w==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-env@3.972.70':
+ resolution: {integrity: sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-http@3.972.55':
resolution: {integrity: sha512-1gBfkWY3RWeBlCoB9lIJjXMx45/54wxcgfzv6BY9otTmMrZPcNPi1v+MwZxxaCUg441NV3jsr1efnFNCXiW70g==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-http@3.972.72':
+ resolution: {integrity: sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-ini@3.972.60':
resolution: {integrity: sha512-CV2md+PXvABwRjApWGhQ0wACy9WSFIhnUGrovLcjnjBCd/46TbuivLADtkF8IWNjtCQmQ+2IagSaxqBYqXBNAQ==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-ini@3.973.15':
+ resolution: {integrity: sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-login@3.972.59':
resolution: {integrity: sha512-JG4S9yyA1GFzJdJXqLKrUzZbyK+VDp2QIsJD7YOicJHAhqymfHpDJIok2dLnhOdVB0I37RjdC53uOwCMVS00gw==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-login@3.972.77':
+ resolution: {integrity: sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-node@3.972.62':
resolution: {integrity: sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-node@3.972.81':
+ resolution: {integrity: sha512-Rml+WitoFvXmv6JZ18U/xGdGDGGvB/mOin0ya0lTnTrdC0Z1lrVxTYh7iNklZBcvcRMrs4DoEf6xy1KWyrLQQw==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-process@3.972.53':
resolution: {integrity: sha512-EhfH+MQlqOMCkXIVa8MMObPzAQqwTTtxA7KhEJiyPeuNVA8PLOOUpgK7nBrgaDaGiIDLN/9LpGdaHuDjomeRTw==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-process@3.972.70':
+ resolution: {integrity: sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-sso@3.972.59':
resolution: {integrity: sha512-h8793pOjcImx0SB+VcLONcaQQ57VAvKVuqyewQMRKqqH+CSXsG2dwOeLMUJPMxLdNvL7dXOM0ueTukyNUnu5mA==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-sso@3.973.14':
+ resolution: {integrity: sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/credential-provider-web-identity@3.972.59':
resolution: {integrity: sha512-VoyO9+vl3XVmpZwn4obskrWIkrA/Jf3lSe1E3ZERlaN9u0D4YZ6+HywC3+L98QOXqZesEfedk67gRER8tK8+8w==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/credential-provider-web-identity@3.972.76':
+ resolution: {integrity: sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/middleware-sdk-s3@3.972.58':
resolution: {integrity: sha512-6uaWRRYJGhOqc9EoTSbLDf9nI/doSAb5vAwGshs5/Hlv5Ce25b246lBkbRd/77fLAi+uMI1a70mJzVyLyCEufQ==}
engines: {node: '>=20.0.0'}
@@ -4480,26 +4503,42 @@ packages:
resolution: {integrity: sha512-A8PIePF9NIIOJ/4Lg1rl9xm/+QaKkHGetq+Z9wb5B+3Da31YYXRo8n7IDMh5C+HQI5eyEmjrwkGWVdYtnLtbXQ==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/nested-clients@3.997.44':
+ resolution: {integrity: sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/signature-v4-multi-region@3.996.38':
resolution: {integrity: sha512-C379Sk+MiFZCfWZphKlMyLHKxV22OjoGM5KJjj5IJNJcOCWL4IGIpnEGzv1FQiRwhYXfq55SJMfxlqPE08JJ9g==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/signature-v4-multi-region@3.996.46':
+ resolution: {integrity: sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/token-providers@3.1079.0':
resolution: {integrity: sha512-cbietrLlHPhhmbnMPTuDS4Zj/KNGhY+3vVhn6dwjO6Dqzrwothzg2srtcY34T9mlICsTXn34avDoWLHSntP54A==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/token-providers@3.1116.0':
+ resolution: {integrity: sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q==}
+ engines: {node: '>=20.0.0'}
+
'@aws-sdk/types@3.973.15':
resolution: {integrity: sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/util-locate-window@3.965.8':
- resolution: {integrity: sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==}
+ '@aws-sdk/types@3.974.5':
+ resolution: {integrity: sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/xml-builder@3.972.33':
resolution: {integrity: sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A==}
engines: {node: '>=20.0.0'}
+ '@aws-sdk/xml-builder@3.972.40':
+ resolution: {integrity: sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA==}
+ engines: {node: '>=20.0.0'}
+
'@aws/lambda-invoke-store@0.3.0':
resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
engines: {node: '>=18.0.0'}
@@ -6481,6 +6520,10 @@ packages:
resolution: {integrity: sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/diff-sequences@30.4.0':
+ resolution: {integrity: sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/environment@29.7.0':
resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -6493,12 +6536,16 @@ packages:
resolution: {integrity: sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/expect-utils@30.4.1':
+ resolution: {integrity: sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/expect@29.7.0':
resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- '@jest/expect@30.3.0':
- resolution: {integrity: sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==}
+ '@jest/expect@30.4.1':
+ resolution: {integrity: sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
'@jest/fake-timers@29.7.0':
@@ -6517,6 +6564,10 @@ packages:
resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/pattern@30.4.0':
+ resolution: {integrity: sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/reporters@29.7.0':
resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -6534,10 +6585,18 @@ packages:
resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/schemas@30.4.1':
+ resolution: {integrity: sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/snapshot-utils@30.3.0':
resolution: {integrity: sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/snapshot-utils@30.4.1':
+ resolution: {integrity: sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/source-map@29.6.3':
resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -6558,6 +6617,10 @@ packages:
resolution: {integrity: sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/transform@30.4.1':
+ resolution: {integrity: sha512-Wz0LyktlTvRefoymh+n64hQ84KNXsRGcwdoZ8CSa0Ea+fgYcHZlnk+hDP7v2MS7il2bQ5uTEIxf4/NNfhMN4KQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jest/types@29.6.3':
resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -6566,6 +6629,10 @@ packages:
resolution: {integrity: sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ '@jest/types@30.4.1':
+ resolution: {integrity: sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@joshwooding/vite-plugin-react-docgen-typescript@0.7.0':
resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==}
peerDependencies:
@@ -8851,17 +8918,29 @@ packages:
resolution: {integrity: sha512-sEvpvkBVoMxjoek35XyJFn2ZD3EJ1RpiZrT47WaZodxzAIWS44zkdvbqGE/ZlugtjiQp62cffYZ9ldyRkjAGnA==}
engines: {node: '>=18.0.0'}
+ '@smithy/core@3.33.3':
+ resolution: {integrity: sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg==}
+ engines: {node: '>=18.0.0'}
+
'@smithy/credential-provider-imds@4.4.5':
resolution: {integrity: sha512-LnjUTNG0GgQlKIq7IioeOrPaEmC5xOd1WtAz24TLSiYQnWX2uHr53GrFuQhkrJBktPYCMga/NbUOW7hFbSA2Cg==}
engines: {node: '>=18.0.0'}
+ '@smithy/credential-provider-imds@4.5.2':
+ resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==}
+ engines: {node: '>=18.0.0'}
+
'@smithy/fetch-http-handler@5.6.2':
resolution: {integrity: sha512-q96PSDOAGw+X+nuELd7Cjebps0SYr+YlPbviEX9sLVw+VM4M7VV8hn1nL1mGS6urDu33eQ5A7WhlphaDO6kUyQ==}
engines: {node: '>=18.0.0'}
- '@smithy/is-array-buffer@2.2.0':
- resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==}
- engines: {node: '>=14.0.0'}
+ '@smithy/fetch-http-handler@5.7.2':
+ resolution: {integrity: sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==}
+ engines: {node: '>=18.0.0'}
+
+ '@smithy/node-http-handler@4.11.3':
+ resolution: {integrity: sha512-2jY1tSpERfPfWqyBV2pH+iGFaghVsIJszJNsT7hxtQYhVJpWDyc0LqOWI+nXOxOAHaEfZ4PXXtp1wW1TGpHhkA==}
+ engines: {node: '>=18.0.0'}
'@smithy/node-http-handler@4.9.2':
resolution: {integrity: sha512-s0yAIRj6TVfHgl+QzVyqal1KMGZ9B5512IrxKc6+dOpw8fUmFL3CvuAhjv0J+aNjUPfVZ2IhqPEDvkB5Ncx9oA==}
@@ -8871,17 +8950,17 @@ packages:
resolution: {integrity: sha512-SqvuP75p/DmgWWI7jv4kf/UW+V4LFmlUn19s604SgAcRuJRB1vDnWwzZMYCLUcmKxko9wDn6iLgGEIpTNgZbIQ==}
engines: {node: '>=18.0.0'}
+ '@smithy/signature-v4@5.7.3':
+ resolution: {integrity: sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==}
+ engines: {node: '>=18.0.0'}
+
'@smithy/types@4.15.1':
resolution: {integrity: sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q==}
engines: {node: '>=18.0.0'}
- '@smithy/util-buffer-from@2.2.0':
- resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
- engines: {node: '>=14.0.0'}
-
- '@smithy/util-utf8@2.3.0':
- resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
- engines: {node: '>=14.0.0'}
+ '@smithy/types@4.17.2':
+ resolution: {integrity: sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==}
+ engines: {node: '>=18.0.0'}
'@socket.io/component-emitter@3.1.2':
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
@@ -9432,48 +9511,48 @@ packages:
resolution: {integrity: sha512-VyMVKRrpHTT8PnotUeV8L/mDaMwD5DaAKCFLP73zAqAtvF0FCqky+Ki7BYbFCYQmqFyTe9316Ed5zS70QUR9eg==}
engines: {node: '>= 10'}
- '@tryghost/api-framework@3.3.9':
- resolution: {integrity: sha512-G05CO9tbwQnLWGlpC7c0tANQlgdQbJUK9l/j0o4ykfqz6d0W/uZ7avvniU2TKFO24D1pA+POZskZhigqMTCzDA==}
+ '@tryghost/api-framework@3.3.12':
+ resolution: {integrity: sha512-L5Q0ZOyYPlZijdo88TTlgpWWhcwvDzfg7ZJz1uzpQRPhzE2Mjo99dQyx+5JGfYhnpnR2mwfcrQStvF34FEMLkg==}
- '@tryghost/bookshelf-collision@2.3.7':
- resolution: {integrity: sha512-CIrIW1BhzyBaybKTKF7Ly6jcnx/AOzCmH1rrLlLhxUjW/5tRZt7qHfXgH7r/SbYbzR8+CVuljq1jGA4vqjM9SA==}
+ '@tryghost/bookshelf-collision@2.3.12':
+ resolution: {integrity: sha512-QawYGMPRdxaaYIauiFT4u7/lTI2KB+vl+cHHd8phrQuErJSgIyXCulpJcD6kSGAX9MD4W8IU74YZtwIso0VgMw==}
- '@tryghost/bookshelf-custom-query@2.3.7':
- resolution: {integrity: sha512-i9P24QcI4SadAkFfIwRr5RfK8c0EFOhRlGka0gkXecAOOsnRLJEK36/+f+7eOfVbhdOZq2drOg6zVBAkBjv4HQ==}
+ '@tryghost/bookshelf-custom-query@2.3.12':
+ resolution: {integrity: sha512-9hIdVz+fj+9w6wWrC7/zs/UVD04bT/4SVCeyn6R/HqM0BGdGDELTeRL5BtVMyZQ4YIJgK7eg3/WkUEv1o0z7vg==}
- '@tryghost/bookshelf-eager-load@2.3.7':
- resolution: {integrity: sha512-k3eB8Xe665PpZxx+t/ycIh0rqQt9XhV1BtnqCyNWRzgIvnTEcrIx0vQqxUQMOOAEtMoZ0s5rFAqGVzDo1H4KjQ==}
+ '@tryghost/bookshelf-eager-load@2.3.12':
+ resolution: {integrity: sha512-va68hgNz08GcEpG3mt8fyIWNx0I83HLk4OxUYvwRxacf5y52A33xQTQ3pDWWxEFd3XcbytOjU9xlpctAu9G83Q==}
- '@tryghost/bookshelf-filter@2.3.7':
- resolution: {integrity: sha512-lR51ryZO4NCNvzVcWv6b4CHDpp41XhflbltwdvJZdXgEej5dIf9kYSZ8km7Mrw8CEbZrGqoPUdiAdCxTgeKUZg==}
+ '@tryghost/bookshelf-filter@2.3.12':
+ resolution: {integrity: sha512-IraUXBhsPJfNf3lAr8pYCo4AFAjNVYAQlGVyGFZtdIMdg03rWoWcRAbHle7ozP58hBMwG6jg5h/Qt6dHZLi7Ag==}
- '@tryghost/bookshelf-has-posts@2.4.7':
- resolution: {integrity: sha512-uWdsQKosBvKhMZnKLArBmK791qH13o6oNnTMcpM9dDRBNWDW3IJBW3XYnZUTJmjDg9HnJ7t5zm7wZxOnKwwP9Q==}
+ '@tryghost/bookshelf-has-posts@2.4.12':
+ resolution: {integrity: sha512-ZwN0/kjMx/lrhJJcER7B80Wnz1qJpqbBLSn9VLtoygbNg4xufVTTrb0iBqHTCu2vqHVTQuMXj8sZxTOwlSyHfA==}
- '@tryghost/bookshelf-include-count@2.3.7':
- resolution: {integrity: sha512-opncKLBLPtc4/lLgMx+fIhXdjDX34V+4a2OYp259eDsKyFOnrm4H1vYdyxy/VIw8d/WnRy7KpdYA9xlJgZhDsQ==}
+ '@tryghost/bookshelf-include-count@2.3.12':
+ resolution: {integrity: sha512-PsnwMetXAPEt5ASWfLFU+j+ST9cBZ42WRoaeRCFVCQwHvWrn/LF4womQNQGwH6+byk9agC9JpjSniUGAkkXFZA==}
- '@tryghost/bookshelf-order@2.3.7':
- resolution: {integrity: sha512-pX4+8ne1W0oo5Kw98gvvgWL7RgzeywywnydnvGe6B48QuSt0NheFqKQ30g9VKZiCanEI7vkyKs9NZkoRTbY9Sw==}
+ '@tryghost/bookshelf-order@2.3.12':
+ resolution: {integrity: sha512-cWd+N1y7nkb1CuPBO+h7I70mkwDFskyseTjJX9oq9erVcz+fJzkHwf0Bb4fn4FUuFXy+75VSwArz5aa/nvClHg==}
- '@tryghost/bookshelf-pagination@2.4.1':
- resolution: {integrity: sha512-oEFuybdPkEhpadvOBUXM83BgVKyKaiFpdALOUqFHR4fk1xHA4vWgOE75ajntXcDUBUmmTSRW8k/4XZDofFWTxA==}
+ '@tryghost/bookshelf-pagination@2.4.6':
+ resolution: {integrity: sha512-K2x5D7P9ipf9QxNmyyVSMdJExD3BlBL4FZ98NmdlxqW6bxSXmAl4Avi8xAw7AWq3G3JKtODvCHZrRZIpwW3qHg==}
- '@tryghost/bookshelf-plugins@2.3.8':
- resolution: {integrity: sha512-CSEMOYJtBqXOxE1JccvYcktPDiC1xAXrYQAYSGGoUPXj/5zIRgU0Lr9z5WfmX4AmxEnpTPpFQl1O/9EoDrsxXA==}
+ '@tryghost/bookshelf-plugins@2.3.12':
+ resolution: {integrity: sha512-MmkYPwfGj6kjkl7IrzNPrpMoyi8A8LF4mqA1/1pANwuXi4kSCQ2TtoFnFvxI7eg0njwCmnM0c+jjO8orXD7gKg==}
- '@tryghost/bookshelf-search@2.3.7':
- resolution: {integrity: sha512-MAy/aLA72BGIJ7lYoBkCooJMpXGcnCRWI1+QwPDtszNdC4lawDOgBANyEmBzUFH+YveCkK0RAzDPCV4UO0xyPA==}
+ '@tryghost/bookshelf-search@2.3.12':
+ resolution: {integrity: sha512-DrAnqHX3re3tI7mKEDeF3xXZBWHQOYHygVGMYQAEdgzfDR3O+aA9hxBkepDQAZxrTg9nwqJvCVzhe0QAkYFMqQ==}
- '@tryghost/bookshelf-transaction-events@2.3.7':
- resolution: {integrity: sha512-m9SP1f999C+pO0HU6wzEVhGAIijXWcv4A4EFooHwTqyYszJTXxSwyzyw3u2dXMaMLHLKO9+iFotlaOBPLZN65g==}
+ '@tryghost/bookshelf-transaction-events@2.3.12':
+ resolution: {integrity: sha512-7Fegy8GZplUP4Q2n7LYodZgUSVORGTm9D2nnHSwaPvqvev0Vk4OOqdsaN4y6/d5mcl+bcKXwJbWvawyRV1LSsg==}
'@tryghost/brute-knex@3.2.2':
resolution: {integrity: sha512-wdhqZV5klysUO+0ZthzxkaWiSxqKKoJm7rkqby3llt5FHZTU5yiaJ55yraio9knm5MHqfDd+IFspNTKEjAnsIw==}
engines: {node: '>=20.20.0'}
- '@tryghost/bunyan-rotating-filestream@0.0.15':
- resolution: {integrity: sha512-slSrnLFWWDoNsPsyXDyf5+mG2gULzQb//Ntp60NDEWu40yq1OVEJsbd8Jl+1F34cKQyoFBD1pm+J6srH+qOr8Q==}
+ '@tryghost/bunyan-rotating-filestream@0.0.18':
+ resolution: {integrity: sha512-aAq68VoZaMJMjYXEkHcFQTmfWjUV4msYvEhvTciNEJ8gkcti8eUANr3bGTtHmccVDPlxfAadc7v4gleIPxJ4UQ==}
'@tryghost/color-utils@0.2.20':
resolution: {integrity: sha512-0KLCQDX7TbJGKNihs+OB1+3hEvhdP4YXOKpdbqJlUkvEFdY+Gl1FlI4WL8wnn0v6oc1aOjvrKmva5BUT0pWtIg==}
@@ -9490,8 +9569,8 @@ packages:
'@tryghost/database-info@0.3.35':
resolution: {integrity: sha512-S9OapApwzdh3GS0d3m+KgwH7IhZII6b9Aw5I89HA5VJRPeo6HdaDXiZzSDNcFaUzpx1FFBR0kDu7G+IRPD0eFA==}
- '@tryghost/database-info@2.3.2':
- resolution: {integrity: sha512-v8DFbv2IrGfCd45akvbjKzZ26tTAqaX4FE7sGYv0aFrj98mEfwedjCd9sc6tjJxOXGNWplAZDAeZo5dcwkbxDQ==}
+ '@tryghost/database-info@2.3.12':
+ resolution: {integrity: sha512-DEk3RH0EitMoIOLjnoM1oafjFE0Wc9pOqBns7HYVUCwVmDziVfj+N/Ca77+EeGUMey0BfCiY7hhg5uGbIRVx6A==}
'@tryghost/debug@0.1.40':
resolution: {integrity: sha512-r8ecoTeoickPsn/59tkrouCNHhUEy79MNhJdPNkhx/Q3Oevw+SQBjnVYa5mHaxTaXryM4nNguKM5fbxPGPBo3Q==}
@@ -9499,30 +9578,27 @@ packages:
'@tryghost/debug@2.3.1':
resolution: {integrity: sha512-m35yRGwmmmvHWzs42qJnf0duCvi5Yd456bPa436Gcldv/rxK5YMPehtGDrwjHstJ4K2If0oguXsdHJf3tjgAjw==}
- '@tryghost/debug@2.3.7':
- resolution: {integrity: sha512-qS8QrBLNdDTu1DBgx/RwnNeF/7abDvT1iRZ+bDJ95TIj6gKcHbQN2gQs0rLhZLsnxQs2aC4arb0QjHRy8JyazA==}
-
- '@tryghost/debug@2.3.9':
- resolution: {integrity: sha512-nWwKuyJIzCzBFbTMh2bcGAocqSeMbjPifb56AqqZybt0KErbuqrw+RfYox92UXTCQR/TLMhPmBq9ccHD0OG33w==}
+ '@tryghost/debug@2.3.12':
+ resolution: {integrity: sha512-x7gtwoO4fmG7LbP3W/RP4C6n4BpBdyf6wpsasIG91E+xtEkTd7krWIXWwcBg2Q+SwUF78O4qFfOejZDtMjH10w==}
- '@tryghost/domain-events@3.3.10':
- resolution: {integrity: sha512-Kh23N3SOCNpp0ozkgAmOt6qMKMwHjXPeXOvAhHAsA8ybaO0t+uEH1KJUn5xjCwptTu9JjgJ5YD3aiqovB8gdxg==}
+ '@tryghost/domain-events@3.3.13':
+ resolution: {integrity: sha512-7/JGHHkogFfmYo7tTc0K+wZzaU5p5OOCliuDMF6D+2A0CWWBb3wTO/HleAr3lKOFYpUsAPJ3CqGzzSI+rjWsVw==}
- '@tryghost/elasticsearch@5.4.6':
- resolution: {integrity: sha512-7bE2Nm4XfXhlOiVSxVV4FrKyHMxbd/NxNHnowe1vXyKzQp6ExWVNdrgPFnUUYoUyT1THz20HMY7SB0bUje1ZLg==}
+ '@tryghost/elasticsearch@5.4.9':
+ resolution: {integrity: sha512-lK51E9rn/ROEY1JQxd1cuy+ZlFLc99b0bcspx3ow3g8khG9te060jm4jqqIqlH/yeaClkih6wlopjSVJhdiWwQ==}
- '@tryghost/email-mock-receiver@2.1.0':
- resolution: {integrity: sha512-bgEVM5eRnN53rnqWJ8ZkjuGCzMwwt5Ch29TTXRp3qSGTJruUW44DtN/mjB36DDti0hq4unJV9+D1qIIKxdbong==}
+ '@tryghost/email-mock-receiver@2.3.12':
+ resolution: {integrity: sha512-9ucMMPTPAfsqaMgki+CtjVkqZ3V04Dkm+zYw/vSIf0NUoYxXsgsnXJPyix90jWp4BMuXmtLJbX74MoEZ+c9ZRg==}
'@tryghost/ember-promise-modals@2.0.1':
resolution: {integrity: sha512-py/Fi3jbr+UiUped74m2VRhNEJQrFSgPEhQu/FSHkPjUPWruIokwJoO4TDedklGcMJ+0RKr3YiigcuMFxXjf7A==}
engines: {node: 12.* || >= 14.*}
- '@tryghost/errors@3.3.9':
- resolution: {integrity: sha512-hcrIXQoWZV0Th8DwndC8bA5BcCcgd7Zw0anAYv6ys/SsKlDMmpzZplECC3pEL8HKI/Cz05/TXkQJiBNrTK11/Q==}
+ '@tryghost/errors@3.3.12':
+ resolution: {integrity: sha512-fjZp4K2u7ic5zDJ1+i+wru2+9URcbqEmYDzS6PZsiXr3z/gI1QSkwGvpVdoBHnyDEWCorR5KTqXts8Fg9H9L4Q==}
- '@tryghost/express-test@2.1.0':
- resolution: {integrity: sha512-gY2AeFzBLvDtDCdc5rE54crDeEC9TzVboViUTmP1Vwbt35BA3O177Ox2j6vb/LQ9HCQ1tp3DOa0hbNYZFaaJAQ==}
+ '@tryghost/express-test@2.3.12':
+ resolution: {integrity: sha512-zNf2BUvaEYXk1dm7/vi8gfXV2U7deMdq3XsNbLsIC6Y6WVnb+vCs735Lqrt4R8uwf12VzNkI0VWEbFIgNMYF1g==}
peerDependencies:
express: ^4.0.0 || ^5.0.0
@@ -9535,14 +9611,14 @@ packages:
'@tryghost/http-cache-utils@0.1.25':
resolution: {integrity: sha512-OJAD1ESvV+F81w6IOTKCX0JLGIiJqNn87HVFMskpUC3IUGpqcDP1pCM79d72khxLWy5oRQDYu8xIqicHJ9ST1Q==}
- '@tryghost/http-stream@2.3.10':
- resolution: {integrity: sha512-qvod+MltdcQhcfii1B+VpNsJD9pi/1QYqdLckH0Z5DnFD3euDgB7cys+dr/2XS0TgxQc9Gj7cHZDl0OOtKe2RQ==}
+ '@tryghost/http-stream@2.3.13':
+ resolution: {integrity: sha512-FEvSnVQeWkp8oGDO3Ak60B/zazuJj0MTvw87Co3/1rGamYYtuCRAU8/VB8eP1GIT2jyYmFmw6VJ8NzCZpZmdgw==}
'@tryghost/image-transform@1.4.17':
resolution: {integrity: sha512-+WipAbQ6gTOB9hbhmTDHW7tzaB1lPIRszoN+z1qV+vlI+cR/4qO70Ux+HkSYT9gt4WpxRZJZCBCk3+x4Nm0LhQ==}
- '@tryghost/jest-snapshot@2.1.0':
- resolution: {integrity: sha512-oOi91KgOVnHzMgFTM6yEBA2jjpVBx0tbE1HJYmmoQ6UYt0rB7giUg1fMFcEvbfXu2DAng1mYKQysrf8EJfHslQ==}
+ '@tryghost/jest-snapshot@2.3.12':
+ resolution: {integrity: sha512-PyjtM7O5tlfafhQbr2Axjmao8DGmoLxvEmvsPKafUWQIj5NX1DjDboAq1iOxlnIjBIVDZUxig1UX//EjAZF8fw==}
'@tryghost/job-manager@1.0.9':
resolution: {integrity: sha512-Wlwr1R8oeU6HLB7RB1g6VxAH6VEZIaXTVV2GdvCbipK+TA0MIo6YOQUgrIky25RpyRqKXR0UuDIfXDB4+S+GgQ==}
@@ -9561,11 +9637,11 @@ packages:
'@tryghost/limit-service@1.5.6':
resolution: {integrity: sha512-wR+Hm2v5k2FjOUhLhfPZ0p0acCfaTQoSEhuw96uw8c15CLZtm/HKsLnxA5d3AXwYmjRo5gkYskP8UYxrCKNcoQ==}
- '@tryghost/logging@5.4.0':
- resolution: {integrity: sha512-H0jWmJBJ0EEwBkq+SErWt4N/LQwwdYCfQcUT3a5RZbF5bcZTRcWnGfSw5aPBIphra9BaOHCiCYeQbyg5wcJkBw==}
+ '@tryghost/logging@5.4.3':
+ resolution: {integrity: sha512-VXJvLI1F5EwZ+4aD+TBqC0nvs40VSc+oSMBvp+ng4hJ/DaN5W0AQXMouQ3zu+6OT1VZKvs7FPTfS1ILgN2GCsg==}
- '@tryghost/metrics@3.5.0':
- resolution: {integrity: sha512-fBIKCodafcG23Eq5rjhmixI+CSzVZ555jNqj7tdDeCXtfVA9ws3X3H3dNo7jgxgZs2SbC7ElYbhBSj4dHX8RKw==}
+ '@tryghost/metrics@3.5.3':
+ resolution: {integrity: sha512-1RXDXzsoOjlabcyDHxQWcxnDhJSAcmY4Sy0LpdAj4xmdi6CNgZhYW+/kmm3aDXwqEOVUJlFWhOvrwlDxbxGE0Q==}
'@tryghost/mg-clean-html@0.12.6':
resolution: {integrity: sha512-ped/cNQdKvcX4F0B8Z5j0VnLuFjyHthElxT4Gny2yWtPHczvFsbVQXlynuHPpQcM3ZLE6o9lemm7Bin1uG/whQ==}
@@ -9588,8 +9664,8 @@ packages:
'@tryghost/mw-vhost@1.0.6':
resolution: {integrity: sha512-FKoSdBw5+fZNbzC58LD3ZLbMEj2UI5+4XOnEau7xINuYBP/c4wN0TXHuJT8y6H1wnYvO4Qu9L+PwHxe1yHBA+Q==}
- '@tryghost/nodemailer@2.3.1':
- resolution: {integrity: sha512-sIek+jnYoHWRbsvXgjA+v1sBiiXS7Gh75iW2fl/jo+ED1H7B0i+svSMTfKwLpDRlGrUTMP2/swvr8EBb59kC4w==}
+ '@tryghost/nodemailer@2.3.12':
+ resolution: {integrity: sha512-uEbAazB4v6gQmXp+wrVyaLyiTKatlWR3nc2l5rBd3FRb2z/6ncIllWCMrKsWLHxRcr9sazgmP4LQrmgimS3CNQ==}
'@tryghost/nql-lang@0.7.0':
resolution: {integrity: sha512-S3P66JRL7kiKhYR7VnYC5S5xnkKqS+A5aW60nCGi/lraAhk/G5+xmPisztQiJWbHxM1odIagt2GpDMbKCDXT2w==}
@@ -9600,11 +9676,11 @@ packages:
'@tryghost/pretty-cli@3.3.1':
resolution: {integrity: sha512-P7/GffeBG0grjmFxMWEeVFONL6HGt1mWUZvI5G36mhlxC/AXSWCSS6+qiQU91ZfenTwBrP6LZRC9Pyt0gqfzLg==}
- '@tryghost/pretty-cli@3.3.2':
- resolution: {integrity: sha512-JOWoEwrdF+flxZBWq+ikww5BRvU95jfUzUnx25pkrSNJEdTYWzJj3bsTGt7LravWCN41M9y4+XvYwEp6cfawpg==}
+ '@tryghost/pretty-cli@3.3.12':
+ resolution: {integrity: sha512-0NKZZXJfhnBzIkNORdGYVmFds8O/N8OZWvt14CM3twJp5CejGY5/0tktNjMDDXIXFVhzudHjjMkrEywU/bp1tg==}
- '@tryghost/pretty-stream@2.3.9':
- resolution: {integrity: sha512-5bq3xDBmLm1auQzsuoIxxwimuQFSnTia+rV9kQ6HmId4GRCbZrqcQOx7y9MVe2kwAUkdHqQrkSZkxoNebCiaRQ==}
+ '@tryghost/pretty-stream@2.3.12':
+ resolution: {integrity: sha512-NegQcNCOCpAoYD7GkdM0NJljYfzVb23Ifaph8cMfUa2PEvJYD8cwPB3xXZspGECRZTVyTYixe6MDxx58tNmyLQ==}
'@tryghost/prometheus-metrics@1.0.8':
resolution: {integrity: sha512-E1LRRwLgiWIN/P20uHgpTK+JVYYQ3+BarKCBszB6qmK5IBANJvQHI3LQV0wDWefVwFyl5FI6AqxLpOOpquvahA==}
@@ -9612,18 +9688,16 @@ packages:
'@tryghost/promise@0.3.20':
resolution: {integrity: sha512-afHCBoS72XabqRi7GmHdVAWC/UMsVPGlxnL/epNVp0c/C7tEn6+MgHABXNAW4wViZFhuOda3k7fk3i2K0FAZQg==}
- '@tryghost/promise@2.3.9':
- resolution: {integrity: sha512-O/d4kTvvHrD/T9Czfhl057uPCJVQulfcQl/XsFHrWOhXewZUc6rsmqTFo6zz9Iv5NRye+SicsUya7BSJFSgKCQ==}
+ '@tryghost/promise@2.3.12':
+ resolution: {integrity: sha512-BrTvKB0o+2GW9Yjf0c4s0HSja/Xz9CxZSKYoJ+u9h/2+OG99KqxYVQDzUs1HVfI4aT8QkE0dflUBePi1zY1olA==}
'@tryghost/referrer-parser@0.1.21':
resolution: {integrity: sha512-Uz7bj8IadLah1j9GgieGQ0VGytdOG6mIlYdbpNu1r8/o9pjR2IS4bt88tvwpGSPNb47P9NrGntGn+Le1W/90jg==}
engines: {node: '>=16.0.0'}
- '@tryghost/request@4.0.2':
- resolution: {integrity: sha512-43mgzdOSd09u7Ek9nIjgk1MIkYteZ5FmiS4UYc+H82G8ci5RnVvkW2qplaNYK8Rpih36KxxjNIb7SglX6IL+kg==}
-
- '@tryghost/request@4.0.3':
- resolution: {integrity: sha512-vcKSJua/W9zjUQrH7jw/16t8dB6UbEbwCFMiFFxMY0uXcn2IbYEJuxmHOg0aMhqpOc11lAk714rDi3K+RNoweQ==}
+ '@tryghost/request@4.0.5':
+ resolution: {integrity: sha512-1I4cmpcu86cfq6R+4pfFxfqa5nkIj+vbprkIEYlvLvhYQj7B2BYaI88VV3A3jqfQc3dh7x/OYeF2udaVrhKpUw==}
+ engines: {node: ^22.12.0 || >=24.0.0}
'@tryghost/root-utils@0.3.38':
resolution: {integrity: sha512-ARn8wC6qv867lCr7BZ+IS8S/88K5go0j6HgQFhP27rKje4b40PsxH/P3rO4Ez2NzF/Do8ywFrTWHoLCSsCazXQ==}
@@ -9631,17 +9705,8 @@ packages:
'@tryghost/root-utils@2.3.1':
resolution: {integrity: sha512-1g0HskTTDJzn3CzcEWhd4aKtcmPm3IztD7cyfQQiG4QX+6gfpPOkYk7Y5gDOwTKAYtfor0nc8npSY90vvIj93A==}
- '@tryghost/root-utils@2.3.10':
- resolution: {integrity: sha512-QqOj7YQxG91ovizRFKUn5f1AHZn5pdkgxcz8Qbg2M9QRJvACRVF9Pxst/yGoWmjdWRchpaDbfl7QipTOT/jH/Q==}
-
- '@tryghost/root-utils@2.3.2':
- resolution: {integrity: sha512-tUyMS4xJUceE62JjZIjWAXCeoVlbNHWF2dIy6xJkaYgeHw4oZ5YoKMu9Mzqa7TPHIapU+BxwdWV0HvMj9dZGlA==}
-
- '@tryghost/root-utils@2.3.7':
- resolution: {integrity: sha512-8HR0W95it+s+ERkRI3syWHDLyYcinBFexpVlmLBhMMf8yEcL7r6tio6H3sUAj09L/YE8Kk5uGhvjAZAT3TU77Q==}
-
- '@tryghost/root-utils@2.3.9':
- resolution: {integrity: sha512-jhnWp6PVubyPoc3BDJSeQ7rX7kC73X7Asp8gv8mCosae9/ciBST95SND/Kblh8FI5yGwuENN8b6Z2w+YBl13FA==}
+ '@tryghost/root-utils@2.3.12':
+ resolution: {integrity: sha512-CyMKL8updcL41ZhNODJj21uSVq9npGDU5INnf22AGePi3kCVSDcOlPlJ4R+0bqE7KzDlTwp3wcn+ZmFX4EKiqQ==}
'@tryghost/security@1.0.6':
resolution: {integrity: sha512-h4FiUK4ndHezlXeuRzfwTZrX/a8ZdCS/FRqmZWCHcMUiBH6lewHv8eIjsPemN6e6Gn9jtsWZsKnuYM2mD0meSQ==}
@@ -9665,17 +9730,8 @@ packages:
'@tryghost/tpl@0.1.40':
resolution: {integrity: sha512-8w94lbNxXptRCIS8pe/IHjzgVFLxljxXx8+UQLO8NRFKraoEXthkPjAphN2MXKp1UGtj5ldh4Ye4D82bUWceOw==}
- '@tryghost/tpl@2.3.1':
- resolution: {integrity: sha512-qqa2SvhnBVKFYN+G4hfj2cYZuZXINBDyJ9cTzNBtev/FRNUKniyGarPKAkyb6ZBtvp3Nqlmyvrqe+SFoqHcfrQ==}
-
- '@tryghost/tpl@2.3.10':
- resolution: {integrity: sha512-jYUMBtCDc7Ok9m7VbdaL5znxhb4cWpRlnoCHZKTtxnP/D5Kt/WWwuV8fBRabqvdpPABkGlMm+momDAKMwst3lw==}
-
- '@tryghost/tpl@2.3.7':
- resolution: {integrity: sha512-TIDQF9tj4MaQKrIxNB8CxpElShAwLfyByozggIBnuzIVkGudX07gy/o9oWGRYslRselrvdByf+NpYonQ9j3Y0Q==}
-
- '@tryghost/tpl@2.3.9':
- resolution: {integrity: sha512-55bUKq9vG9YvJNtrJKptv2zZoLYXxGUPnX7q6mV6cuZEwxZaWY0uukcs2l3oCG9hollXj0pKJW4KdulcuYi20w==}
+ '@tryghost/tpl@2.3.12':
+ resolution: {integrity: sha512-4133W8SPCGd6xydaexFecLu/7poOyzgFEek+dYCZfeODldDGwu3y+a7L/veQX06ojZXGJeLUJ1irYzu/3fKbSw==}
'@tryghost/url-utils@5.2.6':
resolution: {integrity: sha512-3TQRcseZW/rq3UsSMP94n6WgKYZJqufreNdv9wJT5P4Fm5bNQ04rEHvL8i1AggXWa2kUPmwt2ed7KzNY6xx7zA==}
@@ -9683,26 +9739,21 @@ packages:
'@tryghost/url-utils@5.2.7':
resolution: {integrity: sha512-enJ084BtVwsr+q+1wz2hy/jjooBfDLh4FS4g2o8n1ZAgGAly4mch6w7IpDX6MjRcy6an/S1i/Jo3tMsHa2igfw==}
- '@tryghost/validator@3.2.10':
- resolution: {integrity: sha512-mk4bexOTmO4xaGiTvHXwCQIH5okcR3XOA3zF2vSMu89lpwZ0QJPXEaooHZUdLLBGOwuigz0iLVyiNeC58OAyrg==}
-
- '@tryghost/version@2.3.10':
- resolution: {integrity: sha512-4KHPqEZwhyixUFfDiNCoJ6nCjmLrX5VwqrPcAsNQs82W2chkaysvjZU9rXFNULpapRcYu0Y7xX/Sn2JJDlbriQ==}
-
- '@tryghost/version@2.3.2':
- resolution: {integrity: sha512-tBW8gJKLJTUsrGdt/mM1k28Vy4DRTQF7tfZPUf9DQ0KkTgFc+5Z2WipGa50dOaicGysM15imOq7AK7IfXddCHw==}
+ '@tryghost/validator@3.2.12':
+ resolution: {integrity: sha512-3zuGfLCzcWK0DgF40vaWzlLFaPPUDd/+IriCHzrpJgGCb/mMbQh/QbEqouABneH5PSB/D6CWLVrqnm9+Kjpi9Q==}
- '@tryghost/version@2.3.9':
- resolution: {integrity: sha512-jRBIcJuU/ljnTmpGnWZfzUyj+KY/9NChAD+tlkqI9ZQoSn4/VZFnZn8zGb0cRI245wzIi2YTjZokO0RJutqvTg==}
+ '@tryghost/version@2.3.12':
+ resolution: {integrity: sha512-svCEBVRHCLdcjpOFJ6PhqlcwfqbEvkCv7d/hHopUbfIdl/Ipb+FhAhuw7C2O4tw+Tm+eugA/FwPKJeFop0TIsg==}
- '@tryghost/webhook-mock-receiver@2.1.0':
- resolution: {integrity: sha512-Cka5SW4igfgbGv33fFyEjkgt1HCA3lNhKCL88ThsDCw3/9ROxKQLcHMB+S7SNcewIDfsS5kI2INHtD+1Tbp/BA==}
+ '@tryghost/webhook-mock-receiver@2.3.12':
+ resolution: {integrity: sha512-pr237E7u+meWrqlBRW6vERCXNC8TXyysx4fc7vkkCX6Gfcq9euhusJliUc1YR30xf7r6KIsv+sE9bZDfeCxm2g==}
+ engines: {node: ^22.12.0 || >=24.0.0}
'@tryghost/zip@3.5.0':
resolution: {integrity: sha512-igHHPyBasmo+MWM+l8qtWWX/cdHlAQps5HbCfESi4zGPlkTzuScHfmFAnuXsCx+MZKP5LozgnQHOVIf6jkaU8A==}
- '@tryghost/zip@3.5.1':
- resolution: {integrity: sha512-tj+yu8c0OjvSJY6ivtIsOxMzma7pksGcf4cCN0zdvzZdLD0ImuQTkEjqUD4v8rlQ0pL/jjh4W7bKW9Gmjun9vg==}
+ '@tryghost/zip@3.5.11':
+ resolution: {integrity: sha512-eTINMqgZk8XA3cG0jczLlcllM6dUPN6eukxkqy1PBHPMkg2IHZu1wnEFUrwc7YFCmF3Y7XZf4JxxJIKlPIS9bA==}
'@tybys/wasm-util@0.10.3':
resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
@@ -12156,6 +12207,10 @@ packages:
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ chalk@6.0.0:
+ resolution: {integrity: sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==}
+ engines: {node: '>=22'}
+
char-regex@1.0.2:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
@@ -14603,6 +14658,10 @@ packages:
resolution: {integrity: sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ expect@30.4.1:
+ resolution: {integrity: sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
exponential-backoff@3.1.3:
resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
@@ -14988,10 +15047,6 @@ packages:
resolution: {integrity: sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==}
engines: {node: '>= 6'}
- form-data@4.0.5:
- resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
- engines: {node: '>= 6'}
-
form-data@4.0.6:
resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==}
engines: {node: '>= 6'}
@@ -16462,6 +16517,10 @@ packages:
resolution: {integrity: sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-diff@30.4.1:
+ resolution: {integrity: sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-docblock@29.7.0:
resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16486,6 +16545,10 @@ packages:
resolution: {integrity: sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-haste-map@30.4.1:
+ resolution: {integrity: sha512-rFrcONd8jeFsyw+Z9CrScJgglRf2+NFmNam8dKu7n+SoHqNYT47mn0DdEcVUZJpvh7Iz6/si7f7yUH7GJHVgnw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-leak-detector@29.7.0:
resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16498,6 +16561,10 @@ packages:
resolution: {integrity: sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-matcher-utils@30.4.1:
+ resolution: {integrity: sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-message-util@29.7.0:
resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16506,6 +16573,10 @@ packages:
resolution: {integrity: sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-message-util@30.4.1:
+ resolution: {integrity: sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-mock@29.7.0:
resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16514,6 +16585,10 @@ packages:
resolution: {integrity: sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-mock@30.4.1:
+ resolution: {integrity: sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-pnp-resolver@1.2.3:
resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
engines: {node: '>=6'}
@@ -16531,6 +16606,10 @@ packages:
resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-regex-util@30.4.0:
+ resolution: {integrity: sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-resolve-dependencies@29.7.0:
resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16555,6 +16634,10 @@ packages:
resolution: {integrity: sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-snapshot@30.4.1:
+ resolution: {integrity: sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-util@29.7.0:
resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16563,6 +16646,10 @@ packages:
resolution: {integrity: sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-util@30.4.1:
+ resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest-validate@29.7.0:
resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -16583,6 +16670,10 @@ packages:
resolution: {integrity: sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jest-worker@30.4.1:
+ resolution: {integrity: sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
jest@29.7.0:
resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -18454,8 +18545,8 @@ packages:
resolution: {integrity: sha512-nrO/pDAUKl+wXX+lx16tDLbnm0fW6sK/x8mgohaCpg+CdCEl482bD4tCuAZk2DyliruiNTIZxRCoWkDqJEnAiA==}
engines: {node: '>=6.0.0'}
- nodemailer@9.0.1:
- resolution: {integrity: sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw==}
+ nodemailer@9.0.6:
+ resolution: {integrity: sha512-IQUGFdhdGwI9+AWX+FpUt4DLmvFaOjTMEoneTIWX/RXxuy1TdenPwWrvFMSfLkPKl+HQEXWuSAxEMMbPYXtBmg==}
engines: {node: '>=6.0.0'}
nodemon@3.1.14:
@@ -19838,6 +19929,10 @@ packages:
resolution: {integrity: sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ pretty-format@30.4.1:
+ resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
pretty-hrtime@1.0.3:
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
engines: {node: '>= 0.8'}
@@ -20231,6 +20326,9 @@ packages:
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-is@19.2.8:
+ resolution: {integrity: sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==}
+
react-remove-scroll-bar@2.3.8:
resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
engines: {node: '>=10'}
@@ -23217,32 +23315,6 @@ snapshots:
is-potential-custom-element-name: 1.0.1
lru-cache: 11.5.2
- '@aws-crypto/sha256-browser@5.2.0':
- dependencies:
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-crypto/supports-web-crypto': 5.2.0
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.973.15
- '@aws-sdk/util-locate-window': 3.965.8
- '@smithy/util-utf8': 2.3.0
- tslib: 2.8.1
-
- '@aws-crypto/sha256-js@5.2.0':
- dependencies:
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.973.15
- tslib: 2.8.1
-
- '@aws-crypto/supports-web-crypto@5.2.0':
- dependencies:
- tslib: 2.8.1
-
- '@aws-crypto/util@5.2.0':
- dependencies:
- '@aws-sdk/types': 3.973.15
- '@smithy/util-utf8': 2.3.0
- tslib: 2.8.1
-
'@aws-sdk/checksums@3.1000.12':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23265,18 +23337,16 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
- '@aws-sdk/client-sesv2@3.1073.0':
+ '@aws-sdk/client-sesv2@3.1121.0':
dependencies:
- '@aws-crypto/sha256-browser': 5.2.0
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-sdk/core': 3.974.27
- '@aws-sdk/credential-provider-node': 3.972.62
- '@aws-sdk/signature-v4-multi-region': 3.996.38
- '@aws-sdk/types': 3.973.15
- '@smithy/core': 3.29.0
- '@smithy/fetch-http-handler': 5.6.2
- '@smithy/node-http-handler': 4.9.2
- '@smithy/types': 4.15.1
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/credential-provider-node': 3.972.81
+ '@aws-sdk/signature-v4-multi-region': 3.996.46
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/fetch-http-handler': 5.7.2
+ '@smithy/node-http-handler': 4.11.3
+ '@smithy/types': 4.17.2
tslib: 2.8.1
'@aws-sdk/core@3.974.27':
@@ -23290,6 +23360,17 @@ snapshots:
bowser: 2.14.1
tslib: 2.8.1
+ '@aws-sdk/core@3.977.9':
+ dependencies:
+ '@aws-sdk/types': 3.974.5
+ '@aws-sdk/xml-builder': 3.972.40
+ '@aws/lambda-invoke-store': 0.3.0
+ '@smithy/core': 3.33.3
+ '@smithy/signature-v4': 5.7.3
+ '@smithy/types': 4.17.2
+ bowser: 2.14.1
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-env@3.972.53':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23298,6 +23379,14 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-env@3.972.70':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-http@3.972.55':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23308,6 +23397,16 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-http@3.972.72':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/fetch-http-handler': 5.7.2
+ '@smithy/node-http-handler': 4.11.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-ini@3.972.60':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23324,6 +23423,22 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-ini@3.973.15':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/credential-provider-env': 3.972.70
+ '@aws-sdk/credential-provider-http': 3.972.72
+ '@aws-sdk/credential-provider-login': 3.972.77
+ '@aws-sdk/credential-provider-process': 3.972.70
+ '@aws-sdk/credential-provider-sso': 3.973.14
+ '@aws-sdk/credential-provider-web-identity': 3.972.76
+ '@aws-sdk/nested-clients': 3.997.44
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-login@3.972.59':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23333,6 +23448,15 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-login@3.972.77':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/nested-clients': 3.997.44
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-node@3.972.62':
dependencies:
'@aws-sdk/credential-provider-env': 3.972.53
@@ -23347,6 +23471,20 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-node@3.972.81':
+ dependencies:
+ '@aws-sdk/credential-provider-env': 3.972.70
+ '@aws-sdk/credential-provider-http': 3.972.72
+ '@aws-sdk/credential-provider-ini': 3.973.15
+ '@aws-sdk/credential-provider-process': 3.972.70
+ '@aws-sdk/credential-provider-sso': 3.973.14
+ '@aws-sdk/credential-provider-web-identity': 3.972.76
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-process@3.972.53':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23355,6 +23493,14 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-process@3.972.70':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-sso@3.972.59':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23365,6 +23511,16 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-sso@3.973.14':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/nested-clients': 3.997.44
+ '@aws-sdk/token-providers': 3.1116.0
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/credential-provider-web-identity@3.972.59':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23374,6 +23530,15 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/credential-provider-web-identity@3.972.76':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/nested-clients': 3.997.44
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/middleware-sdk-s3@3.972.58':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23394,6 +23559,17 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/nested-clients@3.997.44':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/signature-v4-multi-region': 3.996.46
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/fetch-http-handler': 5.7.2
+ '@smithy/node-http-handler': 4.11.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/signature-v4-multi-region@3.996.38':
dependencies:
'@aws-sdk/types': 3.973.15
@@ -23401,6 +23577,13 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/signature-v4-multi-region@3.996.46':
+ dependencies:
+ '@aws-sdk/types': 3.974.5
+ '@smithy/signature-v4': 5.7.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/token-providers@3.1079.0':
dependencies:
'@aws-sdk/core': 3.974.27
@@ -23410,13 +23593,23 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/token-providers@3.1116.0':
+ dependencies:
+ '@aws-sdk/core': 3.977.9
+ '@aws-sdk/nested-clients': 3.997.44
+ '@aws-sdk/types': 3.974.5
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws-sdk/types@3.973.15':
dependencies:
'@smithy/types': 4.15.1
tslib: 2.8.1
- '@aws-sdk/util-locate-window@3.965.8':
+ '@aws-sdk/types@3.974.5':
dependencies:
+ '@smithy/types': 4.17.2
tslib: 2.8.1
'@aws-sdk/xml-builder@3.972.33':
@@ -23424,6 +23617,11 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@aws-sdk/xml-builder@3.972.40':
+ dependencies:
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@aws/lambda-invoke-store@0.3.0': {}
'@azu/format-text@1.0.2': {}
@@ -25805,7 +26003,10 @@ snapshots:
'@jest/diff-sequences@30.0.1': {}
- '@jest/diff-sequences@30.3.0': {}
+ '@jest/diff-sequences@30.3.0':
+ optional: true
+
+ '@jest/diff-sequences@30.4.0': {}
'@jest/environment@29.7.0':
dependencies:
@@ -25822,6 +26023,11 @@ snapshots:
'@jest/expect-utils@30.3.0':
dependencies:
'@jest/get-type': 30.1.0
+ optional: true
+
+ '@jest/expect-utils@30.4.1':
+ dependencies:
+ '@jest/get-type': 30.1.0
'@jest/expect@29.7.0(supports-color@10.2.2)':
dependencies:
@@ -25831,10 +26037,10 @@ snapshots:
- supports-color
optional: true
- '@jest/expect@30.3.0(supports-color@10.2.2)':
+ '@jest/expect@30.4.1(supports-color@10.2.2)':
dependencies:
- expect: 30.3.0
- jest-snapshot: 30.3.0(supports-color@10.2.2)
+ expect: 30.4.1
+ jest-snapshot: 30.4.1(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
@@ -25864,6 +26070,12 @@ snapshots:
dependencies:
'@types/node': 26.0.0
jest-regex-util: 30.0.1
+ optional: true
+
+ '@jest/pattern@30.4.0':
+ dependencies:
+ '@types/node': 26.0.0
+ jest-regex-util: 30.4.0
'@jest/reporters@29.7.0(node-notifier@10.0.1)(supports-color@10.2.2)':
dependencies:
@@ -25904,6 +26116,11 @@ snapshots:
'@jest/schemas@30.0.5':
dependencies:
'@sinclair/typebox': 0.34.49
+ optional: true
+
+ '@jest/schemas@30.4.1':
+ dependencies:
+ '@sinclair/typebox': 0.34.49
'@jest/snapshot-utils@30.3.0':
dependencies:
@@ -25911,6 +26128,14 @@ snapshots:
chalk: 4.1.2
graceful-fs: 4.2.11
natural-compare: 1.4.0
+ optional: true
+
+ '@jest/snapshot-utils@30.4.1':
+ dependencies:
+ '@jest/types': 30.4.1
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ natural-compare: 1.4.0
'@jest/source-map@29.6.3':
dependencies:
@@ -25974,6 +26199,26 @@ snapshots:
write-file-atomic: 5.0.1
transitivePeerDependencies:
- supports-color
+ optional: true
+
+ '@jest/transform@30.4.1(supports-color@10.2.2)':
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@jest/types': 30.4.1
+ '@jridgewell/trace-mapping': 0.3.31
+ babel-plugin-istanbul: 7.0.1(supports-color@10.2.2)
+ chalk: 4.1.2
+ convert-source-map: 2.0.0
+ fast-json-stable-stringify: 2.1.0
+ graceful-fs: 4.2.11
+ jest-haste-map: 30.4.1
+ jest-regex-util: 30.4.0
+ jest-util: 30.4.1
+ pirates: 4.0.7
+ slash: 3.0.0
+ write-file-atomic: 5.0.1
+ transitivePeerDependencies:
+ - supports-color
'@jest/types@29.6.3':
dependencies:
@@ -25993,6 +26238,17 @@ snapshots:
'@types/node': 26.0.0
'@types/yargs': 17.0.35
chalk: 4.1.2
+ optional: true
+
+ '@jest/types@30.4.1':
+ dependencies:
+ '@jest/pattern': 30.4.0
+ '@jest/schemas': 30.4.1
+ '@types/istanbul-lib-coverage': 2.0.6
+ '@types/istanbul-reports': 3.0.4
+ '@types/node': 26.0.0
+ '@types/yargs': 17.0.35
+ chalk: 4.1.2
'@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(@typescript/typescript6@6.0.2)(vite@8.1.3(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(terser@5.48.0)(tsx@4.23.12)(yaml@2.9.0))':
dependencies:
@@ -28262,20 +28518,39 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@smithy/core@3.33.3':
+ dependencies:
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@smithy/credential-provider-imds@4.4.5':
dependencies:
'@smithy/core': 3.29.0
'@smithy/types': 4.15.1
tslib: 2.8.1
+ '@smithy/credential-provider-imds@4.5.2':
+ dependencies:
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
'@smithy/fetch-http-handler@5.6.2':
dependencies:
'@smithy/core': 3.29.0
'@smithy/types': 4.15.1
tslib: 2.8.1
- '@smithy/is-array-buffer@2.2.0':
+ '@smithy/fetch-http-handler@5.7.2':
dependencies:
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
+ tslib: 2.8.1
+
+ '@smithy/node-http-handler@4.11.3':
+ dependencies:
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
tslib: 2.8.1
'@smithy/node-http-handler@4.9.2':
@@ -28290,18 +28565,18 @@ snapshots:
'@smithy/types': 4.15.1
tslib: 2.8.1
- '@smithy/types@4.15.1':
+ '@smithy/signature-v4@5.7.3':
dependencies:
+ '@smithy/core': 3.33.3
+ '@smithy/types': 4.17.2
tslib: 2.8.1
- '@smithy/util-buffer-from@2.2.0':
+ '@smithy/types@4.15.1':
dependencies:
- '@smithy/is-array-buffer': 2.2.0
tslib: 2.8.1
- '@smithy/util-utf8@2.3.0':
+ '@smithy/types@4.17.2':
dependencies:
- '@smithy/util-buffer-from': 2.2.0
tslib: 2.8.1
'@socket.io/component-emitter@3.1.2': {}
@@ -29024,83 +29299,83 @@ snapshots:
'@tootallnate/once@3.0.1': {}
- '@tryghost/api-framework@3.3.9(supports-color@10.2.2)':
+ '@tryghost/api-framework@3.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/debug': 2.3.9(supports-color@10.2.2)
- '@tryghost/errors': 3.3.9
- '@tryghost/promise': 2.3.9
- '@tryghost/tpl': 2.3.9
- '@tryghost/validator': 3.2.10
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
+ '@tryghost/errors': 3.3.12
+ '@tryghost/promise': 2.3.12
+ '@tryghost/tpl': 2.3.12
+ '@tryghost/validator': 3.2.12
lodash: 4.18.1
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-collision@2.3.7':
+ '@tryghost/bookshelf-collision@2.3.12':
dependencies:
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
lodash: 4.18.1
moment-timezone: 0.5.45
- '@tryghost/bookshelf-custom-query@2.3.7': {}
+ '@tryghost/bookshelf-custom-query@2.3.12': {}
- '@tryghost/bookshelf-eager-load@2.3.7(supports-color@10.2.2)':
+ '@tryghost/bookshelf-eager-load@2.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/debug': 2.3.7(supports-color@10.2.2)
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
lodash: 4.18.1
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-filter@2.3.7(supports-color@10.2.2)':
+ '@tryghost/bookshelf-filter@2.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/debug': 2.3.7(supports-color@10.2.2)
- '@tryghost/errors': 3.3.9
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
+ '@tryghost/errors': 3.3.12
'@tryghost/nql': 0.13.4(supports-color@10.2.2)
- '@tryghost/tpl': 2.3.7
+ '@tryghost/tpl': 2.3.12
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-has-posts@2.4.7(supports-color@10.2.2)':
+ '@tryghost/bookshelf-has-posts@2.4.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/debug': 2.3.7(supports-color@10.2.2)
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
lodash: 4.18.1
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-include-count@2.3.7(supports-color@10.2.2)':
+ '@tryghost/bookshelf-include-count@2.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/debug': 2.3.7(supports-color@10.2.2)
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
lodash: 4.18.1
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-order@2.3.7':
+ '@tryghost/bookshelf-order@2.3.12':
dependencies:
lodash: 4.18.1
- '@tryghost/bookshelf-pagination@2.4.1':
+ '@tryghost/bookshelf-pagination@2.4.6':
dependencies:
- '@tryghost/errors': 3.3.9
- '@tryghost/tpl': 2.3.7
+ '@tryghost/errors': 3.3.12
+ '@tryghost/tpl': 2.3.12
lodash: 4.18.1
- '@tryghost/bookshelf-plugins@2.3.8(supports-color@10.2.2)':
+ '@tryghost/bookshelf-plugins@2.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/bookshelf-collision': 2.3.7
- '@tryghost/bookshelf-custom-query': 2.3.7
- '@tryghost/bookshelf-eager-load': 2.3.7(supports-color@10.2.2)
- '@tryghost/bookshelf-filter': 2.3.7(supports-color@10.2.2)
- '@tryghost/bookshelf-has-posts': 2.4.7(supports-color@10.2.2)
- '@tryghost/bookshelf-include-count': 2.3.7(supports-color@10.2.2)
- '@tryghost/bookshelf-order': 2.3.7
- '@tryghost/bookshelf-pagination': 2.4.1
- '@tryghost/bookshelf-search': 2.3.7
- '@tryghost/bookshelf-transaction-events': 2.3.7
+ '@tryghost/bookshelf-collision': 2.3.12
+ '@tryghost/bookshelf-custom-query': 2.3.12
+ '@tryghost/bookshelf-eager-load': 2.3.12(supports-color@10.2.2)
+ '@tryghost/bookshelf-filter': 2.3.12(supports-color@10.2.2)
+ '@tryghost/bookshelf-has-posts': 2.4.12(supports-color@10.2.2)
+ '@tryghost/bookshelf-include-count': 2.3.12(supports-color@10.2.2)
+ '@tryghost/bookshelf-order': 2.3.12
+ '@tryghost/bookshelf-pagination': 2.4.6
+ '@tryghost/bookshelf-search': 2.3.12
+ '@tryghost/bookshelf-transaction-events': 2.3.12
transitivePeerDependencies:
- supports-color
- '@tryghost/bookshelf-search@2.3.7': {}
+ '@tryghost/bookshelf-search@2.3.12': {}
- '@tryghost/bookshelf-transaction-events@2.3.7': {}
+ '@tryghost/bookshelf-transaction-events@2.3.12': {}
'@tryghost/brute-knex@3.2.2(better-sqlite3@12.11.1)(express@4.22.2(supports-color@10.2.2))(mysql2@3.22.5(@types/node@22.20.1))(supports-color@10.2.2)':
dependencies:
@@ -29116,7 +29391,7 @@ snapshots:
- supports-color
- tedious
- '@tryghost/bunyan-rotating-filestream@0.0.15':
+ '@tryghost/bunyan-rotating-filestream@0.0.18':
dependencies:
long-timeout: 0.1.1
@@ -29136,7 +29411,7 @@ snapshots:
'@tryghost/database-info@0.3.35': {}
- '@tryghost/database-info@2.3.2': {}
+ '@tryghost/database-info@2.3.12': {}
'@tryghost/debug@0.1.40(supports-color@10.2.2)':
dependencies:
@@ -29152,37 +29427,30 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@tryghost/debug@2.3.7(supports-color@10.2.2)':
+ '@tryghost/debug@2.3.12(supports-color@10.2.2)':
dependencies:
- '@tryghost/root-utils': 2.3.7
+ '@tryghost/root-utils': 2.3.12
debug: 4.4.3(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- '@tryghost/debug@2.3.9(supports-color@10.2.2)':
+ '@tryghost/domain-events@3.3.13(supports-color@10.2.2)':
dependencies:
- '@tryghost/root-utils': 2.3.9
- debug: 4.4.3(supports-color@10.2.2)
- transitivePeerDependencies:
- - supports-color
-
- '@tryghost/domain-events@3.3.10(supports-color@10.2.2)':
- dependencies:
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
transitivePeerDependencies:
- '@75lb/nature'
- supports-color
- '@tryghost/elasticsearch@5.4.6(supports-color@10.2.2)':
+ '@tryghost/elasticsearch@5.4.9(supports-color@10.2.2)':
dependencies:
'@elastic/elasticsearch': 8.19.2(supports-color@10.2.2)
- '@tryghost/debug': 2.3.9(supports-color@10.2.2)
+ '@tryghost/debug': 2.3.12(supports-color@10.2.2)
split2: 4.2.0
transitivePeerDependencies:
- '@75lb/nature'
- supports-color
- '@tryghost/email-mock-receiver@2.1.0': {}
+ '@tryghost/email-mock-receiver@2.3.12': {}
'@tryghost/ember-promise-modals@2.0.1(ember-source@3.24.0(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(postcss@8.5.26)(supports-color@10.2.2)':
dependencies:
@@ -29205,14 +29473,14 @@ snapshots:
- webpack-cli
- webpack-command
- '@tryghost/errors@3.3.9': {}
+ '@tryghost/errors@3.3.12': {}
- '@tryghost/express-test@2.1.0(express@4.22.2(supports-color@10.2.2))(supports-color@10.2.2)':
+ '@tryghost/express-test@2.3.12(express@4.22.2(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@tryghost/jest-snapshot': 2.1.0(supports-color@10.2.2)
+ '@tryghost/jest-snapshot': 2.3.12(supports-color@10.2.2)
cookiejar: 2.1.4
express: 4.22.2(supports-color@10.2.2)
- form-data: 4.0.5
+ form-data: 4.0.6
mime-types: 3.0.2
transitivePeerDependencies:
- supports-color
@@ -29228,34 +29496,34 @@ snapshots:
'@tryghost/http-cache-utils@0.1.25': {}
- '@tryghost/http-stream@2.3.10':
+ '@tryghost/http-stream@2.3.13':
dependencies:
- '@tryghost/errors': 3.3.9
- '@tryghost/request': 4.0.2
+ '@tryghost/errors': 3.3.12
+ '@tryghost/request': 4.0.5
'@tryghost/image-transform@1.4.17(@types/node@22.20.1)':
dependencies:
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
fs-extra: 11.3.6
optionalDependencies:
sharp: 0.35.3(@types/node@22.20.1)
transitivePeerDependencies:
- '@types/node'
- '@tryghost/jest-snapshot@2.1.0(supports-color@10.2.2)':
+ '@tryghost/jest-snapshot@2.3.12(supports-color@10.2.2)':
dependencies:
- '@jest/expect': 30.3.0(supports-color@10.2.2)
- '@jest/expect-utils': 30.3.0
- '@tryghost/errors': 3.3.9
- jest-snapshot: 30.3.0(supports-color@10.2.2)
+ '@jest/expect': 30.4.1(supports-color@10.2.2)
+ '@jest/expect-utils': 30.4.1
+ '@tryghost/errors': 3.3.12
+ jest-snapshot: 30.4.1(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
'@tryghost/job-manager@1.0.9(supports-color@10.2.2)':
dependencies:
'@breejs/later': 4.2.0
- '@tryghost/errors': 3.3.9
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/errors': 3.3.12
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
bree: 6.5.0(supports-color@10.2.2)
cron-validate: 1.4.5
fastq: 1.20.1
@@ -29295,17 +29563,17 @@ snapshots:
'@tryghost/limit-service@1.5.6':
dependencies:
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
lodash: 4.18.1
luxon: 3.7.2
- '@tryghost/logging@5.4.0(supports-color@10.2.2)':
+ '@tryghost/logging@5.4.3(supports-color@10.2.2)':
dependencies:
- '@tryghost/bunyan-rotating-filestream': 0.0.15
- '@tryghost/elasticsearch': 5.4.6(supports-color@10.2.2)
- '@tryghost/http-stream': 2.3.10
- '@tryghost/pretty-stream': 2.3.9
- '@tryghost/root-utils': 2.3.9
+ '@tryghost/bunyan-rotating-filestream': 0.0.18
+ '@tryghost/elasticsearch': 5.4.9(supports-color@10.2.2)
+ '@tryghost/http-stream': 2.3.13
+ '@tryghost/pretty-stream': 2.3.12
+ '@tryghost/root-utils': 2.3.12
bunyan: 1.8.15
fs-extra: 11.4.0
gelf-stream: 1.1.1
@@ -29315,11 +29583,11 @@ snapshots:
- '@75lb/nature'
- supports-color
- '@tryghost/metrics@3.5.0(supports-color@10.2.2)':
+ '@tryghost/metrics@3.5.3(supports-color@10.2.2)':
dependencies:
- '@tryghost/elasticsearch': 5.4.6(supports-color@10.2.2)
- '@tryghost/pretty-stream': 2.3.9
- '@tryghost/root-utils': 2.3.9
+ '@tryghost/elasticsearch': 5.4.9(supports-color@10.2.2)
+ '@tryghost/pretty-stream': 2.3.12
+ '@tryghost/root-utils': 2.3.12
json-stringify-safe: 5.0.1
transitivePeerDependencies:
- '@75lb/nature'
@@ -29361,7 +29629,7 @@ snapshots:
'@tryghost/mw-error-handler@1.0.13(supports-color@10.2.2)':
dependencies:
'@tryghost/debug': 0.1.40(supports-color@10.2.2)
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
'@tryghost/http-cache-utils': 0.1.25
'@tryghost/tpl': 0.1.40
lodash: 4.18.1
@@ -29371,12 +29639,12 @@ snapshots:
'@tryghost/mw-vhost@1.0.6': {}
- '@tryghost/nodemailer@2.3.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)':
+ '@tryghost/nodemailer@2.3.12(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@aws-sdk/client-sesv2': 3.1073.0
- '@tryghost/errors': 3.3.9
- '@tryghost/tpl': 2.3.1
- nodemailer: 9.0.1
+ '@aws-sdk/client-sesv2': 3.1121.0
+ '@tryghost/errors': 3.3.12
+ '@tryghost/tpl': 2.3.12
+ nodemailer: 9.0.6
nodemailer-mailgun-transport: 2.1.5(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)
nodemailer-stub-transport: 1.1.0
transitivePeerDependencies:
@@ -29402,12 +29670,12 @@ snapshots:
chalk: 5.6.2
sywac: 1.3.0
- '@tryghost/pretty-cli@3.3.2':
+ '@tryghost/pretty-cli@3.3.12':
dependencies:
- chalk: 5.6.2
+ chalk: 6.0.0
sywac: 1.3.0
- '@tryghost/pretty-stream@2.3.9':
+ '@tryghost/pretty-stream@2.3.12':
dependencies:
date-format: 4.0.14
lodash: 4.18.1
@@ -29415,7 +29683,7 @@ snapshots:
'@tryghost/prometheus-metrics@1.0.8(supports-color@10.2.2)':
dependencies:
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
express: 4.22.1(supports-color@10.2.2)
prom-client: 15.1.3
stoppable: 1.1.0
@@ -29425,24 +29693,15 @@ snapshots:
'@tryghost/promise@0.3.20': {}
- '@tryghost/promise@2.3.9': {}
+ '@tryghost/promise@2.3.12': {}
'@tryghost/referrer-parser@0.1.21': {}
- '@tryghost/request@4.0.2':
- dependencies:
- '@tryghost/errors': 3.3.9
- '@tryghost/validator': 3.2.10
- '@tryghost/version': 2.3.9
- cacheable-lookup: 7.0.0
- got: 15.1.0
- lodash: 4.18.1
-
- '@tryghost/request@4.0.3':
+ '@tryghost/request@4.0.5':
dependencies:
- '@tryghost/errors': 3.3.9
- '@tryghost/validator': 3.2.10
- '@tryghost/version': 2.3.10
+ '@tryghost/errors': 3.3.12
+ '@tryghost/validator': 3.2.12
+ '@tryghost/version': 2.3.12
cacheable-lookup: 7.0.0
got: 15.1.0
lodash: 4.18.1
@@ -29457,22 +29716,7 @@ snapshots:
caller: 1.1.0
find-root: 1.1.0
- '@tryghost/root-utils@2.3.10':
- dependencies:
- caller: 1.1.0
- find-root: 1.1.0
-
- '@tryghost/root-utils@2.3.2':
- dependencies:
- caller: 1.1.0
- find-root: 1.1.0
-
- '@tryghost/root-utils@2.3.7':
- dependencies:
- caller: 1.1.0
- find-root: 1.1.0
-
- '@tryghost/root-utils@2.3.9':
+ '@tryghost/root-utils@2.3.12':
dependencies:
caller: 1.1.0
find-root: 1.1.0
@@ -29485,7 +29729,7 @@ snapshots:
'@tryghost/server@3.1.1(supports-color@10.2.2)':
dependencies:
'@tryghost/debug': 2.3.1(supports-color@10.2.2)
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
transitivePeerDependencies:
- '@75lb/nature'
- supports-color
@@ -29506,13 +29750,7 @@ snapshots:
dependencies:
lodash.template: 4.18.1
- '@tryghost/tpl@2.3.1': {}
-
- '@tryghost/tpl@2.3.10': {}
-
- '@tryghost/tpl@2.3.7': {}
-
- '@tryghost/tpl@2.3.9': {}
+ '@tryghost/tpl@2.3.12': {}
'@tryghost/url-utils@5.2.6':
dependencies:
@@ -29534,36 +29772,26 @@ snapshots:
remark-footnotes: 1.0.0
unist-util-visit: 2.0.3
- '@tryghost/validator@3.2.10':
+ '@tryghost/validator@3.2.12':
dependencies:
- '@tryghost/errors': 3.3.9
- '@tryghost/tpl': 2.3.10
+ '@tryghost/errors': 3.3.12
+ '@tryghost/tpl': 2.3.12
lodash: 4.18.1
moment-timezone: 0.5.45
validator: 13.15.35
- '@tryghost/version@2.3.10':
+ '@tryghost/version@2.3.12':
dependencies:
- '@tryghost/root-utils': 2.3.10
+ '@tryghost/root-utils': 2.3.12
semver: 7.8.5
- '@tryghost/version@2.3.2':
- dependencies:
- '@tryghost/root-utils': 2.3.2
- semver: 7.8.5
-
- '@tryghost/version@2.3.9':
- dependencies:
- '@tryghost/root-utils': 2.3.9
- semver: 7.8.5
-
- '@tryghost/webhook-mock-receiver@2.1.0':
+ '@tryghost/webhook-mock-receiver@2.3.12':
dependencies:
p-wait-for: 6.0.0
'@tryghost/zip@3.5.0(supports-color@10.2.2)':
dependencies:
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
archiver: 8.0.0
extract-zip: 2.0.1(supports-color@10.2.2)
transitivePeerDependencies:
@@ -29572,9 +29800,9 @@ snapshots:
- react-native-b4a
- supports-color
- '@tryghost/zip@3.5.1(supports-color@10.2.2)':
+ '@tryghost/zip@3.5.11(supports-color@10.2.2)':
dependencies:
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
archiver: 8.0.0
extract-zip: 2.0.1(supports-color@10.2.2)
transitivePeerDependencies:
@@ -32351,7 +32579,7 @@ snapshots:
bookshelf-relations@2.8.0(bookshelf@1.2.0(knex@2.4.2(better-sqlite3@12.11.1)(mysql2@3.22.5(@types/node@22.20.1))(supports-color@10.2.2)))(supports-color@10.2.2):
dependencies:
'@tryghost/debug': 0.1.40(supports-color@10.2.2)
- '@tryghost/errors': 3.3.9
+ '@tryghost/errors': 3.3.12
bluebird: 3.7.2
bookshelf: 1.2.0(knex@2.4.2(better-sqlite3@12.11.1)(mysql2@3.22.5(@types/node@22.20.1))(supports-color@10.2.2))
lodash: 4.18.1
@@ -33324,6 +33552,8 @@ snapshots:
chalk@5.6.2: {}
+ chalk@6.0.0: {}
+
char-regex@1.0.2:
optional: true
@@ -37206,6 +37436,16 @@ snapshots:
jest-message-util: 30.3.0
jest-mock: 30.3.0
jest-util: 30.3.0
+ optional: true
+
+ expect@30.4.1:
+ dependencies:
+ '@jest/expect-utils': 30.4.1
+ '@jest/get-type': 30.1.0
+ jest-matcher-utils: 30.4.1
+ jest-message-util: 30.4.1
+ jest-mock: 30.4.1
+ jest-util: 30.4.1
exponential-backoff@3.1.3: {}
@@ -37774,14 +38014,6 @@ snapshots:
hasown: 2.0.4
mime-types: 2.1.35
- form-data@4.0.5:
- dependencies:
- asynckit: 0.4.0
- combined-stream: 1.0.8
- es-set-tostringtag: 2.1.0
- hasown: 2.0.4
- mime-types: 2.1.35
-
form-data@4.0.6:
dependencies:
asynckit: 0.4.0
@@ -38313,8 +38545,8 @@ snapshots:
'@sentry/node': 10.65.0(@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1))(supports-color@10.2.2)
'@tryghost/config': 2.3.1
'@tryghost/debug': 2.3.1(supports-color@10.2.2)
- '@tryghost/errors': 3.3.9
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/errors': 3.3.12
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
'@tryghost/nql': 0.13.4(supports-color@10.2.2)
'@tryghost/pretty-cli': 3.3.1
'@tryghost/server': 3.1.1(supports-color@10.2.2)
@@ -39567,6 +39799,14 @@ snapshots:
'@jest/get-type': 30.1.0
chalk: 4.1.2
pretty-format: 30.3.0
+ optional: true
+
+ jest-diff@30.4.1:
+ dependencies:
+ '@jest/diff-sequences': 30.4.0
+ '@jest/get-type': 30.1.0
+ chalk: 4.1.2
+ pretty-format: 30.4.1
jest-docblock@29.7.0:
dependencies:
@@ -39625,6 +39865,22 @@ snapshots:
walker: 1.0.8
optionalDependencies:
fsevents: 2.3.3
+ optional: true
+
+ jest-haste-map@30.4.1:
+ dependencies:
+ '@jest/types': 30.4.1
+ '@types/node': 26.0.0
+ anymatch: 3.1.3
+ fb-watchman: 2.0.2
+ graceful-fs: 4.2.11
+ jest-regex-util: 30.4.0
+ jest-util: 30.4.1
+ jest-worker: 30.4.1
+ picomatch: 4.0.5
+ walker: 1.0.8
+ optionalDependencies:
+ fsevents: 2.3.3
jest-leak-detector@29.7.0:
dependencies:
@@ -39645,6 +39901,14 @@ snapshots:
chalk: 4.1.2
jest-diff: 30.3.0
pretty-format: 30.3.0
+ optional: true
+
+ jest-matcher-utils@30.4.1:
+ dependencies:
+ '@jest/get-type': 30.1.0
+ chalk: 4.1.2
+ jest-diff: 30.4.1
+ pretty-format: 30.4.1
jest-message-util@29.7.0:
dependencies:
@@ -39669,6 +39933,20 @@ snapshots:
pretty-format: 30.3.0
slash: 3.0.0
stack-utils: 2.0.6
+ optional: true
+
+ jest-message-util@30.4.1:
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@jest/types': 30.4.1
+ '@types/stack-utils': 2.0.3
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ jest-util: 30.4.1
+ picomatch: 4.0.5
+ pretty-format: 30.4.1
+ slash: 3.0.0
+ stack-utils: 2.0.6
jest-mock@29.7.0:
dependencies:
@@ -39682,6 +39960,13 @@ snapshots:
'@jest/types': 30.3.0
'@types/node': 26.0.0
jest-util: 30.3.0
+ optional: true
+
+ jest-mock@30.4.1:
+ dependencies:
+ '@jest/types': 30.4.1
+ '@types/node': 26.0.0
+ jest-util: 30.4.1
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
optionalDependencies:
@@ -39691,7 +39976,10 @@ snapshots:
jest-regex-util@29.6.3:
optional: true
- jest-regex-util@30.0.1: {}
+ jest-regex-util@30.0.1:
+ optional: true
+
+ jest-regex-util@30.4.0: {}
jest-resolve-dependencies@29.7.0(supports-color@10.2.2):
dependencies:
@@ -39820,6 +40108,33 @@ snapshots:
synckit: 0.11.13
transitivePeerDependencies:
- supports-color
+ optional: true
+
+ jest-snapshot@30.4.1(supports-color@10.2.2):
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/generator': 7.29.7
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ '@babel/types': 7.29.7
+ '@jest/expect-utils': 30.4.1
+ '@jest/get-type': 30.1.0
+ '@jest/snapshot-utils': 30.4.1
+ '@jest/transform': 30.4.1(supports-color@10.2.2)
+ '@jest/types': 30.4.1
+ babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@10.2.2))
+ chalk: 4.1.2
+ expect: 30.4.1
+ graceful-fs: 4.2.11
+ jest-diff: 30.4.1
+ jest-matcher-utils: 30.4.1
+ jest-message-util: 30.4.1
+ jest-util: 30.4.1
+ pretty-format: 30.4.1
+ semver: 7.8.5
+ synckit: 0.11.13
+ transitivePeerDependencies:
+ - supports-color
jest-util@29.7.0:
dependencies:
@@ -39838,6 +40153,16 @@ snapshots:
ci-info: 4.4.0
graceful-fs: 4.2.11
picomatch: 4.0.5
+ optional: true
+
+ jest-util@30.4.1:
+ dependencies:
+ '@jest/types': 30.4.1
+ '@types/node': 26.0.0
+ chalk: 4.1.2
+ ci-info: 4.4.0
+ graceful-fs: 4.2.11
+ picomatch: 4.0.5
jest-validate@29.7.0:
dependencies:
@@ -39882,6 +40207,15 @@ snapshots:
jest-util: 30.3.0
merge-stream: 2.0.0
supports-color: 10.2.2
+ optional: true
+
+ jest-worker@30.4.1:
+ dependencies:
+ '@types/node': 26.0.0
+ '@ungap/structured-clone': 1.3.1
+ jest-util: 30.4.1
+ merge-stream: 2.0.0
+ supports-color: 10.2.2
jest@29.7.0(@types/node@22.20.1)(babel-plugin-macros@3.1.0)(node-notifier@10.0.1)(supports-color@10.2.2):
dependencies:
@@ -40190,8 +40524,8 @@ snapshots:
knex-migrator@5.4.1(@types/node@22.20.1)(bluebird@3.7.2)(supports-color@10.2.2):
dependencies:
'@tryghost/database-info': 0.3.35
- '@tryghost/errors': 3.3.9
- '@tryghost/logging': 5.4.0(supports-color@10.2.2)
+ '@tryghost/errors': 3.3.12
+ '@tryghost/logging': 5.4.3(supports-color@10.2.2)
'@tryghost/promise': 0.3.20
commander: 5.1.0
compare-ver: 2.0.2
@@ -42189,7 +42523,7 @@ snapshots:
nodemailer@8.0.11: {}
- nodemailer@9.0.1: {}
+ nodemailer@9.0.6: {}
nodemon@3.1.14:
dependencies:
@@ -43857,6 +44191,14 @@ snapshots:
'@jest/schemas': 30.0.5
ansi-styles: 5.2.0
react-is: 18.3.1
+ optional: true
+
+ pretty-format@30.4.1:
+ dependencies:
+ '@jest/schemas': 30.4.1
+ ansi-styles: 5.2.0
+ react-is-18: react-is@18.3.1
+ react-is-19: react-is@19.2.8
pretty-hrtime@1.0.3: {}
@@ -44317,6 +44659,8 @@ snapshots:
react-is@18.3.1: {}
+ react-is@19.2.8: {}
+
react-remove-scroll-bar@2.3.8(@types/react@18.3.31)(react@18.3.1):
dependencies:
react: 18.3.1
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index c120e7254b2..eb41f64c980 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -79,25 +79,25 @@ catalog:
'@tanstack/react-virtual': 3.14.9
'@testing-library/jest-dom': 6.9.1
'@testing-library/react': 14.3.1
- '@tryghost/api-framework': 3.3.9
+ '@tryghost/api-framework': 3.3.12
'@tryghost/brute-knex': 3.2.2
'@tryghost/color-utils': 0.2.20
'@tryghost/custom-fonts': 1.0.11
- '@tryghost/debug': 2.3.9
- '@tryghost/domain-events': 3.3.10
- '@tryghost/errors': 3.3.9
+ '@tryghost/debug': 2.3.12
+ '@tryghost/domain-events': 3.3.13
+ '@tryghost/errors': 3.3.12
'@tryghost/helpers': 1.1.106
'@tryghost/limit-service': 1.5.6
- '@tryghost/logging': 5.4.0
+ '@tryghost/logging': 5.4.3
'@tryghost/mg-clean-html': 0.12.6
- '@tryghost/metrics': 3.5.0
+ '@tryghost/metrics': 3.5.3
'@tryghost/mongo-knex': 0.11.2
'@tryghost/nql': 0.13.4
'@tryghost/nql-lang': 0.7.0
- '@tryghost/request': 4.0.3
+ '@tryghost/request': 4.0.5
'@tryghost/string': 0.3.5
'@tryghost/timezone-data': 1.0.0
- '@tryghost/tpl': 2.3.9
+ '@tryghost/tpl': 2.3.12
'@types/express': 4.17.25
'@types/html-minifier': ^4.0.6
'@types/lodash': 4.17.25
@@ -223,7 +223,7 @@ catalog:
cron-validate: 1.4.5
'@types/stoppable': 1.1.3
'@types/express-brute': 1.0.6
- '@tryghost/validator': 3.2.10
+ '@tryghost/validator': 3.2.12
catalogs:
react17: