wiki-server 0.26.0-rc.0 → 0.26.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/page.js CHANGED
@@ -13,7 +13,6 @@
13
13
  const fs = require('fs')
14
14
  const path = require('path')
15
15
  const events = require('events')
16
- const glob = require('glob')
17
16
 
18
17
  const async = require('async')
19
18
 
@@ -35,6 +34,25 @@ module.exports = exports = argv => {
35
34
  if (e) throw e
36
35
  })
37
36
 
37
+ // create a list of plugin pages.
38
+ const pluginPages = new Map()
39
+ Object.keys(require.main.require('./package').dependencies)
40
+ .filter(depend => depend.startsWith('wiki-plugin'))
41
+ .forEach(plugin => {
42
+ const pagesPath = path.join(
43
+ path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })),
44
+ 'pages',
45
+ )
46
+ fs.readdir(pagesPath, { withFileTypes: true }, (err, entries) => {
47
+ if (err) return
48
+ entries.forEach(entry => {
49
+ if (entry.isFile() && !pluginPages.has(entry.name)) {
50
+ pluginPages.set(entry.name, { pluginName: plugin, pluginPath: entry.parentPath })
51
+ }
52
+ })
53
+ })
54
+ })
55
+
38
56
  // #### Private utility methods. ####
39
57
  const load_parse = (loc, cb, annotations = {}) => {
40
58
  let page
@@ -46,14 +64,13 @@ module.exports = exports = argv => {
46
64
  const errorPage = path.basename(loc)
47
65
  const errorPagePath = path.dirname(loc)
48
66
  const recyclePage = path.resolve(errorPagePath, '..', 'recycle', errorPage)
49
- // TODO: fs.exists depreciated
50
- fs.exists(path.dirname(recyclePage), exists => {
51
- if (exists) {
67
+ fs.access(path.dirname(recyclePage), fs.constants.F_OK, err => {
68
+ if (!err) {
52
69
  fs.rename(loc, recyclePage, err => {
53
70
  if (err) {
54
- console.log('ERROR: moving problem page #{loc} to recycler', err)
71
+ console.log(`ERROR: moving problem page ${loc} to recycler`, err)
55
72
  } else {
56
- console.log('ERROR: problem page #{loc} moved to recycler')
73
+ console.log(`ERROR: problem page ${loc} moved to recycler`)
57
74
  }
58
75
  })
59
76
  } else {
@@ -63,9 +80,9 @@ module.exports = exports = argv => {
63
80
  } else {
64
81
  fs.rename(loc, recyclePage, err => {
65
82
  if (err) {
66
- console.log('ERROR: moving problem page #{loc} to recycler', err)
83
+ console.log(`ERROR: moving problem page ${loc} to recycler`, err)
67
84
  } else {
68
- console.log('ERROR: problem page #{loc} moved to recycler')
85
+ console.log(`ERROR: problem page ${loc} moved to recycler`)
69
86
  }
70
87
  })
71
88
  }
@@ -104,9 +121,8 @@ module.exports = exports = argv => {
104
121
  const tryDefaults = (file, cb) => {
105
122
  const lastDefault = cb => {
106
123
  const defloc = path.join(argv.root, 'default-data', 'pages', file)
107
- // TODO: fs.exists depreciated
108
- fs.exists(defloc, exists => {
109
- if (exists) {
124
+ fs.access(defloc, fs.constants.F_OK, err => {
125
+ if (!err) {
110
126
  cb(defloc)
111
127
  } else {
112
128
  cb(null)
@@ -115,10 +131,8 @@ module.exports = exports = argv => {
115
131
  }
116
132
  if (argv.defaults) {
117
133
  const defloc = path.join(argv.data, '..', argv.defaults, 'pages', file)
118
- console.log('firstDefault', defloc)
119
- // TODO: fs.exists depreciated
120
- fs.exists(defloc, exists => {
121
- if (exists) {
134
+ fs.access(defloc, fs.constants.F_OK, err => {
135
+ if (!err) {
122
136
  cb(defloc)
123
137
  } else {
124
138
  lastDefault(cb)
@@ -138,22 +152,19 @@ module.exports = exports = argv => {
138
152
  case 'delete':
139
153
  if (file.startsWith('recycler/')) {
140
154
  // delete from recycler
141
- // TODO: fs.exists depreciated
142
- fs.exists(loc, exists => {
143
- if (exists)
155
+ fs.access(loc, fs.constants.F_OK, err => {
156
+ if (!err)
144
157
  fs.unlink(loc, err => {
145
158
  cb(err)
146
159
  })
147
160
  })
148
161
  } else {
149
162
  // move page to recycler
150
- // TODO: fs.exists depreciated
151
- fs.exists(loc, exists => {
152
- if (exists) {
163
+ fs.access(loc, fs.constants.F_OK, err => {
164
+ if (!err) {
153
165
  const recycleLoc = path.join(argv.recycler, file)
154
- // TODO: fs.exists depreciated
155
- fs.exists(path.dirname(recycleLoc), exists => {
156
- if (exists) {
166
+ fs.access(path.dirname(recycleLoc), fs.constants.F_OK, err => {
167
+ if (!err) {
157
168
  fs.rename(loc, recycleLoc, err => {
158
169
  cb(err)
159
170
  })
@@ -203,13 +214,11 @@ module.exports = exports = argv => {
203
214
  return
204
215
  }
205
216
 
206
- // TODO: fs.exists depreciated
207
- fs.exists(loc, exists => {
208
- if (exists) {
217
+ fs.access(loc, fs.constants.F_OK, err => {
218
+ if (!err) {
209
219
  const recycleLoc = path.join(argv.recycler, file)
210
- // TODO: fs.exists depreciated
211
- fs.exists(path.dirname(recycleLoc), exists => {
212
- if (exists) {
220
+ fs.access(path.dirname(recycleLoc), fs.constants.F_OK, err => {
221
+ if (!err) {
213
222
  copyFile(loc, recycleLoc, err => {
214
223
  cb(err)
215
224
  })
@@ -229,42 +238,20 @@ module.exports = exports = argv => {
229
238
  break
230
239
  }
231
240
  case 'get':
232
- // TODO: fs.exists depreciated
233
- fs.exists(loc, exists => {
234
- if (exists) {
241
+ fs.access(loc, fs.constants.F_OK, err => {
242
+ if (!err) {
235
243
  load_parse(loc, cb, { plugin: undefined })
236
244
  } else {
237
245
  tryDefaults(file, defloc => {
238
246
  if (defloc) {
239
247
  load_parse(defloc, cb)
240
248
  } else {
241
- glob('wiki-plugin-*/pages', { cwd: argv.packageDir }, (e, plugins) => {
242
- if (e) return cb(e)
243
-
244
- // if no plugins found
245
- if (plugins.length === 0) {
246
- cb(null, 'Page not found', 404)
247
- }
248
-
249
- let count = plugins.length
250
- const giveUp = () => {
251
- count -= 1
252
- if (count === 0) {
253
- cb(null, 'Page not found', 404)
254
- }
255
- }
256
- plugins.forEach(plugin => {
257
- const pluginName = plugin.slice(12, -6)
258
- const pluginloc = path.join(argv.packageDir, plugin, file)
259
- fs.exists(pluginloc, exists => {
260
- if (exists) {
261
- load_parse(pluginloc, cb, { plugin: pluginName })
262
- } else {
263
- giveUp()
264
- }
265
- })
266
- })
267
- })
249
+ if (pluginPages.has(file)) {
250
+ const { pluginName, pluginPath } = pluginPages.get(file)
251
+ load_parse(path.join(pluginPath, file), cb, { plugin: pluginName.slice(12) })
252
+ } else {
253
+ cb(null, 'Page not found', 404)
254
+ }
268
255
  }
269
256
  })
270
257
  }
@@ -272,11 +259,11 @@ module.exports = exports = argv => {
272
259
  break
273
260
  case 'put':
274
261
  page = JSON.stringify(page, null, 2)
275
- fs.exists(path.dirname(loc), exists => {
276
- if (exists) {
262
+ fs.access(path.dirname(loc), fs.constants.F_OK, err => {
263
+ if (!err) {
277
264
  fs.writeFile(loc, page, err => {
278
265
  if (err) {
279
- console.log('ERROR: write file #{loc} ', err)
266
+ console.log(`ERROR: write file ${loc} `, err)
280
267
  }
281
268
  cb(err)
282
269
  })
@@ -285,7 +272,7 @@ module.exports = exports = argv => {
285
272
  if (err) cb(err)
286
273
  fs.writeFile(loc, page, err => {
287
274
  if (err) {
288
- console.log('ERROR: write file #{loc} ', err)
275
+ console.log(`ERROR: write file ${loc} `, err)
289
276
  }
290
277
  cb(err)
291
278
  })
@@ -294,7 +281,7 @@ module.exports = exports = argv => {
294
281
  })
295
282
  break
296
283
  default:
297
- console.log('pagehandler: unrecognized action #{action}')
284
+ console.log(`pagehandler: unrecognized action ${action}`)
298
285
  }
299
286
  }
300
287
 
@@ -407,7 +394,7 @@ module.exports = exports = argv => {
407
394
  try {
408
395
  pageLinksMap = page.story.reduce(extractPageLinks, new Map())
409
396
  } catch (err) {
410
- console.log('METADATA *** #{wikiName} reduce to extract links on #{file} failed', err.message)
397
+ console.log(`METADATA *** ${wikiName} reduce to extract links on ${file} failed`, err.message)
411
398
  pageLinksMap = []
412
399
  }
413
400
  //
package/lib/plugins.js CHANGED
@@ -9,7 +9,6 @@
9
9
  // support server-side plugins
10
10
 
11
11
  const fs = require('node:fs')
12
- const glob = require('glob')
13
12
  const { pathToFileURL } = require('node:url')
14
13
  // forward = require './forward'
15
14
 
@@ -24,8 +23,8 @@ module.exports = exports = argv => {
24
23
 
25
24
  const startServer = (params, plugin) => {
26
25
  const server = `${argv.packageDir}/${plugin}/server/server.js`
27
- fs.exists(server, exists => {
28
- if (exists) {
26
+ fs.access(server, fs.constants.F_OK, err => {
27
+ if (!err) {
29
28
  console.log('starting plugin', plugin)
30
29
  import(pathToFileURL(server))
31
30
  .then(exported => {
@@ -43,11 +42,12 @@ module.exports = exports = argv => {
43
42
  // emitter = new events.EventEmitter()
44
43
  // forward.init params.app, emitter
45
44
  // params.emitter = emitter
46
- glob('wiki-plugin-*', { cwd: argv.packageDir }, (e, plugins) => {
47
- plugins.forEach(plugin => {
45
+
46
+ Object.keys(require.main.require('./package').dependencies)
47
+ .filter(depend => depend.startsWith('wiki-plugin'))
48
+ .forEach(plugin => {
48
49
  startServer(params, plugin)
49
50
  })
50
- })
51
51
  }
52
52
 
53
53
  return { startServers }
package/lib/search.js CHANGED
@@ -85,8 +85,8 @@ module.exports = exports = argv => {
85
85
 
86
86
  const searchSave = (siteIndex, cb) => {
87
87
  // save index to file
88
- fs.exists(argv.status, exists => {
89
- if (exists) {
88
+ fs.access(argv.status, fs.constants.F_OK, err => {
89
+ if (!err) {
90
90
  writeFileAtomic(siteIndexLoc, JSON.stringify(siteIndex), e => {
91
91
  if (e) return cb(e)
92
92
  touch(indexUpdateFlag, () => {
@@ -108,8 +108,8 @@ module.exports = exports = argv => {
108
108
 
109
109
  const searchRestore = cb => {
110
110
  // restore index, or create if it doesn't already exist
111
- fs.exists(siteIndexLoc, exists => {
112
- if (exists) {
111
+ fs.access(siteIndexLoc, fs.constants.F_OK, err => {
112
+ if (!err) {
113
113
  fs.readFile(siteIndexLoc, (err, data) => {
114
114
  if (err) return cb(err)
115
115
  try {
@@ -250,7 +250,7 @@ module.exports = exports = argv => {
250
250
  // we save the pagehandler, so we can recreate the site index if it is removed
251
251
  searchPageHandler = searchPageHandler ?? pagehandler
252
252
 
253
- //timeLabel = "SITE INDEX #{wikiName} : Created"
253
+ //timeLabel = `SITE INDEX ${wikiName} : Created`
254
254
  //console.time timeLabel
255
255
 
256
256
  pagehandler.slugs((e, slugs) => {
package/lib/security.js CHANGED
@@ -41,8 +41,8 @@ module.exports = exports = (log, loga, argv) => {
41
41
 
42
42
  // Retrieve owner infomation from identity file in status directory
43
43
  security.retrieveOwner = cb => {
44
- fs.exists(idFile, exists => {
45
- if (exists) {
44
+ fs.access(idFile, fs.constants.F_OK, err => {
45
+ if (!err) {
46
46
  fs.readFile(idFile, (err, data) => {
47
47
  if (err) return cb(err)
48
48
  owner += data
package/lib/server.js CHANGED
@@ -28,7 +28,6 @@ const { pipeline } = require('node:stream/promises')
28
28
  // From npm
29
29
  const express = require('express')
30
30
  const hbs = require('express-hbs')
31
- const glob = require('glob')
32
31
  const async = require('async')
33
32
  const f = require('flates')
34
33
 
@@ -38,8 +37,7 @@ const { JSDOM } = require('jsdom')
38
37
  const window = new JSDOM('').window
39
38
  const DOMPurify = createDOMPurify(window)
40
39
 
41
- // node-fetch is now ESM only
42
- const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args))
40
+ // Using native fetch API (available in Node.js 18+)
43
41
 
44
42
  // Express 4 middleware
45
43
  const logger = require('morgan')
@@ -163,7 +161,7 @@ module.exports = exports = argv => {
163
161
 
164
162
  const remoteGet = (remote, slug, cb) => {
165
163
  // assume http, as we know no better at this point and we need to specify a protocol.
166
- const remoteURL = new URL('http://#{remote}/#{slug}.json').toString()
164
+ const remoteURL = new URL(`http://${remote}/${slug}.json`).toString()
167
165
  // set a two second timeout
168
166
  fetch(remoteURL, { signal: AbortSignal.timeout(2000) })
169
167
  .then(res => {
@@ -271,13 +269,16 @@ module.exports = exports = argv => {
271
269
  app.use('/assets', cors, express.static(argv.assets))
272
270
 
273
271
  // Add static routes to the plugins client.
274
- glob('wiki-plugin-*/client', { cwd: argv.packageDir }, (e, plugins) => {
275
- plugins.map(plugin => {
276
- const pluginName = plugin.slice(12, -7)
277
- const pluginPath = '/plugins/' + pluginName
278
- app.use(pluginPath, cors, express.static(path.join(argv.packageDir, plugin), staticPathOptions))
272
+ Object.keys(require.main.require('./package').dependencies)
273
+ .filter(depend => depend.startsWith('wiki-plugin'))
274
+ .forEach(plugin => {
275
+ const clientPath = path.join(
276
+ path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })),
277
+ 'client',
278
+ )
279
+ const pluginPath = '/plugins/' + plugin.slice(12)
280
+ app.use(pluginPath, cors, express.static(clientPath, staticPathOptions))
279
281
  })
280
- })
281
282
 
282
283
  // Add static routes to the security client.
283
284
  if (argv.security != './security') {
@@ -387,32 +388,17 @@ module.exports = exports = argv => {
387
388
  app.get('/system/factories.json', (req, res) => {
388
389
  res.status(200)
389
390
  res.header('Content-Type', 'application/json')
390
- // Plugins are located in packages in argv.packageDir, with package names of the form wiki-plugin-*
391
- glob(path.join(argv.packageDir, 'wiki-plugin-*', 'factory.json'), (e, files) => {
392
- if (e) {
393
- return res.e(e)
394
- }
395
-
396
- const doFactories = (file, cb) => {
397
- fs.readFile(file, (err, data) => {
398
- if (err) {
399
- return cb()
400
- }
401
- try {
402
- const factory = JSON.parse(data)
403
- cb(null, factory)
404
- } catch (err) {
405
- return cb()
406
- }
407
- })
408
- }
409
- async.map(files, doFactories, (e, factories) => {
410
- if (e) {
411
- res.e(e)
391
+ const factories = []
392
+ Object.keys(require.main.require('./package').dependencies)
393
+ .filter(depend => depend.startsWith('wiki-plugin'))
394
+ .forEach(plugin => {
395
+ try {
396
+ factories.push(require.main.require(`${plugin}/factory`))
397
+ } catch {
398
+ // do nothing if plugin doesn't have a factory category.
412
399
  }
413
- res.end(JSON.stringify(factories))
414
400
  })
415
- })
401
+ res.end(JSON.stringify(factories))
416
402
  })
417
403
 
418
404
  // ###### Json Routes ######
@@ -444,7 +430,7 @@ module.exports = exports = argv => {
444
430
  // If themes doesn't exist send 404 and let the client
445
431
  // deal with it.
446
432
  app.get(/^\/theme\/(\w+\.\w+)$/, cors, (req, res) => {
447
- res.sendFile(path.join(argv.status, 'theme', req.params[0]), e => {
433
+ res.sendFile(path.join(argv.status, 'theme', req.params[0]), { dotfiles: 'allow' }, e => {
448
434
  if (e) {
449
435
  // swallow the error if the theme does not exist...
450
436
  if (req.path === '/theme/style.css') {
@@ -462,9 +448,9 @@ module.exports = exports = argv => {
462
448
  const favLoc = path.join(argv.status, 'favicon.png')
463
449
  const defaultFavLoc = path.join(argv.root, 'default-data', 'status', 'favicon.png')
464
450
  app.get('/favicon.png', cors, (req, res) => {
465
- fs.exists(favLoc, exists => {
466
- if (exists) {
467
- res.sendFile(favLoc)
451
+ fs.access(favLoc, fs.constants.F_OK, err => {
452
+ if (!err) {
453
+ res.sendFile(favLoc, { dotfiles: 'allow' })
468
454
  } else {
469
455
  res.sendFile(defaultFavLoc)
470
456
  }
@@ -484,9 +470,9 @@ module.exports = exports = argv => {
484
470
  // save it.
485
471
  app.post('/favicon.png', authorized, (req, res) => {
486
472
  const favicon = req.body.image.replace(/^data:image\/png;base64,/, '')
487
- const buf = new Buffer(favicon, 'base64')
488
- fs.exists(argv.status, exists => {
489
- if (exists) {
473
+ const buf = Buffer.from(favicon, 'base64')
474
+ fs.access(argv.status, fs.constants.F_OK, err => {
475
+ if (!err) {
490
476
  fs.writeFile(favLoc, buf, e => {
491
477
  if (e) {
492
478
  return res.e(e)
@@ -508,7 +494,7 @@ module.exports = exports = argv => {
508
494
 
509
495
  // Redirect remote favicons to the server they are needed from.
510
496
  app.get(/^\/remote\/([a-zA-Z0-9:.-]+\/favicon.png)$/, (req, res) => {
511
- const remotefav = 'http://#{req.params[0]}'
497
+ const remotefav = `http://${req.params[0]}`
512
498
  res.redirect(remotefav)
513
499
  })
514
500
 
@@ -519,7 +505,7 @@ module.exports = exports = argv => {
519
505
  // negative space outward pointing arrows nicely indicates that items can be removed
520
506
  const recyclerFavLoc = path.join(argv.root, 'default-data', 'status', 'recycler.png')
521
507
  app.get('/recycler/favicon.png', authorized, (req, res) => {
522
- res.sendFile(recyclerFavLoc)
508
+ res.sendFile(recyclerFavLoc, { dotfiles: 'allow' })
523
509
  })
524
510
 
525
511
  // Send an array of pages currently in the recycler via json
@@ -590,21 +576,21 @@ module.exports = exports = argv => {
590
576
 
591
577
  // Returns a list of installed plugins. (does this get called anymore!)
592
578
  app.get('/system/plugins.json', cors, (req, res) => {
593
- glob('wiki-plugin-*', { cwd: argv.packageDir }, (e, files) => {
594
- if (e) {
595
- return res.e(e)
596
- }
597
- // extract the plugin name from the name of the directory it's installed in
598
- files = files.map(file => file.slice(12))
599
- res.send(files)
600
- })
579
+ try {
580
+ const pluginNames = Object.keys(require.main.require('./package').dependencies)
581
+ .filter(depend => depend.startsWith('wiki-plugin'))
582
+ .map(name => name.slice(12))
583
+ res.send(pluginNames)
584
+ } catch (e) {
585
+ return res.e(e)
586
+ }
601
587
  })
602
588
  //{
603
589
  const sitemapLoc = path.join(argv.status, 'sitemap.json')
604
590
  app.get('/system/sitemap.json', cors, (req, res) => {
605
- fs.exists(sitemapLoc, exists => {
606
- if (exists) {
607
- res.sendFile(sitemapLoc)
591
+ fs.access(sitemapLoc, fs.constants.F_OK, err => {
592
+ if (!err) {
593
+ res.sendFile(sitemapLoc, { dotfiles: 'allow' })
608
594
  } else {
609
595
  // only createSitemap if we are not already creating one
610
596
  if (!sitemaphandler.isWorking()) {
@@ -612,7 +598,7 @@ module.exports = exports = argv => {
612
598
  }
613
599
  // wait for the sitemap file to be written, before sending
614
600
  sitemaphandler.once('finished', () => {
615
- res.sendFile(sitemapLoc)
601
+ res.sendFile(sitemapLoc, { dotfiles: 'allow' })
616
602
  })
617
603
  }
618
604
  })
@@ -620,15 +606,15 @@ module.exports = exports = argv => {
620
606
 
621
607
  const xmlSitemapLoc = path.join(argv.status, 'sitemap.xml')
622
608
  app.get('/sitemap.xml', cors, (req, res) => {
623
- fs.exists(sitemapLoc, exists => {
624
- if (exists) {
625
- res.sendFile(xmlSitemapLoc)
609
+ fs.access(sitemapLoc, fs.constants.F_OK, err => {
610
+ if (!err) {
611
+ res.sendFile(xmlSitemapLoc, { dotfiles: 'allow' })
626
612
  } else {
627
613
  if (!sitemaphandler.isWorking()) {
628
614
  sitemaphandler.createSitemap(pagehandler)
629
615
  }
630
616
  sitemaphandler.once('finished', () => {
631
- res.sendFile(xmlSitemapLoc)
617
+ res.sendFile(xmlSitemapLoc, { dotfiles: 'allow' })
632
618
  })
633
619
  }
634
620
  })
@@ -636,16 +622,16 @@ module.exports = exports = argv => {
636
622
 
637
623
  const searchIndexLoc = path.join(argv.status, 'site-index.json')
638
624
  app.get('/system/site-index.json', cors, (req, res) => {
639
- fs.exists(searchIndexLoc, exists => {
640
- if (exists) {
641
- res.sendFile(searchIndexLoc)
625
+ fs.access(searchIndexLoc, fs.constants.F_OK, err => {
626
+ if (!err) {
627
+ res.sendFile(searchIndexLoc, { dotfiles: 'allow' })
642
628
  } else {
643
629
  // only create index if we are not already creating one
644
630
  if (!searchhandler.isWorking()) {
645
631
  searchhandler.createIndex(pagehandler)
646
632
  }
647
633
  searchhandler.once('indexed', () => {
648
- res.sendFile(searchIndexLoc)
634
+ res.sendFile(searchIndexLoc, { dotfiles: 'allow' })
649
635
  })
650
636
  }
651
637
  })
@@ -692,32 +678,31 @@ module.exports = exports = argv => {
692
678
 
693
679
  app.get('/system/version.json', admin, (req, res) => {
694
680
  const versions = {}
695
- const wikiModule = module.parent.parent.parent
681
+ const wikiModule = require.main
696
682
  versions[wikiModule.require('./package').name] = wikiModule.require('./package').version
697
683
  versions[wikiModule.require('wiki-server/package').name] = wikiModule.require('wiki-server/package').version
698
684
  versions[wikiModule.require('wiki-client/package').name] = wikiModule.require('wiki-client/package').version
685
+
699
686
  versions['security'] = {}
700
- versions['plugins'] = {}
687
+ Object.keys(require.main.require('./package').dependencies)
688
+ .filter(depend => depend.startsWith('wiki-security'))
689
+ .forEach(key => {
690
+ versions.security[key] = wikiModule.require(`${key}/package`).version
691
+ })
701
692
 
702
- glob('+(wiki-security-*|wiki-plugin-*)', { cwd: argv.packageDir }, (e, plugins) => {
703
- plugins.map(plugin => {
704
- if (plugin.includes('wiki-security')) {
705
- versions.security[wikiModule.require(plugin + '/package').name] = wikiModule.require(
706
- plugin + '/package',
707
- ).version
708
- } else {
709
- versions.plugins[wikiModule.require(plugin + '/package').name] = wikiModule.require(
710
- plugin + '/package',
711
- ).version
712
- }
713
- res.json(versions)
693
+ versions['plugins'] = {}
694
+ Object.keys(require.main.require('./package').dependencies)
695
+ .filter(depend => depend.startsWith('wiki-plugin'))
696
+ .forEach(key => {
697
+ versions.plugins[key] = wikiModule.require(`${key}/package`).version
714
698
  })
715
- })
699
+
700
+ res.json(versions)
716
701
  })
717
702
 
718
703
  // ##### Proxy routes #####
719
704
 
720
- app.get('/proxy/*', authorized, (req, res) => {
705
+ app.get('/proxy/*splat', authorized, (req, res) => {
721
706
  const pathParts = req.originalUrl.split('/')
722
707
  const remoteHost = pathParts[2]
723
708
  pathParts.splice(0, 3)
@@ -731,7 +716,7 @@ module.exports = exports = argv => {
731
716
  requestURL.endsWith('.jpg') ||
732
717
  pathParts[0] === 'plugin'
733
718
  ) {
734
- fetch(requestURL, { timeout: 2000 })
719
+ fetch(requestURL, { signal: AbortSignal.timeout(2000) })
735
720
  .then(async fetchRes => {
736
721
  if (fetchRes.ok) {
737
722
  res.set('content-type', fetchRes.headers.get('content-type'))
package/lib/sitemap.js CHANGED
@@ -119,8 +119,8 @@ module.exports = exports = argv => {
119
119
  }
120
120
 
121
121
  const sitemapSave = (sitemap, cb) => {
122
- fs.exists(argv.status, exists => {
123
- if (exists) {
122
+ fs.access(argv.status, fs.constants.F_OK, err => {
123
+ if (!err) {
124
124
  writeFileAtomic(sitemapLoc, JSON.stringify(sitemap), e => {
125
125
  if (e) return cb(e)
126
126
  cb()
@@ -136,8 +136,8 @@ module.exports = exports = argv => {
136
136
  }
137
137
 
138
138
  const sitemapRestore = cb => {
139
- fs.exists(sitemapLoc, exists => {
140
- if (exists) {
139
+ fs.access(sitemapLoc, fs.constants.F_OK, err => {
140
+ if (!err) {
141
141
  fs.readFile(sitemapLoc, (err, data) => {
142
142
  if (err) return cb(err)
143
143
  try {
@@ -172,8 +172,8 @@ module.exports = exports = argv => {
172
172
  const xmlmap = { urlset: { $: { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' }, url: xmlmapPages } }
173
173
  const builder = new xml2js.Builder()
174
174
  const xml = builder.buildObject(xmlmap)
175
- fs.exists(argv.status, exists => {
176
- if (exists) {
175
+ fs.access(argv.status, fs.constants.F_OK, err => {
176
+ if (!err) {
177
177
  writeFileAtomic(xmlSitemapLoc, xml, e => {
178
178
  if (e) return cb(e)
179
179
  cb()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wiki-server",
3
3
  "description": "A Federated Wiki Server",
4
- "version": "0.26.0-rc.0",
4
+ "version": "0.26.0-rc.1",
5
5
  "author": {
6
6
  "name": "Ward Cunningham",
7
7
  "email": "ward@c2.com",
@@ -37,15 +37,13 @@
37
37
  "cookie-parser": "^1.4.4",
38
38
  "dompurify": "^3.1.0",
39
39
  "errorhandler": "^1.5.1",
40
- "express": "^4.21.2",
40
+ "express": "^5.1.0",
41
41
  "express-hbs": "^2.5.0",
42
42
  "flates": "0.0.5",
43
- "glob": "^7.2.3",
44
43
  "jsdom": "^26.0.0",
45
44
  "method-override": "^3.0.0",
46
45
  "minisearch": "^7.1.0",
47
46
  "morgan": "^1.9.1",
48
- "node-fetch": "^3.3.2",
49
47
  "write-file-atomic": "^6.0.0",
50
48
  "xml2js": "^0.6.2"
51
49
  },