From 0914cb4572f7208048306ad746d4531491c3a9d8 Mon Sep 17 00:00:00 2001 From: SamAxe <1377880+SamAxe@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:06:03 -0700 Subject: [PATCH 01/30] Rebased from latest --- index.js | 7 ++++--- lib/defaultargs.js | 23 ++++++++++++++++------- lib/forward.js | 3 +-- lib/page.js | 33 +++++++++++++++++++++++---------- lib/plugins.js | 13 ++++++++----- lib/random_id.js | 3 ++- lib/search.js | 17 ++++++++++------- lib/security.js | 7 +++++-- lib/{server.js => server.cjs} | 22 +++++++++++----------- lib/sitemap.js | 18 ++++++++++-------- package.json | 1 + test/defaultargs.js | 6 +++--- test/page.js | 24 +++++++++++++++++------- test/random.js | 6 +++--- test/server.js | 30 ++++++++++++++++++++---------- test/sitemap.js | 31 +++++++++++++++++++++---------- 16 files changed, 155 insertions(+), 89 deletions(-) rename lib/{server.js => server.cjs} (98%) diff --git a/index.js b/index.js index 2c472d71..a916a138 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,8 @@ // 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') +import * as server from './lib/server.cjs' +export default server diff --git a/lib/defaultargs.js b/lib/defaultargs.js index 1f050009..e9b35b49 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 => { +const exports = 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 @@ -81,3 +87,6 @@ module.exports = argv => { } return argv } + +export default exports +export { exports } 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 68e55187..583275c8 100644 --- a/lib/page.js +++ b/lib/page.js @@ -10,15 +10,25 @@ // Everything is stored using json flat files. // #### Requires #### -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') -const synopsis = require('wiki-client/lib/synopsis') +// 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 events from 'node:events' +import glob from 'glob' + +import async from 'async' + +// 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 @@ -28,7 +38,7 @@ const asSlug = name => // Export a function that generates a page handler // when called with options object. -module.exports = exports = argv => { +const exports = argv => { const wikiName = new URL(argv.url).hostname fs.mkdir(argv.db, { recursive: true }, e => { @@ -446,3 +456,6 @@ module.exports = exports = argv => { return itself } + +export default exports +export { exports } diff --git a/lib/plugins.js b/lib/plugins.js index b6c40b4f..04fda174 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -8,12 +8,12 @@ // support server-side plugins -const fs = require('node:fs') -const glob = require('glob') -const { pathToFileURL } = require('node:url') -// forward = require './forward' +import fs from 'node:fs' +import glob from 'glob' +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 => { +const exports = 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 @@ -52,3 +52,6 @@ module.exports = exports = argv => { return { startServers } } + +export default exports +export { exports } diff --git a/lib/random_id.js b/lib/random_id.js index 52476aab..b0388c9f 100644 --- a/lib/random_id.js +++ b/lib/random_id.js @@ -12,4 +12,5 @@ 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 random_id +export { random_id } diff --git a/lib/search.js b/lib/search.js index 90e4be40..ddba08ca 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 => { +const exports = argv => { const wikiName = new URL(argv.url).hostname let siteIndex = [] const queue = [] @@ -388,3 +388,6 @@ module.exports = exports = argv => { return itself } + +export default exports +export { exports } diff --git a/lib/security.js b/lib/security.js index 7efe0a8d..bce81a3f 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) => { +const exports = (log, loga, argv) => { const security = {} // #### Private utility methods. #### @@ -92,3 +92,6 @@ module.exports = exports = (log, loga, argv) => { return security } + +export default exports +export { exports } diff --git a/lib/server.js b/lib/server.cjs similarity index 98% rename from lib/server.js rename to lib/server.cjs index 10b03d18..dd8f96a4 100644 --- a/lib/server.js +++ b/lib/server.cjs @@ -51,12 +51,12 @@ const bodyParser = require('body-parser') const errorHandler = require('errorhandler') // Local files -const random = require('./random_id') -const defargs = require('./defaultargs') +// const random = require('./random_id.cjs') +const defargs = require('./defaultargs.js') const resolveClient = require('wiki-client/lib/resolve') -const pluginsFactory = require('./plugins') -const sitemapFactory = require('./sitemap') -const searchFactory = require('./search') +const pluginsFactory = require('./plugins.js') +const sitemapFactory = require('./sitemap.js') +const searchFactory = require('./search.js') const render = page => { return ( @@ -103,7 +103,7 @@ module.exports = exports = argv => { // defaultargs.coffee exports a function that takes the argv object // that is passed in and then does its // best to supply sane defaults for any arguments that are missing. - argv = defargs(argv) + argv = defargs.default(argv) app.startOpts = argv @@ -130,16 +130,16 @@ module.exports = exports = argv => { } let pagehandler, sitemaphandler, searchhandler, securityhandler // Require the database adapter and initialize it with options. - app.pagehandler = pagehandler = require(argv.database.type)(argv) + app.pagehandler = pagehandler = require(argv.database.type).default(argv) // Require the sitemap adapter and initialize it with options. - app.sitemaphandler = sitemaphandler = sitemapFactory(argv) + app.sitemaphandler = sitemaphandler = sitemapFactory.default(argv) // Require the site indexer and initialize it with options - app.searchhandler = searchhandler = searchFactory(argv) + app.searchhandler = searchhandler = searchFactory.default(argv) // Require the security adapter and initialize it with options. - app.securityhandler = securityhandler = require(argv.security_type)(log, loga, argv) + app.securityhandler = securityhandler = require(argv.security_type).default(log, loga, argv) // If the site is owned, owner will contain the name of the owner let owner = '' @@ -928,7 +928,7 @@ module.exports = exports = argv => { app.on('running-serv', server => { // ### Plugins ### // Should replace most WebSocketServers below. - const plugins = pluginsFactory(argv) + const plugins = pluginsFactory.default(argv) plugins.startServers({ argv, app }) // ### Sitemap ### // create sitemap at start-up diff --git a/lib/sitemap.js b/lib/sitemap.js index d1fa29bb..51b1fafe 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 => { +const exports = argv => { const wikiName = new URL(argv.url).hostname let sitemap = [] @@ -286,3 +285,6 @@ module.exports = exports = argv => { return itself } + +export default exports +export { exports } diff --git a/package.json b/package.json index 4a0e9b90..5b7e87f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", + "type":"module", "version": "0.25.10", "author": { "name": "Ward Cunningham", 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/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..60c33358 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 { default: 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, @@ -25,7 +35,7 @@ describe('server', () => { fs.mkdirSync(path.join('/tmp', 'sfwtests', testid, 'status')) fs.writeFileSync(sitemapLoc, JSON.stringify([])) - app = server(argv) + app = server.default(argv) app.once('owner-set', () => { runningServer = app.listen(app.startOpts.port, app.startOpts.host, done) }) diff --git a/test/sitemap.js b/test/sitemap.js index b4d60c45..75c33dc6 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 { default: 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, @@ -19,7 +30,7 @@ describe('sitemap', () => { let runningServer = null before(done => { - app = server(argv) + app = server.default(argv) app.once('owner-set', () => { runningServer = app.listen(app.startOpts.port, app.startOpts.host, done) }) From 897e862c532b139f9d6198b8e74fd9aea35f9a20 Mon Sep 17 00:00:00 2001 From: SamAxe <1377880+SamAxe@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:55:28 -0700 Subject: [PATCH 02/30] Convert server to ESM --- index.js | 2 +- lib/{server.cjs => server.js} | 204 +++++++++++++++++++++++----------- test/server.js | 12 +- test/sitemap.js | 9 +- 4 files changed, 153 insertions(+), 74 deletions(-) rename lib/{server.cjs => server.js} (83%) diff --git a/index.js b/index.js index a916a138..69462aa1 100644 --- a/index.js +++ b/index.js @@ -5,5 +5,5 @@ import('coffeescript') import('coffeescript/register.js') -import * as server from './lib/server.cjs' +const { default: server } = await import ('./lib/server.js') export default server diff --git a/lib/server.cjs b/lib/server.js similarity index 83% rename from lib/server.cjs rename to lib/server.js index dd8f96a4..d28afc43 100644 --- a/lib/server.cjs +++ b/lib/server.js @@ -19,44 +19,48 @@ // 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 http from 'http'; +import url from 'url'; +import { pipeline } from 'node:stream/promises'; +import { fileURLToPath } from 'url'; + // From npm -const express = require('express') -const hbs = require('express-hbs') -const glob = require('glob') -const async = require('async') -const f = require('flates') +import express from 'express'; +import hbs from 'express-hbs'; +import glob from 'glob'; +import async from 'async'; +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) +const window = new JSDOM('').window; +const DOMPurify = createDOMPurify(window); -// node-fetch is now ESM only -const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)) +// node-fetch is now ESM only — already ESM-style, leaving as-is +const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); // 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.cjs') -const defargs = require('./defaultargs.js') -const resolveClient = require('wiki-client/lib/resolve') -const pluginsFactory = require('./plugins.js') -const sitemapFactory = require('./sitemap.js') -const searchFactory = require('./search.js') +// 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'; const render = page => { return ( @@ -93,7 +97,7 @@ const render = page => { ) } // Set export objects for node and coffee to a function that generates a sfw server. -module.exports = exports = argv => { +const exports = async argv => { // Create the main application object, app. const app = express() @@ -103,7 +107,7 @@ module.exports = exports = argv => { // defaultargs.coffee exports a function that takes the argv object // that is passed in and then does its // best to supply sane defaults for any arguments that are missing. - argv = defargs.default(argv) + argv = defargs(argv) app.startOpts = argv @@ -128,18 +132,22 @@ 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).default(argv) - // Require the sitemap adapter and initialize it with options. - app.sitemaphandler = sitemaphandler = sitemapFactory.default(argv) + let pagehandler, sitemaphandler, searchhandler, securityhandler; + + // 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 - app.searchhandler = searchhandler = searchFactory.default(argv) + // Initialize search handler + app.searchhandler = searchhandler = searchFactory(argv); - // Require the security adapter and initialize it with options. - app.securityhandler = securityhandler = require(argv.security_type).default(log, loga, argv) + // Dynamically import security adapter (also dynamic) + 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 = '' @@ -198,7 +206,16 @@ module.exports = exports = argv => { maxAge: '1h', } - app.set('views', path.join(require.resolve('wiki-client/package.json'), '..', 'views')) +// app.set('views', path.join(require.resolve('wiki-client/package.json'), '..', 'views')) + // Convert ESM URL to file path + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + + // Resolve the path to wiki-client's package.json and build the views path + // import wikiPkgJsonPath from 'wiki-client/package.json' assert { type: 'json' }; + + const wikiClientRoot = path.dirname(fileURLToPath(import.meta.resolve('wiki-client/package.json'))); + app.set('views', path.join(wikiClientRoot, 'views')); app.set('view engine', 'html') app.engine('html', hbs.express4()) app.set('view options', { layout: false }) @@ -690,30 +707,84 @@ module.exports = exports = argv => { } } - app.get('/system/version.json', admin, (req, res) => { - const versions = {} - const wikiModule = module.parent.parent.parent - 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'] = {} - versions['plugins'] = {} - - glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (e, plugins) => { - plugins.map(plugin => { - if (plugin.includes('wiki-security')) { - versions.security[wikiModule.require(plugin + '/package').name] = wikiModule.require( - plugin + '/package', - ).version - } else { - versions.plugins[wikiModule.require(plugin + '/package').name] = wikiModule.require( - plugin + '/package', - ).version - } - res.json(versions) - }) - }) - }) +// app.get('/system/version.json', admin, (req, res) => { +// const versions = {} +// const wikiModule = module.parent.parent.parent +// 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'] = {} +// versions['plugins'] = {} +// +// glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (e, plugins) => { +// plugins.map(plugin => { +// if (plugin.includes('wiki-security')) { +// versions.security[wikiModule.require(plugin + '/package').name] = wikiModule.require( +// plugin + '/package', +// ).version +// } else { +// versions.plugins[wikiModule.require(plugin + '/package').name] = wikiModule.require( +// plugin + '/package', +// ).version +// } +// res.json(versions) +// }) +// }) +// }) + +// import { createRequire } from 'module'; +// import glob from 'glob'; +// import path from 'path'; +// import { fileURLToPath } from 'url'; +// +// const require = createRequire(import.meta.url); +// +// app.get('/system/version.json', admin, (req, res) => { +// const versions = {}; +// +// try { +// // Statically resolve packages +// const wikiPackage = require('./package.json'); +// const wikiServerPackage = require('wiki-server/package.json'); +// const wikiClientPackage = require('wiki-client/package.json'); +// +// versions[wikiPackage.name] = wikiPackage.version; +// versions[wikiServerPackage.name] = wikiServerPackage.version; +// versions[wikiClientPackage.name] = wikiClientPackage.version; +// +// versions['security'] = {}; +// versions['plugins'] = {}; +// +// // Dynamically resolve plugin packages +// glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (err, plugins) => { +// if (err) { +// console.error('Error loading plugins:', err); +// return res.status(500).json({ error: 'Failed to load plugin versions' }); +// } +// +// for (const plugin of plugins) { +// try { +// const pkg = require(path.join(argv.packageDir, plugin, 'package.json')); +// +// if (plugin.includes('wiki-security')) { +// versions.security[pkg.name] = pkg.version; +// } else { +// versions.plugins[pkg.name] = pkg.version; +// } +// } catch (e) { +// console.warn(`Failed to load package.json for ${plugin}:`, e.message); +// } +// } +// +// res.json(versions); +// }); +// } catch (e) { +// console.error('Error loading version info:', e.message); +// res.status(500).json({ error: 'Failed to load versions' }); +// } +// }); +//  + // ##### Proxy routes ##### @@ -940,3 +1011,6 @@ module.exports = exports = argv => { // Return app when called, so that it can be watched for events and shutdown with .close() externally. return app } + +export default exports +export {exports} diff --git a/test/server.js b/test/server.js index 60c33358..e9f097cd 100644 --- a/test/server.js +++ b/test/server.js @@ -10,7 +10,7 @@ const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) // CommonJS server module (.cjs) -const { default: server } = await import('../index.js') +const server = await import('../index.js') // ESM modules import random from '../lib/random_id.js' @@ -28,16 +28,18 @@ const argv = 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.default(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) }) }) diff --git a/test/sitemap.js b/test/sitemap.js index 75c33dc6..adf85049 100644 --- a/test/sitemap.js +++ b/test/sitemap.js @@ -11,7 +11,7 @@ const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) // Dynamic import of CommonJS module -const { default: server } = await import('../index.js') +const server = await import('../index.js') // ESM imports import random from '../lib/random_id.js' @@ -29,8 +29,11 @@ describe('sitemap', () => { let app = {} let runningServer = null - before(done => { - app = server.default(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) }) From ddb2beb66dad9f39d28d55a178a809222adff60a Mon Sep 17 00:00:00 2001 From: SamAxe <1377880+SamAxe@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:59:25 -0700 Subject: [PATCH 03/30] Formatting --- index.js | 2 +- lib/server.js | 238 ++++++++++++++++++++++++------------------------- test/server.js | 2 +- 3 files changed, 120 insertions(+), 122 deletions(-) diff --git a/index.js b/index.js index 69462aa1..1b9300b9 100644 --- a/index.js +++ b/index.js @@ -5,5 +5,5 @@ import('coffeescript') import('coffeescript/register.js') -const { default: server } = await import ('./lib/server.js') +const { default: server } = await import('./lib/server.js') export default server diff --git a/lib/server.js b/lib/server.js index d28afc43..f9817ce8 100644 --- a/lib/server.js +++ b/lib/server.js @@ -19,48 +19,47 @@ // npm install // Standard lib -import fs from 'fs'; -import path from 'path'; -import http from 'http'; -import url from 'url'; -import { pipeline } from 'node:stream/promises'; -import { fileURLToPath } from 'url'; - +import fs from 'fs' +import path from 'path' +import http from 'http' +import url from 'url' +import { pipeline } from 'node:stream/promises' +import { fileURLToPath } from 'url' // From npm -import express from 'express'; -import hbs from 'express-hbs'; -import glob from 'glob'; -import async from 'async'; -import f from 'flates'; +import express from 'express' +import hbs from 'express-hbs' +import glob from 'glob' +import async from 'async' +import f from 'flates' -import createDOMPurify from 'dompurify'; -import { JSDOM } from 'jsdom'; +import createDOMPurify from 'dompurify' +import { JSDOM } from 'jsdom' -const window = new JSDOM('').window; -const DOMPurify = createDOMPurify(window); +const window = new JSDOM('').window +const DOMPurify = createDOMPurify(window) // node-fetch is now ESM only — already ESM-style, leaving as-is -const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); +const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)) // Express 4 middleware -import logger from 'morgan'; -import cookieParser from 'cookie-parser'; -import methodOverride from 'method-override'; +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'; +import sessions from 'client-sessions' +import bodyParser from 'body-parser' +import errorHandler from 'errorhandler' // Local files // 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 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' const render = page => { return ( @@ -133,21 +132,21 @@ const exports = async argv => { next() } - let pagehandler, sitemaphandler, searchhandler, securityhandler; + let pagehandler, sitemaphandler, searchhandler, securityhandler // Dynamically import database adapter (since the module name is dynamic) - const dbModule = await import(argv.database.type); - app.pagehandler = pagehandler = dbModule.default(argv); + const dbModule = await import(argv.database.type) + app.pagehandler = pagehandler = dbModule.default(argv) // Initialize sitemap handler - app.sitemaphandler = sitemaphandler = sitemapFactory(argv); + app.sitemaphandler = sitemaphandler = sitemapFactory(argv) // Initialize search handler - app.searchhandler = searchhandler = searchFactory(argv); + app.searchhandler = searchhandler = searchFactory(argv) // Dynamically import security adapter (also dynamic) - const securityModule = await import(argv.security_type); - app.securityhandler = securityhandler = securityModule.default(log, loga, argv); + 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 = '' @@ -206,16 +205,16 @@ const exports = async argv => { maxAge: '1h', } -// app.set('views', path.join(require.resolve('wiki-client/package.json'), '..', 'views')) + // app.set('views', path.join(require.resolve('wiki-client/package.json'), '..', 'views')) // Convert ESM URL to file path - const __filename = fileURLToPath(import.meta.url); - const __dirname = path.dirname(__filename); + const __filename = fileURLToPath(import.meta.url) + const __dirname = path.dirname(__filename) // Resolve the path to wiki-client's package.json and build the views path // import wikiPkgJsonPath from 'wiki-client/package.json' assert { type: 'json' }; - const wikiClientRoot = path.dirname(fileURLToPath(import.meta.resolve('wiki-client/package.json'))); - app.set('views', path.join(wikiClientRoot, 'views')); + const wikiClientRoot = path.dirname(fileURLToPath(import.meta.resolve('wiki-client/package.json'))) + app.set('views', path.join(wikiClientRoot, 'views')) app.set('view engine', 'html') app.engine('html', hbs.express4()) app.set('view options', { layout: false }) @@ -707,84 +706,83 @@ const exports = async argv => { } } -// app.get('/system/version.json', admin, (req, res) => { -// const versions = {} -// const wikiModule = module.parent.parent.parent -// 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'] = {} -// versions['plugins'] = {} -// -// glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (e, plugins) => { -// plugins.map(plugin => { -// if (plugin.includes('wiki-security')) { -// versions.security[wikiModule.require(plugin + '/package').name] = wikiModule.require( -// plugin + '/package', -// ).version -// } else { -// versions.plugins[wikiModule.require(plugin + '/package').name] = wikiModule.require( -// plugin + '/package', -// ).version -// } -// res.json(versions) -// }) -// }) -// }) - -// import { createRequire } from 'module'; -// import glob from 'glob'; -// import path from 'path'; -// import { fileURLToPath } from 'url'; -// -// const require = createRequire(import.meta.url); -// -// app.get('/system/version.json', admin, (req, res) => { -// const versions = {}; -// -// try { -// // Statically resolve packages -// const wikiPackage = require('./package.json'); -// const wikiServerPackage = require('wiki-server/package.json'); -// const wikiClientPackage = require('wiki-client/package.json'); -// -// versions[wikiPackage.name] = wikiPackage.version; -// versions[wikiServerPackage.name] = wikiServerPackage.version; -// versions[wikiClientPackage.name] = wikiClientPackage.version; -// -// versions['security'] = {}; -// versions['plugins'] = {}; -// -// // Dynamically resolve plugin packages -// glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (err, plugins) => { -// if (err) { -// console.error('Error loading plugins:', err); -// return res.status(500).json({ error: 'Failed to load plugin versions' }); -// } -// -// for (const plugin of plugins) { -// try { -// const pkg = require(path.join(argv.packageDir, plugin, 'package.json')); -// -// if (plugin.includes('wiki-security')) { -// versions.security[pkg.name] = pkg.version; -// } else { -// versions.plugins[pkg.name] = pkg.version; -// } -// } catch (e) { -// console.warn(`Failed to load package.json for ${plugin}:`, e.message); -// } -// } -// -// res.json(versions); -// }); -// } catch (e) { -// console.error('Error loading version info:', e.message); -// res.status(500).json({ error: 'Failed to load versions' }); -// } -// }); -//  - + // app.get('/system/version.json', admin, (req, res) => { + // const versions = {} + // const wikiModule = module.parent.parent.parent + // 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'] = {} + // versions['plugins'] = {} + // + // glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (e, plugins) => { + // plugins.map(plugin => { + // if (plugin.includes('wiki-security')) { + // versions.security[wikiModule.require(plugin + '/package').name] = wikiModule.require( + // plugin + '/package', + // ).version + // } else { + // versions.plugins[wikiModule.require(plugin + '/package').name] = wikiModule.require( + // plugin + '/package', + // ).version + // } + // res.json(versions) + // }) + // }) + // }) + + // import { createRequire } from 'module'; + // import glob from 'glob'; + // import path from 'path'; + // import { fileURLToPath } from 'url'; + // + // const require = createRequire(import.meta.url); + // + // app.get('/system/version.json', admin, (req, res) => { + // const versions = {}; + // + // try { + // // Statically resolve packages + // const wikiPackage = require('./package.json'); + // const wikiServerPackage = require('wiki-server/package.json'); + // const wikiClientPackage = require('wiki-client/package.json'); + // + // versions[wikiPackage.name] = wikiPackage.version; + // versions[wikiServerPackage.name] = wikiServerPackage.version; + // versions[wikiClientPackage.name] = wikiClientPackage.version; + // + // versions['security'] = {}; + // versions['plugins'] = {}; + // + // // Dynamically resolve plugin packages + // glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (err, plugins) => { + // if (err) { + // console.error('Error loading plugins:', err); + // return res.status(500).json({ error: 'Failed to load plugin versions' }); + // } + // + // for (const plugin of plugins) { + // try { + // const pkg = require(path.join(argv.packageDir, plugin, 'package.json')); + // + // if (plugin.includes('wiki-security')) { + // versions.security[pkg.name] = pkg.version; + // } else { + // versions.plugins[pkg.name] = pkg.version; + // } + // } catch (e) { + // console.warn(`Failed to load package.json for ${plugin}:`, e.message); + // } + // } + // + // res.json(versions); + // }); + // } catch (e) { + // console.error('Error loading version info:', e.message); + // res.status(500).json({ error: 'Failed to load versions' }); + // } + // }); + //  // ##### Proxy routes ##### @@ -1013,4 +1011,4 @@ const exports = async argv => { } export default exports -export {exports} +export { exports } diff --git a/test/server.js b/test/server.js index e9f097cd..e627ddc6 100644 --- a/test/server.js +++ b/test/server.js @@ -37,7 +37,7 @@ describe('server', () => { let x = await server.default(argv) app = x -// app = server(argv) + // app = server(argv) app.once('owner-set', async () => { runningServer = await app.listen(app.startOpts.port, app.startOpts.host, done) }) From b8360cfd1fac48447b127b61996ae584add15e39 Mon Sep 17 00:00:00 2001 From: SamAxe <1377880+SamAxe@users.noreply.github.com> Date: Tue, 3 Jun 2025 18:21:48 -0700 Subject: [PATCH 04/30] anticipate version code and test --- lib/server.js | 105 ++++++++++++++++++++++++------------------------- test/server.js | 16 ++++++++ 2 files changed, 67 insertions(+), 54 deletions(-) diff --git a/lib/server.js b/lib/server.js index f9817ce8..efac4944 100644 --- a/lib/server.js +++ b/lib/server.js @@ -60,6 +60,8 @@ 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 render = page => { return ( @@ -491,7 +493,7 @@ const exports = async argv => { if (securityhandler.isAuthorized(req)) { next() } else { - console.log('rejecting', req.path) + console.log('rejecting 1', req.path) res.sendStatus(403) } } @@ -701,7 +703,7 @@ const exports = async argv => { if (securityhandler.isAdmin(req)) { next() } else { - console.log('rejecting', req.path) + console.log('rejecting 2', req.path) res.sendStatus(403) } } @@ -731,58 +733,53 @@ const exports = async argv => { // }) // }) - // import { createRequire } from 'module'; - // import glob from 'glob'; - // import path from 'path'; - // import { fileURLToPath } from 'url'; - // - // const require = createRequire(import.meta.url); - // - // app.get('/system/version.json', admin, (req, res) => { - // const versions = {}; - // - // try { - // // Statically resolve packages - // const wikiPackage = require('./package.json'); - // const wikiServerPackage = require('wiki-server/package.json'); - // const wikiClientPackage = require('wiki-client/package.json'); - // - // versions[wikiPackage.name] = wikiPackage.version; - // versions[wikiServerPackage.name] = wikiServerPackage.version; - // versions[wikiClientPackage.name] = wikiClientPackage.version; - // - // versions['security'] = {}; - // versions['plugins'] = {}; - // - // // Dynamically resolve plugin packages - // glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (err, plugins) => { - // if (err) { - // console.error('Error loading plugins:', err); - // return res.status(500).json({ error: 'Failed to load plugin versions' }); - // } - // - // for (const plugin of plugins) { - // try { - // const pkg = require(path.join(argv.packageDir, plugin, 'package.json')); - // - // if (plugin.includes('wiki-security')) { - // versions.security[pkg.name] = pkg.version; - // } else { - // versions.plugins[pkg.name] = pkg.version; - // } - // } catch (e) { - // console.warn(`Failed to load package.json for ${plugin}:`, e.message); - // } - // } - // - // res.json(versions); - // }); - // } catch (e) { - // console.error('Error loading version info:', e.message); - // res.status(500).json({ error: 'Failed to load versions' }); - // } - // }); - //  + const require = createRequire(import.meta.url); + + app.get('/system/version.json', admin, (req, res) => { + const versions = {}; + + try { + // Statically resolve packages + const wikiPackage = require('./package.json'); + const wikiServerPackage = require('wiki-server/package.json'); + const wikiClientPackage = require('wiki-client/package.json'); + + versions[wikiPackage.name] = wikiPackage.version; + versions[wikiServerPackage.name] = wikiServerPackage.version; + versions[wikiClientPackage.name] = wikiClientPackage.version; + + versions['security'] = {}; + versions['plugins'] = {}; + + // Dynamically resolve plugin packages + glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (err, plugins) => { + if (err) { + console.error('Error loading plugins:', err); + return res.status(500).json({ error: 'Failed to load plugin versions' }); + } + + for (const plugin of plugins) { + try { + const pkg = require(path.join(argv.packageDir, plugin, 'package.json')); + + if (plugin.includes('wiki-security')) { + versions.security[pkg.name] = pkg.version; + } else { + versions.plugins[pkg.name] = pkg.version; + } + } catch (e) { + console.warn(`Failed to load package.json for ${plugin}:`, e.message); + } + } + + res.json(versions); + }); + } catch (e) { + console.error('Error loading version info:', e.message); + res.status(500).json({ error: 'Failed to load versions' }); + } + }); + // ##### Proxy routes ##### diff --git a/test/server.js b/test/server.js index e627ddc6..6e34c2ff 100644 --- a/test/server.js +++ b/test/server.js @@ -236,4 +236,20 @@ describe('server', () => { throw err }) }) + +// Should be a version test, but doesn't seem it's supported in test mode yet. +// it('server should return a version', async () => { +// await request +// .get('/system/version.json') +// .expect(200) +// .expect('Content-Type', /json/) +// .then(res => { +// assert.equal(res.body.length, 1) +// +// assert.equal(res.body[0], 'adsf-test-page') +// }) +// .catch(err => { +// throw err +// }) +// }) }) From 88e8f1fe234009545c57a584d0b4abe1d904a9eb Mon Sep 17 00:00:00 2001 From: SamAxe <1377880+SamAxe@users.noreply.github.com> Date: Tue, 3 Jun 2025 18:54:05 -0700 Subject: [PATCH 05/30] Update default exports --- lib/defaultargs.js | 5 +---- lib/page.js | 5 +---- lib/plugins.js | 5 +---- lib/random_id.js | 4 +--- lib/search.js | 5 +---- lib/security.js | 5 +---- lib/server.js | 5 +---- lib/sitemap.js | 5 +---- 8 files changed, 8 insertions(+), 31 deletions(-) diff --git a/lib/defaultargs.js b/lib/defaultargs.js index e9b35b49..1e06369d 100644 --- a/lib/defaultargs.js +++ b/lib/defaultargs.js @@ -21,7 +21,7 @@ const getUserHome = () => { return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE } -const exports = argv => { +export default argv => { argv = argv || {} argv.root ||= __dirname // the directory that contains all the packages that makeup the wiki @@ -87,6 +87,3 @@ const exports = argv => { } return argv } - -export default exports -export { exports } diff --git a/lib/page.js b/lib/page.js index 583275c8..8141c340 100644 --- a/lib/page.js +++ b/lib/page.js @@ -38,7 +38,7 @@ const asSlug = name => // Export a function that generates a page handler // when called with options object. -const exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname fs.mkdir(argv.db, { recursive: true }, e => { @@ -456,6 +456,3 @@ const exports = argv => { return itself } - -export default exports -export { exports } diff --git a/lib/plugins.js b/lib/plugins.js index 04fda174..610315b6 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -13,7 +13,7 @@ import glob from 'glob' import { pathToFileURL } from 'node:url' // import forward from './forward.cjs'; // Uncomment if needed and adjust import style if it's not a default export -const 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 @@ -52,6 +52,3 @@ const exports = argv => { return { startServers } } - -export default exports -export { exports } diff --git a/lib/random_id.js b/lib/random_id.js index b0388c9f..e69dca9c 100644 --- a/lib/random_id.js +++ b/lib/random_id.js @@ -10,7 +10,5 @@ // 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('') +export default (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('') -export default random_id -export { random_id } diff --git a/lib/search.js b/lib/search.js index ddba08ca..53e092e0 100644 --- a/lib/search.js +++ b/lib/search.js @@ -16,7 +16,7 @@ import writeFileAtomic from 'write-file-atomic' import MiniSearch from 'minisearch' -const exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname let siteIndex = [] const queue = [] @@ -388,6 +388,3 @@ const exports = argv => { return itself } - -export default exports -export { exports } diff --git a/lib/security.js b/lib/security.js index bce81a3f..0e209a6c 100644 --- a/lib/security.js +++ b/lib/security.js @@ -17,7 +17,7 @@ import fs from 'node:fs' // Export a function that generates security handler // when called with options object. -const exports = (log, loga, argv) => { +export default (log, loga, argv) => { const security = {} // #### Private utility methods. #### @@ -92,6 +92,3 @@ const exports = (log, loga, argv) => { return security } - -export default exports -export { exports } diff --git a/lib/server.js b/lib/server.js index efac4944..e146e399 100644 --- a/lib/server.js +++ b/lib/server.js @@ -98,7 +98,7 @@ const render = page => { ) } // Set export objects for node and coffee to a function that generates a sfw server. -const exports = async argv => { +export default async argv => { // Create the main application object, app. const app = express() @@ -1006,6 +1006,3 @@ const exports = async argv => { // Return app when called, so that it can be watched for events and shutdown with .close() externally. return app } - -export default exports -export { exports } diff --git a/lib/sitemap.js b/lib/sitemap.js index 51b1fafe..d3fc5122 100644 --- a/lib/sitemap.js +++ b/lib/sitemap.js @@ -21,7 +21,7 @@ const asSlug = name => .replace(/[^A-Za-z0-9-]/g, '') .toLowerCase() -const exports = argv => { +export default argv => { const wikiName = new URL(argv.url).hostname let sitemap = [] @@ -285,6 +285,3 @@ const exports = argv => { return itself } - -export default exports -export { exports } From 2473b1a40d5410adc4cc963876f496868ac4e5d1 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 17 Jul 2025 09:43:43 +0100 Subject: [PATCH 06/30] A few extra ESM bits --- eslint.config.js | 2 +- lib/page.js | 3 -- lib/plugins.js | 1 - lib/server.js | 5 +- package-lock.json | 129 +++++++++++++++++++++------------------------- package.json | 2 +- test/package.json | 1 + 7 files changed, 62 insertions(+), 81 deletions(-) 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/lib/page.js b/lib/page.js index 81c81192..53796c0b 100644 --- a/lib/page.js +++ b/lib/page.js @@ -23,9 +23,6 @@ import fs from 'node:fs' import path from 'node:path' import events from 'node:events' -import glob from 'glob' - -import async from 'async' // import random_id from './random_id.cjs'; // Uncomment if needed import synopsis from 'wiki-client/lib/synopsis.js' // Add correct extension if necessary diff --git a/lib/plugins.js b/lib/plugins.js index be13b22d..b2bad35b 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -9,7 +9,6 @@ // support server-side plugins import fs from 'node:fs' -import glob from 'glob' import { pathToFileURL } from 'node:url' // import forward from './forward.cjs'; // Uncomment if needed and adjust import style if it's not a default export diff --git a/lib/server.js b/lib/server.js index 819b19de..684b0ebf 100644 --- a/lib/server.js +++ b/lib/server.js @@ -29,8 +29,6 @@ import { fileURLToPath } from 'url' // From npm import express from 'express' import hbs from 'express-hbs' -import glob from 'glob' -import async from 'async' import f from 'flates' import createDOMPurify from 'dompurify' @@ -59,8 +57,7 @@ import pluginsFactory from './plugins.js' import sitemapFactory from './sitemap.js' import searchFactory from './search.js' import { warn } from 'node:console' -import { createRequire } from 'module'; - +import { createRequire } from 'module' const render = page => { return ( diff --git a/package-lock.json b/package-lock.json index a05b5f92..81385262 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,9 +41,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.29.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz", - "integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==", + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", + "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", "dev": true, "license": "MIT", "engines": { @@ -53,13 +53,6 @@ "url": "https://eslint.org/donate" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, "node_modules/body-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", @@ -706,19 +699,19 @@ } }, "node_modules/eslint": { - "version": "9.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz", - "integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==", + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", + "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.1", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.14.0", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.29.0", + "@eslint/js": "9.31.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -809,9 +802,9 @@ } }, "node_modules/eslint/node_modules/@eslint/config-array": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", - "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -824,9 +817,9 @@ } }, "node_modules/eslint/node_modules/@eslint/config-helpers": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", - "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -834,9 +827,9 @@ } }, "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -881,32 +874,19 @@ } }, "node_modules/eslint/node_modules/@eslint/plugin-kit": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", - "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/eslint/node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", - "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -3291,9 +3271,9 @@ } }, "node_modules/globals": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", - "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", "engines": { @@ -3481,18 +3461,18 @@ } }, "node_modules/jsdom/node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/jsdom/node_modules/cssstyle": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.4.0.tgz", - "integrity": "sha512-W0Y2HOXlPkb2yaKrCVRjinYKciu/qSLEmK0K9mcfDei3zwlnHFEHAs/Du3cIRwPqY+J4JsiBzUjoHyc8RsJ03A==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", "license": "MIT", "dependencies": { "@asamuzakjp/css-color": "^3.2.0", @@ -3533,9 +3513,9 @@ } }, "node_modules/jsdom/node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "license": "MIT" }, "node_modules/jsdom/node_modules/entities": { @@ -3773,9 +3753,9 @@ } }, "node_modules/jsdom/node_modules/ws": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", - "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -3957,9 +3937,9 @@ "license": "MIT" }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -3973,14 +3953,14 @@ } }, "node_modules/supertest": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.1.tgz", - "integrity": "sha512-aI59HBTlG9e2wTjxGJV+DygfNLgnWbGdZxiA/sgrnNNikIW8lbDvCtF6RnhZoJ82nU7qv7ZLjrvWqCEm52fAmw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.3.tgz", + "integrity": "sha512-ORY0gPa6ojmg/C74P/bDoS21WL6FMXq5I8mawkEz30/zkwdu0gOeqstFy316vHG6OKxqQ+IbGneRemHI8WraEw==", "dev": true, "license": "MIT", "dependencies": { "methods": "^1.1.2", - "superagent": "^10.2.1" + "superagent": "^10.2.2" }, "engines": { "node": ">=14.18.0" @@ -4512,9 +4492,9 @@ } }, "node_modules/supertest/node_modules/superagent": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.1.tgz", - "integrity": "sha512-O+PCv11lgTNJUzy49teNAWLjBZfc+A1enOwTpLlH6/rsvKcTwcdTT8m9azGkVqM7HBl5jpyZ7KTPhHweokBcdg==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.2.tgz", + "integrity": "sha512-vWMq11OwWCC84pQaFPzF/VO3BrjkCeewuvJgt1jfV0499Z1QSAWN4EqfMM5WlFDDX9/oP8JjlDKpblrmEoyu4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4540,9 +4520,9 @@ "license": "ISC" }, "node_modules/wiki-client": { - "version": "0.31.2", - "resolved": "https://registry.npmjs.org/wiki-client/-/wiki-client-0.31.2.tgz", - "integrity": "sha512-dwHpfarpn25xlK86jNrXMqZJ5GrdGR4T6xL+6PPagx0+Wynf7P51ZXvJolvx4oA5y0JLpiXI7SBnX6iVEztKtg==", + "version": "0.31.3", + "resolved": "https://registry.npmjs.org/wiki-client/-/wiki-client-0.31.3.tgz", + "integrity": "sha512-+F9ZeZKvl7OmeFWAiRjuZsCcD7tcctPn8fFbh25mOH+942MTiKc8sngw+VOGfkG+B6JMQc+3neCELeifOKviyg==", "dev": true, "license": "MIT", "dependencies": { @@ -4554,6 +4534,13 @@ "node": ">=18.x" } }, + "node_modules/wiki-client/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/wiki-client/node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", diff --git a/package.json b/package.json index 53c10fc9..2c167be7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "type":"module", + "type": "module", "version": "0.25.10", "author": { "name": "Ward Cunningham", diff --git a/test/package.json b/test/package.json index c6dcf84e..f9d804b2 100644 --- a/test/package.json +++ b/test/package.json @@ -1,6 +1,7 @@ { "comment": "This exists so that the tests have a package to read", "name": "wiki-server", + "type": "module", "dependencies": { "wiki-plugin-activity": "0.1", "wiki-plugin-video": "0.1" From 6d64b1ca78c01e2433094054c2faa4af3cbf809f Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Tue, 29 Jul 2025 11:42:18 +0100 Subject: [PATCH 07/30] Replace require calls with ESM package.json imports The changes modernize plugin loading by switching from CommonJS require() to ESM dynamic imports, using the new JSON modules feature to load both package.json and plugin factory data. Requires changes to wiki, as it doesn't load ESM with top-level await. So, this might not be the final changes. --- lib/page.js | 17 ++++++++++++----- lib/server.js | 38 ++++++++++++++++++++++---------------- package.json | 2 +- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/lib/page.js b/lib/page.js index 53796c0b..8af49a05 100644 --- a/lib/page.js +++ b/lib/page.js @@ -22,8 +22,17 @@ import fs from 'node:fs' import path from 'node:path' +import { pathToFileURL } 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 packageJsonPath = path.join(process.cwd(), 'package.json') +const packageJsonUrl = pathToFileURL(packageJsonPath).href +const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } }) + // import random_id from './random_id.cjs'; // Uncomment if needed import synopsis from 'wiki-client/lib/synopsis.js' // Add correct extension if necessary @@ -44,13 +53,11 @@ export default 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/server.js b/lib/server.js index 684b0ebf..cfa2bb8c 100644 --- a/lib/server.js +++ b/lib/server.js @@ -58,6 +58,25 @@ 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 dynamic import to load package.json from the main application's working directory +const packageJsonPath = path.join(process.cwd(), 'package.json') +const packageJsonUrl = url.pathToFileURL(packageJsonPath).href +const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } }) + +// Load factory details at startup +const factories = [] +Object.keys(packageJson.dependencies) + .filter(depend => depend.startsWith('wiki-plugin')) + .forEach(async plugin => { + try { + const { default: factory } = await import(`${plugin}/factory.json`, { with: { type: 'json' } }) + factories.push(factory) + } catch { + // do nothing if plugin doesn't have a factory category. + } + }) const render = page => { return ( @@ -276,13 +295,10 @@ export default async 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)) }) @@ -392,19 +408,9 @@ export default async argv => { }) }) - app.get('/system/factories.json', (req, res) => { + app.get('/system/factories.json', async (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. - } - }) res.end(JSON.stringify(factories)) }) diff --git a/package.json b/package.json index 2c167be7..3d999172 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "scripts": { "prettier:format": "prettier --write './**/*.js'", "prettier:check": "prettier --check ./**/*.js", - "test": "node --test", + "test": "cd test; node --test", "update-authors": "node scripts/update-authors.js" }, "devDependencies": { From 5943d9de57902a8e5f03c93f23b73bfdade1cd57 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 7 Aug 2025 10:21:26 +0100 Subject: [PATCH 08/30] Add version test and test package version info --- test/package.json | 9 ++++++--- test/server.js | 33 ++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/test/package.json b/test/package.json index f9d804b2..ed3e0961 100644 --- a/test/package.json +++ b/test/package.json @@ -1,9 +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/server.js b/test/server.js index 6e34c2ff..4fd6626a 100644 --- a/test/server.js +++ b/test/server.js @@ -237,19 +237,22 @@ describe('server', () => { }) }) -// Should be a version test, but doesn't seem it's supported in test mode yet. -// it('server should return a version', async () => { -// await request -// .get('/system/version.json') -// .expect(200) -// .expect('Content-Type', /json/) -// .then(res => { -// assert.equal(res.body.length, 1) -// -// assert.equal(res.body[0], 'adsf-test-page') -// }) -// .catch(err => { -// throw err -// }) -// }) + // Should be a version test, but doesn't seem it's supported in test mode yet. + it('server should return a version', async () => { + await request + .get('/system/version.json') + .expect(200) + .expect('Content-Type', /json/) + .then(res => { + console.log('*+*', res.body) + 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 + }) + }) }) From 42ac7bddfd31756ef0908609c39669255afd20d1 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 7 Aug 2025 10:22:15 +0100 Subject: [PATCH 09/30] add test watch --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 3d999172..d731e93d 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "prettier:format": "prettier --write './**/*.js'", "prettier:check": "prettier --check ./**/*.js", "test": "cd test; node --test", + "watch": "cd test; node --test --watch", "update-authors": "node scripts/update-authors.js" }, "devDependencies": { From a5b6ecb81d46ddabd590402b70316c27a2bd8abb Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 7 Aug 2025 11:25:31 +0100 Subject: [PATCH 10/30] Refactor version endpoint to use dynamic imports --- lib/security.js | 11 ++++++++- lib/server.js | 63 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/lib/security.js b/lib/security.js index add437de..8b0b3423 100644 --- a/lib/security.js +++ b/lib/security.js @@ -84,7 +84,16 @@ export default (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 cfa2bb8c..7486d0b4 100644 --- a/lib/server.js +++ b/lib/server.js @@ -692,28 +692,57 @@ export default async argv => { } } - app.get('/system/version.json', admin, (req, res) => { + app.get('/system/version.json', admin, async (req, res) => { + const getPackageVersion = packageName => { + return new Promise(resolve => { + try { + // Use dynamic import to load package.json from the main application's working directory + const packageJsonPath = path.join(process.cwd(), 'node_modules', packageName, 'package.json') + const packageJsonUrl = url.pathToFileURL(packageJsonPath).href + import(packageJsonUrl, { 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 ##### From 6a287f6ed00f9b7cc76a84369b413f5c486eec4b Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 7 Aug 2025 14:15:42 +0100 Subject: [PATCH 11/30] Move factory loading from startup back to request time --- lib/server.js | 41 +++++++++++++++++++++++++---------------- test/server.js | 1 - 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/server.js b/lib/server.js index 7486d0b4..5ebff600 100644 --- a/lib/server.js +++ b/lib/server.js @@ -65,19 +65,6 @@ const packageJsonPath = path.join(process.cwd(), 'package.json') const packageJsonUrl = url.pathToFileURL(packageJsonPath).href const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } }) -// Load factory details at startup -const factories = [] -Object.keys(packageJson.dependencies) - .filter(depend => depend.startsWith('wiki-plugin')) - .forEach(async plugin => { - try { - const { default: factory } = await import(`${plugin}/factory.json`, { with: { type: 'json' } }) - factories.push(factory) - } catch { - // do nothing if plugin doesn't have a factory category. - } - }) - const render = page => { return ( f.div({ class: 'twins' }, f.p('')) + @@ -408,10 +395,32 @@ export default async argv => { }) }) - app.get('/system/factories.json', async (req, res) => { + app.get('/system/factories.json', (req, res) => { res.status(200) res.header('Content-Type', 'application/json') - res.end(JSON.stringify(factories)) + + const factories = [] + + const getPackageFactory = plugin => { + return new Promise(resolve => { + try { + import(`${plugin}/factory.json`, { with: { type: 'json' } }).then(({ default: factory }) => { + console.log(plugin, factory) + resolve(factories.push(factory)) + }) + } catch (error) { + resolve() + } + }) + } + + 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 ###### @@ -692,7 +701,7 @@ export default async argv => { } } - app.get('/system/version.json', admin, async (req, res) => { + app.get('/system/version.json', admin, (req, res) => { const getPackageVersion = packageName => { return new Promise(resolve => { try { diff --git a/test/server.js b/test/server.js index 4fd6626a..c1e3e94e 100644 --- a/test/server.js +++ b/test/server.js @@ -244,7 +244,6 @@ describe('server', () => { .expect(200) .expect('Content-Type', /json/) .then(res => { - console.log('*+*', res.body) assert.equal(res.body.wiki, '0.1') assert.equal(res.body['wiki-server'], '0.2') assert.equal(res.body['wiki-client'], '0.3') From e85c819a4623b4a7ec8049d6ebcd6e2f2e1b31b3 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 25 Sep 2025 11:45:57 +0100 Subject: [PATCH 12/30] Update import statements to modern ESM syntax remove unused imports --- index.js | 9 ++++++--- lib/server.js | 2 -- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 1b9300b9..658e262f 100644 --- a/index.js +++ b/index.js @@ -2,8 +2,11 @@ // Simple file so that if you require this directory // in node it instead requires ./lib/server.coffee // with coffee-script already loaded. -import('coffeescript') -import('coffeescript/register.js') +// import('coffeescript') +// import('coffeescript/register.js') -const { default: server } = await import('./lib/server.js') +// 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/server.js b/lib/server.js index 5ebff600..60d50217 100644 --- a/lib/server.js +++ b/lib/server.js @@ -21,10 +21,8 @@ // Standard lib import fs from 'fs' import path from 'path' -import http from 'http' import url from 'url' import { pipeline } from 'node:stream/promises' -import { fileURLToPath } from 'url' // From npm import express from 'express' From 1c7237a93264d79f324754d5731bcf9ecb05ab0b Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 25 Sep 2025 12:45:19 +0100 Subject: [PATCH 13/30] 0.26.0-rc.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e5bdbb70..7c5bf804 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.5", "license": "MIT", "dependencies": { "body-parser": "^2.2.0", diff --git a/package.json b/package.json index bc2174a6..c03448f0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.4", + "version": "0.26.0-rc.5", "type": "module", "author": { "name": "Ward Cunningham", From 65b68b4f28f7fdbba893c47af95916b4b67af45f Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 27 Sep 2025 17:17:07 +0100 Subject: [PATCH 14/30] Add index.js as main entry point --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c03448f0..abb1535a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "Andrew Shell ", "jon r " ], + "main": "index.js", "dependencies": { "body-parser": "^2.2.0", "client-sessions": "^0.8.0", From 89be7cc12d84969ef68b2f26086663a235a7ee5e Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 27 Sep 2025 17:18:38 +0100 Subject: [PATCH 15/30] 0.26.0-rc.6 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c5bf804..e50830ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.5", + "version": "0.26.0-rc.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.5", + "version": "0.26.0-rc.6", "license": "MIT", "dependencies": { "body-parser": "^2.2.0", diff --git a/package.json b/package.json index abb1535a..eadf7797 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.5", + "version": "0.26.0-rc.6", "type": "module", "author": { "name": "Ward Cunningham", From d71b24f8564c1d019f3ab69510f12ea116dcbe79 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 2 Oct 2025 11:58:25 +0100 Subject: [PATCH 16/30] Corrent plugin loading for ESM --- lib/plugins.js | 7 ++----- lib/search.js | 2 +- lib/server.js | 3 ++- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/plugins.js b/lib/plugins.js index b2bad35b..dfa7e087 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -39,11 +39,8 @@ export default 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/search.js b/lib/search.js index b0cd3b57..5d2cd4bc 100644 --- a/lib/search.js +++ b/lib/search.js @@ -14,7 +14,7 @@ import events from 'node:events' import url from 'node:url' import writeFileAtomic from 'write-file-atomic' -import MiniSearch from 'minisearch' +import miniSearch from 'minisearch' export default argv => { const wikiName = new URL(argv.url).hostname diff --git a/lib/server.js b/lib/server.js index 60d50217..6cd6ebd4 100644 --- a/lib/server.js +++ b/lib/server.js @@ -147,6 +147,7 @@ export default async argv => { app.searchhandler = searchhandler = searchFactory(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) @@ -966,7 +967,7 @@ export default async 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) From f1f1ccac2760415551d907dd682db0df77372e92 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 25 Oct 2025 17:34:21 +0100 Subject: [PATCH 17/30] improved import of plugin factory.json --- lib/server.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/server.js b/lib/server.js index 6cd6ebd4..bea763bf 100644 --- a/lib/server.js +++ b/lib/server.js @@ -402,14 +402,13 @@ export default async argv => { const getPackageFactory = plugin => { return new Promise(resolve => { - try { - import(`${plugin}/factory.json`, { with: { type: 'json' } }).then(({ default: factory }) => { - console.log(plugin, factory) + import(`${plugin}/factory.json`, { with: { type: 'json' } }) + .then(({ default: factory }) => { resolve(factories.push(factory)) }) - } catch (error) { - resolve() - } + .catch(() => { + resolve() + }) }) } From 5b9e59d90201a4bb8c6ae77f384812f0cd193b79 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 22 Nov 2025 15:02:15 +0000 Subject: [PATCH 18/30] update dependencies --- package-lock.json | 366 ++++++++++++++++++++++++++++------------------ package.json | 16 +- 2 files changed, 233 insertions(+), 149 deletions(-) diff --git a/package-lock.json b/package-lock.json index e50830ea..f8a7cb38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,26 +13,26 @@ "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", "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": { @@ -621,9 +621,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 +699,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 +759,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": { @@ -802,13 +801,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 +816,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": { @@ -864,9 +866,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 +876,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": { @@ -3271,9 +3273,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 +3301,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 +3339,48 @@ } } }, + "node_modules/jsdom/node_modules/@acemir/cssom": { + "version": "0.9.23", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.23.tgz", + "integrity": "sha512-2kJ1HxBKzPLbmhZpxBiTZggjtgCwKg1ma5RHShxvd6zgqhDEdEkzpiwe7jLkI2p2BrZvFCXIihdoMkl1H39VnA==", + "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.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.4", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.4.tgz", + "integrity": "sha512-buQDjkm+wDPXd6c13534URWZqbz0RP5PAhXZ+LIoa5LgwInT9HVJvGIJivg75vi8I13CxDGdTnz+aY5YUJlIAA==", "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" + "@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 +3420,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 +3435,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 +3468,25 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/jsdom/node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.17.tgz", + "integrity": "sha512-LCC++2h8pLUSPY+EsZmrrJ1EOUu+5iClpEiDhhdw3zRJpPbABML/N5lmRuBHjxtKm9VnRcsUzioyD0sekFMF0A==", + "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,30 +3515,53 @@ "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": { @@ -3587,10 +3656,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.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "license": "ISC", + "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 +3676,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 +3697,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 +3724,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 +3740,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.18", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.18.tgz", + "integrity": "sha512-lCcgTAgMxQ1JKOWrVGo6E69Ukbnx4Gc1wiYLRf6J5NN4HRYJtCby1rPF8rkQ4a6qqoFBK5dvjJ1zJ0F7VfDSvw==", "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "tldts-core": "^7.0.18" }, "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.18", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.18.tgz", + "integrity": "sha512-jqJC13oP4FFAahv4JT/0WTDrCF9Okv7lpKtOZUGPLiAnNbACcSg8Y8T+Z9xthOmRBqi/Sob4yi0TE0miRCvF7Q==", "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 +3794,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 +3824,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 +3930,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": { @@ -4520,9 +4604,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 +4615,7 @@ "underscore": "^1.13.6" }, "engines": { - "node": ">=18.x" + "node": ">=20.x" } }, "node_modules/wiki-client/node_modules/async": { @@ -4596,16 +4680,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": { diff --git a/package.json b/package.json index eadf7797..f1882e3c 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,16 @@ "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": { @@ -56,13 +56,13 @@ "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", "supertest": "^7.1.4", - "wiki-client": "^0.31.3", + "wiki-client": "^0.31.6", "wiki-plugin-activity": "0.7", "wiki-plugin-video": "^0.4" }, From aeb5b65111d0a0bca28f63dfd66ae538e196770c Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 22 Nov 2025 15:08:18 +0000 Subject: [PATCH 19/30] 0.26.0-rc.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8a7cb38..1e996f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.6", + "version": "0.26.0-rc.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.6", + "version": "0.26.0-rc.7", "license": "MIT", "dependencies": { "body-parser": "^2.2.0", diff --git a/package.json b/package.json index f1882e3c..cb2a6301 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.6", + "version": "0.26.0-rc.7", "type": "module", "author": { "name": "Ward Cunningham", From 8e7c18e35f4f854af5f67e40178fb579d9fe50b7 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 29 Nov 2025 16:56:19 +0000 Subject: [PATCH 20/30] Refactor package import with async fallback skip version test, will need extra work to get a fallback working --- lib/server.js | 34 ++++++++++++++++++++++++++-------- test/server.js | 2 +- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/server.js b/lib/server.js index bea763bf..8e7409a8 100644 --- a/lib/server.js +++ b/lib/server.js @@ -58,10 +58,30 @@ import { warn } from 'node:console' import { createRequire } from 'module' const require = createRequire(import.meta.url) -// Use dynamic import to load package.json from the main application's working directory -const packageJsonPath = path.join(process.cwd(), 'package.json') -const packageJsonUrl = url.pathToFileURL(packageJsonPath).href -const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } }) +// 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 () => { + return new Promise(resolve => { + import('wiki/package.json', { with: { type: 'json' } }) + .then(imported => { + resolve(imported.default) + }) + .catch(e => { + return e + }) + .then(async () => { + 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 ( @@ -703,10 +723,8 @@ export default async argv => { const getPackageVersion = packageName => { return new Promise(resolve => { try { - // Use dynamic import to load package.json from the main application's working directory - const packageJsonPath = path.join(process.cwd(), 'node_modules', packageName, 'package.json') - const packageJsonUrl = url.pathToFileURL(packageJsonPath).href - import(packageJsonUrl, { with: { type: 'json' } }).then(({ default: packageJson }) => { + // Use import to load package.json from the main application's working directory + import('wiki/package.json', { with: { type: 'json' } }).then(({ default: packageJson }) => { resolve({ [packageName]: packageJson.version }) }) } catch (error) { diff --git a/test/server.js b/test/server.js index c1e3e94e..b6ed51d4 100644 --- a/test/server.js +++ b/test/server.js @@ -238,7 +238,7 @@ describe('server', () => { }) // Should be a version test, but doesn't seem it's supported in test mode yet. - it('server should return a version', async () => { + it.skip('server should return a version', async () => { await request .get('/system/version.json') .expect(200) From b07f14cec9af25efda63850e28b20d30ed0bd0af Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Mon, 1 Dec 2025 11:24:21 +0000 Subject: [PATCH 21/30] update dependencies --- package-lock.json | 342 ++++++++++++++++++++++------------------------ package.json | 4 +- 2 files changed, 165 insertions(+), 181 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1e996f86..4a62e98e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.26.0-rc.7", "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", @@ -30,7 +30,7 @@ "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.6", "wiki-plugin-activity": "0.7", @@ -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" @@ -791,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": { @@ -842,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": { @@ -854,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" }, @@ -900,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", @@ -1120,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": { @@ -1427,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": { @@ -1860,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": { @@ -1873,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": { @@ -2009,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": { @@ -2274,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": { @@ -2396,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": { @@ -2611,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": { @@ -2650,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" @@ -2867,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": { @@ -2952,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": { @@ -3021,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": { @@ -3082,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", @@ -3340,9 +3324,9 @@ } }, "node_modules/jsdom/node_modules/@acemir/cssom": { - "version": "0.9.23", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.23.tgz", - "integrity": "sha512-2kJ1HxBKzPLbmhZpxBiTZggjtgCwKg1ma5RHShxvd6zgqhDEdEkzpiwe7jLkI2p2BrZvFCXIihdoMkl1H39VnA==", + "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": { @@ -3359,9 +3343,9 @@ } }, "node_modules/jsdom/node_modules/@asamuzakjp/dom-selector": { - "version": "6.7.4", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.4.tgz", - "integrity": "sha512-buQDjkm+wDPXd6c13534URWZqbz0RP5PAhXZ+LIoa5LgwInT9HVJvGIJivg75vi8I13CxDGdTnz+aY5YUJlIAA==", + "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", @@ -3469,9 +3453,9 @@ } }, "node_modules/jsdom/node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.17.tgz", - "integrity": "sha512-LCC++2h8pLUSPY+EsZmrrJ1EOUu+5iClpEiDhhdw3zRJpPbABML/N5lmRuBHjxtKm9VnRcsUzioyD0sekFMF0A==", + "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", @@ -3565,9 +3549,9 @@ } }, "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" @@ -3656,10 +3640,10 @@ "license": "MIT" }, "node_modules/jsdom/node_modules/lru-cache": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", - "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", - "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" } @@ -3740,21 +3724,21 @@ "license": "MIT" }, "node_modules/jsdom/node_modules/tldts": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.18.tgz", - "integrity": "sha512-lCcgTAgMxQ1JKOWrVGo6E69Ukbnx4Gc1wiYLRf6J5NN4HRYJtCby1rPF8rkQ4a6qqoFBK5dvjJ1zJ0F7VfDSvw==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "license": "MIT", "dependencies": { - "tldts-core": "^7.0.18" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/jsdom/node_modules/tldts-core": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.18.tgz", - "integrity": "sha512-jqJC13oP4FFAahv4JT/0WTDrCF9Okv7lpKtOZUGPLiAnNbACcSg8Y8T+Z9xthOmRBqi/Sob4yi0TE0miRCvF7Q==", + "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": { @@ -4021,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": { @@ -4064,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": { @@ -4149,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": { @@ -4259,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": { @@ -4727,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 cb2a6301..750f26b4 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ ], "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", @@ -60,7 +60,7 @@ "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.6", "wiki-plugin-activity": "0.7", From 4c9a50aff30186fad17ec724aa85be4562c6e8c7 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Mon, 1 Dec 2025 11:26:25 +0000 Subject: [PATCH 22/30] 0.26.0-rc.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4a62e98e..a1f902f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.7", + "version": "0.26.0-rc.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.7", + "version": "0.26.0-rc.8", "license": "MIT", "dependencies": { "body-parser": "^2.2.1", diff --git a/package.json b/package.json index 750f26b4..b4a5c130 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.7", + "version": "0.26.0-rc.8", "type": "module", "author": { "name": "Ward Cunningham", From 1fc84685e79423ec2f11307e8e404f1b9d034fe5 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Mon, 1 Dec 2025 15:24:14 +0000 Subject: [PATCH 23/30] import alt only if not already done --- lib/page.js | 30 ++++++++++++++++++++++++++---- lib/server.js | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/lib/page.js b/lib/page.js index 8af49a05..60d549bd 100644 --- a/lib/page.js +++ b/lib/page.js @@ -22,16 +22,38 @@ import fs from 'node:fs' import path from 'node:path' -import { pathToFileURL } from 'node:url' +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 packageJsonPath = path.join(process.cwd(), 'package.json') -const packageJsonUrl = pathToFileURL(packageJsonPath).href -const { default: packageJson } = await import(packageJsonUrl, { 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() // import random_id from './random_id.cjs'; // Uncomment if needed import synopsis from 'wiki-client/lib/synopsis.js' // Add correct extension if necessary diff --git a/lib/server.js b/lib/server.js index 8e7409a8..9e625f73 100644 --- a/lib/server.js +++ b/lib/server.js @@ -61,15 +61,18 @@ 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' } }) From a27ab9f1eef16ac5b21d726ff754068afa51a66b Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Tue, 2 Dec 2025 09:25:13 +0000 Subject: [PATCH 24/30] requested package, not just wiki --- lib/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/server.js b/lib/server.js index 9e625f73..9401ff5a 100644 --- a/lib/server.js +++ b/lib/server.js @@ -727,7 +727,7 @@ export default async argv => { return new Promise(resolve => { try { // Use import to load package.json from the main application's working directory - import('wiki/package.json', { with: { type: 'json' } }).then(({ default: packageJson }) => { + import(`${packageName}/package.json`, { with: { type: 'json' } }).then(({ default: packageJson }) => { resolve({ [packageName]: packageJson.version }) }) } catch (error) { From a6f748550ff58aec8c01d4416cadb88c7982d62d Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Tue, 2 Dec 2025 09:30:33 +0000 Subject: [PATCH 25/30] 0.26.0-rc.9 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1f902f2..bcb048e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.8", + "version": "0.26.0-rc.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.8", + "version": "0.26.0-rc.9", "license": "MIT", "dependencies": { "body-parser": "^2.2.1", diff --git a/package.json b/package.json index b4a5c130..e1605741 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.8", + "version": "0.26.0-rc.9", "type": "module", "author": { "name": "Ward Cunningham", From 97baca72d46fc3d72e07c4faf97f8c9ae38625d9 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 4 Dec 2025 10:10:49 +0000 Subject: [PATCH 26/30] remove extra trailing blank line --- lib/random_id.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/random_id.js b/lib/random_id.js index e69dca9c..61762f35 100644 --- a/lib/random_id.js +++ b/lib/random_id.js @@ -11,4 +11,3 @@ // chars that defaults to 16 and returns a random id. export default (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('') - From 2a71704438fc796213a99e28533d06f033b699f0 Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 4 Dec 2025 12:08:56 +0000 Subject: [PATCH 27/30] fix for fedwiki/wiki-server#203 `req.hostname` is not always set, but can be determined from args. --- lib/server.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/server.js b/lib/server.js index 9401ff5a..4e106c80 100644 --- a/lib/server.js +++ b/lib/server.js @@ -135,6 +135,8 @@ export default async argv => { app.startOpts = argv + const wikiName = new URL(argv.url).hostname + const log = (...stuff) => { if (argv.debug) console.log(stuff) } @@ -255,7 +257,7 @@ export default async 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()) From ecf900702ff6104bca0d7b458caef8c4b379f06e Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 4 Dec 2025 12:14:02 +0000 Subject: [PATCH 28/30] 0.26.0-rc.10 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bcb048e5..541f6d79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.9", + "version": "0.26.0-rc.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.9", + "version": "0.26.0-rc.10", "license": "MIT", "dependencies": { "body-parser": "^2.2.1", diff --git a/package.json b/package.json index e1605741..d12d5576 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.9", + "version": "0.26.0-rc.10", "type": "module", "author": { "name": "Ward Cunningham", From ecf9adfe5ada1402e2f2e7445d4c4aeb97634efc Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 6 Dec 2025 09:39:16 +0000 Subject: [PATCH 29/30] also dotfiles for default favicon this one got missed when dotfiles became a required setting. --- lib/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/server.js b/lib/server.js index 4e106c80..e2ad4cb9 100644 --- a/lib/server.js +++ b/lib/server.js @@ -497,7 +497,7 @@ export default async argv => { if (!err) { res.sendFile(favLoc, { dotfiles: 'allow' }) } else { - res.sendFile(defaultFavLoc) + res.sendFile(defaultFavLoc, { dotfiles: 'allow' }) } }) }) From 4646d8c94507ac8ee1a80aad4d96544448b7e36a Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Sat, 6 Dec 2025 09:40:42 +0000 Subject: [PATCH 30/30] 0.26.0-rc.11 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 541f6d79..55e98da2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wiki-server", - "version": "0.26.0-rc.10", + "version": "0.26.0-rc.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wiki-server", - "version": "0.26.0-rc.10", + "version": "0.26.0-rc.11", "license": "MIT", "dependencies": { "body-parser": "^2.2.1", diff --git a/package.json b/package.json index d12d5576..ec5822a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wiki-server", "description": "A Federated Wiki Server", - "version": "0.26.0-rc.10", + "version": "0.26.0-rc.11", "type": "module", "author": { "name": "Ward Cunningham",