diff --git a/eslint.config.js b/eslint.config.js index 0877defc..bf8315c1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -12,7 +12,7 @@ export default [ { ignores: ['client/*'] }, { languageOptions: { - sourceType: 'commonjs', + sourceType: 'module', globals: { wiki: 'readonly', ...globals.node, diff --git a/index.js b/index.js index 2c472d71..658e262f 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,11 @@ // Simple file so that if you require this directory // in node it instead requires ./lib/server.coffee // with coffee-script already loaded. -require('coffeescript') -require('coffeescript/register') +// import('coffeescript') +// import('coffeescript/register.js') -module.exports = require('./lib/server') +// const { default: server } = await import('./lib/server.js') +// export default server + +import { default as server } from './lib/server.js' +export default server diff --git a/lib/defaultargs.js b/lib/defaultargs.js index 1f050009..1e06369d 100644 --- a/lib/defaultargs.js +++ b/lib/defaultargs.js @@ -9,13 +9,19 @@ // **defaultargs.coffee** when called on the argv object this // module will create reasonable defaults for options not supplied, // based on what information is provided. -const path = require('node:path') +import path from 'node:path' +import { randomBytes } from 'node:crypto' +import { fileURLToPath } from 'node:url' +import { dirname } from 'node:path' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) const getUserHome = () => { return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE } -module.exports = argv => { +export default argv => { argv = argv || {} argv.root ||= __dirname // the directory that contains all the packages that makeup the wiki @@ -32,7 +38,7 @@ module.exports = argv => { argv.url ||= `http://localhost${argv.port === 80 ? '' : ':' + argv.port}` argv.id ||= path.join(argv.status, 'owner.json') argv.uploadLimit ||= '5mb' - argv.cookieSecret ||= require('crypto').randomBytes(64).toString('hex') + argv.cookieSecret ||= randomBytes(64).toString('hex') argv.secure_cookie ||= false argv.session_duration ||= 7 argv.neighbors ||= '' @@ -43,9 +49,9 @@ module.exports = argv => { argv.database = JSON.parse(argv.database) } argv.database ||= {} - argv.database.type ||= './page' + argv.database.type ||= './page.js' if (argv.database.type.charAt(0) === '.') { - if (argv.database.type != './page') { + if (argv.database.type != './page.js') { console.log('\n\nWARNING: This storage option is depeciated.') console.log(' See ReadMe for details of the changes required.\n\n') } @@ -53,8 +59,8 @@ module.exports = argv => { argv.database.type = 'wiki-storage-' + argv.database.type } - argv.security_type ||= './security' - if (argv.security_type === './security') { + argv.security_type ||= './security.js' + if (argv.security_type === './security.js') { console.log('\n\nINFORMATION: Using default security module.') } else { argv.security_type = 'wiki-security-' + argv.security_type diff --git a/lib/forward.js b/lib/forward.js index 8c608364..096a5bb9 100644 --- a/lib/forward.js +++ b/lib/forward.js @@ -1,4 +1,4 @@ -const init = (app, emitter) => { +export const init = (app, emitter) => { let sockets = [] app.io.on('connection', socket => { let listeners = [] @@ -35,4 +35,3 @@ const init = (app, emitter) => { }) }) } -module.exports = { init } diff --git a/lib/page.js b/lib/page.js index da44f7eb..60d549bd 100644 --- a/lib/page.js +++ b/lib/page.js @@ -10,12 +10,53 @@ // Everything is stored using json flat files. // #### Requires #### -const fs = require('fs') -const path = require('path') -const events = require('events') +// const fs = require('fs') +// const path = require('path') +// const events = require('events') +// const glob = require('glob') +// +// const async = require('async') +// +// // const random_id = require('./random_id.cjs') +// const synopsis = require('wiki-client/lib/synopsis') + +import fs from 'node:fs' +import path from 'node:path' +import url from 'node:url' +import events from 'node:events' + +import { createRequire } from 'node:module' +const require = createRequire(import.meta.url) + +// Use dynamic import to load package.json from the main application's working directory +const wikiPackageImport = async () => { + let done = false + return new Promise(resolve => { + import('wiki/package.json', { with: { type: 'json' } }) + .then(imported => { + done = true + resolve(imported.default) + }) + .catch(e => { + return e + }) + .then(async () => { + if (done) return + const packageJsonPath = path.join(process.cwd(), 'package.json') + const packageJsonUrl = url.pathToFileURL(packageJsonPath).href + import(packageJsonUrl, { with: { type: 'json' } }) + .then(imported => { + resolve(imported.default) + }) + .catch(e => console.error('problems importing package', e)) + }) + }) +} -const random_id = require('./random_id') -const synopsis = require('wiki-client/lib/synopsis') +const packageJson = await wikiPackageImport() + +// import random_id from './random_id.cjs'; // Uncomment if needed +import synopsis from 'wiki-client/lib/synopsis.js' // Add correct extension if necessary const asSlug = name => name @@ -25,7 +66,7 @@ const asSlug = name => // Export a function that generates a page handler // when called with options object. -module.exports = exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname fs.mkdir(argv.db, { recursive: true }, e => { @@ -34,13 +75,11 @@ module.exports = exports = argv => { // create a list of plugin pages. const pluginPages = new Map() - Object.keys(require.main.require('./package').dependencies) + + Object.keys(packageJson.dependencies) .filter(depend => depend.startsWith('wiki-plugin')) .forEach(plugin => { - const pagesPath = path.join( - path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })), - 'pages', - ) + const pagesPath = path.join(path.dirname(require.resolve(`${plugin}/package`)), 'pages') fs.readdir(pagesPath, { withFileTypes: true }, (err, entries) => { if (err) return entries.forEach(entry => { diff --git a/lib/plugins.js b/lib/plugins.js index 4bb48a6e..dfa7e087 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -8,11 +8,11 @@ // support server-side plugins -const fs = require('node:fs') -const { pathToFileURL } = require('node:url') -// forward = require './forward' +import fs from 'node:fs' +import { pathToFileURL } from 'node:url' +// import forward from './forward.cjs'; // Uncomment if needed and adjust import style if it's not a default export -module.exports = exports = argv => { +export default argv => { // NOTE: plugins are now in their own package directories alongside this one... // Plugins are in directories of the form wiki-package-* // those with a server component will have a server directory @@ -39,11 +39,8 @@ module.exports = exports = argv => { } const startServers = params => { - // emitter = new events.EventEmitter() - // forward.init params.app, emitter - // params.emitter = emitter - - Object.keys(require.main.require('./package').dependencies) + const dependencies = params.packageJson.dependencies + Object.keys(dependencies) .filter(depend => depend.startsWith('wiki-plugin')) .forEach(plugin => { startServer(params, plugin) diff --git a/lib/random_id.js b/lib/random_id.js index 52476aab..61762f35 100644 --- a/lib/random_id.js +++ b/lib/random_id.js @@ -10,6 +10,4 @@ // Simple random hex generator, takes an optional number of // chars that defaults to 16 and returns a random id. -const random_id = (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('') - -module.exports = random_id.random_id = random_id +export default (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('') diff --git a/lib/search.js b/lib/search.js index f318f74a..5d2cd4bc 100644 --- a/lib/search.js +++ b/lib/search.js @@ -8,15 +8,15 @@ // **search.js** -const fs = require('node:fs') -const path = require('node:path') -const events = require('node:events') -const url = require('node:url') -const writeFileAtomic = require('write-file-atomic') +import fs from 'node:fs' +import path from 'node:path' +import events from 'node:events' +import url from 'node:url' +import writeFileAtomic from 'write-file-atomic' -const miniSearch = require('minisearch') +import miniSearch from 'minisearch' -module.exports = exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname let siteIndex = [] const queue = [] diff --git a/lib/security.js b/lib/security.js index e79228aa..8b0b3423 100644 --- a/lib/security.js +++ b/lib/security.js @@ -13,11 +13,11 @@ // allow the server to run read-only. // #### Requires #### -const fs = require('node:fs') +import fs from 'node:fs' // Export a function that generates security handler // when called with options object. -module.exports = exports = (log, loga, argv) => { +export default (log, loga, argv) => { const security = {} // #### Private utility methods. #### @@ -84,7 +84,16 @@ module.exports = exports = (log, loga, argv) => { } // Wiki server admin security.isAdmin = () => { - return false + // nobody is admin - unless legacy support, and test + if (argv.security_legacy) { + if (argv.test) { + return true + } else { + return false + } + } else { + return false + } } security.defineRoutes = (app, cors, updateOwner) => { // default security does not have any routes diff --git a/lib/server.js b/lib/server.js index 3ea16e98..e2ad4cb9 100644 --- a/lib/server.js +++ b/lib/server.js @@ -19,19 +19,18 @@ // npm install // Standard lib -const fs = require('fs') -const path = require('path') -const http = require('http') -const url = require('url') -const { pipeline } = require('node:stream/promises') +import fs from 'fs' +import path from 'path' +import url from 'url' +import { pipeline } from 'node:stream/promises' // From npm -const express = require('express') -const hbs = require('express-hbs') -const f = require('flates') +import express from 'express' +import hbs from 'express-hbs' +import f from 'flates' -const createDOMPurify = require('dompurify') -const { JSDOM } = require('jsdom') +import createDOMPurify from 'dompurify' +import { JSDOM } from 'jsdom' const window = new JSDOM('').window const DOMPurify = createDOMPurify(window) @@ -39,21 +38,53 @@ const DOMPurify = createDOMPurify(window) // Using native fetch API (available in Node.js 18+) // Express 4 middleware -const logger = require('morgan') -const cookieParser = require('cookie-parser') -const methodOverride = require('method-override') -// session = require 'express-session' -const sessions = require('client-sessions') -const bodyParser = require('body-parser') -const errorHandler = require('errorhandler') +import logger from 'morgan' +import cookieParser from 'cookie-parser' +import methodOverride from 'method-override' +// session = require('express-session') // This one was commented out — uncomment if used +import sessions from 'client-sessions' +import bodyParser from 'body-parser' +import errorHandler from 'errorhandler' // Local files -const random = require('./random_id') -const defargs = require('./defaultargs') -const resolveClient = require('wiki-client/lib/resolve') -const pluginsFactory = require('./plugins') -const sitemapFactory = require('./sitemap') -const searchFactory = require('./search') +// Make sure these files are ESM modules or compatible +// If they are CommonJS, you will need to dynamically import them (see below) +import defargs from './defaultargs.js' +import resolveClient from 'wiki-client/lib/resolve.js' +import pluginsFactory from './plugins.js' +import sitemapFactory from './sitemap.js' +import searchFactory from './search.js' +import { warn } from 'node:console' +import { createRequire } from 'module' +const require = createRequire(import.meta.url) + +// Use import to load package.json from the main application's working directory +//const { default: packageJson } = await import('wiki/package.json', { with: { type: 'json' } }) +const wikiPackageImport = async () => { + let done = false + return new Promise(resolve => { + import('wiki/package.json', { with: { type: 'json' } }) + .then(imported => { + done = true + resolve(imported.default) + }) + .catch(e => { + return e + }) + .then(async () => { + if (done) return + const packageJsonPath = path.join(process.cwd(), 'package.json') + const packageJsonUrl = url.pathToFileURL(packageJsonPath).href + import(packageJsonUrl, { with: { type: 'json' } }) + .then(imported => { + resolve(imported.default) + }) + .catch(e => console.error('problems importing package', e)) + }) + }) +} + +const packageJson = await wikiPackageImport() const render = page => { return ( @@ -90,7 +121,7 @@ const render = page => { ) } // Set export objects for node and coffee to a function that generates a sfw server. -module.exports = exports = argv => { +export default async argv => { // Create the main application object, app. const app = express() @@ -104,6 +135,8 @@ module.exports = exports = argv => { app.startOpts = argv + const wikiName = new URL(argv.url).hostname + const log = (...stuff) => { if (argv.debug) console.log(stuff) } @@ -125,18 +158,23 @@ module.exports = exports = argv => { } next() } + let pagehandler, sitemaphandler, searchhandler, securityhandler - // Require the database adapter and initialize it with options. - app.pagehandler = pagehandler = require(argv.database.type)(argv) - // Require the sitemap adapter and initialize it with options. + // Dynamically import database adapter (since the module name is dynamic) + const dbModule = await import(argv.database.type) + app.pagehandler = pagehandler = dbModule.default(argv) + + // Initialize sitemap handler app.sitemaphandler = sitemaphandler = sitemapFactory(argv) - // Require the site indexer and initialize it with options + // Initialize search handler app.searchhandler = searchhandler = searchFactory(argv) - // Require the security adapter and initialize it with options. - app.securityhandler = securityhandler = require(argv.security_type)(log, loga, argv) + // Dynamically import security adapter (also dynamic) + console.log('security_type', argv.security_type) + const securityModule = await import(argv.security_type) + app.securityhandler = securityhandler = securityModule.default(log, loga, argv) // If the site is owned, owner will contain the name of the owner let owner = '' @@ -219,7 +257,7 @@ module.exports = exports = argv => { // use logger, at least in development, probably needs a param to configure (or turn off). // use stream to direct to somewhere other than stdout. logger.token('vhost', (req, res) => { - return colorString(req.hostname) + return colorString(wikiName) }) app.use(logger(':vhost :method :url :status :res[content-length] - :response-time ms')) app.use(cookieParser()) @@ -268,13 +306,10 @@ module.exports = exports = argv => { app.use('/assets', cors, express.static(argv.assets)) // Add static routes to the plugins client. - Object.keys(require.main.require('./package').dependencies) + Object.keys(packageJson.dependencies) .filter(depend => depend.startsWith('wiki-plugin')) .forEach(plugin => { - const clientPath = path.join( - path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })), - 'client', - ) + const clientPath = path.join(path.dirname(require.resolve(`${plugin}/package`)), 'client') const pluginPath = '/plugins/' + plugin.slice(12) app.use(pluginPath, cors, express.static(clientPath, staticPathOptions)) }) @@ -387,17 +422,28 @@ module.exports = exports = argv => { app.get('/system/factories.json', (req, res) => { res.status(200) res.header('Content-Type', 'application/json') + const factories = [] - Object.keys(require.main.require('./package').dependencies) - .filter(depend => depend.startsWith('wiki-plugin')) - .forEach(plugin => { - try { - factories.push(require.main.require(`${plugin}/factory`)) - } catch { - // do nothing if plugin doesn't have a factory category. - } + + const getPackageFactory = plugin => { + return new Promise(resolve => { + import(`${plugin}/factory.json`, { with: { type: 'json' } }) + .then(({ default: factory }) => { + resolve(factories.push(factory)) + }) + .catch(() => { + resolve() + }) }) - res.end(JSON.stringify(factories)) + } + + Promise.all( + Object.keys(packageJson.dependencies) + .filter(depend => depend.startsWith('wiki-plugin')) + .map(plugin => { + return getPackageFactory(plugin) + }), + ).then(() => res.end(JSON.stringify(factories))) }) // ###### Json Routes ###### @@ -451,7 +497,7 @@ module.exports = exports = argv => { if (!err) { res.sendFile(favLoc, { dotfiles: 'allow' }) } else { - res.sendFile(defaultFavLoc) + res.sendFile(defaultFavLoc, { dotfiles: 'allow' }) } }) }) @@ -679,27 +725,54 @@ module.exports = exports = argv => { } app.get('/system/version.json', admin, (req, res) => { + const getPackageVersion = packageName => { + return new Promise(resolve => { + try { + // Use import to load package.json from the main application's working directory + import(`${packageName}/package.json`, { with: { type: 'json' } }).then(({ default: packageJson }) => { + resolve({ [packageName]: packageJson.version }) + }) + } catch (error) { + console.error(`Error reading package for ${packageName}:`, error) + resolve({ [packageName]: 'unknown' }) + } + }) + } + const versions = {} - const wikiModule = require.main - versions[wikiModule.require('./package').name] = wikiModule.require('./package').version - versions[wikiModule.require('wiki-server/package').name] = wikiModule.require('wiki-server/package').version - versions[wikiModule.require('wiki-client/package').name] = wikiModule.require('wiki-client/package').version - - versions['security'] = {} - Object.keys(require.main.require('./package').dependencies) - .filter(depend => depend.startsWith('wiki-security')) - .forEach(key => { - versions.security[key] = wikiModule.require(`${key}/package`).version + + const security = () => { + return new Promise(resolve => { + Promise.all( + Object.keys(packageJson.dependencies) + .filter(depend => depend.startsWith('wiki-security')) + .map(key => { + return getPackageVersion(key) + }), + ).then(values => { + resolve({ security: values.reduce((acc, cV) => Object.assign(acc, cV), {}) }) + }) }) + } - versions['plugins'] = {} - Object.keys(require.main.require('./package').dependencies) - .filter(depend => depend.startsWith('wiki-plugin')) - .forEach(key => { - versions.plugins[key] = wikiModule.require(`${key}/package`).version + const plugins = () => { + return new Promise(resolve => { + Promise.all( + Object.keys(packageJson.dependencies) + .filter(depend => depend.startsWith('wiki-plugin')) + .map(key => { + return getPackageVersion(key) + }), + ).then(values => { + resolve({ plugins: values.reduce((acc, cV) => Object.assign(acc, cV), {}) }) + }) }) + } - res.json(versions) + Promise.all([getPackageVersion('wiki-server'), getPackageVersion('wiki-client'), security(), plugins()]).then(v => { + Object.assign(versions, { [packageJson.name]: packageJson.version }, ...v) + res.json(versions) + }) }) // ##### Proxy routes ##### @@ -916,7 +989,7 @@ module.exports = exports = argv => { // ### Plugins ### // Should replace most WebSocketServers below. const plugins = pluginsFactory(argv) - plugins.startServers({ argv, app }) + plugins.startServers({ argv, app, packageJson }) // ### Sitemap ### // create sitemap at start-up sitemaphandler.createSitemap(pagehandler) diff --git a/lib/sitemap.js b/lib/sitemap.js index feb758e6..5bc8a0b3 100644 --- a/lib/sitemap.js +++ b/lib/sitemap.js @@ -7,14 +7,13 @@ */ // **sitemap.coffee** +import fs from 'node:fs' +import path from 'node:path' +import events from 'node:events' +import writeFileAtomic from 'write-file-atomic' +import xml2js from 'xml2js' -const fs = require('fs') -const path = require('path') -const events = require('events') -const writeFileAtomic = require('write-file-atomic') -const xml2js = require('xml2js') - -const synopsis = require('wiki-client/lib/synopsis') +import synopsis from 'wiki-client/lib/synopsis.js' // Add .js if needed const asSlug = name => name @@ -22,7 +21,7 @@ const asSlug = name => .replace(/[^A-Za-z0-9-]/g, '') .toLowerCase() -module.exports = exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname let sitemap = [] diff --git a/package-lock.json b/package-lock.json index e5bdbb70..55e98da2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,38 +1,38 @@ { "name": "wiki-server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.11", "license": "MIT", "dependencies": { - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "client-sessions": "^0.8.0", "coffeescript": "^2.5.0", "cookie-parser": "^1.4.4", - "dompurify": "^3.1.0", + "dompurify": "^3.3.0", "errorhandler": "^1.5.1", "express": "^5.1.0", "express-hbs": "^2.5.0", "flates": "0.0.5", - "jsdom": "^26.0.0", + "jsdom": "^27.2.0", "method-override": "^3.0.0", - "minisearch": "^7.1.0", + "minisearch": "^7.2.0", "morgan": "^1.10.1", - "write-file-atomic": "^6.0.0", + "write-file-atomic": "^7.0.0", "xml2js": "^0.6.2" }, "devDependencies": { - "@eslint/js": "^9.32.0", - "eslint": "^9.32.0", - "globals": "^16.1.0", + "@eslint/js": "^9.39.1", + "eslint": "^9.39.1", + "globals": "^16.5.0", "grunt-git-authors": "^3.2.0", - "prettier": "^3.5.3", + "prettier": "^3.7.3", "supertest": "^7.1.4", - "wiki-client": "^0.31.3", + "wiki-client": "^0.31.6", "wiki-plugin-activity": "0.7", "wiki-plugin-video": "^0.4" }, @@ -41,9 +41,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "dev": true, "license": "MIT", "engines": { @@ -54,23 +54,27 @@ } }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^4.4.0", + "debug": "^4.4.3", "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/bytes": { @@ -121,9 +125,9 @@ } }, "node_modules/body-parser/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -279,31 +283,39 @@ } }, "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/inherits": { @@ -340,15 +352,19 @@ } }, "node_modules/body-parser/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/ms": { @@ -397,18 +413,18 @@ } }, "node_modules/body-parser/node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, "node_modules/body-parser/node_modules/safer-buffer": { @@ -496,9 +512,9 @@ } }, "node_modules/body-parser/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -574,6 +590,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz", "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT", "engines": { "node": ">= 0.6" @@ -621,9 +638,9 @@ "license": "MIT" }, "node_modules/dompurify": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", - "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", + "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -699,25 +716,24 @@ } }, "node_modules/eslint": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", - "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.32.0", - "@eslint/plugin-kit": "^0.3.4", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -760,9 +776,9 @@ } }, "node_modules/eslint/node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -792,9 +808,9 @@ } }, "node_modules/eslint/node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -802,13 +818,13 @@ } }, "node_modules/eslint/node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -817,19 +833,22 @@ } }, "node_modules/eslint/node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -840,9 +859,9 @@ } }, "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -852,7 +871,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -864,9 +883,9 @@ } }, "node_modules/eslint/node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -874,13 +893,13 @@ } }, "node_modules/eslint/node_modules/@eslint/plugin-kit": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", - "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -898,33 +917,19 @@ } }, "node_modules/eslint/node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, - "node_modules/eslint/node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/eslint/node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1118,9 +1123,9 @@ } }, "node_modules/eslint/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -1425,9 +1430,9 @@ "license": "ISC" }, "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -1858,9 +1863,9 @@ } }, "node_modules/express-hbs/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "optional": true, "engines": { @@ -1871,9 +1876,9 @@ } }, "node_modules/express-hbs/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "optional": true, "engines": { @@ -2007,9 +2012,9 @@ } }, "node_modules/express-hbs/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "optional": true, "dependencies": { @@ -2272,9 +2277,9 @@ } }, "node_modules/express-hbs/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "optional": true, "bin": { @@ -2394,9 +2399,9 @@ } }, "node_modules/express-hbs/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "optional": true, "dependencies": { @@ -2609,15 +2614,16 @@ } }, "node_modules/express/node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/content-type": { @@ -2648,9 +2654,9 @@ } }, "node_modules/express/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2865,28 +2871,23 @@ } }, "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/inherits": { @@ -2950,15 +2951,19 @@ } }, "node_modules/express/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/ms": { @@ -3019,12 +3024,13 @@ } }, "node_modules/express/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", - "engines": { - "node": ">=16" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/proxy-addr": { @@ -3080,26 +3086,6 @@ "node": ">= 18" } }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/express/node_modules/send": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", @@ -3271,9 +3257,9 @@ } }, "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -3299,34 +3285,34 @@ "dev": true }, "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.2.0.tgz", + "integrity": "sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==", "license": "MIT", "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", + "@acemir/cssom": "^0.9.23", + "@asamuzakjp/dom-selector": "^6.7.4", + "cssstyle": "^5.3.3", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", + "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", + "tough-cookie": "^6.0.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", + "webidl-conversions": "^8.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { "canvas": "^3.0.0" @@ -3337,23 +3323,48 @@ } } }, + "node_modules/jsdom/node_modules/@acemir/cssom": { + "version": "0.9.24", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.24.tgz", + "integrity": "sha512-5YjgMmAiT2rjJZU7XK1SNI7iqTy92DpaYVgG6x63FxkJ11UpYfLndHJATtinWJClAXiOlW9XWaUyAQf8pMrQPg==", + "license": "MIT" + }, "node_modules/jsdom/node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.0.tgz", + "integrity": "sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==", "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "lru-cache": "^11.2.2" + } + }, + "node_modules/jsdom/node_modules/@asamuzakjp/dom-selector": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.5.tgz", + "integrity": "sha512-Eks6dY8zau4m4wNRQjRVaKQRTalNcPcBvU1ZQ35w5kKRk1gUeNCkVLsRiATurjASTp3TKM4H10wsI50nx3NZdw==", + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.2" } }, + "node_modules/jsdom/node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "license": "MIT" + }, "node_modules/jsdom/node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", "funding": [ { "type": "github", @@ -3393,9 +3404,9 @@ } }, "node_modules/jsdom/node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", "funding": [ { "type": "github", @@ -3408,7 +3419,7 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "engines": { @@ -3441,6 +3452,25 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/jsdom/node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.20.tgz", + "integrity": "sha512-8BHsjXfSciZxjmHQOuVdW2b8WLUPts9a+mfL13/PzEviufUEW2xnvQuOlKs9dRBHgRqJ53SF/DUoK9+MZk72oQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, "node_modules/jsdom/node_modules/@csstools/css-tokenizer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", @@ -3469,36 +3499,59 @@ "node": ">= 14" } }, + "node_modules/jsdom/node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/jsdom/node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/jsdom/node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.3.tgz", + "integrity": "sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==", "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" + "@asamuzakjp/css-color": "^4.0.3", + "@csstools/css-syntax-patches-for-csstree": "^1.0.14", + "css-tree": "^3.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/jsdom/node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz", + "integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==", "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" + "whatwg-url": "^15.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/jsdom/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3587,10 +3640,19 @@ "license": "MIT" }, "node_modules/jsdom/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/jsdom/node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "license": "CC0-1.0" }, "node_modules/jsdom/node_modules/ms": { "version": "2.1.3", @@ -3598,16 +3660,10 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/jsdom/node_modules/nwsapi": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", - "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", - "license": "MIT" - }, "node_modules/jsdom/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -3625,11 +3681,14 @@ "node": ">=6" } }, - "node_modules/jsdom/node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "license": "MIT" + "node_modules/jsdom/node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/jsdom/node_modules/safer-buffer": { "version": "2.1.2", @@ -3649,6 +3708,15 @@ "node": ">=v12.22.7" } }, + "node_modules/jsdom/node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jsdom/node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -3656,45 +3724,45 @@ "license": "MIT" }, "node_modules/jsdom/node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/jsdom/node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "license": "MIT" }, "node_modules/jsdom/node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "tldts": "^7.0.5" }, "engines": { "node": ">=16" } }, "node_modules/jsdom/node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/jsdom/node_modules/w3c-xmlserializer": { @@ -3710,12 +3778,12 @@ } }, "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=20" } }, "node_modules/jsdom/node_modules/whatwg-encoding": { @@ -3740,16 +3808,16 @@ } }, "node_modules/jsdom/node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/jsdom/node_modules/ws": { @@ -3846,9 +3914,9 @@ } }, "node_modules/minisearch": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.1.2.tgz", - "integrity": "sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", "license": "MIT" }, "node_modules/morgan": { @@ -3937,9 +4005,9 @@ "license": "MIT" }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.3.tgz", + "integrity": "sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==", "dev": true, "license": "MIT", "bin": { @@ -3980,9 +4048,9 @@ } }, "node_modules/supertest/node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", - "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", "dev": true, "license": "MIT", "dependencies": { @@ -4065,9 +4133,9 @@ "license": "MIT" }, "node_modules/supertest/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -4175,9 +4243,9 @@ "license": "MIT" }, "node_modules/supertest/node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { @@ -4520,9 +4588,9 @@ "license": "ISC" }, "node_modules/wiki-client": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/wiki-client/-/wiki-client-0.31.3.tgz", - "integrity": "sha512-+F9ZeZKvl7OmeFWAiRjuZsCcD7tcctPn8fFbh25mOH+942MTiKc8sngw+VOGfkG+B6JMQc+3neCELeifOKviyg==", + "version": "0.31.6", + "resolved": "https://registry.npmjs.org/wiki-client/-/wiki-client-0.31.6.tgz", + "integrity": "sha512-pECWIW3nAv8FoNlb0qD6BTSLO5bAqpgz1JSOIe+VDUnxm2rG/dvJQ3jx2ft9U7fp1CD/JQUe1VqFnESx5YtBlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4531,7 +4599,7 @@ "underscore": "^1.13.6" }, "engines": { - "node": ">=18.x" + "node": ">=20.x" } }, "node_modules/wiki-client/node_modules/async": { @@ -4596,16 +4664,16 @@ } }, "node_modules/write-file-atomic": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz", - "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.0.tgz", + "integrity": "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==", "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/write-file-atomic/node_modules/imurmurhash": { @@ -4643,10 +4711,10 @@ } }, "node_modules/xml2js/node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "license": "ISC" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" }, "node_modules/xml2js/node_modules/xmlbuilder": { "version": "11.0.1", diff --git a/package.json b/package.json index 166ffde2..ec5822a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.11", + "type": "module", "author": { "name": "Ward Cunningham", "email": "ward@c2.com", @@ -29,37 +30,39 @@ "Andrew Shell ", "jon r " ], + "main": "index.js", "dependencies": { - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "client-sessions": "^0.8.0", "coffeescript": "^2.5.0", "cookie-parser": "^1.4.4", - "dompurify": "^3.1.0", + "dompurify": "^3.3.0", "errorhandler": "^1.5.1", "express": "^5.1.0", "express-hbs": "^2.5.0", "flates": "0.0.5", - "jsdom": "^26.0.0", + "jsdom": "^27.2.0", "method-override": "^3.0.0", - "minisearch": "^7.1.0", + "minisearch": "^7.2.0", "morgan": "^1.10.1", - "write-file-atomic": "^6.0.0", + "write-file-atomic": "^7.0.0", "xml2js": "^0.6.2" }, "scripts": { "prettier:format": "prettier --write './**/*.js'", "prettier:check": "prettier --check ./**/*.js", - "test": "node --test", + "test": "cd test; node --test", + "watch": "cd test; node --test --watch", "update-authors": "node scripts/update-authors.js" }, "devDependencies": { - "@eslint/js": "^9.32.0", - "eslint": "^9.32.0", - "globals": "^16.1.0", + "@eslint/js": "^9.39.1", + "eslint": "^9.39.1", + "globals": "^16.5.0", "grunt-git-authors": "^3.2.0", - "prettier": "^3.5.3", + "prettier": "^3.7.3", "supertest": "^7.1.4", - "wiki-client": "^0.31.3", + "wiki-client": "^0.31.6", "wiki-plugin-activity": "0.7", "wiki-plugin-video": "^0.4" }, diff --git a/test/defaultargs.js b/test/defaultargs.js index 00ae570c..b310d96e 100644 --- a/test/defaultargs.js +++ b/test/defaultargs.js @@ -1,7 +1,7 @@ -const { describe, it } = require('node:test') -const assert = require('node:assert/strict') +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' -const defaultargs = require('../lib/defaultargs') +import defaultargs from '../lib/defaultargs.js' describe('defaultargs', () => { describe('#defaultargs()', () => { diff --git a/test/package.json b/test/package.json index c6dcf84e..ed3e0961 100644 --- a/test/package.json +++ b/test/package.json @@ -1,8 +1,12 @@ { "comment": "This exists so that the tests have a package to read", - "name": "wiki-server", + "name": "wiki", + "type": "module", + "version": "0.1", "dependencies": { - "wiki-plugin-activity": "0.1", - "wiki-plugin-video": "0.1" + "wiki-server": "0.2", + "wiki-client": "0.3", + "wiki-plugin-activity": "0.4", + "wiki-plugin-video": "0.5" } } diff --git a/test/page.js b/test/page.js index ebca772b..590d8a4c 100644 --- a/test/page.js +++ b/test/page.js @@ -1,17 +1,27 @@ -const { describe, it } = require('node:test') -const assert = require('node:assert/strict') +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' + +import path from 'node:path' +import fs from 'node:fs' + +import { fileURLToPath } from 'node:url' +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// ESM module imports (assuming default exports) +import random from '../lib/random_id.js' +import defaultargs from '../lib/defaultargs.js' +import pageFactory from '../lib/page.js' -const path = require('node:path') -const random = require('../lib/random_id') const testid = random() -const argv = require('../lib/defaultargs')({ +const argv = defaultargs({ data: path.join('/tmp', 'sfwtests', testid), root: path.join(__dirname, '..'), packageDir: path.join(__dirname, '..', 'node_modules'), security_legacy: true, }) -const page = require('../lib/page')(argv) -const fs = require('node:fs') + +const page = pageFactory(argv) const testpage = { title: 'Asdf' } diff --git a/test/random.js b/test/random.js index b2b88d9f..8a2c2d23 100644 --- a/test/random.js +++ b/test/random.js @@ -1,7 +1,7 @@ -const { describe, it } = require('node:test') -const assert = require('node:assert/strict') +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' -const random = require('../lib/random_id') +import random from '../lib/random_id.js' describe('random', () => { describe('#random_id', () => { diff --git a/test/server.js b/test/server.js index 8f132f32..b6ed51d4 100644 --- a/test/server.js +++ b/test/server.js @@ -1,13 +1,23 @@ -const { describe, it, before, after } = require('node:test') -const assert = require('node:assert/strict') - -const supertest = require('supertest') -const fs = require('node:fs') -const server = require('..') -const path = require('node:path') -const random = require('../lib/random_id') +import { describe, it, before, after } from 'node:test' +import assert from 'node:assert/strict' + +import supertest from 'supertest' +import fs from 'node:fs' +import path from 'node:path' + +import { fileURLToPath } from 'node:url' +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// CommonJS server module (.cjs) +const server = await import('../index.js') + +// ESM modules +import random from '../lib/random_id.js' +import defaultargs from '../lib/defaultargs.js' + const testid = random() -const argv = require('../lib/defaultargs')({ +const argv = defaultargs({ data: path.join('/tmp', 'sfwtests', testid), packageDir: path.join(__dirname, '..', 'node_modules'), port: 55557, @@ -18,16 +28,18 @@ const argv = require('../lib/defaultargs')({ describe('server', () => { var app = {} let runningServer = null - before(done => { + before(async done => { // as starting the server this was does not create a sitemap file, create an empty one const sitemapLoc = path.join('/tmp', 'sfwtests', testid, 'status', 'sitemap.json') fs.mkdirSync(path.join('/tmp', 'sfwtests', testid)) fs.mkdirSync(path.join('/tmp', 'sfwtests', testid, 'status')) fs.writeFileSync(sitemapLoc, JSON.stringify([])) - app = server(argv) - app.once('owner-set', () => { - runningServer = app.listen(app.startOpts.port, app.startOpts.host, done) + let x = await server.default(argv) + app = x + // app = server(argv) + app.once('owner-set', async () => { + runningServer = await app.listen(app.startOpts.port, app.startOpts.host, done) }) }) @@ -224,4 +236,22 @@ describe('server', () => { throw err }) }) + + // Should be a version test, but doesn't seem it's supported in test mode yet. + it.skip('server should return a version', async () => { + await request + .get('/system/version.json') + .expect(200) + .expect('Content-Type', /json/) + .then(res => { + assert.equal(res.body.wiki, '0.1') + assert.equal(res.body['wiki-server'], '0.2') + assert.equal(res.body['wiki-client'], '0.3') + assert.equal(res.body.plugins['wiki-plugin-activity'], '0.4') + assert.equal(res.body.plugins['wiki-plugin-video'], '0.5') + }) + .catch(err => { + throw err + }) + }) }) diff --git a/test/sitemap.js b/test/sitemap.js index b4d60c45..adf85049 100644 --- a/test/sitemap.js +++ b/test/sitemap.js @@ -1,13 +1,24 @@ -const { describe, it, before, after } = require('node:test') -const assert = require('node:assert/strict') - -const supertest = require('supertest') -const fs = require('node:fs') -const server = require('..') -const path = require('node:path') -const random = require('../lib/random_id') +import { describe, it, before, after } from 'node:test' +import assert from 'node:assert/strict' + +import supertest from 'supertest' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +// Emulate __dirname in ESM +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// Dynamic import of CommonJS module +const server = await import('../index.js') + +// ESM imports +import random from '../lib/random_id.js' +import defaultargs from '../lib/defaultargs.js' + const testid = random() -const argv = require('../lib/defaultargs')({ +const argv = defaultargs({ data: path.join('/tmp', 'sfwtests', testid), port: 55556, security_legacy: true, @@ -18,8 +29,11 @@ describe('sitemap', () => { let app = {} let runningServer = null - before(done => { - app = server(argv) + before(async done => { + let x = await server.default(argv) + app = x + + // app = server(argv) app.once('owner-set', () => { runningServer = app.listen(app.startOpts.port, app.startOpts.host, done) })