diff --git a/agents.md b/agents.md
new file mode 100644
index 000000000..ddc5010f6
--- /dev/null
+++ b/agents.md
@@ -0,0 +1,41 @@
+# Agents
+
+## Success Criteria for Feed Processing
+
+The fulltext RSS proxy must be able to process the following feeds without any issue, with full content retrieved, and essential fields kept:
+
+### Test Feeds
+
+1. **UN News RSS** — `https://news.un.org/feed/subscribe/en/news/all/rss.xml`
+ - Standard RSS 2.0 feed
+
+2. **FreshRSS Atom** — `https://github.com/FreshRSS/FreshRSS/releases.atom`
+ - Atom feed format
+ - Author is in `...` (mapped to `item.author` by rss-parser, not `item.creator`)
+ - Entry ID is in `` (mapped to `item.id`, not `item.guid`)
+
+3. **AliasVault RSS** — `https://www.aliasvault.net/rss.xml`
+ - RSS 2.0 with `` elements (Dublin Core namespace)
+ - Has categories per item
+ - `item.creator` maps directly from rss-parser
+
+### Essential Fields
+
+For each feed item in the output:
+
+| Field | RSS Output | JSON Feed Output |
+|-------|-----------|-----------------|
+| Title | `` | `title` |
+| Link | `` | `url` |
+| Date | `` | `date_published` |
+| Full content | `` | `content_html` |
+| Description | `` | `summary` |
+| Author/Creator | `` | `authors[].name` |
+| Categories | `` | `tags` |
+| GUID/ID | `` | `id` |
+
+### Author Handling
+
+- RSS feeds with ``: mapped via `item.creator` from rss-parser
+- Atom feeds with ``: mapped via `item.author` from rss-parser (fallback when `item.creator` is absent)
+- Output as `` in RSS and `authors` array in JSON Feed
diff --git a/package.json b/package.json
index cd6d8c400..c9ae5ef5a 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"@types/cypress": "^1.1.3",
"@types/express": "^4.17.17",
"@types/jest": "^27.5.2",
+ "@types/node": "^22",
"@types/redis": "2.8.32",
"@types/xml2js": "^0.4.11",
"@whtsky/prettier-config": "^1.0.1",
@@ -31,7 +32,7 @@
"tailwindcss": "3.2.7",
"ts-jest": "^29.4.6",
"ts-node": "^10.9.1",
- "typescript": "^4.9.5"
+ "typescript": "^5.0.0"
},
"dependencies": {
"@postlight/parser": "^2.2.3",
@@ -39,7 +40,7 @@
"@sentry/node": "^7.29.0",
"crypto-js": "^4.1.1",
"express": "^4.18.2",
- "feed": "^4.2.2",
+ "feedsmith": "^2.9.1",
"redis": "3.1.2",
"rss-parser": "^3.12.0"
},
diff --git a/src/app.ts b/src/app.ts
index 475800ecc..30e93a4a9 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -1,8 +1,7 @@
import express from 'express'
import bodyParser from 'body-parser'
import Parser from 'rss-parser'
-import { Feed } from 'feed'
-import type { FeedOptions, Item } from 'feed/lib/typings'
+import { generateRssFeed, generateJsonFeed } from 'feedsmith'
import * as Sentry from '@sentry/node'
import { RewriteFrames } from '@sentry/integrations'
@@ -48,60 +47,104 @@ app.use(express.static(constants.publicPath))
app.use(bodyParser.urlencoded({ extended: false }))
-async function getFullTextFeed(feedUrl: string, maxItemsPerFeed: number) {
- const parser = new Parser()
+interface FeedData {
+ title: string
+ description?: string
+ link: string
+ image?: string
+ items: Array<{
+ title: string
+ link: string
+ date: Date
+ content?: string
+ description?: string
+ creator?: string
+ categories?: string[]
+ guid?: string
+ }>
+}
+
+async function getFullTextFeed(feedUrl: string, maxItemsPerFeed: number): Promise {
+ const parser = new Parser<{}, { author?: string; id?: string }>()
try {
const feed = await parser.parseURL(feedUrl)
- const feedOptions: FeedOptions = {
- ...feed,
- title: feed.title!,
- description: feed.description,
- link: feedUrl,
- id: feedUrl,
- image: feed.image?.url,
- copyright: '',
- }
- const outputFeed = new Feed(feedOptions)
- const newItems = await Promise.all((feed.items || []).filter(item => !!item.link).slice(0, maxItemsPerFeed).map(async item => {
- const newItem: Item = {
- ...item,
- title: item.title!,
- link: item.link!,
- date: new Date(item.pubDate!),
- }
+ const items = await Promise.all((feed.items || []).filter(item => !!item.link).slice(0, maxItemsPerFeed).map(async item => {
let content: string | undefined = await cache.get(item.link!)
if (!content) {
content = (await parsePageUsingMercury(item.link!)).content
await cache.set(item.link!, content)
}
- newItem.content = content
- return newItem
+ return {
+ ...item,
+ title: item.title!,
+ link: item.link!,
+ date: new Date(item.pubDate || item.isoDate || Date.now()),
+ content,
+ description: item.contentSnippet || item.content,
+ creator: item.creator || item.author,
+ guid: item.guid || item.id,
+ }
}))
- for (const newItem of newItems) {
- outputFeed.addItem(newItem)
+
+ return {
+ title: feed.title!,
+ description: feed.description,
+ link: feedUrl,
+ image: feed.image?.url,
+ items,
}
- return outputFeed
} catch (e) {
if (constants.sentryDsn) {
Sentry.captureException(e)
}
- const outputFeed = new Feed({
- id: `${feedUrl}-failed`,
+ return {
title: `Failed to get fulltext rss for ${feedUrl}.`,
- copyright: '',
- })
- const errorItem: Item = {
- title: `Failed to get fulltext rss for ${feedUrl}.`,
- content: `Exception: ${e}`,
- link: 'https://github.com/whtsky/fulltextrssplz/issues',
- date: new Date(),
+ link: feedUrl,
+ items: [{
+ title: `Failed to get fulltext rss for ${feedUrl}.`,
+ content: `Exception: ${e}`,
+ link: 'https://github.com/whtsky/fulltextrssplz/issues',
+ date: new Date(),
+ }],
}
- outputFeed.addItem(errorItem)
- return outputFeed
}
}
+function feedToRss(data: FeedData): string {
+ return generateRssFeed({
+ ...data,
+ description: data.description || '',
+ image: data.image ? { url: data.image } : undefined,
+ items: data.items.map(item => ({
+ ...item,
+ pubDate: item.date,
+ guid: item.guid ? { value: item.guid } : undefined,
+ dc: item.creator ? { creator: item.creator } : undefined,
+ content: item.content ? { encoded: item.content } : undefined,
+ categories: item.categories?.map(name => ({ name })),
+ })),
+ }, { lenient: true })
+}
+
+function feedToJson(data: FeedData): string {
+ return JSON.stringify(generateJsonFeed({
+ title: data.title,
+ home_page_url: data.link,
+ description: data.description,
+ items: data.items.map(item => ({
+ id: item.guid || item.link,
+ url: item.link,
+ title: item.title,
+ date_published: item.date,
+ content_html: item.content,
+ summary: item.description,
+ authors: item.creator ? [{ name: item.creator }] : undefined,
+ tags: item.categories,
+ })),
+ }, { lenient: true }))
+}
+
app.get('/feed', async (req, res) => {
const feedUrl = req.query.url
@@ -145,7 +188,7 @@ app.get('/feed', async (req, res) => {
}
}
- const outputFeed = await getFullTextFeed(feedUrl, maxItemsPerFeed)
+ const feedData = await getFullTextFeed(feedUrl, maxItemsPerFeed)
if (constants.cacheControlMaxAge > 0) {
res.set('Cache-control', `public, max-age=${constants.cacheControlMaxAge}`)
@@ -153,10 +196,10 @@ app.get('/feed', async (req, res) => {
if (format == Format.RSS) {
res.set('Content-type', 'application/rss+xml;charset=UTF-8')
- res.end(outputFeed.rss2())
+ res.end(feedToRss(feedData))
} else if (format == Format.JSON) {
res.set('Content-type', 'application/json;charset=UTF-8')
- res.end(outputFeed.json1())
+ res.end(feedToJson(feedData))
} else {
res.end('unknown format:' + format)
}
diff --git a/yarn.lock b/yarn.lock
index 3bcf60125..fe29f6a40 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -657,15 +657,15 @@
dependencies:
"@babel/runtime-corejs2" "^7.2.0"
"@postlight/ci-failed-test-reporter" "^1.0"
- browser-request "*"
+ browser-request "github:postlight/browser-request#feat-add-headers-to-response"
cheerio "^0.22.0"
difflib "github:postlight/difflib.js"
ellipsize "0.1.0"
iconv-lite "0.5.0"
- jquery "*"
+ jquery "^3.5.0"
moment "^2.23.0"
moment-parseformat "3.0.0"
- moment-timezone "*"
+ moment-timezone "0.5.37"
postman-request "^2.88.1-postman.31"
string-direction "^0.1.2"
turndown "^7.1.1"
@@ -1001,6 +1001,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.37.tgz#0bfcd173e8e1e328337473a8317e37b3b14fd30d"
integrity sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg==
+"@types/node@^22":
+ version "22.19.15"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.15.tgz#6091d99fdf7c08cb57dc8b1345d407ba9a1df576"
+ integrity sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==
+ dependencies:
+ undici-types "~6.21.0"
+
"@types/prettier@^2.1.5":
version "2.7.2"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0"
@@ -1421,10 +1428,11 @@ brotli@^1.3.3:
dependencies:
base64-js "^1.1.2"
-browser-request@*:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17"
- integrity sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg==
+"browser-request@github:postlight/browser-request#feat-add-headers-to-response":
+ version "0.3.2"
+ resolved "https://codeload.github.com/postlight/browser-request/tar.gz/38faa5b85741aabfca61aa37d1ef044d68969ddf"
+ dependencies:
+ http-headers "^3.0.1"
browserslist@^4.0.0, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5:
version "4.21.5"
@@ -2082,7 +2090,6 @@ diff@^4.0.1:
"difflib@github:postlight/difflib.js":
version "0.2.6"
- uid "32e8e38c7fcd935241b9baab71bb432fd9b166ed"
resolved "https://codeload.github.com/postlight/difflib.js/tar.gz/32e8e38c7fcd935241b9baab71bb432fd9b166ed"
dependencies:
heap ">= 0.2.0"
@@ -2243,6 +2250,11 @@ entities@^2.0.0, entities@^2.0.3:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+entities@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.1.tgz#26e8a88889db63417dcb9a1e79a3f1bc92b5976b"
+ integrity sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==
+
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@@ -2455,6 +2467,21 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+fast-xml-builder@^1.0.0:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz#0c407a1d9d5996336c0cd76f7ff785cac6413017"
+ integrity sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==
+ dependencies:
+ path-expression-matcher "^1.1.3"
+
+fast-xml-parser@~5.4.2:
+ version "5.4.2"
+ resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.4.2.tgz#7fc66463b59260b0c5fd57edf46148a418bde68b"
+ integrity sha512-pw/6pIl4k0CSpElPEJhDppLzaixDEuWui2CUQQBH/ECDf7+y6YwA4Gf7Tyb0Rfe4DIMuZipYj4AEL0nACKglvQ==
+ dependencies:
+ fast-xml-builder "^1.0.0"
+ strnum "^2.1.2"
+
fastq@^1.6.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
@@ -2476,12 +2503,13 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
-feed@^4.2.2:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e"
- integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==
+feedsmith@^2.9.1:
+ version "2.9.1"
+ resolved "https://registry.yarnpkg.com/feedsmith/-/feedsmith-2.9.1.tgz#aeaf00984b7a6b530f125c7b2e2685108ac5ea9a"
+ integrity sha512-XsHf3lv+i3juaUjE4FHB56nKN+lwvjJTmH3ZMVO4yELaeHV/siLygDlmfJXJoMzP9JZC+zYZUhPEH+9tL3ijzQ==
dependencies:
- xml-js "^1.6.11"
+ entities "^7.0.1"
+ fast-xml-parser "~5.4.2"
figures@^3.2.0:
version "3.2.0"
@@ -2780,6 +2808,13 @@ http-errors@2.0.0:
statuses "2.0.1"
toidentifier "1.0.1"
+http-headers@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/http-headers/-/http-headers-3.0.2.tgz#5147771292f0b39d6778d930a3a59a76fc7ef44d"
+ integrity sha512-87E1I+2Wg4dxxz4rcxElo3dxO/w1ZtgL1yA0Sb6vH3qU16vRKq1NjWQv9SCY3ly2OQROcoxHZOUpmelS+k6wOw==
+ dependencies:
+ next-line "^1.1.0"
+
http-signature@~1.3.1, http-signature@~1.3.6:
version "1.3.6"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9"
@@ -3442,10 +3477,10 @@ joi@^17.7.0:
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
-jquery@*:
- version "3.6.4"
- resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.4.tgz#ba065c188142100be4833699852bf7c24dc0252f"
- integrity sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ==
+jquery@^3.5.0:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de"
+ integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
js-tokens@^4.0.0:
version "4.0.0"
@@ -3814,14 +3849,19 @@ moment-parseformat@3.0.0:
resolved "https://registry.yarnpkg.com/moment-parseformat/-/moment-parseformat-3.0.0.tgz#3a1dc438b4bc073b7e93cc298cfb6c5daac26dba"
integrity sha512-dVgXe6b6DLnv4CHG7a1zUe5mSXaIZ3c6lSHm/EKeVeQI2/4pwe0VRde8OyoCE1Ro2lKT5P6uT9JElF7KDLV+jw==
-moment-timezone@*:
- version "0.5.41"
- resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.41.tgz#a7ad3285fd24aaf5f93b8119a9d749c8039c64c5"
- integrity sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==
+moment-timezone@0.5.37:
+ version "0.5.37"
+ resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.37.tgz#adf97f719c4e458fdb12e2b4e87b8bec9f4eef1e"
+ integrity sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==
dependencies:
- moment "^2.29.4"
+ moment ">= 2.9.0"
-moment@^2.23.0, moment@^2.29.4:
+"moment@>= 2.9.0":
+ version "2.30.1"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
+ integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
+
+moment@^2.23.0:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
@@ -3861,6 +3901,11 @@ neo-async@^2.6.2:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+next-line@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/next-line/-/next-line-1.1.0.tgz#fcae57853052b6a9bae8208e40dd7d3c2d304603"
+ integrity sha512-+I10J3wKNoKddNxn0CNpoZ3eTZuqxjNM3b1GImVx22+ePI+Y15P8g/j3WsbP0fhzzrFzrtjOAoq5NCCucswXOQ==
+
node-fetch@^2.3.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6"
@@ -4028,6 +4073,11 @@ path-exists@^4.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+path-expression-matcher@^1.1.3:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz#9bdae3787f43b0857b0269e9caaa586c12c8abee"
+ integrity sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==
+
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -4770,7 +4820,7 @@ safe-identifier@^0.4.2:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sax@>=0.6.0, sax@^1.2.4:
+sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@@ -5049,6 +5099,11 @@ strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+strnum@^2.1.2:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.1.tgz#d28f896b4ef9985212494ce8bcf7ca304fad8368"
+ integrity sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==
+
style-inject@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3"
@@ -5308,16 +5363,21 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
-typescript@^4.9.5:
- version "4.9.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
- integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
+typescript@^5.0.0:
+ version "5.9.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
+ integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
uglify-js@^3.1.4:
version "3.19.3"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f"
integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==
+undici-types@~6.21.0:
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
+ integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
+
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
@@ -5495,13 +5555,6 @@ wuzzy@^0.1.4:
dependencies:
lodash "^4.17.15"
-xml-js@^1.6.11:
- version "1.6.11"
- resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9"
- integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==
- dependencies:
- sax "^1.2.4"
-
xml2js@^0.4.19:
version "0.4.23"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"