Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 91 additions & 57 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@
// **cli.coffee** command line interface for the
// Smallest-Federated-Wiki express server

const http = require('http')
// socketio = require('socket.io')
import http from 'node:http'

const path = require('path')
const cluster = require('cluster')
import path from 'node:path'
import url from 'node:url'
import cluster from 'node:cluster'

const parseArgs = require('minimist')
const cc = require('config-chain')
const server = require('wiki-server')
import fs from 'node:fs/promises'
import crypto from 'node:crypto'

const farm = require('./farm')
import minimist from 'minimist'
const parseArgs = minimist

import server from 'wiki-server'

import { farm } from './farm.js'
import { version } from './version.js'
import { exit } from 'node:process'

const getUserHome = () => process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE

Expand All @@ -41,23 +47,49 @@ const opts = {

const argv = parseArgs(process.argv.slice(2), opts)

const config = cc(
argv,
argv.config,
'config.json',
path.join(__dirname, '..', 'config.json'),
path.join(getUserHome(), '.wiki', 'config.json'),
cc.env('wiki_'),
{
port: 3000,
root: path.dirname(require.resolve('wiki-server')),
home: 'welcome-visitors',
security_type: './security',
data: path.join(getUserHome(), '.wiki'), // see also defaultargs
packageDir: path.resolve(path.join(__dirname, 'node_modules')),
cookieSecret: require('crypto').randomBytes(64).toString('hex'),
},
).store
// replacing config-chain
const createConfig = async (...sources) => {
const config = {}
for (const source of sources) {
if (source && typeof source === 'object') {
Object.assign(config, source)
} else if (typeof source === 'string') {
try {
const jsonConfig = JSON.parse(await fs.readFile(source, 'utf-8'))
Object.assign(config, jsonConfig)
} catch (error) {
// skip silently
}
}
}
return config
}

const parseEnvVars = prefix => {
return Object.fromEntries(Object.entries(process.env).filter(([k, v]) => k.startsWith(prefix)))
}

const defaultConfig = {
port: 3000,
root: path.dirname(url.fileURLToPath(import.meta.resolve('wiki-server'))),
home: 'welcome-visitors',
security_type: './security.js',
data: path.join(getUserHome(), '.wiki'), // see also defaultargs
packageDir: path.resolve(path.join(path.dirname(new URL(import.meta.url).pathname), 'node_modules')),
cookieSecret: crypto.randomBytes(64).toString('hex'),
}

// Create config by merging sources in priority order
// while some of thise config sources are unlikely, they are needed for backward compatability.
const config = await createConfig(
defaultConfig, // lowest priority
parseEnvVars('wiki_'), // environment variables
path.join(getUserHome(), '.wiki', 'config.json'), // user config
path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'config.json'), // parent dir config
'config.json', // current dir config
argv.config, // specified config file
argv, // command line args (highest priority)
)

if (!config.commons) {
config.commons = path.join(config.data, 'commons')
Expand All @@ -73,27 +105,13 @@ Options:
--config, --conf Optional config file.
--version, -v Show version number and exit\
`)
return
}

// If v/version is set print the version of the wiki components and exit.
if (argv.version) {
const details = require('./package')
console.log('wiki: ' + require('./package').version)
const components = Object.keys(details.dependencies).filter(i => i.startsWith('wiki'))
components.forEach(component => {
console.log(component + ': ' + require(component + '/package').version)
})
return
}

if (argv.test) {
} else if (argv.version) {
// If v/version is set print the version of the wiki components and exit.
version()
} else if (argv.test) {
console.log('WARNING: Server started in testing mode, other options ignored')
server({ port: 33333, data: path.join(argv.root, 'spec', 'data') })
return
}

if (cluster.isMaster) {
} else if (cluster.isPrimary) {
cluster.on('exit', function (worker, code, signal) {
if (code === 0) {
console.log('restarting wiki server')
Expand All @@ -109,26 +127,42 @@ if (cluster.isMaster) {
if (!argv.wikiDomains && !argv.allowed) {
console.log('WARNING : Starting Wiki Farm in promiscous mode\n')
}
if (argv.security_type === './security') {
if (argv.security_type === './security.js') {
if (!argv.security_legacy) {
console.log('INFORMATION : Using default security - Wiki Farm will be read-only\n')
}
}
farm(config)
} else {
const app = server(config)
app.on('owner-set', function (e) {
const local = http.Server(app)
// app.io = socketio(local)

const serv = local.listen(app.startOpts.port, app.startOpts.host)
console.log('Federated Wiki server listening on', app.startOpts.port, 'in mode:', app.settings.env)
if (argv.security_type === './security') {
if (!argv.security_legacy) {
console.log('INFORMATION : Using default security - Wiki will be read-only\n')
server(config).then(app => {
app.on('owner-set', function (e) {
const local = http.Server(app)
// app.io = socketio(local)

const serv = local.listen(app.startOpts.port, app.startOpts.host)
console.log('Federated Wiki server listening on', app.startOpts.port, 'in mode:', app.settings.env)
if (argv.security_type === './security.js') {
if (!argv.security_legacy) {
console.log('INFORMATION : Using default security - Wiki will be read-only\n')
}
}
}
app.emit('running-serv', serv)
app.emit('running-serv', serv)
})
})

// const app = server(config)
// app.on('owner-set', function (e) {
// const local = http.Server(app)
// // app.io = socketio(local)

// const serv = local.listen(app.startOpts.port, app.startOpts.host)
// console.log('Federated Wiki server listening on', app.startOpts.port, 'in mode:', app.settings.env)
// if (argv.security_type === './security') {
// if (!argv.security_legacy) {
// console.log('INFORMATION : Using default security - Wiki will be read-only\n')
// }
// }
// app.emit('running-serv', serv)
// })
}
}
2 changes: 1 addition & 1 deletion error-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ const render = function (title, errorText, messageText) {
`
}

module.exports = { render }
export { render }
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default [
},
{
languageOptions: {
sourceType: 'commonjs',
sourceType: 'module',
globals: {
wiki: 'readonly',
...globals.node,
Expand Down
52 changes: 26 additions & 26 deletions farm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,17 @@
// The farm module works by putting a bouncy host based proxy
// in front of servers that it creates

const path = require('path')
const fs = require('fs')
const chokidar = require('chokidar')
import path from 'node:path'
import fs from 'node:fs'
import chokidar from 'chokidar'

const http = require('http')
// socketio = require 'socket.io'
import http from 'node:http'

const server = require('wiki-server')
import server from 'wiki-server'

const _ = require('lodash')
import * as errorPage from './error-page.js'

const errorPage = require('./error-page')

module.exports = exports = function (argv) {
export function farm(argv) {
// Map incoming hosts to their wiki's port
let allowDomain, allowHost, inWikiDomain, runningFarmServ, wikiDomains
const hosts = {}
Expand Down Expand Up @@ -54,7 +51,9 @@ module.exports = exports = function (argv) {
})
.on('unlinkDir', function (delWiki) {
delWiki = path.basename(delWiki)
_.pull(allowedHosts, delWiki)
// remove deleted wiki directory from the list of allowed wiki
allowedHosts.splice(allowedHosts.indexOf(delWiki), 1)
// TODO: if wiki server is already running, it needs to be stopped, if that is even possible.
})
} else {
// we have a list of wiki that are allowed
Expand Down Expand Up @@ -211,27 +210,28 @@ module.exports = exports = function (argv) {

// apply wiki domain configuration, if defined
if (inWikiDomain) {
newargv = _.assignIn(newargv, newargv.wikiDomains[inWikiDomain])
newargv = Object.assign({}, newargv, newargv.wikiDomains[inWikiDomain])
newargv.wiki_domain = inWikiDomain
}

// Create a new server, add it to the list of servers, and
// once it's ready send the request to it.
const local = server(newargv)
// local.io = io
hosts[incHost] = local
runningServers.push(local)

// patch in new neighbors
if (argv.autoseed) {
let neighbors = argv.neighbors ? argv.neighbors + ',' : ''
neighbors += Object.keys(hosts).join(',')
runningServers.forEach(server => (server.startOpts.neighbors = neighbors))
}

return local.once('owner-set', function () {
local.emit('running-serv', farmServ)
return hosts[incHost](req, res)
server(newargv).then(local => {
hosts[incHost] = local
runningServers.push(local)

// patch in new neighbors
if (argv.autoseed) {
let neighbors = argv.neighbors ? argv.neighbors + ',' : ''
neighbors += Object.keys(hosts).join(',')
runningServers.forEach(server => (server.startOpts.neighbors = neighbors))
}

return local.once('owner-set', function () {
local.emit('running-serv', farmServ)
return hosts[incHost](req, res)
})
})
}
})
Expand Down
4 changes: 1 addition & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#!/usr/bin/env node
// **index.js**
require('coffeescript')
require('coffeescript/register')

module.exports = require('./cli')
export * from './cli.js'
Loading