wiki-server 0.26.0-rc.4 → 0.26.0-rc.5

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/index.js CHANGED
@@ -2,7 +2,11 @@
2
2
  // Simple file so that if you require this directory
3
3
  // in node it instead requires ./lib/server.coffee
4
4
  // with coffee-script already loaded.
5
- require('coffeescript')
6
- require('coffeescript/register')
5
+ // import('coffeescript')
6
+ // import('coffeescript/register.js')
7
7
 
8
- module.exports = require('./lib/server')
8
+ // const { default: server } = await import('./lib/server.js')
9
+ // export default server
10
+
11
+ import { default as server } from './lib/server.js'
12
+ export default server
@@ -9,13 +9,19 @@
9
9
  // **defaultargs.coffee** when called on the argv object this
10
10
  // module will create reasonable defaults for options not supplied,
11
11
  // based on what information is provided.
12
- const path = require('node:path')
12
+ import path from 'node:path'
13
+ import { randomBytes } from 'node:crypto'
14
+ import { fileURLToPath } from 'node:url'
15
+ import { dirname } from 'node:path'
16
+
17
+ const __filename = fileURLToPath(import.meta.url)
18
+ const __dirname = dirname(__filename)
13
19
 
14
20
  const getUserHome = () => {
15
21
  return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE
16
22
  }
17
23
 
18
- module.exports = argv => {
24
+ export default argv => {
19
25
  argv = argv || {}
20
26
  argv.root ||= __dirname
21
27
  // the directory that contains all the packages that makeup the wiki
@@ -32,7 +38,7 @@ module.exports = argv => {
32
38
  argv.url ||= `http://localhost${argv.port === 80 ? '' : ':' + argv.port}`
33
39
  argv.id ||= path.join(argv.status, 'owner.json')
34
40
  argv.uploadLimit ||= '5mb'
35
- argv.cookieSecret ||= require('crypto').randomBytes(64).toString('hex')
41
+ argv.cookieSecret ||= randomBytes(64).toString('hex')
36
42
  argv.secure_cookie ||= false
37
43
  argv.session_duration ||= 7
38
44
  argv.neighbors ||= ''
@@ -43,9 +49,9 @@ module.exports = argv => {
43
49
  argv.database = JSON.parse(argv.database)
44
50
  }
45
51
  argv.database ||= {}
46
- argv.database.type ||= './page'
52
+ argv.database.type ||= './page.js'
47
53
  if (argv.database.type.charAt(0) === '.') {
48
- if (argv.database.type != './page') {
54
+ if (argv.database.type != './page.js') {
49
55
  console.log('\n\nWARNING: This storage option is depeciated.')
50
56
  console.log(' See ReadMe for details of the changes required.\n\n')
51
57
  }
@@ -53,8 +59,8 @@ module.exports = argv => {
53
59
  argv.database.type = 'wiki-storage-' + argv.database.type
54
60
  }
55
61
 
56
- argv.security_type ||= './security'
57
- if (argv.security_type === './security') {
62
+ argv.security_type ||= './security.js'
63
+ if (argv.security_type === './security.js') {
58
64
  console.log('\n\nINFORMATION: Using default security module.')
59
65
  } else {
60
66
  argv.security_type = 'wiki-security-' + argv.security_type
package/lib/forward.js CHANGED
@@ -1,4 +1,4 @@
1
- const init = (app, emitter) => {
1
+ export const init = (app, emitter) => {
2
2
  let sockets = []
3
3
  app.io.on('connection', socket => {
4
4
  let listeners = []
@@ -35,4 +35,3 @@ const init = (app, emitter) => {
35
35
  })
36
36
  })
37
37
  }
38
- module.exports = { init }
package/lib/page.js CHANGED
@@ -10,12 +10,31 @@
10
10
  // Everything is stored using json flat files.
11
11
 
12
12
  // #### Requires ####
13
- const fs = require('fs')
14
- const path = require('path')
15
- const events = require('events')
16
-
17
- const random_id = require('./random_id')
18
- const synopsis = require('wiki-client/lib/synopsis')
13
+ // const fs = require('fs')
14
+ // const path = require('path')
15
+ // const events = require('events')
16
+ // const glob = require('glob')
17
+ //
18
+ // const async = require('async')
19
+ //
20
+ // // const random_id = require('./random_id.cjs')
21
+ // const synopsis = require('wiki-client/lib/synopsis')
22
+
23
+ import fs from 'node:fs'
24
+ import path from 'node:path'
25
+ import { pathToFileURL } from 'node:url'
26
+ import events from 'node:events'
27
+
28
+ import { createRequire } from 'node:module'
29
+ const require = createRequire(import.meta.url)
30
+
31
+ // Use dynamic import to load package.json from the main application's working directory
32
+ const packageJsonPath = path.join(process.cwd(), 'package.json')
33
+ const packageJsonUrl = pathToFileURL(packageJsonPath).href
34
+ const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } })
35
+
36
+ // import random_id from './random_id.cjs'; // Uncomment if needed
37
+ import synopsis from 'wiki-client/lib/synopsis.js' // Add correct extension if necessary
19
38
 
20
39
  const asSlug = name =>
21
40
  name
@@ -25,7 +44,7 @@ const asSlug = name =>
25
44
 
26
45
  // Export a function that generates a page handler
27
46
  // when called with options object.
28
- module.exports = exports = argv => {
47
+ export default argv => {
29
48
  const wikiName = new URL(argv.url).hostname
30
49
 
31
50
  fs.mkdir(argv.db, { recursive: true }, e => {
@@ -34,13 +53,11 @@ module.exports = exports = argv => {
34
53
 
35
54
  // create a list of plugin pages.
36
55
  const pluginPages = new Map()
37
- Object.keys(require.main.require('./package').dependencies)
56
+
57
+ Object.keys(packageJson.dependencies)
38
58
  .filter(depend => depend.startsWith('wiki-plugin'))
39
59
  .forEach(plugin => {
40
- const pagesPath = path.join(
41
- path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })),
42
- 'pages',
43
- )
60
+ const pagesPath = path.join(path.dirname(require.resolve(`${plugin}/package`)), 'pages')
44
61
  fs.readdir(pagesPath, { withFileTypes: true }, (err, entries) => {
45
62
  if (err) return
46
63
  entries.forEach(entry => {
package/lib/plugins.js CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
  // support server-side plugins
10
10
 
11
- const fs = require('node:fs')
12
- const { pathToFileURL } = require('node:url')
13
- // forward = require './forward'
11
+ import fs from 'node:fs'
12
+ import { pathToFileURL } from 'node:url'
13
+ // import forward from './forward.cjs'; // Uncomment if needed and adjust import style if it's not a default export
14
14
 
15
- module.exports = exports = argv => {
15
+ export default argv => {
16
16
  // NOTE: plugins are now in their own package directories alongside this one...
17
17
  // Plugins are in directories of the form wiki-package-*
18
18
  // those with a server component will have a server directory
package/lib/random_id.js CHANGED
@@ -10,6 +10,5 @@
10
10
  // Simple random hex generator, takes an optional number of
11
11
  // chars that defaults to 16 and returns a random id.
12
12
 
13
- const random_id = (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
13
+ export default (chars = 16) => [...Array(chars)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
14
14
 
15
- module.exports = random_id.random_id = random_id
package/lib/search.js CHANGED
@@ -8,15 +8,15 @@
8
8
 
9
9
  // **search.js**
10
10
 
11
- const fs = require('node:fs')
12
- const path = require('node:path')
13
- const events = require('node:events')
14
- const url = require('node:url')
15
- const writeFileAtomic = require('write-file-atomic')
11
+ import fs from 'node:fs'
12
+ import path from 'node:path'
13
+ import events from 'node:events'
14
+ import url from 'node:url'
15
+ import writeFileAtomic from 'write-file-atomic'
16
16
 
17
- const miniSearch = require('minisearch')
17
+ import MiniSearch from 'minisearch'
18
18
 
19
- module.exports = exports = argv => {
19
+ export default argv => {
20
20
  const wikiName = new URL(argv.url).hostname
21
21
  let siteIndex = []
22
22
  const queue = []
package/lib/security.js CHANGED
@@ -13,11 +13,11 @@
13
13
  // allow the server to run read-only.
14
14
 
15
15
  // #### Requires ####
16
- const fs = require('node:fs')
16
+ import fs from 'node:fs'
17
17
 
18
18
  // Export a function that generates security handler
19
19
  // when called with options object.
20
- module.exports = exports = (log, loga, argv) => {
20
+ export default (log, loga, argv) => {
21
21
  const security = {}
22
22
 
23
23
  // #### Private utility methods. ####
@@ -84,7 +84,16 @@ module.exports = exports = (log, loga, argv) => {
84
84
  }
85
85
  // Wiki server admin
86
86
  security.isAdmin = () => {
87
- return false
87
+ // nobody is admin - unless legacy support, and test
88
+ if (argv.security_legacy) {
89
+ if (argv.test) {
90
+ return true
91
+ } else {
92
+ return false
93
+ }
94
+ } else {
95
+ return false
96
+ }
88
97
  }
89
98
  security.defineRoutes = (app, cors, updateOwner) => {
90
99
  // default security does not have any routes
package/lib/server.js CHANGED
@@ -19,19 +19,18 @@
19
19
  // npm install
20
20
 
21
21
  // Standard lib
22
- const fs = require('fs')
23
- const path = require('path')
24
- const http = require('http')
25
- const url = require('url')
26
- const { pipeline } = require('node:stream/promises')
22
+ import fs from 'fs'
23
+ import path from 'path'
24
+ import url from 'url'
25
+ import { pipeline } from 'node:stream/promises'
27
26
 
28
27
  // From npm
29
- const express = require('express')
30
- const hbs = require('express-hbs')
31
- const f = require('flates')
28
+ import express from 'express'
29
+ import hbs from 'express-hbs'
30
+ import f from 'flates'
32
31
 
33
- const createDOMPurify = require('dompurify')
34
- const { JSDOM } = require('jsdom')
32
+ import createDOMPurify from 'dompurify'
33
+ import { JSDOM } from 'jsdom'
35
34
 
36
35
  const window = new JSDOM('').window
37
36
  const DOMPurify = createDOMPurify(window)
@@ -39,21 +38,30 @@ const DOMPurify = createDOMPurify(window)
39
38
  // Using native fetch API (available in Node.js 18+)
40
39
 
41
40
  // Express 4 middleware
42
- const logger = require('morgan')
43
- const cookieParser = require('cookie-parser')
44
- const methodOverride = require('method-override')
45
- // session = require 'express-session'
46
- const sessions = require('client-sessions')
47
- const bodyParser = require('body-parser')
48
- const errorHandler = require('errorhandler')
41
+ import logger from 'morgan'
42
+ import cookieParser from 'cookie-parser'
43
+ import methodOverride from 'method-override'
44
+ // session = require('express-session') // This one was commented out — uncomment if used
45
+ import sessions from 'client-sessions'
46
+ import bodyParser from 'body-parser'
47
+ import errorHandler from 'errorhandler'
49
48
 
50
49
  // Local files
51
- const random = require('./random_id')
52
- const defargs = require('./defaultargs')
53
- const resolveClient = require('wiki-client/lib/resolve')
54
- const pluginsFactory = require('./plugins')
55
- const sitemapFactory = require('./sitemap')
56
- const searchFactory = require('./search')
50
+ // Make sure these files are ESM modules or compatible
51
+ // If they are CommonJS, you will need to dynamically import them (see below)
52
+ import defargs from './defaultargs.js'
53
+ import resolveClient from 'wiki-client/lib/resolve.js'
54
+ import pluginsFactory from './plugins.js'
55
+ import sitemapFactory from './sitemap.js'
56
+ import searchFactory from './search.js'
57
+ import { warn } from 'node:console'
58
+ import { createRequire } from 'module'
59
+ const require = createRequire(import.meta.url)
60
+
61
+ // Use dynamic import to load package.json from the main application's working directory
62
+ const packageJsonPath = path.join(process.cwd(), 'package.json')
63
+ const packageJsonUrl = url.pathToFileURL(packageJsonPath).href
64
+ const { default: packageJson } = await import(packageJsonUrl, { with: { type: 'json' } })
57
65
 
58
66
  const render = page => {
59
67
  return (
@@ -90,7 +98,7 @@ const render = page => {
90
98
  )
91
99
  }
92
100
  // Set export objects for node and coffee to a function that generates a sfw server.
93
- module.exports = exports = argv => {
101
+ export default async argv => {
94
102
  // Create the main application object, app.
95
103
  const app = express()
96
104
 
@@ -125,18 +133,22 @@ module.exports = exports = argv => {
125
133
  }
126
134
  next()
127
135
  }
136
+
128
137
  let pagehandler, sitemaphandler, searchhandler, securityhandler
129
- // Require the database adapter and initialize it with options.
130
- app.pagehandler = pagehandler = require(argv.database.type)(argv)
131
138
 
132
- // Require the sitemap adapter and initialize it with options.
139
+ // Dynamically import database adapter (since the module name is dynamic)
140
+ const dbModule = await import(argv.database.type)
141
+ app.pagehandler = pagehandler = dbModule.default(argv)
142
+
143
+ // Initialize sitemap handler
133
144
  app.sitemaphandler = sitemaphandler = sitemapFactory(argv)
134
145
 
135
- // Require the site indexer and initialize it with options
146
+ // Initialize search handler
136
147
  app.searchhandler = searchhandler = searchFactory(argv)
137
148
 
138
- // Require the security adapter and initialize it with options.
139
- app.securityhandler = securityhandler = require(argv.security_type)(log, loga, argv)
149
+ // Dynamically import security adapter (also dynamic)
150
+ const securityModule = await import(argv.security_type)
151
+ app.securityhandler = securityhandler = securityModule.default(log, loga, argv)
140
152
 
141
153
  // If the site is owned, owner will contain the name of the owner
142
154
  let owner = ''
@@ -268,13 +280,10 @@ module.exports = exports = argv => {
268
280
  app.use('/assets', cors, express.static(argv.assets))
269
281
 
270
282
  // Add static routes to the plugins client.
271
- Object.keys(require.main.require('./package').dependencies)
283
+ Object.keys(packageJson.dependencies)
272
284
  .filter(depend => depend.startsWith('wiki-plugin'))
273
285
  .forEach(plugin => {
274
- const clientPath = path.join(
275
- path.dirname(require.resolve(`${plugin}/package`, { paths: require.main.paths })),
276
- 'client',
277
- )
286
+ const clientPath = path.join(path.dirname(require.resolve(`${plugin}/package`)), 'client')
278
287
  const pluginPath = '/plugins/' + plugin.slice(12)
279
288
  app.use(pluginPath, cors, express.static(clientPath, staticPathOptions))
280
289
  })
@@ -387,17 +396,29 @@ module.exports = exports = argv => {
387
396
  app.get('/system/factories.json', (req, res) => {
388
397
  res.status(200)
389
398
  res.header('Content-Type', 'application/json')
399
+
390
400
  const factories = []
391
- Object.keys(require.main.require('./package').dependencies)
392
- .filter(depend => depend.startsWith('wiki-plugin'))
393
- .forEach(plugin => {
401
+
402
+ const getPackageFactory = plugin => {
403
+ return new Promise(resolve => {
394
404
  try {
395
- factories.push(require.main.require(`${plugin}/factory`))
396
- } catch {
397
- // do nothing if plugin doesn't have a factory category.
405
+ import(`${plugin}/factory.json`, { with: { type: 'json' } }).then(({ default: factory }) => {
406
+ console.log(plugin, factory)
407
+ resolve(factories.push(factory))
408
+ })
409
+ } catch (error) {
410
+ resolve()
398
411
  }
399
412
  })
400
- res.end(JSON.stringify(factories))
413
+ }
414
+
415
+ Promise.all(
416
+ Object.keys(packageJson.dependencies)
417
+ .filter(depend => depend.startsWith('wiki-plugin'))
418
+ .map(plugin => {
419
+ return getPackageFactory(plugin)
420
+ }),
421
+ ).then(() => res.end(JSON.stringify(factories)))
401
422
  })
402
423
 
403
424
  // ###### Json Routes ######
@@ -679,27 +700,56 @@ module.exports = exports = argv => {
679
700
  }
680
701
 
681
702
  app.get('/system/version.json', admin, (req, res) => {
703
+ const getPackageVersion = packageName => {
704
+ return new Promise(resolve => {
705
+ try {
706
+ // Use dynamic import to load package.json from the main application's working directory
707
+ const packageJsonPath = path.join(process.cwd(), 'node_modules', packageName, 'package.json')
708
+ const packageJsonUrl = url.pathToFileURL(packageJsonPath).href
709
+ import(packageJsonUrl, { with: { type: 'json' } }).then(({ default: packageJson }) => {
710
+ resolve({ [packageName]: packageJson.version })
711
+ })
712
+ } catch (error) {
713
+ console.error(`Error reading package for ${packageName}:`, error)
714
+ resolve({ [packageName]: 'unknown' })
715
+ }
716
+ })
717
+ }
718
+
682
719
  const versions = {}
683
- const wikiModule = require.main
684
- versions[wikiModule.require('./package').name] = wikiModule.require('./package').version
685
- versions[wikiModule.require('wiki-server/package').name] = wikiModule.require('wiki-server/package').version
686
- versions[wikiModule.require('wiki-client/package').name] = wikiModule.require('wiki-client/package').version
687
-
688
- versions['security'] = {}
689
- Object.keys(require.main.require('./package').dependencies)
690
- .filter(depend => depend.startsWith('wiki-security'))
691
- .forEach(key => {
692
- versions.security[key] = wikiModule.require(`${key}/package`).version
720
+
721
+ const security = () => {
722
+ return new Promise(resolve => {
723
+ Promise.all(
724
+ Object.keys(packageJson.dependencies)
725
+ .filter(depend => depend.startsWith('wiki-security'))
726
+ .map(key => {
727
+ return getPackageVersion(key)
728
+ }),
729
+ ).then(values => {
730
+ resolve({ security: values.reduce((acc, cV) => Object.assign(acc, cV), {}) })
731
+ })
693
732
  })
733
+ }
694
734
 
695
- versions['plugins'] = {}
696
- Object.keys(require.main.require('./package').dependencies)
697
- .filter(depend => depend.startsWith('wiki-plugin'))
698
- .forEach(key => {
699
- versions.plugins[key] = wikiModule.require(`${key}/package`).version
735
+ const plugins = () => {
736
+ return new Promise(resolve => {
737
+ Promise.all(
738
+ Object.keys(packageJson.dependencies)
739
+ .filter(depend => depend.startsWith('wiki-plugin'))
740
+ .map(key => {
741
+ return getPackageVersion(key)
742
+ }),
743
+ ).then(values => {
744
+ resolve({ plugins: values.reduce((acc, cV) => Object.assign(acc, cV), {}) })
745
+ })
700
746
  })
747
+ }
701
748
 
702
- res.json(versions)
749
+ Promise.all([getPackageVersion('wiki-server'), getPackageVersion('wiki-client'), security(), plugins()]).then(v => {
750
+ Object.assign(versions, { [packageJson.name]: packageJson.version }, ...v)
751
+ res.json(versions)
752
+ })
703
753
  })
704
754
 
705
755
  // ##### Proxy routes #####
package/lib/sitemap.js CHANGED
@@ -7,14 +7,13 @@
7
7
  */
8
8
 
9
9
  // **sitemap.coffee**
10
+ import fs from 'node:fs'
11
+ import path from 'node:path'
12
+ import events from 'node:events'
13
+ import writeFileAtomic from 'write-file-atomic'
14
+ import xml2js from 'xml2js'
10
15
 
11
- const fs = require('fs')
12
- const path = require('path')
13
- const events = require('events')
14
- const writeFileAtomic = require('write-file-atomic')
15
- const xml2js = require('xml2js')
16
-
17
- const synopsis = require('wiki-client/lib/synopsis')
16
+ import synopsis from 'wiki-client/lib/synopsis.js' // Add .js if needed
18
17
 
19
18
  const asSlug = name =>
20
19
  name
@@ -22,7 +21,7 @@ const asSlug = name =>
22
21
  .replace(/[^A-Za-z0-9-]/g, '')
23
22
  .toLowerCase()
24
23
 
25
- module.exports = exports = argv => {
24
+ export default argv => {
26
25
  const wikiName = new URL(argv.url).hostname
27
26
 
28
27
  let sitemap = []
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "wiki-server",
3
3
  "description": "A Federated Wiki Server",
4
- "version": "0.26.0-rc.4",
4
+ "version": "0.26.0-rc.5",
5
+ "type": "module",
5
6
  "author": {
6
7
  "name": "Ward Cunningham",
7
8
  "email": "ward@c2.com",
@@ -49,12 +50,13 @@
49
50
  "scripts": {
50
51
  "prettier:format": "prettier --write './**/*.js'",
51
52
  "prettier:check": "prettier --check ./**/*.js",
52
- "test": "node --test",
53
+ "test": "cd test; node --test",
54
+ "watch": "cd test; node --test --watch",
53
55
  "update-authors": "node scripts/update-authors.js"
54
56
  },
55
57
  "devDependencies": {
56
- "@eslint/js": "^9.31.0",
57
- "eslint": "^9.31.0",
58
+ "@eslint/js": "^9.32.0",
59
+ "eslint": "^9.32.0",
58
60
  "globals": "^16.1.0",
59
61
  "grunt-git-authors": "^3.2.0",
60
62
  "prettier": "^3.5.3",