diff --git a/.eslintignore b/.eslintignore index cc924c6b4..aa0777f45 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,6 @@ build/* dist/* lambda/* +**/*.ts +cdk/node_modules/* +cdk/cdk.out/* diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..a45fd52cc --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3483ee99e..9ad779c3e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,12 +2,16 @@ ## Initial Setup +Use the Node version from `.nvmrc` (`nvm use`). Yarn 1 is pinned via `packageManager` in `package.json`, so corepack picks it up automatically. + To install the dependencies, run: ```sh yarn install ``` +Build failures for the optional native modules `printer` and `snappy` can be ignored. `printer` is only needed for `yarn start:printer` and requires `libcups2-dev`. + Copy the file `.env.example` to `.env`: ```sh diff --git a/cdk/.nvmrc b/cdk/.nvmrc new file mode 100644 index 000000000..a45fd52cc --- /dev/null +++ b/cdk/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/cdk/DEPLOYMENT.md b/cdk/DEPLOYMENT.md index ae12a9273..d93ac9746 100644 --- a/cdk/DEPLOYMENT.md +++ b/cdk/DEPLOYMENT.md @@ -57,7 +57,7 @@ Die URL im Browser bleibt dabei unverändert. Die Liste der Dateien ist eine All Bewusst **kein** `errorResponses` an der Distribution: Das hätte für alle Behaviors gegolten und auch Fehler von `/api/*` und `/data/*` in „200 + `index.html`" verwandelt. Fehlende Assets und API-Fehler kommen so als echte Fehler beim Frontend an. -Kommt eine weitere eigenständige Seite dazu, muss sie an drei Stellen eingetragen werden: `customHtmlPlugin` in `webpack.config.js`, die Function in `functions/entrypoint-rewrite.js` und die `navigateFallbackDenylist` des Service Workers. +Kommt eine weitere eigenständige Seite dazu, muss sie an drei Stellen eingetragen werden: `customHtmlPlugin` in `webpack.config.js`, die Function in `functions/entrypoint-rewrite.js` und die `denylist` der `NavigationRoute` in `src/service-worker.js`. ### TLS-Zertifikate diff --git a/cdk/functions/entrypoint-rewrite.js b/cdk/functions/entrypoint-rewrite.js index edd991f5c..f8d0503be 100644 --- a/cdk/functions/entrypoint-rewrite.js +++ b/cdk/functions/entrypoint-rewrite.js @@ -23,7 +23,7 @@ function handler(event) { // Eigenständige Seiten mit eigener index.html (webpack.config.js, // customHtmlPlugin mit `filename`). Neue Seiten hier, in webpack.config.js - // und in der navigateFallbackDenylist des Service Workers ergänzen. + // und in der denylist der NavigationRoute in src/service-worker.js ergänzen. var pages = { '/teilen': '/teilen/index.html', '/teilen/': '/teilen/index.html', diff --git a/cdk/package-lock.json b/cdk/package-lock.json index ed8e8c7ed..3086f3941 100644 --- a/cdk/package-lock.json +++ b/cdk/package-lock.json @@ -48,6 +48,7 @@ "semver" ], "license": "Apache-2.0", + "peer": true, "dependencies": { "jsonschema": "~1.4.1", "semver": "^7.7.4" @@ -106,6 +107,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1256,6 +1258,7 @@ "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -2288,6 +2291,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -2608,7 +2612,8 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.6.0.tgz", "integrity": "sha512-TxHOnBO5zMo/G76ykzGF/wMpEHu257TbWiIxP9K0Yv/+t70UzgBQiTqjkAsWOPC6jW91DzJI0+ehQV6xDRNBuQ==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -3526,6 +3531,7 @@ "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "30.3.0", "@jest/types": "30.3.0", @@ -5226,6 +5232,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -5301,6 +5308,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 2e60909d7..c8854840c 100644 --- a/package.json +++ b/package.json @@ -41,16 +41,14 @@ "@babel/polyfill": "^7.2.5", "@babel/preset-env": "^7.3.1", "@babel/preset-react": "^7.0.0", - "@babel/register": "^7.4.4", "@storybook/react": "^6.0.0", "@svgr/webpack": "^8.1.0", - "@types/node": "^11.11.3", + "@types/node": "^24.10.1", "arraybuffer-loader": "^1.0.3", "autoprefixer": "^9.5.0", "aws-sdk": "^2.423.0", "babel-eslint": "^10.1.0", "babel-loader": "^8.0.5", - "babel-plugin-import-noop": "^1.0.1", "bowser": "^1.9.3", "chromedriver": "^2.39.0", "classnames": "^2.2.5", @@ -139,15 +137,22 @@ "style-loader": "^0.23.1", "svg-to-image": "^1.1.3", "svgo-loader": "^4.0.0", + "terser-webpack-plugin": "^5.3.10", "text-encoding": "^0.7.0", - "ts-node": "^8.0.2", - "typescript": "^3.2.4", + "ts-node": "^10.9.2", + "typescript": "~5.9.3", "wav-encoder": "^1.3.0", "web-audio-test-api": "^0.5.2", "webpack": "^5.67.0", "webpack-cli": "^5.0.0", "webpack-dev-server": "^4.0.10", "webpack-visualizer-plugin": "^0.1.11", + "workbox-cacheable-response": "^5.1.4", + "workbox-core": "^5.1.4", + "workbox-precaching": "^5.1.4", + "workbox-range-requests": "^5.1.4", + "workbox-routing": "^5.1.4", + "workbox-strategies": "^5.1.4", "workbox-webpack-plugin": "^5.1.3", "xhr": "^2.5.0", "yarn": "^1.9.4" @@ -212,5 +217,6 @@ "last 3 versions", "Safari >= 8", "iOS >= 8" - ] + ], + "packageManager": "yarn@1.22.22" } diff --git a/scripts/generate-s3-sw-precache-plugin/index.js b/scripts/generate-s3-sw-precache-plugin/index.js deleted file mode 100644 index d313840a3..000000000 --- a/scripts/generate-s3-sw-precache-plugin/index.js +++ /dev/null @@ -1,51 +0,0 @@ -require('@babel/polyfill') -require('@babel/register')({ - configFile: false, - babelrc: false, - presets: [['@babel/env', { targets: { node: 8 } }]], - plugins: [['import-noop', { extensions: ['mp3', 'svg', 'jpg'] }]], -}) - -const crypto = require('crypto') -const { getAllAssets } = require('../lib/assets') -const defaultAssets = require('../../src/lib/default-project/').default - -const defaultAssetIDs = defaultAssets.map( - (asset) => `${asset.id}.${asset.dataFormat.toLowerCase()}` -) - -function GenerateS3SWPrecachePlugin(options) { - this.filename = options.filename || 's3-manifest.[hash].js' -} - -GenerateS3SWPrecachePlugin.prototype.apply = function (compiler) { - let filenameTemplate = this.filename - compiler.plugin('emit', function (compilation, callback) { - getAllAssets() - .then((files) => files.filter((file) => !defaultAssetIDs.includes(file))) - .then((files) => { - const list = JSON.stringify(files.map((file) => '/data/assets/' + file)) - const hash = crypto.createHash('md5').update(list, 'utf8').digest('hex') - const filename = filenameTemplate.replace('[hash]', hash) - const absUrl = '/' + filename - - compilation.assets[filename] = { - source: function () { - return `self.__precacheManifest = (self.__precacheManifest || []).concat(${list});` - }, - size: function () { - return this.source().length - }, - } - - const swSource = compilation.assets['service-worker.js'].source - compilation.assets['service-worker.js'].source = function () { - return swSource().replace(filenameTemplate, absUrl) - } - callback() - }) - .catch((e) => callback(e)) - }) -} - -module.exports = GenerateS3SWPrecachePlugin diff --git a/src/components/sharing-toolbox/sharing-toolbox.jsx b/src/components/sharing-toolbox/sharing-toolbox.jsx index e506c5cf7..9597d7563 100644 --- a/src/components/sharing-toolbox/sharing-toolbox.jsx +++ b/src/components/sharing-toolbox/sharing-toolbox.jsx @@ -12,7 +12,7 @@ import VM from 'scratch-vm' import QRCode from 'qrcode.react' import html2canvas from 'html2canvas' import JsPDF from 'jspdf' -import ffmpegWorkerPath from 'file-loader!ffmpeg.js/ffmpeg-worker-mp4' // eslint-disable-line import/no-unresolved +import ffmpegWorkerPath from 'ffmpeg.js/ffmpeg-worker-mp4' import InlineSvg from '../inline-svg/inline-svg.jsx' import Modal from '../modal/modal.jsx' diff --git a/src/service-worker.js b/src/service-worker.js new file mode 100644 index 000000000..73b4df406 --- /dev/null +++ b/src/service-worker.js @@ -0,0 +1,78 @@ +/* eslint-env serviceworker */ +import { + cacheNames, + clientsClaim, + registerQuotaErrorCallback, + skipWaiting, +} from 'workbox-core' +import { + cleanupOutdatedCaches, + createHandlerBoundToURL, + getCacheKeyForURL, + precacheAndRoute, +} from 'workbox-precaching' +import { NavigationRoute, registerRoute } from 'workbox-routing' +import { CacheFirst, NetworkFirst } from 'workbox-strategies' +import { CacheableResponsePlugin } from 'workbox-cacheable-response' +import { RangeRequestsPlugin } from 'workbox-range-requests' + +skipWaiting() +clientsClaim() + +// Safari requests videos with Range headers, which the precache route cannot +// answer. Registered before it; ignoreSearch matches the revisioned cache keys. +registerRoute( + /\.mp4$/, + new CacheFirst({ + cacheName: cacheNames.precache, + matchOptions: { ignoreSearch: true }, + plugins: [new RangeRequestsPlugin()], + }) +) + +precacheAndRoute(self.__WB_MANIFEST) +cleanupOutdatedCaches() + +// Serve the precached settings page for /settings too. The precache route +// only appends index.html to URLs ending in a slash. +registerRoute( + new NavigationRoute(createHandlerBoundToURL('/settings/index.html'), { + allowlist: [/^\/settings\/?$/], + }) +) + +// /teilen und /settings sind eigene Seiten, nicht Teil der Haupt-SPA +// Neu hinzukommende Seiten müssen hier, in webpack.config.js und in +// cdk/functions/entrypoint-rewrite.js gepflegt werden! +registerRoute( + new NavigationRoute(createHandlerBoundToURL('/index.html'), { + denylist: [/^\/data\//, /^\/teilen/, /^\/settings/], + }) +) + +// Media that is not precached, e.g. assets uploaded by users. The router's +// fetch listener runs before the precache listener, so skip precached URLs. +registerRoute( + ({ url }) => + (url.pathname.startsWith('/data/assets/') || + url.pathname.startsWith('/static/assets')) && + !getCacheKeyForURL(url.href), + new CacheFirst({ + cacheName: 'assets', + plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], + }) +) + +registerRoute( + /data\/projects\/[^/]+\/index\.json$/, + new NetworkFirst({ cacheName: 'projects' }) +) + +// Report quota errors +self.addEventListener('message', (event) => { + if (event.data && event.data.type === 'GET_QUOTA_ERRORS') { + registerQuotaErrorCallback(() => { + event.ports[0].postMessage({ type: 'QUOTA_ERROR' }) + }) + } +}) diff --git a/static/sw-helper.js b/static/sw-helper.js deleted file mode 100644 index 381429e75..000000000 --- a/static/sw-helper.js +++ /dev/null @@ -1,21 +0,0 @@ -/* global workbox */ -// Handle Range requests from Safari correctly -workbox.routing.registerRoute( - /\.mp4$/, - new workbox.strategies.CacheFirst({ - cacheName: workbox.core.cacheNames.precache, - plugins: [new workbox.rangeRequests.Plugin()], - }) -) - -// Report quota errors -self.addEventListener('message', (event) => { - if (event.data && event.data.type === 'GET_QUOTA_ERRORS') { - // eslint-disable-next-line require-await - workbox.core.registerQuotaErrorCallback(async (_e) => { - event.ports[0].postMessage({ - type: 'QUOTA_ERROR', - }) - }) - } -}) diff --git a/tsconfig.json b/tsconfig.json index c0a5567b1..f7a3d7094 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,11 @@ { "compilerOptions": { "module": "commonjs", - "target": "es2016", - "experimentalDecorators": true, - "lib": [ - "esnext", - ], + "target": "es2022", + "lib": ["esnext"], + "types": ["node"], + "skipLibCheck": true, + "experimentalDecorators": true }, - "exclude": [ - "node_modules", - "**/node_modules/*" - ], - "include": [ - "scripts/" - ], + "include": ["scripts/**/*.ts"] } diff --git a/webpack.config.js b/webpack.config.js index 9b3205a4f..716bd33c7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,15 +1,17 @@ require('dotenv').config() +const fs = require('fs') const path = require('path') const webpack = require('webpack') // Plugins const CopyWebpackPlugin = require('copy-webpack-plugin') -const { GenerateSW } = require('workbox-webpack-plugin') +const TerserPlugin = require('terser-webpack-plugin') +const { InjectManifest } = require('workbox-webpack-plugin') // Custom Plugins const customHtmlPlugin = require('./scripts/custom-html-plugin') -// const { getAssetsList } = require('./scripts/generate-s3-sw-precache-plugin') +const { getAllAssets } = require('./scripts/lib/assets') const branch = process.env.BRANCH || process.env.TRAVIS_BRANCH const bucketSuffix = branch === 'production' ? 'prod' : 'staging' @@ -23,6 +25,18 @@ const enableServiceWorker = 'ENABLE_SERVICE_WORKER' in process.env || process.env.NODE_ENV === 'production' +// Precache project media loaded from /data/assets/ for offline mode. +// Default project media is bundled and excluded. +const precacheProjectMedia = async (entries) => { + const bundled = new Set( + fs.readdirSync(path.join(__dirname, 'assets/project-assets')) + ) + const media = (await getAllAssets()) + .filter((name) => !bundled.has(name)) + .map((name) => ({ url: `/data/assets/${name}`, revision: null, size: 0 })) + return { manifest: entries.concat(media), warnings: [] } +} + // fix for Netlify, where we cannot define AWS_REGION in the environment if ('FUNCTIONS_AWS_REGION' in process.env) { process.env.AWS_REGION = process.env.FUNCTIONS_AWS_REGION @@ -161,6 +175,14 @@ module.exports = { include: /node_modules/, type: 'javascript/auto', }, + { + // Prebuilt emscripten worker, shipped as-is and excluded from minification. + test: /ffmpeg\.js[\\/]ffmpeg-worker-mp4\.js$/, + type: 'asset/resource', + generator: { + filename: 'static/ffmpeg-worker-mp4.[contenthash][ext]', + }, + }, { test: require.resolve('zepto'), use: [ @@ -174,6 +196,11 @@ module.exports = { }, optimization: { runtimeChunk: 'single', + minimizer: [ + new TerserPlugin({ + exclude: /ffmpeg-worker-mp4/, + }), + ], }, plugins: [ new webpack.DefinePlugin({ @@ -189,7 +216,7 @@ module.exports = { }), // Eigenständige Seiten neben der Haupt-App. Neue Einträge auch in der // CloudFront Function (cdk/functions/entrypoint-rewrite.js) und in der - // navigateFallbackDenylist des Service Workers unten ergänzen. + // denylist der NavigationRoute in src/service-worker.js ergänzen. customHtmlPlugin({ entrypoint: 'sharingpage', filename: 'teilen/index.html', @@ -229,47 +256,20 @@ module.exports = { ].concat( enableServiceWorker ? [ - new GenerateSW({ - navigateFallback: '/index.html', - // /teilen und /settings sind eigene Seiten, nicht Teil der Haupt-SPA - // Neu hinzukommende Seiten müssen hier und in entrypoint-rewrite.js gepflegt werden! - navigateFallbackDenylist: [/^\/data\//, /^\/teilen/, /^\/settings/], + new InjectManifest({ + swSrc: './src/service-worker.js', + swDest: 'service-worker.js', exclude: [ /\.map$/, /^manifest.*\.js$/, /\/1x1\.gif$/, /^static\/assets\/edu\/beispiel/, + // Shows shared media from /data/sharing/, useless offline + /^teilen\//, ], - runtimeCaching: [ - { - urlPattern: ({ url }) => { - return ( - url.pathname.startsWith('/data/assets/') || - url.pathname.startsWith('/static/assets') - ) - }, - handler: 'CacheFirst', - options: { - cacheName: 'assets', - cacheableResponse: { - statuses: [0, 200], - }, - }, - }, - { - urlPattern: new RegExp(/data\/projects\/[^/]+\/index\.json$/), - handler: 'NetworkFirst', - options: { - cacheName: 'projects', - }, - }, - ], - clientsClaim: true, - skipWaiting: true, - importScripts: ['/static/sw-helper.js'], - cleanupOutdatedCaches: true, - excludeChunks: ['settings', 'sharingpage', 'mobile-screen'], + excludeChunks: ['sharingpage', 'mobile-screen'], maximumFileSizeToCacheInBytes: 19 * 1024 * 1024, + manifestTransforms: [precacheProjectMedia], }), ] : [] diff --git a/yarn.lock b/yarn.lock index ca22d2ce4..6b6b1888f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1178,7 +1178,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.24.7" "@babel/plugin-transform-typescript" "^7.24.7" -"@babel/register@^7.12.1", "@babel/register@^7.4.4": +"@babel/register@^7.12.1": version "7.24.6" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.24.6.tgz#59e21dcc79e1d04eed5377633b0f88029a6bef9e" integrity sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w== @@ -1259,6 +1259,13 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -2032,7 +2039,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -2055,6 +2062,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -3289,6 +3304,26 @@ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tsconfig/node10@^1.0.7": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.13.tgz#56105a9a8c786e8f15e35746879cf2d52275485b" + integrity sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@types/babel__core@*", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -3597,16 +3632,18 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== -"@types/node@^11.11.3": - version "11.15.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.15.54.tgz#59ed60e7b0d56905a654292e8d73275034eb6283" - integrity sha512-1RWYiq+5UfozGsU6MwJyFX6BtktcT10XRjvcAQmskCtMcW3tPske88lM/nHv7BQG1w9KBXI1zPGuu5PnNCX14g== - "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0": version "16.18.105" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.105.tgz#7147176852774ec4d6dd626803888adf6b999feb" integrity sha512-w2d0Z9yMk07uH3+Cx0N8lqFyi3yjXZxlbYappPj+AsOlT02OyxyiuNoNHdGt6EuiSm8Wtgp2YV7vWg+GMFrvFA== +"@types/node@^24.10.1": + version "24.19.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.19.1.tgz#3a1c3ed9e9fc94fe48d4a72d83dfd0bfcf379c62" + integrity sha512-aS3/DG0oM05K0RIXXP+hKjinGG5IgSSVGzswZxW3O0sS3pH4/fycXundUC9XsszgKCk4gHXylTEK6hyFxVxnoQ== + dependencies: + undici-types ">=7.24.0 <7.24.7" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" @@ -4135,6 +4172,13 @@ acorn-walk@^7.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.3.5" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.5.tgz#8a6b8ca8fc5b34685af15dabb44118663c296496" + integrity sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw== + dependencies: + acorn "^8.11.0" + acorn@^5.2.1: version "5.7.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" @@ -4150,6 +4194,11 @@ acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.11.0, acorn@^8.4.1: + version "8.19.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.19.0.tgz#6b26fd97ce1cc9dc50bdf7ad305e9f1384d4f28a" + integrity sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw== + acorn@^8.7.1, acorn@^8.8.2: version "8.12.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" @@ -4977,11 +5026,6 @@ babel-plugin-formatjs@^10.5.16: "@types/babel__traverse" "^7.1.7" tslib "^2.4.0" -babel-plugin-import-noop@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-import-noop/-/babel-plugin-import-noop-1.0.1.tgz#ceb9afa4006de68579fe676afc77dc1899a146eb" - integrity sha512-LcEOxEZ+/QZvO0BqTuDfOg6dISFEZjIJ2kep+kaVSl/D4MtiYy/TvZgqe5P19atn6nG0HPpvVz6n8Gl5Ab/XXw== - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -6692,6 +6736,11 @@ create-react-context@^0.2.2: fbjs "^0.8.0" gud "^1.0.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cron-parser@^4.2.0: version "4.9.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.9.0.tgz#0340694af3e46a0894978c6f52a6dbb5c0f11ad5" @@ -16893,7 +16942,7 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@~0.5.12, source-map-support@~0.5.20: +source-map-support@^0.5.16, source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -18130,15 +18179,23 @@ ts-dedent@^2.0.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== -ts-node@^8.0.2: - version "8.10.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" - integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== - dependencies: +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" arg "^4.1.0" + create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - source-map-support "^0.5.17" + v8-compile-cache-lib "^3.0.1" yn "3.1.1" ts-pnp@^1.1.6: @@ -18316,10 +18373,10 @@ typescript@5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== -typescript@^3.2.4: - version "3.9.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" - integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== +typescript@~5.9.3: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== ua-parser-js@^0.7.30, ua-parser-js@^0.7.9: version "0.7.38" @@ -18354,6 +18411,11 @@ unbzip2-stream@^1.0.9: buffer "^5.2.1" through "^2.3.8" +"undici-types@>=7.24.0 <7.24.7": + version "7.24.6" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.24.6.tgz#61275b485d7fd4e9d269c7cf04ec2873c9cc0f91" + integrity sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg== + undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" @@ -18722,6 +18784,11 @@ uuid@^8.3.1, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.4.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128"