diff --git a/lib/config.ts b/lib/config.ts
index 0d55e685f9a76d..2f1793201e599f 100644
--- a/lib/config.ts
+++ b/lib/config.ts
@@ -230,6 +230,9 @@ export type Config = {
pkubbs: {
cookie?: string;
};
+ qingting: {
+ id?: string;
+ };
saraba1st: {
cookie?: string;
};
@@ -575,6 +578,9 @@ const calculateValue = () => {
pkubbs: {
cookie: envs.PKUBBS_COOKIE,
},
+ qingting: {
+ id: envs.QINGTING_ID,
+ },
saraba1st: {
cookie: envs.SARABA1ST_COOKIE,
},
diff --git a/lib/errors/index.test.ts b/lib/errors/index.test.ts
index e1af5105878618..2538b7a8876b09 100644
--- a/lib/errors/index.test.ts
+++ b/lib/errors/index.test.ts
@@ -66,13 +66,13 @@ describe('route throws an error', () => {
expect(value).toBe('9');
break;
case 'Hot Routes:':
- expect(value).toBe('6 /test/:id ');
+ expect(value).toBe('6 /test/:id/:params? ');
break;
case 'Hot Paths:':
expect(value).toBe('2 /test/error 2 /test/slow 1 /test/httperror 1 /test/config-not-found-error 1 /test/invalid-parameter-error 1 /thisDoesNotExist 1 / ');
break;
case 'Hot Error Routes:':
- expect(value).toBe('5 /test/:id ');
+ expect(value).toBe('5 /test/:id/:params? ');
break;
case 'Hot Error Paths:':
expect(value).toBe('2 /test/error 1 /test/httperror 1 /test/slow 1 /test/config-not-found-error 1 /test/invalid-parameter-error 1 /thisDoesNotExist ');
diff --git a/lib/routes/0x80/index.ts b/lib/routes/0x80/index.ts
new file mode 100644
index 00000000000000..d6aa248a436061
--- /dev/null
+++ b/lib/routes/0x80/index.ts
@@ -0,0 +1,87 @@
+import { Route } from '@/types';
+
+import cache from '@/utils/cache';
+import got from '@/utils/got';
+import { load } from 'cheerio';
+import { parseDate } from '@/utils/parse-date';
+
+export const route: Route = {
+ path: '/blog',
+ categories: ['blog'],
+ example: '/0x80/blog',
+ url: '0x80.pl/notesen.html',
+ name: 'Articles',
+ maintainers: ['xnum'],
+ handler,
+};
+
+function extractDateFromURL(url: string) {
+ const regex = /\d{4}-\d{2}-\d{2}/;
+ const match = url.match(regex);
+
+ return match ? match[0] : null;
+}
+
+async function handler() {
+ // The TLS cert is invalid, we are limited to use HTTP unfortunately.
+ const baseUrl = 'http://0x80.pl/';
+ const targetUrl = `${baseUrl}notesen.html`;
+
+ const response = await got({
+ method: 'get',
+ url: targetUrl,
+ });
+
+ const $ = load(response.data);
+
+ const alist = $('a.reference.external');
+
+ const list = alist
+ .toArray()
+ .map((item) => {
+ item = $(item);
+
+ const link = item.attr('href') || '';
+ const title = item.text() || '';
+ const pubDate = extractDateFromURL(link);
+
+ return {
+ title,
+ link,
+ pubDate,
+ category: 'Uncategoried',
+ };
+ })
+ .filter((item) => item.link.startsWith('notesen'));
+
+ const items = await Promise.all(
+ list.map((item) =>
+ cache.tryGet(item.link, async () => {
+ const articleUrl = `${baseUrl}${item.link}`;
+ const response = await got({
+ method: 'get',
+ url: articleUrl,
+ });
+
+ const $ = load(response.data);
+
+ const author = $('tr.author.field td.field-body').text();
+ const articlePubDate = $('tr.added-on.field td.field-body').text();
+
+ item.author = author;
+ // Some articles might be missing the added-on field.
+ // As a safeguard, if the date from url is null, fallbacks to the article one.
+ item.pubDate = parseDate(item.pubDate || articlePubDate);
+ item.description = $('div.document').first().html();
+
+ return item;
+ })
+ )
+ );
+
+ return {
+ title: '0x80.pl articles',
+ link: targetUrl,
+ item: items,
+ };
+}
diff --git a/lib/routes/0x80/namespace.ts b/lib/routes/0x80/namespace.ts
new file mode 100644
index 00000000000000..8866d08e7919a9
--- /dev/null
+++ b/lib/routes/0x80/namespace.ts
@@ -0,0 +1,7 @@
+import type { Namespace } from '@/types';
+
+export const namespace: Namespace = {
+ name: 'Wojciech Muła',
+ url: '0x80.pl',
+ description: '',
+};
diff --git a/lib/routes/apple/podcast.ts b/lib/routes/apple/podcast.ts
new file mode 100644
index 00000000000000..07d1acd36e875b
--- /dev/null
+++ b/lib/routes/apple/podcast.ts
@@ -0,0 +1,64 @@
+import { Route } from '@/types';
+import got from '@/utils/got';
+import { load } from 'cheerio';
+import { parseDate } from '@/utils/parse-date';
+
+export const route: Route = {
+ path: '/podcast/:id',
+ categories: ['multimedia'],
+ example: '/apple/podcast/id1559695855',
+ parameters: { id: '播客id,可以在 Apple 播客app 内分享的播客的 URL 中找到' },
+ features: {
+ requireConfig: false,
+ requirePuppeteer: false,
+ antiCrawler: false,
+ supportBT: false,
+ supportPodcast: false,
+ supportScihub: false,
+ },
+ radar: [
+ {
+ source: ['podcasts.apple.com/cn/podcast/:id'],
+ },
+ ],
+ name: '播客',
+ maintainers: ['Acring'],
+ handler,
+ url: 'https://www.apple.com.cn/apple-podcasts/',
+};
+
+async function handler(ctx) {
+ const link = `https://podcasts.apple.com/cn/podcast/${ctx.req.param('id')}`;
+ const response = await got({
+ method: 'get',
+ url: link,
+ });
+
+ const $ = load(response.data);
+
+ const page_data = JSON.parse($('#shoebox-media-api-cache-amp-podcasts').text());
+
+ const data = JSON.parse(page_data[Object.keys(page_data)[0]]).d[0];
+ const attributes = data.attributes;
+
+ const episodes = data.relationships.episodes.data.map((item) => {
+ const attr = item.attributes;
+ return {
+ title: attr.name,
+ enclosure_url: attr.assetUrl,
+ itunes_duration: attr.durationInMilliseconds / 1000,
+ enclosure_type: 'audio/mp4',
+ link: attr.url,
+ pubDate: parseDate(attr.releaseDateTime),
+ description: attr.description.standard.replaceAll('\n', ' '),
+ };
+ });
+
+ return {
+ title: attributes.name,
+ link: attributes.url,
+ itunes_author: attributes.artistName,
+ item: episodes,
+ description: attributes.description.standard,
+ };
+}
diff --git a/lib/routes/bilibili/cache.ts b/lib/routes/bilibili/cache.ts
index 86699ef7e5ef33..01f58714b6b1e1 100644
--- a/lib/routes/bilibili/cache.ts
+++ b/lib/routes/bilibili/cache.ts
@@ -27,7 +27,7 @@ const getCookie = () => {
await page.goto('https://space.bilibili.com/1/dynamic');
const cookieString = await waitForRequest;
logger.debug(`Got bilibili cookie: ${cookieString}`);
-
+ await browser.close();
return cookieString;
});
};
diff --git a/lib/routes/qingting/podcast.ts b/lib/routes/qingting/podcast.ts
index 9211f3e8c9df41..17d1c6b4bab23a 100644
--- a/lib/routes/qingting/podcast.ts
+++ b/lib/routes/qingting/podcast.ts
@@ -1,9 +1,12 @@
-import { Route } from '@/types';
+import type { DataItem, Route } from '@/types';
import cache from '@/utils/cache';
import crypto from 'crypto';
import got from '@/utils/got';
import timezone from '@/utils/timezone';
import { parseDate } from '@/utils/parse-date';
+import { config } from '@/config';
+
+const qingtingId = config.qingting.id ?? '';
export const route: Route = {
path: '/podcast/:id',
@@ -11,12 +14,14 @@ export const route: Route = {
example: '/qingting/podcast/293411',
parameters: { id: '专辑id, 可在专辑页 URL 中找到' },
features: {
- requireConfig: false,
- requirePuppeteer: false,
- antiCrawler: false,
- supportBT: false,
supportPodcast: true,
- supportScihub: false,
+ requireConfig: [
+ {
+ name: 'QINGTING_ID',
+ optional: true,
+ description: '用户id, 部分专辑需要会员身份,用户id可以通过从网页端登录蜻蜓fm后使用开发者工具,在控制台中运行JSON.parse(localStorage.getItem("user")).qingting_id获取',
+ },
+ ],
},
radar: [
{
@@ -29,21 +34,35 @@ export const route: Route = {
description: `获取的播放 URL 有效期只有 1 天,需要开启播客 APP 的自动下载功能。`,
};
+function getMediaUrl(channelId: string, mediaId: string) {
+ const path = `/audiostream/redirect/${channelId}/${mediaId}?access_token=&device_id=MOBILESITE&qingting_id=${qingtingId}&t=${Date.now()}`;
+ const sign = crypto.createHmac('md5', 'fpMn12&38f_2e').update(path).digest('hex').toString();
+ return `https://audio.qingting.fm${path}&sign=${sign}`;
+}
+
async function handler(ctx) {
- const channelUrl = `https://i.qingting.fm/capi/v3/channel/${ctx.req.param('id')}`;
- let response = await got({
+ const channelId = ctx.req.param('id');
+
+ const channelUrl = `https://i.qingting.fm/capi/v3/channel/${channelId}`;
+ const response = await got({
method: 'get',
url: channelUrl,
headers: {
Referer: 'https://www.qingting.fm/',
},
});
+
const title = response.data.data.title;
const channel_img = response.data.data.thumbs['400_thumb'];
const authors = response.data.data.podcasters.map((author) => author.nick_name).join(',');
const desc = response.data.data.description;
- const programUrl = `https://i.qingting.fm/capi/channel/${ctx.req.param('id')}/programs/${response.data.data.v}?curpage=1&pagesize=10&order=asc`;
- response = await got({
+ const programUrl = `https://i.qingting.fm/capi/channel/${channelId}/programs/${response.data.data.v}?curpage=1&pagesize=10&order=asc`;
+
+ const {
+ data: {
+ data: { programs },
+ },
+ } = await got({
method: 'get',
url: programUrl,
headers: {
@@ -51,45 +70,48 @@ async function handler(ctx) {
},
});
+ const {
+ data: { data: channelInfo },
+ } = await got(`https://i.qingting.fm/capi/v3/channel/${channelId}?user_id=${qingtingId}`);
+
+ const isCharged = channelInfo.purchase?.item_type !== 0;
+
+ const isPaid = channelInfo.user_relevance?.sale_status === 'paid';
+
const resultItems = await Promise.all(
- response.data.data.programs.map((item) =>
- cache.tryGet(`qingting:podcast:${ctx.req.param('id')}:${item.id}`, async () => {
- const link = `https://www.qingting.fm/channels/${ctx.req.param('id')}/programs/${item.id}/`;
-
- const path = `/audiostream/redirect/${ctx.req.param('id')}/${item.id}?access_token=&device_id=MOBILESITE&qingting_id=&t=${Date.now()}`;
- const sign = crypto.createHmac('md5', 'fpMn12&38f_2e').update(path).digest('hex').toString();
-
- const [detailRes, mediaRes] = await Promise.all([
- got({
- method: 'get',
- url: link,
- headers: {
- Referer: 'https://www.qingting.fm/',
- },
- }),
- got({
- method: 'get',
- url: `https://audio.qingting.fm${path}&sign=${sign}`,
- headers: {
- Referer: 'https://www.qingting.fm/',
- },
- }),
- ]);
+ programs.map(async (item) => {
+ const data = (await cache.tryGet(`qingting:podcast:${channelId}:${item.id}`, async () => {
+ const link = `https://www.qingting.fm/channels/${channelId}/programs/${item.id}/`;
+
+ const detailRes = await got({
+ method: 'get',
+ url: link,
+ headers: {
+ Referer: 'https://www.qingting.fm/',
+ },
+ });
const detail = JSON.parse(detailRes.data.match(/},"program":(.*?),"plist":/)[1]);
- return {
+ const rssItem = {
title: item.title,
link,
itunes_item_image: item.cover,
itunes_duration: item.duration,
pubDate: timezone(parseDate(item.update_time), +8),
description: detail.richtext,
- enclosure_url: mediaRes.url,
- enclosure_type: 'audio/x-m4a',
};
- })
- )
+
+ return rssItem;
+ })) as DataItem;
+
+ if (!isCharged || isPaid || item.isfree) {
+ data.enclosure_url = getMediaUrl(channelId, item.id);
+ data.enclosure_type = 'audio/x-m4a';
+ }
+
+ return data;
+ })
);
return {
@@ -97,7 +119,7 @@ async function handler(ctx) {
description: desc,
itunes_author: authors,
image: channel_img,
- link: `https://www.qingting.fm/channels/${ctx.req.param('id')}`,
+ link: `https://www.qingting.fm/channels/${channelId}`,
item: resultItems,
};
}
diff --git a/lib/routes/test/index.ts b/lib/routes/test/index.ts
index 138e3691b4896c..2990917bd7bcd8 100644
--- a/lib/routes/test/index.ts
+++ b/lib/routes/test/index.ts
@@ -3,13 +3,14 @@ import { config } from '@/config';
import got from '@/utils/got';
import wait from '@/utils/wait';
import cache from '@/utils/cache';
+import { fetchArticle } from '@/utils/wechat-mp';
import ConfigNotFoundError from '@/errors/types/config-not-found';
import InvalidParameterError from '@/errors/types/invalid-parameter';
let cacheIndex = 0;
export const route: Route = {
- path: '/:id',
+ path: '/:id/:params?',
name: 'Unknown',
maintainers: ['DIYgod', 'NeverBehave'],
handler,
@@ -384,6 +385,15 @@ async function handler(ctx) {
];
}
+ if (ctx.req.param('id') === 'wechat-mp') {
+ const params = ctx.req.param('params');
+ if (!params) {
+ throw new InvalidParameterError('Invalid parameter');
+ }
+ const mpUrl = 'https:/mp.weixin.qq.com/s' + (params.includes('&') ? '?' : '/') + params;
+ item = [await fetchArticle(mpUrl)];
+ }
+
return {
title: `Test ${ctx.req.param('id')}`,
itunes_author: ctx.req.param('id') === 'enclosure' ? 'DIYgod' : null,
diff --git a/lib/setup.test.ts b/lib/setup.test.ts
index 192d9fe8275c3f..a06f67c51c2a30 100644
--- a/lib/setup.test.ts
+++ b/lib/setup.test.ts
@@ -2,6 +2,29 @@ import { afterAll, afterEach } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';
+const genWeChatMpPage = (rich_media_content: string, scripts: string[] | string) => {
+ if (!Array.isArray(scripts)) {
+ scripts = [scripts];
+ }
+ let pageHtml = `
+
+
+
+
+
+
+${rich_media_content}
+
+mpName
`;
+ for (const script of scripts) {
+ pageHtml += `
+`;
+ }
+ return pageHtml;
+};
+
const server = setupServer(
http.post(`https://api.openai.mock/v1/chat/completions`, () =>
HttpResponse.json({
@@ -33,21 +56,106 @@ const server = setupServer(
`)
),
- http.get(`https://mp.weixin.qq.com/rsshub_test/wechatMp_fetchArticle`, () =>
+ http.get(`https://mp.weixin.qq.com/rsshub_test/appMsg`, () =>
+ HttpResponse.text(
+ genWeChatMpPage(
+ `
+description
+
+
+`,
+ `
+var item_show_type = "0";
+var real_item_show_type = "0";
+var appmsg_type = "9";
+var ct = "${1_636_626_300}";
+var msg_source_url = "https://mp.weixin.qq.com/rsshub_test/fake";
+window.ip_wording = {
+ countryName: '中国',
+ countryId: '156',
+ provinceName: '福建',
+ provinceId: '',
+ cityName: '',
+ cityId: ''
+};`
+ )
+ )
+ ),
+ http.get(`https://mp.weixin.qq.com/rsshub_test/img`, () =>
+ HttpResponse.text(
+ genWeChatMpPage('fake_description', [
+ `
+var item_show_type = "8";
+var real_item_show_type = "8";
+var appmsg_type = "9";
+var ct = "${1_636_626_300}";
+`,
+ `
+window.picture_page_info_list = [
+{
+ cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_1/0?wx_fmt=jpeg',
+},
+{
+ cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_2/0?wx_fmt=jpeg',
+},
+].slice(0, 20);
+`,
+ ])
+ )
+ ),
+ http.get(`https://mp.weixin.qq.com/rsshub_test/audio`, () =>
+ HttpResponse.text(
+ genWeChatMpPage('fake_description', [
+ `
+var item_show_type = "7";
+var real_item_show_type = "7";
+var appmsg_type = "9";
+var ct = "${1_636_626_300}";
+`,
+ `
+reportOpt = {
+ voiceid: "",
+ uin: "",
+ biz: "",
+ mid: "",
+ idx: ""
+};
+window.cgiData = {
+ voiceid: "rsshub_test_voiceid_1",
+ duration: "6567" * 1,
+};
+`,
+ ])
+ )
+ ),
+ http.get(`https://mp.weixin.qq.com/rsshub_test/video`, () =>
+ HttpResponse.text(
+ genWeChatMpPage(
+ 'fake_description',
+ `
+var item_show_type = "5";
+var real_item_show_type = "5";
+var appmsg_type = "9";
+var ct = "${1_636_626_300}";
+`
+ )
+ )
+ ),
+ http.get(`https://mp.weixin.qq.com/rsshub_test/fallback`, () =>
HttpResponse.text(
- '\n' +
- ' \n' +
- ' \n' +
- ' \n' +
- ' \n' +
- 'description
\n' +
- 'mpName
\n' +
- ''
+ genWeChatMpPage(
+ 'fake_description',
+ `
+var item_show_type = "99988877";
+var real_item_show_type = "99988877";
+var appmsg_type = "9";
+var ct = "${1_636_626_300}";
+`
+ )
)
),
+ http.get(`https://mp.weixin.qq.com/s/rsshub_test`, () => HttpResponse.text(genWeChatMpPage('', ''))),
+ http.get(`https://mp.weixin.qq.com/s?__biz=rsshub_test&mid=1&idx=1&sn=1`, () => HttpResponse.text(genWeChatMpPage('', ''))),
http.get(`http://rsshub.test/headers`, ({ request }) =>
HttpResponse.json({
...Object.fromEntries(request.headers.entries()),
diff --git a/lib/utils/wechat-mp.test.ts b/lib/utils/wechat-mp.test.ts
index e700a6e425bdc6..2343ee69c6b9e7 100644
--- a/lib/utils/wechat-mp.test.ts
+++ b/lib/utils/wechat-mp.test.ts
@@ -1,6 +1,27 @@
-import { describe, expect, it } from 'vitest';
+import { describe, expect, it, vi } from 'vitest';
import { load } from 'cheerio';
-import { fixArticleContent, fetchArticle, finishArticleItem, normalizeUrl } from '@/utils/wechat-mp';
+import Parser from 'rss-parser';
+import InvalidParameterError from '@/errors/types/invalid-parameter';
+import { exportedForTestingOnly, fetchArticle, finishArticleItem, fixArticleContent, normalizeUrl } from '@/utils/wechat-mp';
+const { ExtractMetadata, showTypeMapReverse } = exportedForTestingOnly;
+
+vi.mock('@/utils/request-rewriter', () => ({ default: null }));
+const { default: app } = await import('@/app');
+const parser = new Parser();
+
+const expectedItem: {
+ title: string;
+ summary: string;
+ author: string;
+ mpName: string;
+ link: string;
+} = {
+ title: 'title',
+ summary: 'summary',
+ author: 'author',
+ mpName: 'mpName',
+ link: '', // to be filled
+};
// date from the cache will be an ISO8601 string, so we need to use this function
const compareDate = (date1, date2) => {
@@ -8,8 +29,227 @@ const compareDate = (date1, date2) => {
date2 = typeof date2 === 'string' ? new Date(date2) : date2;
return date1.getTime() === date2.getTime();
};
+const genScriptHtmlStr = (script: string) => `
+
+
+
+`;
+const testFetchArticleFinishArticleItem = async (path: string, { setMpNameAsAuthor = false, skipLink = false } = {}) => {
+ const ct = 1_636_626_300;
+ const httpsUrl = `https://mp.weixin.qq.com/rsshub_test${path}`;
+ const httpUrl = 'http' + httpsUrl.slice(5);
+
+ const expectedDate = new Date(ct * 1000);
+
+ const expectedItem_ = {
+ ...expectedItem,
+ link: httpsUrl,
+ };
+
+ const fetchArticleItem = await fetchArticle(httpUrl);
+ expect(compareDate(fetchArticleItem.pubDate, expectedDate)).toBe(true);
+ expect(fetchArticleItem).toMatchObject(expectedItem_);
+
+ const ToBeFinishedArticleItem = { link: httpUrl };
+ const expectedFinishedArticleItem = { ...fetchArticleItem };
+ expectedFinishedArticleItem.author = setMpNameAsAuthor ? expectedFinishedArticleItem.mpName : expectedFinishedArticleItem.author;
+ expectedFinishedArticleItem.link = skipLink ? ToBeFinishedArticleItem.link : expectedFinishedArticleItem.link;
+
+ const finishedArticleItem = await finishArticleItem(ToBeFinishedArticleItem, setMpNameAsAuthor, skipLink);
+ expect(compareDate(finishedArticleItem.pubDate, fetchArticleItem.pubDate)).toBe(true);
+ delete expectedFinishedArticleItem.pubDate;
+ expect(finishedArticleItem).toMatchObject(expectedFinishedArticleItem);
+
+ return fetchArticleItem;
+};
describe('wechat-mp', () => {
+ it('ExtractMetadata.common', () => {
+ expect(ExtractMetadata.common(load(''))).toStrictEqual({});
+
+ expect(
+ ExtractMetadata.common(
+ load(
+ genScriptHtmlStr(`
+ window.fake_item_show_type = '5' || '';
+ window.fake_real_item_show_type = '5' || '';
+ window.fake_ct = '1713009660' || '';
+ `)
+ )
+ )
+ ).toMatchObject({});
+
+ expect(
+ ExtractMetadata.common(
+ load(
+ genScriptHtmlStr(`
+ window.item_show_type = '5' || '';
+ window.real_item_show_type = '5' || '';
+ window.ct = '1713009660' || '';
+ `)
+ )
+ )
+ ).toMatchObject({
+ showType: showTypeMapReverse['5'],
+ realShowType: showTypeMapReverse['5'],
+ createTime: '1713009660',
+ });
+
+ expect(
+ ExtractMetadata.common(
+ load(
+ genScriptHtmlStr(`
+ var item_show_type = "5";
+ var real_item_show_type = "5";
+ var ct = "1713009660";
+ var msg_source_url = 'https://mp.weixin.qq.com/rsshub_test/fake';
+ `)
+ )
+ )
+ ).toMatchObject({
+ showType: showTypeMapReverse['5'],
+ realShowType: showTypeMapReverse['5'],
+ createTime: '1713009660',
+ sourceUrl: 'https://mp.weixin.qq.com/rsshub_test/fake',
+ });
+
+ expect(
+ ExtractMetadata.common(
+ load(
+ genScriptHtmlStr(`
+ var item_show_type = "998877665544332211";
+ var real_item_show_type = "112233445566778899";
+ var ct = "1713009660";
+ `)
+ )
+ )
+ ).toMatchObject({
+ showType: '998877665544332211',
+ realShowType: '112233445566778899',
+ createTime: '1713009660',
+ });
+ });
+ it('ExtractMetadata.img', () => {
+ expect(ExtractMetadata.img(load(''))).toStrictEqual({});
+
+ expect(
+ ExtractMetadata.img(
+ load(
+ genScriptHtmlStr(`
+ window.picture_page_info_list = [
+ {
+ cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_1/0?wx_fmt=jpeg',
+ },
+ {
+ cdn_url: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_2/0?wx_fmt=jpeg',
+ },
+ ].slice(0, 20);
+ `)
+ )
+ )
+ ).toMatchObject({
+ imgUrls: ['https://mmbiz.qpic.cn/rsshub_test/fake_img_1/0?wx_fmt=jpeg', 'https://mmbiz.qpic.cn/rsshub_test/fake_img_2/0?wx_fmt=jpeg'],
+ });
+ });
+ it('ExtractMetadata.audio', () => {
+ expect(ExtractMetadata.audio(load(''))).toStrictEqual({});
+
+ expect(
+ ExtractMetadata.audio(
+ load(
+ genScriptHtmlStr(`
+ reportOpt = {
+ voiceid: "",
+ uin: "",
+ biz: "",
+ mid: "",
+ idx: ""
+ };
+ `)
+ )
+ )
+ ).toMatchObject({});
+
+ expect(
+ ExtractMetadata.audio(
+ load(
+ genScriptHtmlStr(`
+ window.cgiData = {
+ voiceid: "rsshub_test_voiceid_1",
+ duration: "6567" * 1,
+ };
+ `)
+ )
+ )
+ ).toMatchObject({
+ voiceId: 'rsshub_test_voiceid_1',
+ duration: '6567',
+ });
+
+ expect(
+ ExtractMetadata.audio(
+ load(
+ genScriptHtmlStr(`
+ window.cgiData = {
+ voiceid: "rsshub_test_voiceid_1",
+ };
+ `)
+ )
+ )
+ ).toMatchObject({
+ voiceId: 'rsshub_test_voiceid_1',
+ duration: null,
+ });
+
+ expect(
+ ExtractMetadata.audio(
+ load(
+ genScriptHtmlStr(`
+ reportOpt = {
+ voiceid: "",
+ uin: "",
+ biz: "",
+ mid: "",
+ idx: ""
+ };
+ window.cgiData = {
+ voiceid: "rsshub_test_voiceid_1",
+ duration: "6567" * 1,
+ };
+ `)
+ )
+ )
+ ).toMatchObject({
+ voiceId: 'rsshub_test_voiceid_1',
+ duration: '6567',
+ });
+ });
+ it('ExtractMetadata.location', () => {
+ expect(ExtractMetadata.location(load(''))).toStrictEqual({});
+
+ expect(
+ ExtractMetadata.location(
+ load(
+ genScriptHtmlStr(`
+ window.ip_wording = {
+ countryName: '中国',
+ countryId: '156',
+ provinceName: '广东',
+ provinceId: '',
+ cityName: '',
+ cityId: ''
+ };
+ `)
+ )
+ )
+ ).toMatchObject({
+ countryName: '中国',
+ provinceName: '广东',
+ cityName: '',
+ });
+ });
it('fixArticleContent', () => {
const divHeader = '';
const divFooter = '
';
@@ -88,37 +328,105 @@ describe('wechat-mp', () => {
expect(normalizeUrl(notWechatMp, true)).toBe(notWechatMp);
});
- it('fetchArticle_&_finishArticleItem', async () => {
- const ct = 1_636_626_300;
- const httpsUrl = 'https://mp.weixin.qq.com/rsshub_test/wechatMp_fetchArticle';
- const httpUrl = httpsUrl.replace(/^https:\/\//, 'http://');
-
- const expectedItem: {
- title: string;
- summary: string;
- author: string;
- description: string;
- mpName?: string;
- link: string;
- } = {
+ it('fetchArticle_&_finishArticleItem_appMsg', async () => {
+ const fetchArticleItem = await testFetchArticleFinishArticleItem('/appMsg');
+ const $ = load(fetchArticleItem.description);
+ expect($('iframe').attr()).toMatchObject({
+ src:
+ 'https://v.qq.com/txp/iframe/player.html?origin=https%3A%2F%2Fmp.weixin.qq.com' +
+ '&containerId=js_tx_video_container_0.3863487104715233&vid=fake&width=677&height=380.8125' +
+ '&autoplay=false&allowFullScreen=true&chid=17&full=true&show1080p=false&isDebugIframe=false',
+ width: '677',
+ height: '380.8125',
+ });
+ expect($('audio').attr()).toMatchObject({
+ src: 'https://res.wx.qq.com/voice/getvoice?mediaid=rsshub_test',
+ title: 'title',
+ });
+ expect($('a').attr()).toMatchObject({
+ href: 'https://mp.weixin.qq.com/rsshub_test/fake',
+ });
+ expect(fetchArticleItem.description).toContain('description');
+ expect(fetchArticleItem.description).toContain('📍发表于:中国 福建');
+ expect(fetchArticleItem.description).toContain('🔗️ 阅读原文');
+ });
+
+ it('fetchArticle_&_finishArticleItem_img', async () => {
+ const fetchArticleItem = await testFetchArticleFinishArticleItem('/img');
+ const $ = load(fetchArticleItem.description);
+ expect($.text()).toBe('summary');
+ expect($('img:nth-of-type(1)').attr()).toMatchObject({
+ src: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_1/0?wx_fmt=jpeg',
+ });
+ expect($('img:nth-of-type(2)').attr()).toMatchObject({
+ src: 'https://mmbiz.qpic.cn/rsshub_test/fake_img_2/0?wx_fmt=jpeg',
+ });
+ });
+
+ it('fetchArticle_&_finishArticleItem_audio', async () => {
+ const fetchArticleItem = await testFetchArticleFinishArticleItem('/audio');
+ const $ = load(fetchArticleItem.description);
+ expect($.text()).toBe('summary');
+ expect($('audio').attr()).toMatchObject({
+ controls: '',
+ src: 'https://res.wx.qq.com/voice/getvoice?mediaid=rsshub_test_voiceid_1',
+ style: 'width:100%',
title: 'title',
- summary: 'summary',
- author: 'author',
- description: 'description',
- mpName: 'mpName',
- link: httpsUrl,
+ });
+ expect(fetchArticleItem).toMatchObject({
+ enclosure_type: 'audio/mp3',
+ enclosure_url: 'https://res.wx.qq.com/voice/getvoice?mediaid=rsshub_test_voiceid_1',
+ itunes_duration: '6567',
+ });
+ });
+
+ it('fetchArticle_&_finishArticleItem_video', async () => {
+ const fetchArticleItem = await testFetchArticleFinishArticleItem('/video');
+ const $ = load(fetchArticleItem.description);
+ expect($.text()).toBe('summary');
+ expect($('img').attr()).toMatchObject({
+ src: 'https://mmbiz.qpic.cn/rsshub_test/og_img_1/0?wx_fmt=jpeg',
+ });
+ });
+
+ it('fetchArticle_&_finishArticleItem_fallback', async () => {
+ const fetchArticleItem = await testFetchArticleFinishArticleItem('/fallback');
+ const $ = load(fetchArticleItem.description);
+ expect($.text()).toBe('summary');
+ expect($('img').attr()).toMatchObject({
+ src: 'https://mmbiz.qpic.cn/rsshub_test/og_img_1/0?wx_fmt=jpeg',
+ });
+ });
+
+ it('finishArticleItem_param', async () => {
+ await testFetchArticleFinishArticleItem('/fallback', { setMpNameAsAuthor: false, skipLink: false });
+ await testFetchArticleFinishArticleItem('/fallback', { setMpNameAsAuthor: true, skipLink: false });
+ await testFetchArticleFinishArticleItem('/fallback', { setMpNameAsAuthor: false, skipLink: true });
+ await testFetchArticleFinishArticleItem('/fallback', { setMpNameAsAuthor: true, skipLink: true });
+ });
+
+ it('route_test', async () => {
+ try {
+ await app.request('/test/wechat-mp');
+ } catch (error) {
+ expect(error).toBeInstanceOf(InvalidParameterError);
+ }
+
+ const responseShort = await app.request('/test/wechat-mp/rsshub_test');
+ const parsedShort = await parser.parseString(await responseShort.text());
+ const expectedItemShort = {
+ author: expectedItem.author,
+ title: expectedItem.title,
+ link: 'https://mp.weixin.qq.com/s/rsshub_test',
+ };
+ expect(parsedShort.items[0]).toMatchObject(expectedItemShort);
+
+ const responseLong = await app.request('/test/wechat-mp/__biz=rsshub_test&mid=1&idx=1&sn=1');
+ const parsedLong = await parser.parseString(await responseLong.text());
+ const expectedItemLong = {
+ ...expectedItemShort,
+ link: 'https://mp.weixin.qq.com/s?__biz=rsshub_test&mid=1&idx=1&sn=1',
};
- const expectedDate = new Date(ct * 1000);
-
- const fetchArticleItem = await fetchArticle(httpUrl);
- expect(compareDate(fetchArticleItem.pubDate, expectedDate)).toBe(true);
- delete fetchArticleItem.pubDate;
- expect(fetchArticleItem).toEqual(expectedItem);
-
- delete expectedItem.mpName;
- const finishedArticleItem = await finishArticleItem({ link: httpUrl });
- expect(compareDate(finishedArticleItem.pubDate, expectedDate)).toBe(true);
- delete finishedArticleItem.pubDate;
- expect(finishedArticleItem).toEqual(expectedItem);
+ expect(parsedLong.items[0]).toMatchObject(expectedItemLong);
});
});
diff --git a/lib/utils/wechat-mp.ts b/lib/utils/wechat-mp.ts
index 0615ab1c944950..a45ee305027e56 100644
--- a/lib/utils/wechat-mp.ts
+++ b/lib/utils/wechat-mp.ts
@@ -26,9 +26,215 @@
*/
import ofetch from '@/utils/ofetch';
-import { load, type Cheerio, type Element } from 'cheerio';
+import { type Cheerio, type CheerioAPI, type Element, load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import cache from '@/utils/cache';
+import logger from '@/utils/logger';
+
+const MAINTAINERS = ['Rongronggg9'];
+
+const warn = (reason: string, details: string) =>
+ logger.warn(`wechat-mp: ${reason}: ${details},
+consider raise an issue (mentioning ${MAINTAINERS.join(', ')}) with the article URL for further investigation`);
+
+const replaceReturnNewline = (() => {
+ const returnRegExp = /\r|\\(r|x0d)/g;
+ const newlineRegExp = /\n|\\(n|x0a)/g;
+ return (text: string, replaceReturnWith = '', replaceNewlineWith = ' ') => text.replaceAll(returnRegExp, replaceReturnWith).replaceAll(newlineRegExp, replaceNewlineWith);
+})();
+const fixUrl = (() => {
+ const ampRegExp = /(&|\\x26)amp;/g;
+ return (text: string) => text.replaceAll(ampRegExp, '&');
+})();
+
+class LoopContinue extends Error {
+ constructor() {
+ super('');
+ this.name = 'LoopContinue';
+ }
+}
+
+class LoopReturn extends Error {
+ to_return: any;
+
+ constructor(to_return: any) {
+ super('');
+ this.name = 'LoopReturn';
+ this.to_return = to_return;
+ }
+}
+
+const forEachScript = ($: CheerioAPI | string, callback: (script) => void, defaultReturn: any = null, selector = 'script[nonce][type="text/javascript"]') => {
+ const scripts = typeof $ === 'string' ? [$] : $(selector).toArray();
+ for (const script of scripts) {
+ try {
+ callback(script);
+ } catch (error) {
+ if (error instanceof LoopReturn) {
+ return error.to_return;
+ } else if (error instanceof LoopContinue) {
+ continue;
+ }
+ throw error;
+ }
+ }
+ return defaultReturn;
+};
+
+// view-source a *_SHARE_PAGE type article and search for `ITEM_SHOW_TYPE_MAP`
+// Please update the comments below if you find new types or new examples
+const showTypeMap = {
+ // "Article".
+ // May be combined with media, but type won't change
+ // Combined with audio and iframe: https://mp.weixin.qq.com/s/FnjcMXZ1xdS-d6n-pUUyyw
+ APP_MSG_PAGE: '0',
+ // https://mp.weixin.qq.com/s?__biz=Mzg4NTA1MTkwNA==&mid=2247532942&idx=1&sn=a84e4adbe49fdb39e4d4c1b5c12a4c3f
+ VIDEO_SHARE_PAGE: '5',
+ MUSIC_SHARE_PAGE: '6',
+ // https://mp.weixin.qq.com/s/FY6yQC_e4NMAxK0FBr6jwQ
+ AUDIO_SHARE_PAGE: '7',
+ // https://mp.weixin.qq.com/s/4p5YmYuASiQSYFiy7KqydQ
+ // https://mp.weixin.qq.com/s?__biz=Mzg4NTA1MTkwNA==&mid=2247532936&idx=4&sn=624054c20ded6ee85c6632f419c6f758
+ IMG_SHARE_PAGE: '8',
+ TEXT_SHARE_PAGE: '10',
+ SHORT_CONTENT_PAGE: '17',
+};
+const showTypeMapReverse = Object.fromEntries(Object.entries(showTypeMap).map(([k, v]) => [v, k]));
+
+class ExtractMetadata {
+ private static genAssignmentRegExp = (varName: string, valuePattern: string, assignPattern: string) => RegExp(`\\b${varName}\\s*${assignPattern}\\s*(?["'])(?${valuePattern})\\k`, 'mg');
+
+ private static genExtractFunc = (
+ varName: string,
+ {
+ valuePattern = '\\w+',
+ assignPattern = '=',
+ allowNotFound = false,
+ multiple = false,
+ }: {
+ valuePattern?: string;
+ assignPattern?: string;
+ allowNotFound?: boolean;
+ multiple?: boolean;
+ }
+ ) => {
+ const regExp = this.genAssignmentRegExp(varName, valuePattern, assignPattern);
+ return (str: string) => {
+ const values: string[] = [];
+ for (const match of str.matchAll(regExp)) {
+ const value = match.groups?.value;
+ if (!multiple) {
+ return value;
+ }
+ values.push(value);
+ }
+ if (!allowNotFound && values.length === 0) {
+ throw new LoopContinue();
+ }
+ return multiple ? values : null;
+ };
+ };
+
+ private static doExtract = (metadataToBeExtracted: Record string | string[] | null | undefined>, scriptText: string) => {
+ const metadataExtracted: Record = {};
+ for (const [key, extractFunc] of Object.entries(metadataToBeExtracted)) {
+ metadataExtracted[key] = extractFunc(scriptText);
+ }
+ metadataExtracted._extractedFrom = scriptText;
+ return metadataExtracted;
+ };
+
+ private static commonMetadataToBeExtracted = {
+ showType: this.genExtractFunc('item_show_type', { valuePattern: '\\d+' }),
+ realShowType: this.genExtractFunc('real_item_show_type', { valuePattern: '\\d+' }),
+ createTime: this.genExtractFunc('ct', { valuePattern: '\\d+' }),
+ sourceUrl: this.genExtractFunc('msg_source_url', { valuePattern: `https?://[^'"]*`, allowNotFound: true }),
+ };
+
+ static common = ($: CheerioAPI) =>
+ forEachScript(
+ $,
+ (script) => {
+ const scriptText = $(script).text();
+ const metadataExtracted = >this.doExtract(this.commonMetadataToBeExtracted, scriptText);
+ const showType = showTypeMapReverse[metadataExtracted.showType];
+ const realShowType = showTypeMapReverse[metadataExtracted.realShowType];
+ metadataExtracted.sourceUrl = metadataExtracted.sourceUrl && fixUrl(metadataExtracted.sourceUrl);
+ if (showType) {
+ metadataExtracted.showType = showType;
+ } else {
+ warn('showType not found', `item_show_type=${metadataExtracted.showType}`);
+ }
+ if (realShowType) {
+ metadataExtracted.realShowType = realShowType;
+ } else {
+ warn('realShowType not found', `real_item_show_type=${metadataExtracted.realShowType}`);
+ }
+ if (metadataExtracted.showType !== metadataExtracted.realShowType) {
+ // never seen this happen, waiting for examples
+ warn('showType mismatch', `item_show_type=${metadataExtracted.showType}, real_item_show_type=${metadataExtracted.realShowType}`);
+ }
+ throw new LoopReturn(metadataExtracted);
+ },
+ {},
+ 'script[nonce][type="text/javascript"]:contains("real_item_show_type")'
+ );
+
+ private static audioMetadataToBeExtracted = {
+ voiceId: this.genExtractFunc('voiceid', { assignPattern: ':' }),
+ duration: this.genExtractFunc('duration', { valuePattern: '\\d*', assignPattern: ':', allowNotFound: true }),
+ };
+
+ // never seen a audio article containing multiple audio, waiting for examples
+ static audio = ($: CheerioAPI) =>
+ forEachScript(
+ $,
+ (script) => {
+ const scriptText = $(script).text();
+ const metadataExtracted = >this.doExtract(this.audioMetadataToBeExtracted, scriptText);
+ throw new LoopReturn(metadataExtracted);
+ },
+ {},
+ 'script[nonce][type="text/javascript"]:contains("voiceid")'
+ );
+
+ private static imgMetadataToBeExtracted = {
+ imgUrls: this.genExtractFunc('cdn_url', { valuePattern: `https?://[^'"]*`, assignPattern: ':', multiple: true }),
+ };
+
+ static img = ($: CheerioAPI) =>
+ forEachScript(
+ $,
+ (script) => {
+ const scriptText = $(script).text();
+ const metadataExtracted = >this.doExtract(this.imgMetadataToBeExtracted, scriptText);
+ if (Array.isArray(metadataExtracted.imgUrls)) {
+ metadataExtracted.imgUrls = metadataExtracted.imgUrls.map((url) => fixUrl(url));
+ }
+ throw new LoopReturn(metadataExtracted);
+ },
+ {},
+ 'script[nonce][type="text/javascript"]:contains("picture_page_info_list")'
+ );
+
+ private static locationMetadataToBeExtracted = {
+ countryName: this.genExtractFunc('countryName', { valuePattern: `[^'"]*`, assignPattern: ':' }),
+ provinceName: this.genExtractFunc('provinceName', { valuePattern: `[^'"]*`, assignPattern: ':' }),
+ cityName: this.genExtractFunc('cityName', { valuePattern: `[^'"]*`, assignPattern: ':' }),
+ };
+
+ static location = ($: CheerioAPI) =>
+ forEachScript(
+ $,
+ (script) => {
+ const scriptText = $(script).text();
+ const metadataExtracted = this.doExtract(this.locationMetadataToBeExtracted, scriptText);
+ throw new LoopReturn(metadataExtracted);
+ },
+ {},
+ 'script[nonce][type="text/javascript"]:contains("countryName")'
+ );
+}
const replaceTag = ($, oldTag, newTagName) => {
oldTag = $(oldTag);
@@ -55,15 +261,23 @@ const detectOriginalArticleUrl = ($) => {
return null;
};
-const detectSourceUrl = ($) => {
- const matchs = $.root()
- .html()
- .match(/msg_source_url = '(.+)';/);
-
- if (matchs) {
- return matchs[1];
- }
- return null;
+const genAudioSrc = (voiceId: string) => `https://res.wx.qq.com/voice/getvoice?mediaid=${voiceId}`;
+const genAudioTag = (src: string, title: string) => ` `;
+const genVideoSrc = (videoId: string) => {
+ const newSearchParams = new URLSearchParams({
+ origin: 'https://mp.weixin.qq.com',
+ containerId: 'js_tx_video_container_0.3863487104715233',
+ vid: videoId,
+ width: '677',
+ height: '380.8125',
+ autoplay: 'false',
+ allowFullScreen: 'true',
+ chid: '17',
+ full: 'true',
+ show1080p: 'false',
+ isDebugIframe: 'false',
+ });
+ return `https://v.qq.com/txp/iframe/player.html?${newSearchParams.toString()}`;
};
/**
@@ -99,6 +313,33 @@ const fixArticleContent = (html?: string | Cheerio, skipImg = false) =>
}
});
}
+ // fix audio: https://mp.weixin.qq.com/s/FnjcMXZ1xdS-d6n-pUUyyw
+ $('mpvoice[voice_encode_fileid]').each((_, voice) => {
+ const $voice = $(voice);
+ const voiceId = $voice.attr('voice_encode_fileid');
+ if (voiceId) {
+ const title = $voice.attr('name') || 'Audio';
+ $voice.replaceWith(genAudioTag(genAudioSrc(voiceId), title));
+ }
+ });
+ // fix iframe: https://mp.weixin.qq.com/s/FnjcMXZ1xdS-d6n-pUUyyw
+ $('iframe.video_iframe[data-src]').each((_, iframe) => {
+ const $iframe = $(iframe);
+ const dataSrc = $iframe.attr('data-src');
+ const srcUrlObj = new URL(dataSrc);
+ if (srcUrlObj.host === 'v.qq.com' && srcUrlObj.searchParams.has('vid')) {
+ const newSrc = genVideoSrc(srcUrlObj.searchParams.get('vid'));
+ $iframe.attr('src', newSrc);
+ $iframe.removeAttr('data-src');
+ const width = $iframe.attr('data-w');
+ const ratio = $iframe.attr('data-ratio');
+ if (width && ratio) {
+ const width_ = Math.min(Number.parseInt(width), 677);
+ $iframe.attr('width', width_.toString());
+ $iframe.attr('height', (width_ / Number.parseFloat(ratio)).toString());
+ }
+ } // else {} FIXME: https://mp.weixin.qq.com/s?__biz=Mzg5Mjk3MzE4OQ==&mid=2247549515&idx=2&sn=a608fca597f0589c1aebd6d0b82ff6e9
+ });
// fix section
$('section').each((_, section) => {
const $section = $(section);
@@ -122,17 +363,6 @@ const fixArticleContent = (html?: string | Cheerio, skipImg = false) =>
// clear line index tags in code section
$('.code-snippet__line-index').remove();
- // fix single picture article
- // example: https://mp.weixin.qq.com/s/4p5YmYuASiQSYFiy7KqydQ
- $('script').each((_, script) => {
- const $script = $(script);
- const matchs = $script.html()?.match(/document\.getElementById\('js_image_desc'\)\.innerHTML = "(.*)"\.replace/);
-
- if (matchs) {
- $script.replaceWith(matchs[1].replaceAll('\r', '').replaceAll('\n', ' ').replaceAll('\\x0d', '').replaceAll('\\x0a', ' '));
- }
- });
-
// clean scripts
$('script').remove();
return $.html();
@@ -184,51 +414,124 @@ const normalizeUrl = (url, bypassHostCheck = false) => {
return urlObj.href;
};
+class PageParsers {
+ private static common = ($: CheerioAPI, commonMetadata: Record) => {
+ const title = replaceReturnNewline($('meta[property="og:title"]').attr('content') || '', '', ' ');
+ const author = replaceReturnNewline($('meta[name=author]').attr('content') || '', '', ' ');
+ const pubDate = commonMetadata.createTime ? parseDate(Number.parseInt(commonMetadata.createTime) * 1000) : undefined;
+ const mpName = $('.wx_follow_nickname').first().text()?.trim();
+
+ let summary = replaceReturnNewline($('meta[name=description]').attr('content') || '');
+ const description = summary;
+ summary = summary.replaceAll(' ', ' ') === title ? '' : summary;
+
+ return { title, author, description, summary, pubDate, mpName } as {
+ title: string;
+ author: string;
+ description: string;
+ summary: string;
+ pubDate?: Date;
+ mpName?: string;
+ enclosure_url?: string;
+ itunes_duration?: string | number;
+ enclosure_type?: string;
+ };
+ };
+ private static appMsg = async ($: CheerioAPI, commonMetadata: Record) => {
+ const page = PageParsers.common($, commonMetadata);
+ page.description = fixArticleContent($('#js_content'));
+ const originalArticleUrl = detectOriginalArticleUrl($);
+ if (originalArticleUrl) {
+ // No article or article is too short, try to fetch the description from the original article
+ const data = await ofetch(normalizeUrl(originalArticleUrl));
+ const original$ = load(data);
+ page.description += fixArticleContent(original$('#js_content'));
+ }
+ return page;
+ };
+ private static img = ($: CheerioAPI, commonMetadata: Record) => {
+ const page = PageParsers.common($, commonMetadata);
+ const imgUrls = ExtractMetadata.img($)?.imgUrls;
+ let imgHtml = '';
+ if (Array.isArray(imgUrls) && imgUrls.length > 0) {
+ for (const imgUrl of imgUrls) {
+ imgHtml += ` `;
+ }
+ }
+ page.description += imgHtml;
+ return page;
+ };
+ private static audio = ($: CheerioAPI, commonMetadata: Record) => {
+ const page = PageParsers.common($, commonMetadata);
+ const audioMetadata = ExtractMetadata.audio($);
+ const audioUrl = genAudioSrc(audioMetadata.voiceId);
+ page.enclosure_url = audioUrl;
+ page.itunes_duration = audioMetadata.duration;
+ page.enclosure_type = 'audio/mp3'; // FIXME: may it be other types?
+ page.description += ' ' + genAudioTag(audioUrl, page.title);
+ return page;
+ };
+ private static fallback = ($: CheerioAPI, commonMetadata: Record) => {
+ const page = PageParsers.common($, commonMetadata);
+ const image = $('meta[property="og:image"]').attr('content');
+ if (image) {
+ page.description += ` `;
+ }
+ return page;
+ };
+ static dispatch = async ($: CheerioAPI) => {
+ const commonMetadata = ExtractMetadata.common($);
+ let page: Record;
+ switch (commonMetadata.showType) {
+ case 'APP_MSG_PAGE':
+ page = await PageParsers.appMsg($, commonMetadata);
+ break;
+ case 'AUDIO_SHARE_PAGE':
+ page = PageParsers.audio($, commonMetadata);
+ break;
+ case 'IMG_SHARE_PAGE':
+ page = PageParsers.img($, commonMetadata);
+ break;
+ case 'VIDEO_SHARE_PAGE':
+ page = PageParsers.fallback($, commonMetadata);
+ break;
+ default:
+ warn('new showType, trying fallback method', `showType=${commonMetadata.showType}`);
+ page = PageParsers.fallback($, commonMetadata);
+ }
+ const locationMetadata = ExtractMetadata.location($);
+ let location = '';
+ for (const loc of [locationMetadata.countryName, locationMetadata.provinceName, locationMetadata.cityName]) {
+ if (loc) {
+ location += loc + ' ';
+ }
+ }
+ location = location.trim();
+ if (location) {
+ page.description += `📍发表于:${location}
`;
+ }
+ if (commonMetadata.sourceUrl) {
+ page.description += `🔗️ 阅读原文
`;
+ }
+ return page;
+ };
+}
+
/**
* Fetch article and its metadata from WeChat MP (mp.weixin.qq.com).
*
* If you use this function, no need to call `fixArticleContent`
- * @param {object} ctx - The context object.
- * @param {string} url - The url of the article.
- * @param {boolean} bypassHostCheck - Whether to bypass host check.
- * @return {Promise} - An object containing the article and its metadata.
+ * @param url - The url of the article.
+ * @param bypassHostCheck - Whether to bypass host check.
+ * @return - An object containing the article and its metadata.
*/
-const fetchArticle = (url, bypassHostCheck = false) => {
+const fetchArticle = (url: string, bypassHostCheck: boolean = false) => {
url = normalizeUrl(url, bypassHostCheck);
return cache.tryGet(url, async () => {
const data = await ofetch(url);
const $ = load(data);
-
- const title = ($('meta[property="og:title"]').attr('content') || '').replaceAll('\\r', '').replaceAll('\\n', ' ');
- const author = $('meta[name=author]').attr('content');
- let summary = $('meta[name=description]').attr('content');
- summary = summary === title ? '' : summary;
- let description = fixArticleContent($('#js_content'));
- // No article get or article is too short, try the original url
- const originalUrl = detectOriginalArticleUrl($);
- if (originalUrl) {
- // try to fetch the description from the original article
- const data = await ofetch(normalizeUrl(originalUrl, bypassHostCheck));
- const original$ = load(data);
- description += fixArticleContent(original$('#js_content'));
- }
-
- const sourceUrl = detectSourceUrl($);
- if (sourceUrl) {
- description += `阅读原文 `;
- }
-
- let pubDate;
- const publish_time_script = $('script[nonce][type="text/javascript"]:contains("var ct")').text();
- const publish_time_match = publish_time_script && publish_time_script.match(/var ct *= *"?(\d{10})"?/);
- const publish_timestamp = publish_time_match && publish_time_match[1];
- if (publish_timestamp) {
- pubDate = parseDate(Number.parseInt(publish_timestamp) * 1000);
- }
-
- let mpName = $('.profile_nickname').first().text();
- mpName = mpName && mpName.trim();
- return { title, author, description, summary, pubDate, mpName, link: url };
+ const page = await PageParsers.dispatch($);
+ return { ...page, link: url };
}) as Promise<{
title: string;
author: string;
@@ -237,6 +540,9 @@ const fetchArticle = (url, bypassHostCheck = false) => {
pubDate?: Date;
mpName?: string;
link: string;
+ enclosure_type?: string;
+ enclosure_url?: string;
+ itunes_duration?: string | number;
}>;
};
@@ -257,18 +563,23 @@ const fetchArticle = (url, bypassHostCheck = false) => {
* @return {Promise} - The incoming `item` object, with the article and its metadata filled in.
*/
const finishArticleItem = async (item, setMpNameAsAuthor = false, skipLink = false) => {
- const { title, author, description, summary, pubDate, mpName, link } = await fetchArticle(item.link);
- item.title = title || item.title;
- item.description = description || item.description;
- item.summary = summary || item.summary;
- item.pubDate = pubDate || item.pubDate;
- item.author = setMpNameAsAuthor
- ? mpName || item.author // the Official Account itself. if your route return articles from different accounts, you may want to use this
- : author || item.author; // the real author of the article. if your route return articles from a certain account, use this
- if (!skipLink) {
- item.link = link || item.link;
+ const fetchedItem = await fetchArticle(item.link);
+ for (const key in fetchedItem) {
+ switch (key) {
+ case 'author':
+ item.author = setMpNameAsAuthor
+ ? fetchedItem.mpName || item.author // the Official Account itself. if your route return articles from different accounts, you may want to use this
+ : fetchedItem.author || item.author; // the real author of the article. if your route return articles from a certain account, use this
+ break;
+ case 'link':
+ item.link = skipLink ? item.link : fetchedItem.link || item.link;
+ break;
+ default:
+ item[key] = item[key] || fetchedItem[key];
+ }
}
return item;
};
-export { fixArticleContent, fetchArticle, finishArticleItem, normalizeUrl };
+const exportedForTestingOnly = { ExtractMetadata, showTypeMapReverse };
+export { exportedForTestingOnly, fixArticleContent, fetchArticle, finishArticleItem, normalizeUrl };
diff --git a/package.json b/package.json
index 7aa19c12e21c95..bf4cec03fa882b 100644
--- a/package.json
+++ b/package.json
@@ -40,12 +40,12 @@
},
"lint-staged": {
"*.js": [
- "eslint --cache --fix",
- "prettier --ignore-unknown --ignore-path ./.gitignore --write"
+ "prettier --ignore-unknown --ignore-path ./.gitignore --write",
+ "eslint --cache --fix"
],
"*.{ts,tsx}": [
- "eslint --cache --fix",
- "prettier --ignore-unknown --ignore-path ./.gitignore --write"
+ "prettier --ignore-unknown --ignore-path ./.gitignore --write",
+ "eslint --cache --fix"
],
"*.yml": "eslint --cache --fix"
},
@@ -81,7 +81,7 @@
"iconv-lite": "0.6.3",
"imapflow": "1.0.159",
"instagram-private-api": "1.46.1",
- "ioredis": "5.3.2",
+ "ioredis": "5.4.1",
"ip-regex": "5.0.0",
"jsdom": "24.0.0",
"json-bigint": "1.0.0",
@@ -171,7 +171,7 @@
"js-beautify": "1.15.1",
"lint-staged": "15.2.2",
"mockdate": "3.0.5",
- "msw": "2.2.13",
+ "msw": "2.2.14",
"prettier": "3.2.5",
"remark-parse": "11.0.0",
"supertest": "6.3.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b922ea65859b8c..b953295a4d10af 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -99,8 +99,8 @@ dependencies:
specifier: 1.46.1
version: 1.46.1
ioredis:
- specifier: 5.3.2
- version: 5.3.2
+ specifier: 5.4.1
+ version: 5.4.1
ip-regex:
specifier: 5.0.0
version: 5.0.0
@@ -365,8 +365,8 @@ devDependencies:
specifier: 3.0.5
version: 3.0.5
msw:
- specifier: 2.2.13
- version: 2.2.13(typescript@5.4.5)
+ specifier: 2.2.14
+ version: 2.2.14(typescript@5.4.5)
prettier:
specifier: 3.2.5
version: 3.2.5
@@ -642,8 +642,8 @@ packages:
'@babel/types': 7.24.0
dev: true
- /@babel/helper-string-parser@7.24.1:
- resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
+ /@babel/helper-string-parser@7.23.4:
+ resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
engines: {node: '>=6.9.0'}
dev: true
@@ -685,6 +685,14 @@ packages:
js-tokens: 4.0.0
picocolors: 1.0.0
+ /@babel/parser@7.24.1:
+ resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.24.0
+ dev: true
+
/@babel/parser@7.24.4:
resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==}
engines: {node: '>=6.0.0'}
@@ -1600,8 +1608,8 @@ packages:
resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==}
dev: true
- /@babel/runtime-corejs2@7.24.4:
- resolution: {integrity: sha512-ZCKqyUKt/Coimg+3Kafu43yNetgYnTXzNbEGAgxc81J5sI0qFNbQ613w7PNny+SmijAmGVroL0GDvx5rG/JI5Q==}
+ /@babel/runtime-corejs2@7.23.9:
+ resolution: {integrity: sha512-lwwDy5QfMkO2rmSz9AvLj6j2kWt5a4ulMi1t21vWQEO0kNCFslHoszat8reU/uigIQSUDF31zraZG/qMkcqAlw==}
engines: {node: '>=6.9.0'}
dependencies:
core-js: 2.6.12
@@ -1646,7 +1654,7 @@ packages:
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/helper-string-parser': 7.24.1
+ '@babel/helper-string-parser': 7.23.4
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
dev: true
@@ -2175,7 +2183,7 @@ packages:
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'}
dependencies:
- '@humanwhocodes/object-schema': 2.0.3
+ '@humanwhocodes/object-schema': 2.0.2
debug: 4.3.4
minimatch: 3.1.2
transitivePeerDependencies:
@@ -2187,8 +2195,8 @@ packages:
engines: {node: '>=12.22'}
dev: true
- /@humanwhocodes/object-schema@2.0.3:
- resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+ /@humanwhocodes/object-schema@2.0.2:
+ resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
dev: true
/@ianvs/eslint-stats@2.0.0:
@@ -2199,20 +2207,19 @@ packages:
lodash: 4.17.21
dev: true
- /@inquirer/confirm@3.1.5:
- resolution: {integrity: sha512-6+dwZrpko5vr5EFEQmUbfBVhtu6IsnB8lQNsLHgO9S9fbfS5J6MuUj+NY0h98pPpYZXEazLR7qzypEDqVzf6aQ==}
+ /@inquirer/confirm@3.1.1:
+ resolution: {integrity: sha512-epf2RVHJJxX5qF85U41PBq9qq2KTJW9sKNLx6+bb2/i2rjXgeoHVGUm8kJxZHavrESgXgBLKCABcfOJYIso8cQ==}
engines: {node: '>=18'}
dependencies:
- '@inquirer/core': 8.0.1
- '@inquirer/type': 1.3.0
+ '@inquirer/core': 7.1.1
+ '@inquirer/type': 1.2.1
dev: true
- /@inquirer/core@8.0.1:
- resolution: {integrity: sha512-qJRk1y51Os2ARc11Bg2N6uIwiQ9qBSrmZeuMonaQ/ntFpb4+VlcQ8Gl1TFH67mJLz3HA2nvuave0nbv6Lu8pbg==}
+ /@inquirer/core@7.1.1:
+ resolution: {integrity: sha512-rD1UI3eARN9qJBcLRXPOaZu++Bg+xsk0Tuz1EUOXEW+UbYif1sGjr0Tw7lKejHzKD9IbXE1CEtZ+xR/DrNlQGQ==}
engines: {node: '>=18'}
dependencies:
- '@inquirer/figures': 1.0.1
- '@inquirer/type': 1.3.0
+ '@inquirer/type': 1.2.1
'@types/mute-stream': 0.0.4
'@types/node': 20.12.7
'@types/wrap-ansi': 3.0.0
@@ -2220,19 +2227,15 @@ packages:
chalk: 4.1.2
cli-spinners: 2.9.2
cli-width: 4.1.0
+ figures: 3.2.0
mute-stream: 1.0.0
signal-exit: 4.1.0
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
dev: true
- /@inquirer/figures@1.0.1:
- resolution: {integrity: sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==}
- engines: {node: '>=18'}
- dev: true
-
- /@inquirer/type@1.3.0:
- resolution: {integrity: sha512-RW4Zf6RCTnInRaOZuRHTqAUl+v6VJuQGglir7nW2BkT3OXOphMhkIFhvFRjorBx2l0VwtC/M4No8vYR65TdN9Q==}
+ /@inquirer/type@1.2.1:
+ resolution: {integrity: sha512-xwMfkPAxeo8Ji/IxfUSqzRi0/+F2GIqJmpc5/thelgMGsjNZcjDDRBO9TLXT1s/hdx/mK5QbVIvgoLIFgXhTMQ==}
engines: {node: '>=18'}
dev: true
@@ -2294,15 +2297,15 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
- /@lifeomic/attempt@3.1.0:
- resolution: {integrity: sha512-QZqem4QuAnAyzfz+Gj5/+SLxqwCAw2qmt7732ZXodr6VDWGeYLG6w1i/vYLa55JQM9wRuBKLmXmiZ2P0LtE5rw==}
+ /@lifeomic/attempt@3.0.3:
+ resolution: {integrity: sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==}
dev: false
/@mapbox/node-pre-gyp@1.0.11:
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
hasBin: true
dependencies:
- detect-libc: 2.0.3
+ detect-libc: 2.0.2
https-proxy-agent: 5.0.1
make-dir: 3.1.0
node-fetch: 2.7.0
@@ -2310,7 +2313,7 @@ packages:
npmlog: 5.0.1
rimraf: 3.0.2
semver: 7.6.0
- tar: 6.2.1
+ tar: 6.2.0
transitivePeerDependencies:
- encoding
- supports-color
@@ -2455,7 +2458,7 @@ packages:
engines: {node: '>=10'}
hasBin: true
dependencies:
- '@babel/runtime-corejs2': 7.24.4
+ '@babel/runtime-corejs2': 7.23.9
'@postlight/ci-failed-test-reporter': 1.0.26
cheerio: 0.22.0
difflib: github.com/postlight/difflib.js/32e8e38c7fcd935241b9baab71bb432fd9b166ed
@@ -2465,7 +2468,7 @@ packages:
moment-parseformat: 3.0.0
postman-request: 2.88.1-postman.33
string-direction: 0.1.2
- turndown: 7.1.3
+ turndown: 7.1.2
valid-url: 1.0.9
wuzzy: 0.1.8
yargs-parser: 15.0.3
@@ -3020,8 +3023,8 @@ packages:
resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==}
dev: true
- /@types/superagent@8.1.6:
- resolution: {integrity: sha512-yzBOv+6meEHSzV2NThYYOA6RtqvPr3Hbob9ZLp3i07SH27CrYVfm8CrF7ydTmidtelsFiKx2I4gZAiAOamGgvQ==}
+ /@types/superagent@8.1.3:
+ resolution: {integrity: sha512-R/CfN6w2XsixLb1Ii8INfn+BT9sGPvw74OavfkW4SwY+jeUcAwLZv2+bXLJkndnimxjEBm0RPHgcjW9pLCa8cw==}
dependencies:
'@types/cookiejar': 2.1.5
'@types/methods': 1.1.4
@@ -3032,7 +3035,7 @@ packages:
resolution: {integrity: sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==}
dependencies:
'@types/methods': 1.1.4
- '@types/superagent': 8.1.6
+ '@types/superagent': 8.1.3
dev: true
/@types/tiny-async-pool@2.0.3:
@@ -3276,7 +3279,7 @@ packages:
'@mapbox/node-pre-gyp': 1.0.11
'@rollup/pluginutils': 4.2.1
acorn: 8.11.3
- acorn-import-attributes: 1.9.5(acorn@8.11.3)
+ acorn-import-attributes: 1.9.2(acorn@8.11.3)
async-sema: 3.1.1
bindings: 1.5.0
estree-walker: 2.0.2
@@ -3301,12 +3304,12 @@ packages:
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
istanbul-lib-source-maps: 5.0.4
- istanbul-reports: 3.1.7
- magic-string: 0.30.9
- magicast: 0.3.4
+ istanbul-reports: 3.1.6
+ magic-string: 0.30.8
+ magicast: 0.3.3
picocolors: 1.0.0
std-env: 3.7.0
- strip-literal: 2.1.0
+ strip-literal: 2.0.0
test-exclude: 6.0.0
vitest: 1.5.0(@types/node@20.12.7)(jsdom@24.0.0)
transitivePeerDependencies:
@@ -3332,7 +3335,7 @@ packages:
/@vitest/snapshot@1.5.0:
resolution: {integrity: sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==}
dependencies:
- magic-string: 0.30.9
+ magic-string: 0.30.8
pathe: 1.1.2
pretty-format: 29.7.0
dev: true
@@ -3368,8 +3371,8 @@ packages:
event-target-shim: 5.0.1
dev: false
- /acorn-import-attributes@1.9.5(acorn@8.11.3):
- resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
+ /acorn-import-attributes@1.9.2(acorn@8.11.3):
+ resolution: {integrity: sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==}
peerDependencies:
acorn: ^8
dependencies:
@@ -3414,6 +3417,14 @@ packages:
- supports-color
dev: true
+ /agent-base@7.1.0:
+ resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==}
+ engines: {node: '>= 14'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+
/agent-base@7.1.1:
resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
engines: {node: '>= 14'}
@@ -3437,9 +3448,11 @@ packages:
type-fest: 0.21.3
dev: true
- /ansi-escapes@6.2.1:
- resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==}
+ /ansi-escapes@6.2.0:
+ resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==}
engines: {node: '>=14.16'}
+ dependencies:
+ type-fest: 3.13.1
dev: true
/ansi-regex@2.1.1:
@@ -3638,8 +3651,8 @@ packages:
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
- /bare-events@2.2.2:
- resolution: {integrity: sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==}
+ /bare-events@2.2.0:
+ resolution: {integrity: sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==}
requiresBuild: true
dev: false
optional: true
@@ -3648,14 +3661,14 @@ packages:
resolution: {integrity: sha512-amG72llr9pstfXOBOHve1WjiuKKAMnebcmMbPWDZ7BCevAoJLpugjuAPRsDINEyjT0a6tbaVx3DctkXIRbLuJw==}
requiresBuild: true
dependencies:
- bare-events: 2.2.2
+ bare-events: 2.2.0
bare-path: 2.1.1
- streamx: 2.16.1
+ streamx: 2.15.8
dev: false
optional: true
- /bare-os@2.2.1:
- resolution: {integrity: sha512-OwPyHgBBMkhC29Hl3O4/YfxW9n7mdTr2+SsO29XBWKKJsbgj3mnorDB80r5TiCQgQstgE5ga1qNYrpes6NvX2w==}
+ /bare-os@2.2.0:
+ resolution: {integrity: sha512-hD0rOPfYWOMpVirTACt4/nK8mC55La12K5fY1ij8HAdfQakD62M+H4o4tpfKzVGLgRDTuk3vjA4GqGXXCeFbag==}
requiresBuild: true
dev: false
optional: true
@@ -3664,15 +3677,15 @@ packages:
resolution: {integrity: sha512-OHM+iwRDRMDBsSW7kl3dO62JyHdBKO3B25FB9vNQBPcGHMo4+eA8Yj41Lfbk3pS/seDY+siNge0LdRTulAau/A==}
requiresBuild: true
dependencies:
- bare-os: 2.2.1
+ bare-os: 2.2.0
dev: false
optional: true
/base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
- /basic-ftp@5.0.5:
- resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==}
+ /basic-ftp@5.0.4:
+ resolution: {integrity: sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA==}
engines: {node: '>=10.0.0'}
dev: false
@@ -3751,8 +3764,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
- caniuse-lite: 1.0.30001610
- electron-to-chromium: 1.4.737
+ caniuse-lite: 1.0.30001587
+ electron-to-chromium: 1.4.669
node-releases: 2.0.14
update-browserslist-db: 1.0.13(browserslist@4.23.0)
dev: true
@@ -3809,7 +3822,7 @@ packages:
http-cache-semantics: 4.1.1
keyv: 4.5.4
mimic-response: 4.0.0
- normalize-url: 8.0.1
+ normalize-url: 8.0.0
responselike: 3.0.0
/call-bind@1.0.7:
@@ -3820,7 +3833,7 @@ packages:
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.4
- set-function-length: 1.2.2
+ set-function-length: 1.2.1
/callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
@@ -3853,8 +3866,8 @@ packages:
engines: {node: '>=10'}
dev: false
- /caniuse-lite@1.0.30001610:
- resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==}
+ /caniuse-lite@1.0.30001587:
+ resolution: {integrity: sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==}
dev: true
/caseless@0.12.0:
@@ -4305,12 +4318,11 @@ packages:
resolution: {integrity: sha512-LO/lzYRw134LMDVnLyAf1dHE5tyO6axEFkR3TXjQIOmMkAM9YL6QsiUwuXzZAmFnuDJcs4hayOgyIYtViXFrLw==}
dev: false
- /d@1.0.2:
- resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
- engines: {node: '>=0.12'}
+ /d@1.0.1:
+ resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==}
dependencies:
es5-ext: 0.10.64
- type: 2.7.2
+ type: 1.2.0
dev: false
/dashdash@1.14.1:
@@ -4460,8 +4472,8 @@ packages:
resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==}
dev: false
- /detect-libc@2.0.3:
- resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ /detect-libc@2.0.2:
+ resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
engines: {node: '>=8'}
dev: true
@@ -4625,8 +4637,8 @@ packages:
semver: 7.6.0
dev: true
- /electron-to-chromium@1.4.737:
- resolution: {integrity: sha512-QvLTxaLHKdy5YxvixAw/FfHq2eWLUL9KvsPjp0aHK1gI5d3EDuDgITkvj0nFO2c6zUY3ZqVAJQiBYyQP9tQpfw==}
+ /electron-to-chromium@1.4.669:
+ resolution: {integrity: sha512-E2SmpffFPrZhBSgf8ibqanRS2mpuk3FIRDzLDwt7WFpfgJMKDHJs0hmacyP0PS1cWsq0dVkwIIzlscNaterkPg==}
dev: true
/ellipsize@0.1.0:
@@ -4710,7 +4722,7 @@ packages:
requiresBuild: true
dependencies:
es6-iterator: 2.0.3
- es6-symbol: 3.1.4
+ es6-symbol: 3.1.3
esniff: 2.0.1
next-tick: 1.1.0
dev: false
@@ -4718,16 +4730,15 @@ packages:
/es6-iterator@2.0.3:
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
dependencies:
- d: 1.0.2
+ d: 1.0.1
es5-ext: 0.10.64
- es6-symbol: 3.1.4
+ es6-symbol: 3.1.3
dev: false
- /es6-symbol@3.1.4:
- resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
- engines: {node: '>=0.12'}
+ /es6-symbol@3.1.3:
+ resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==}
dependencies:
- d: 1.0.2
+ d: 1.0.1
ext: 1.7.0
dev: false
@@ -4830,6 +4841,15 @@ packages:
source-map: 0.6.1
dev: false
+ /eslint-compat-utils@0.1.2(eslint@8.57.0):
+ resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ eslint: '>=6.0.0'
+ dependencies:
+ eslint: 8.57.0
+ dev: true
+
/eslint-compat-utils@0.5.0(eslint@8.57.0):
resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==}
engines: {node: '>=12'}
@@ -4887,8 +4907,8 @@ packages:
optionator: 0.9.3
dev: true
- /eslint-plugin-es-x@7.6.0(eslint@8.57.0):
- resolution: {integrity: sha512-I0AmeNgevgaTR7y2lrVCJmGYF0rjoznpDvqV/kIkZSZbZ8Rw3eu4cGlvBBULScfkSOCzqKbff5LR4CNrV7mZHA==}
+ /eslint-plugin-es-x@7.5.0(eslint@8.57.0):
+ resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
eslint: '>=8'
@@ -4896,7 +4916,7 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
'@eslint-community/regexpp': 4.10.0
eslint: 8.57.0
- eslint-compat-utils: 0.5.0(eslint@8.57.0)
+ eslint-compat-utils: 0.1.2(eslint@8.57.0)
dev: true
/eslint-plugin-n@17.2.1(eslint@8.57.0):
@@ -4908,8 +4928,8 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
enhanced-resolve: 5.16.0
eslint: 8.57.0
- eslint-plugin-es-x: 7.6.0(eslint@8.57.0)
- get-tsconfig: 4.7.3
+ eslint-plugin-es-x: 7.5.0(eslint@8.57.0)
+ get-tsconfig: 4.7.2
globals: 14.0.0
ignore: 5.3.1
minimatch: 9.0.4
@@ -5053,7 +5073,7 @@ packages:
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
engines: {node: '>=0.10'}
dependencies:
- d: 1.0.2
+ d: 1.0.1
es5-ext: 0.10.64
event-emitter: 0.3.5
type: 2.7.2
@@ -5119,7 +5139,7 @@ packages:
/event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
dependencies:
- d: 1.0.2
+ d: 1.0.1
es5-ext: 0.10.64
dev: false
@@ -5159,7 +5179,7 @@ packages:
human-signals: 5.0.0
is-stream: 3.0.0
merge-stream: 2.0.0
- npm-run-path: 5.3.0
+ npm-run-path: 5.2.0
onetime: 6.0.0
signal-exit: 4.1.0
strip-final-newline: 3.0.0
@@ -5244,8 +5264,8 @@ packages:
/fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
- /fast-redact@3.5.0:
- resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
+ /fast-redact@3.3.0:
+ resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==}
engines: {node: '>=6'}
dev: false
@@ -5324,13 +5344,13 @@ packages:
resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
engines: {node: ^10.12.0 || >=12.0.0}
dependencies:
- flatted: 3.3.1
+ flatted: 3.2.9
keyv: 4.5.4
rimraf: 3.0.2
dev: true
- /flatted@3.3.1:
- resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+ /flatted@3.2.9:
+ resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
dev: true
/fn.name@1.1.0:
@@ -5407,7 +5427,7 @@ packages:
dezalgo: 1.0.4
hexoid: 1.0.0
once: 1.4.0
- qs: 6.12.1
+ qs: 6.11.2
dev: true
/fs-extra@10.1.0:
@@ -5462,15 +5482,14 @@ packages:
wide-align: 1.1.5
dev: true
- /gaxios@6.5.0:
- resolution: {integrity: sha512-R9QGdv8j4/dlNoQbX3hSaK/S0rkMijqjVvW3YM06CoBdbU/VdKd159j4hePpng0KuE6Lh6JJ7UdmVGJZFcAG1w==}
+ /gaxios@6.2.0:
+ resolution: {integrity: sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==}
engines: {node: '>=14'}
dependencies:
extend: 3.0.2
https-proxy-agent: 7.0.4
is-stream: 2.0.1
node-fetch: 2.7.0
- uuid: 9.0.1
transitivePeerDependencies:
- encoding
- supports-color
@@ -5480,7 +5499,7 @@ packages:
resolution: {integrity: sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==}
engines: {node: '>=14'}
dependencies:
- gaxios: 6.5.0
+ gaxios: 6.2.0
json-bigint: 1.0.0
transitivePeerDependencies:
- encoding
@@ -5511,9 +5530,9 @@ packages:
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
- has-proto: 1.0.3
+ has-proto: 1.0.1
has-symbols: 1.0.3
- hasown: 2.0.2
+ hasown: 2.0.1
/get-stream@3.0.0:
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
@@ -5536,8 +5555,8 @@ packages:
engines: {node: '>=16'}
dev: true
- /get-tsconfig@4.7.3:
- resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==}
+ /get-tsconfig@4.7.2:
+ resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==}
dependencies:
resolve-pkg-maps: 1.0.0
@@ -5545,7 +5564,7 @@ packages:
resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==}
engines: {node: '>= 14'}
dependencies:
- basic-ftp: 5.0.5
+ basic-ftp: 5.0.4
data-uri-to-buffer: 6.0.2
debug: 4.3.4
fs-extra: 11.2.0
@@ -5573,16 +5592,16 @@ packages:
is-glob: 4.0.3
dev: true
- /glob@10.3.12:
- resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==}
+ /glob@10.3.10:
+ resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
dependencies:
foreground-child: 3.1.1
jackspeak: 2.3.6
minimatch: 9.0.4
- minipass: 7.0.4
- path-scurry: 1.10.2
+ minipass: 5.0.0
+ path-scurry: 1.10.1
dev: true
/glob@7.2.3:
@@ -5628,13 +5647,13 @@ packages:
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
dev: true
- /google-auth-library@9.8.0:
- resolution: {integrity: sha512-TJJXFzMlVGRlIH27gYZ6XXyPf5Y3OItsKFfefsDAafNNywYRTkei83nEO29IrYj8GtdHWU78YnW+YZdaZaXIJA==}
+ /google-auth-library@9.6.3:
+ resolution: {integrity: sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==}
engines: {node: '>=14'}
dependencies:
base64-js: 1.5.1
ecdsa-sig-formatter: 1.0.11
- gaxios: 6.5.0
+ gaxios: 6.2.0
gcp-metadata: 6.1.0
gtoken: 7.1.0
jws: 4.0.0
@@ -5643,14 +5662,14 @@ packages:
- supports-color
dev: false
- /googleapis-common@7.1.0:
- resolution: {integrity: sha512-p3KHiWDBBWJEXk6SYauBEvxw5+UmRy7k2scxGtsNv9eHsTbpopJ3/7If4OrNnzJ9XMLg3IlyQXpVp8YPQsStiw==}
+ /googleapis-common@7.0.1:
+ resolution: {integrity: sha512-mgt5zsd7zj5t5QXvDanjWguMdHAcJmmDrF9RkInCecNsyV7S7YtGqm5v2IWONNID88osb7zmx5FtrAP12JfD0w==}
engines: {node: '>=14.0.0'}
dependencies:
extend: 3.0.2
- gaxios: 6.5.0
- google-auth-library: 9.8.0
- qs: 6.12.1
+ gaxios: 6.2.0
+ google-auth-library: 9.6.3
+ qs: 6.11.2
url-template: 2.0.8
uuid: 9.0.1
transitivePeerDependencies:
@@ -5662,8 +5681,8 @@ packages:
resolution: {integrity: sha512-o8LhD1754W6MHWtpwAPeP1WUHgNxuMxCnLMDFlMKAA5kCMTNqX9/eaTXnkkAIv6YRfoKMQ6D1vyR6/biXuhE9g==}
engines: {node: '>=14.0.0'}
dependencies:
- google-auth-library: 9.8.0
- googleapis-common: 7.1.0
+ google-auth-library: 9.6.3
+ googleapis-common: 7.0.1
transitivePeerDependencies:
- encoding
- supports-color
@@ -5724,7 +5743,7 @@ packages:
resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==}
engines: {node: '>=14.0.0'}
dependencies:
- gaxios: 6.5.0
+ gaxios: 6.2.0
jws: 4.0.0
transitivePeerDependencies:
- encoding
@@ -5771,8 +5790,8 @@ packages:
dependencies:
es-define-property: 1.0.0
- /has-proto@1.0.3:
- resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
engines: {node: '>= 0.4'}
/has-symbols@1.0.3:
@@ -5783,8 +5802,8 @@ packages:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
dev: true
- /hasown@2.0.2:
- resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ /hasown@2.0.1:
+ resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
@@ -5886,8 +5905,8 @@ packages:
/http-cache-semantics@4.1.1:
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
- /http-proxy-agent@7.0.2:
- resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ /http-proxy-agent@7.0.1:
+ resolution: {integrity: sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==}
engines: {node: '>= 14'}
dependencies:
agent-base: 7.1.1
@@ -5934,7 +5953,7 @@ packages:
resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==}
engines: {node: '>= 14'}
dependencies:
- agent-base: 7.1.1
+ agent-base: 7.1.0
debug: 4.3.4
transitivePeerDependencies:
- supports-color
@@ -6057,7 +6076,7 @@ packages:
re2:
optional: true
dependencies:
- '@lifeomic/attempt': 3.1.0
+ '@lifeomic/attempt': 3.0.3
'@types/chance': 1.1.6
'@types/request-promise': 4.1.51
bluebird: 3.7.2
@@ -6082,8 +6101,8 @@ packages:
- supports-color
dev: false
- /ioredis@5.3.2:
- resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==}
+ /ioredis@5.4.1:
+ resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==}
engines: {node: '>=12.22.0'}
dependencies:
'@ioredis/commands': 1.2.0
@@ -6138,7 +6157,7 @@ packages:
/is-core-module@2.13.1:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
- hasown: 2.0.2
+ hasown: 2.0.1
dev: true
/is-extendable@0.1.1:
@@ -6279,8 +6298,8 @@ packages:
- supports-color
dev: true
- /istanbul-reports@3.1.7:
- resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
+ /istanbul-reports@3.1.6:
+ resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==}
engines: {node: '>=8'}
dependencies:
html-escaper: 2.0.2
@@ -6303,7 +6322,7 @@ packages:
dependencies:
config-chain: 1.1.13
editorconfig: 1.0.4
- glob: 10.3.12
+ glob: 10.3.10
js-cookie: 3.0.5
nopt: 7.2.0
dev: true
@@ -6320,8 +6339,8 @@ packages:
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
- /js-tokens@9.0.0:
- resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
+ /js-tokens@8.0.3:
+ resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==}
dev: true
/js-yaml@4.1.0:
@@ -6357,7 +6376,7 @@ packages:
decimal.js: 10.4.3
form-data: 4.0.0
html-encoding-sniffer: 4.0.0
- http-proxy-agent: 7.0.2
+ http-proxy-agent: 7.0.1
https-proxy-agent: 7.0.4
is-potential-custom-element-name: 1.0.1
nwsapi: 2.2.7
@@ -6711,7 +6730,7 @@ packages:
resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==}
engines: {node: '>=18'}
dependencies:
- ansi-escapes: 6.2.1
+ ansi-escapes: 6.2.0
cli-cursor: 4.0.0
slice-ansi: 7.1.0
strip-ansi: 7.1.0
@@ -6781,19 +6800,19 @@ packages:
hasBin: true
dev: false
- /magic-string@0.30.9:
- resolution: {integrity: sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==}
+ /magic-string@0.30.8:
+ resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
- /magicast@0.3.4:
- resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==}
+ /magicast@0.3.3:
+ resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==}
dependencies:
- '@babel/parser': 7.24.4
+ '@babel/parser': 7.24.1
'@babel/types': 7.24.0
- source-map-js: 1.2.0
+ source-map-js: 1.0.2
dev: true
/mailparser@3.7.0:
@@ -6935,7 +6954,7 @@ packages:
micromark-util-html-tag-name: 2.0.0
micromark-util-normalize-identifier: 2.0.0
micromark-util-resolve-all: 2.0.0
- micromark-util-subtokenize: 2.0.1
+ micromark-util-subtokenize: 2.0.0
micromark-util-symbol: 2.0.0
micromark-util-types: 2.0.0
dev: true
@@ -7053,8 +7072,8 @@ packages:
micromark-util-symbol: 2.0.0
dev: true
- /micromark-util-subtokenize@2.0.1:
- resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==}
+ /micromark-util-subtokenize@2.0.0:
+ resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==}
dependencies:
devlop: 1.1.0
micromark-util-chunked: 2.0.0
@@ -7087,7 +7106,7 @@ packages:
micromark-util-normalize-identifier: 2.0.0
micromark-util-resolve-all: 2.0.0
micromark-util-sanitize-uri: 2.0.0
- micromark-util-subtokenize: 2.0.1
+ micromark-util-subtokenize: 2.0.0
micromark-util-symbol: 2.0.0
micromark-util-types: 2.0.0
transitivePeerDependencies:
@@ -7185,11 +7204,6 @@ packages:
engines: {node: '>=8'}
dev: true
- /minipass@7.0.4:
- resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
- engines: {node: '>=16 || 14 >=14.17'}
- dev: true
-
/minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
@@ -7252,8 +7266,8 @@ packages:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: false
- /msw@2.2.13(typescript@5.4.5):
- resolution: {integrity: sha512-ljFf1xZsU0b4zv1l7xzEmC6OZA6yD06hcx0H+dc8V0VypaP3HGYJa1rMLjQbBWl32ptGhcfwcPCWDB1wjmsftw==}
+ /msw@2.2.14(typescript@5.4.5):
+ resolution: {integrity: sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==}
engines: {node: '>=18'}
hasBin: true
requiresBuild: true
@@ -7265,7 +7279,7 @@ packages:
dependencies:
'@bundled-es-modules/cookie': 2.0.0
'@bundled-es-modules/statuses': 1.0.1
- '@inquirer/confirm': 3.1.5
+ '@inquirer/confirm': 3.1.1
'@mswjs/cookies': 1.1.0
'@mswjs/interceptors': 0.26.15
'@open-draft/until': 2.1.0
@@ -7276,9 +7290,9 @@ packages:
headers-polyfill: 4.0.3
is-node-process: 1.2.0
outvariant: 1.4.2
- path-to-regexp: 6.2.2
+ path-to-regexp: 6.2.1
strict-event-emitter: 0.5.1
- type-fest: 4.15.0
+ type-fest: 4.14.0
typescript: 5.4.5
yargs: 17.7.2
dev: true
@@ -7381,8 +7395,8 @@ packages:
validate-npm-package-license: 3.0.4
dev: true
- /normalize-url@8.0.1:
- resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
+ /normalize-url@8.0.0:
+ resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==}
engines: {node: '>=14.16'}
/notion-to-md@3.1.1:
@@ -7402,8 +7416,8 @@ packages:
path-key: 2.0.1
dev: false
- /npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
+ /npm-run-path@5.2.0:
+ resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
path-key: 4.0.0
@@ -7609,10 +7623,10 @@ packages:
engines: {node: '>= 14'}
dependencies:
'@tootallnate/quickjs-emscripten': 0.23.0
- agent-base: 7.1.1
+ agent-base: 7.1.0
debug: 4.3.4
get-uri: 6.0.3
- http-proxy-agent: 7.0.2
+ http-proxy-agent: 7.0.1
https-proxy-agent: 7.0.4
pac-resolver: 7.0.1
socks-proxy-agent: 8.0.3
@@ -7707,16 +7721,16 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
- /path-scurry@1.10.2:
- resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==}
+ /path-scurry@1.10.1:
+ resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
lru-cache: 10.2.0
- minipass: 7.0.4
+ minipass: 5.0.0
dev: true
- /path-to-regexp@6.2.2:
- resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==}
+ /path-to-regexp@6.2.1:
+ resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
dev: true
/path-type@4.0.0:
@@ -7779,7 +7793,7 @@ packages:
hasBin: true
dependencies:
atomic-sleep: 1.0.0
- fast-redact: 3.5.0
+ fast-redact: 3.3.0
on-exit-leak-free: 2.1.2
pino-abstract-transport: 1.1.0
pino-std-serializers: 6.2.2
@@ -7787,7 +7801,7 @@ packages:
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.4.3
- sonic-boom: 3.8.1
+ sonic-boom: 3.8.0
thread-stream: 2.4.1
dev: false
@@ -7804,6 +7818,15 @@ packages:
engines: {node: '>=4'}
dev: true
+ /postcss@8.4.35:
+ resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: false
+
/postcss@8.4.38:
resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
engines: {node: ^10 || ^12 || >=14}
@@ -7811,6 +7834,7 @@ packages:
nanoid: 3.3.7
picocolors: 1.0.0
source-map-js: 1.2.0
+ dev: true
/postman-request@2.88.1-postman.33:
resolution: {integrity: sha512-uL9sCML4gPH6Z4hreDWbeinKU0p0Ke261nU7OvII95NU22HN6Dk7T/SaVPaj6T4TsQqGKIFw6/woLZnH7ugFNA==}
@@ -7896,7 +7920,7 @@ packages:
dependencies:
agent-base: 7.1.1
debug: 4.3.4
- http-proxy-agent: 7.0.2
+ http-proxy-agent: 7.0.1
https-proxy-agent: 7.0.4
lru-cache: 7.18.3
pac-proxy-agent: 7.0.1
@@ -8077,11 +8101,11 @@ packages:
- utf-8-validate
dev: false
- /qs@6.12.1:
- resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+ /qs@6.11.2:
+ resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==}
engines: {node: '>=0.6'}
dependencies:
- side-channel: 1.0.6
+ side-channel: 1.0.5
/qs@6.5.3:
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
@@ -8472,7 +8496,7 @@ packages:
htmlparser2: 8.0.2
is-plain-object: 5.0.0
parse-srcset: 1.0.2
- postcss: 8.4.38
+ postcss: 8.4.35
dev: false
/sax@1.3.0:
@@ -8512,8 +8536,8 @@ packages:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: true
- /set-function-length@1.2.2:
- resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ /set-function-length@1.2.1:
+ resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==}
engines: {node: '>= 0.4'}
dependencies:
define-data-property: 1.1.4
@@ -8555,8 +8579,8 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
- /side-channel@1.0.6:
- resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
+ /side-channel@1.0.5:
+ resolution: {integrity: sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
@@ -8630,11 +8654,19 @@ packages:
dependencies:
agent-base: 7.1.1
debug: 4.3.4
- socks: 2.8.3
+ socks: 2.8.1
transitivePeerDependencies:
- supports-color
dev: false
+ /socks@2.8.1:
+ resolution: {integrity: sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==}
+ engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
+ dependencies:
+ ip-address: 9.0.5
+ smart-buffer: 4.2.0
+ dev: false
+
/socks@2.8.3:
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
@@ -8643,15 +8675,20 @@ packages:
smart-buffer: 4.2.0
dev: false
- /sonic-boom@3.8.1:
- resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==}
+ /sonic-boom@3.8.0:
+ resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==}
dependencies:
atomic-sleep: 1.0.0
dev: false
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
/source-map-js@1.2.0:
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
engines: {node: '>=0.10.0'}
+ dev: true
/source-map@0.5.7:
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
@@ -8675,14 +8712,14 @@ packages:
spdx-license-ids: 3.0.17
dev: true
- /spdx-exceptions@2.5.0:
- resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
+ /spdx-exceptions@2.4.0:
+ resolution: {integrity: sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==}
dev: true
/spdx-expression-parse@3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
dependencies:
- spdx-exceptions: 2.5.0
+ spdx-exceptions: 2.4.0
spdx-license-ids: 3.0.17
dev: true
@@ -8761,13 +8798,13 @@ packages:
bluebird: 2.11.0
dev: false
- /streamx@2.16.1:
- resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==}
+ /streamx@2.15.8:
+ resolution: {integrity: sha512-6pwMeMY/SuISiRsuS8TeIrAzyFbG5gGPHFQsYjUr/pbBadaL1PCWmzKw+CHZSwainfvcF6Si6cVLq4XTEwswFQ==}
dependencies:
fast-fifo: 1.3.2
queue-tick: 1.0.1
optionalDependencies:
- bare-events: 2.2.2
+ bare-events: 2.2.0
dev: false
/strict-event-emitter@0.5.1:
@@ -8868,10 +8905,10 @@ packages:
engines: {node: '>=8'}
dev: true
- /strip-literal@2.1.0:
- resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
+ /strip-literal@2.0.0:
+ resolution: {integrity: sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==}
dependencies:
- js-tokens: 9.0.0
+ js-tokens: 8.0.3
dev: true
/superagent@8.1.2:
@@ -8886,7 +8923,7 @@ packages:
formidable: 2.1.2
methods: 1.1.2
mime: 2.6.0
- qs: 6.12.1
+ qs: 6.11.2
semver: 7.6.0
transitivePeerDependencies:
- supports-color
@@ -8963,11 +9000,11 @@ packages:
dependencies:
b4a: 1.6.6
fast-fifo: 1.3.2
- streamx: 2.16.1
+ streamx: 2.15.8
dev: false
- /tar@6.2.1:
- resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
+ /tar@6.2.0:
+ resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==}
engines: {node: '>=10'}
dependencies:
chownr: 2.0.0
@@ -8991,7 +9028,7 @@ packages:
pako: 2.1.0
path-browserify: 1.0.1
real-cancellable-promise: 1.2.0
- socks: 2.8.3
+ socks: 2.8.1
store2: 2.14.3
ts-custom-error: 3.3.1
websocket: 1.0.34
@@ -9037,12 +9074,12 @@ packages:
resolution: {integrity: sha512-ltAHPh/9k0STRQqaoUX52NH4ZQYAJz24ZAEwf1Zm+HYg3l9OXTWeqWKyYsHu40wF/F0rxd2N2bk5sLvX2qlSvg==}
dev: false
- /tinybench@2.7.0:
- resolution: {integrity: sha512-Qgayeb106x2o4hNzNjsZEfFziw8IbKqtbXBjVh7VIZfBxfD5M4gWtpyx5+YTae2gJ6Y6Dz/KLepiv16RFeQWNA==}
+ /tinybench@2.6.0:
+ resolution: {integrity: sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==}
dev: true
- /tinypool@0.8.4:
- resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==}
+ /tinypool@0.8.3:
+ resolution: {integrity: sha512-Ud7uepAklqRH1bvwy22ynrliC7Dljz7Tm8M/0RBUW+YRa4YHhZ6e4PpgE+fu1zr/WqB1kbeuVrdfeuyIBpy4tw==}
engines: {node: '>=14.0.0'}
dev: true
@@ -9071,11 +9108,6 @@ packages:
hasBin: true
dev: false
- /tlds@1.252.0:
- resolution: {integrity: sha512-GA16+8HXvqtfEnw/DTcwB0UU354QE1n3+wh08oFjr6Znl7ZLAeUgYzCcK+/CCrOyE0vnHR8/pu3XXG3vDijXpQ==}
- hasBin: true
- dev: false
-
/tldts-core@6.1.16:
resolution: {integrity: sha512-rxnuCux+zn3hMF57nBzr1m1qGZH7Od2ErbDZjVm04fk76cEynTg3zqvHjx5BsBl8lvRTjpzIhsEGMHDH/Hr2Vw==}
dev: false
@@ -9212,7 +9244,7 @@ packages:
hasBin: true
dependencies:
esbuild: 0.19.12
- get-tsconfig: 4.7.3
+ get-tsconfig: 4.7.2
optionalDependencies:
fsevents: 2.3.3
dev: false
@@ -9223,8 +9255,8 @@ packages:
safe-buffer: 5.2.1
dev: false
- /turndown@7.1.3:
- resolution: {integrity: sha512-Z3/iJ6IWh8VBiACWQJaA5ulPQE5E1QwvBHj00uGzdQxdRnd8fh1DPqNOJqzQDu6DkOstORrtXzf/9adB+vMtEA==}
+ /turndown@7.1.2:
+ resolution: {integrity: sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==}
dependencies:
domino: 2.1.6
dev: false
@@ -9281,11 +9313,20 @@ packages:
engines: {node: '>=10'}
dev: false
- /type-fest@4.15.0:
- resolution: {integrity: sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==}
+ /type-fest@3.13.1:
+ resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
+ engines: {node: '>=14.16'}
+ dev: true
+
+ /type-fest@4.14.0:
+ resolution: {integrity: sha512-on5/Cw89wwqGZQu+yWO0gGMGu8VNxsaW9SB2HE8yJjllEk7IDTwnSN1dUVldYILhYPN5HzD7WAaw2cc/jBfn0Q==}
engines: {node: '>=16'}
dev: true
+ /type@1.2.0:
+ resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==}
+ dev: false
+
/type@2.7.2:
resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==}
dev: false
@@ -9417,7 +9458,7 @@ packages:
optional: true
dependencies:
ip-regex: 4.3.0
- tlds: 1.252.0
+ tlds: 1.250.0
dev: false
/url-template@2.0.8:
@@ -9609,13 +9650,13 @@ packages:
execa: 8.0.1
jsdom: 24.0.0
local-pkg: 0.5.0
- magic-string: 0.30.9
+ magic-string: 0.30.8
pathe: 1.1.2
picocolors: 1.0.0
std-env: 3.7.0
- strip-literal: 2.1.0
- tinybench: 2.7.0
- tinypool: 0.8.4
+ strip-literal: 2.0.0
+ tinybench: 2.6.0
+ tinypool: 0.8.3
vite: 5.2.9(@types/node@20.12.7)
vite-node: 1.5.0(@types/node@20.12.7)
why-is-node-running: 2.2.2
@@ -9859,7 +9900,7 @@ packages:
dependencies:
eslint-visitor-keys: 3.4.3
lodash: 4.17.21
- yaml: 2.4.1
+ yaml: 2.3.4
dev: true
/yaml@2.3.4:
@@ -9871,6 +9912,7 @@ packages:
resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==}
engines: {node: '>= 14'}
hasBin: true
+ dev: false
/yargs-parser@15.0.3:
resolution: {integrity: sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==}