typescript migration

This commit is contained in:
bhavya3024
2022-12-21 02:35:06 +05:30
parent c3c63bfe92
commit 0ba54a2b37
535 changed files with 5570 additions and 4522 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
dist/
build/
yarn.lock
npm-debug.log
node_modules/

44
app.ts
View File

@@ -19,35 +19,40 @@
'use strict';
require('./require-main');
import './require-main';
const nconf = require('nconf');
import nconf from 'nconf';
nconf.argv().env({
separator: '__',
});
const winston = require('winston');
const path = require('path');
import winston from 'winston';
import path from 'path';
import file from './src/file';
import web from './install/web';
import * as Upgrade from './src/cli/upgrade';
import manage from './src/cli/manage';
import * as Reset from './src/cli/reset';
import * as Running from './src/cli/running';
import Setup from './src/cli/setup';
const file = require('./src/file');
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
global.env = process.env.NODE_ENV || 'production';
(process as any).env.NODE_ENV = (process as any).env.NODE_ENV || 'production';
(global as any).env = (process as any).env.NODE_ENV || 'production';
// Alternate configuration file support
const configFile = path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'config.json');
const configExists = file.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
const prestart = require('./src/prestart');
import * as prestart from './src/prestart';
prestart.loadConfig(configFile);
prestart.setupWinston();
prestart.versionCheck();
winston.verbose('* using configuration stored in: %s', configFile);
if (!process.send) {
if (!(process as any).send) {
// If run using `node app`, log GNU copyright info along with server info
winston.info(`NodeBB v${nconf.get('version')} Copyright (C) 2013-${(new Date()).getFullYear()} NodeBB Inc.`);
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
@@ -56,13 +61,13 @@ if (!process.send) {
}
if (nconf.get('setup') || nconf.get('install')) {
require('./src/cli/setup').setup();
Setup.setup();
} else if (!configExists) {
require('./install/web').install(nconf.get('port'));
web.install(nconf.get('port'));
} else if (nconf.get('upgrade')) {
require('./src/cli/upgrade').upgrade(true);
Upgrade.upgrade(true);
} else if (nconf.get('reset')) {
require('./src/cli/reset').reset({
Reset.reset({
theme: nconf.get('t'),
plugin: nconf.get('p'),
widgets: nconf.get('w'),
@@ -70,13 +75,14 @@ if (nconf.get('setup') || nconf.get('install')) {
all: nconf.get('a'),
});
} else if (nconf.get('activate')) {
require('./src/cli/manage').activate(nconf.get('activate'));
manage.activate(nconf.get('activate'));
} else if (nconf.get('plugins') && typeof nconf.get('plugins') !== 'object') {
require('./src/cli/manage').listPlugins();
manage.listPlugins();
} else if (nconf.get('build')) {
require('./src/cli/manage').build(nconf.get('build'));
manage.buildWrapper(nconf.get('build'));
} else if (nconf.get('events')) {
require('./src/cli/manage').listEvents();
manage.listEvents();
} else {
require('./src/start').start();
require('./src/cli/manage')
Running.start();
}

4
build/.gitignore vendored
View File

@@ -1,4 +0,0 @@
*
*/
!export
!.gitignore

View File

@@ -1,3 +0,0 @@
.
!.gitignore
!README

View File

@@ -1,5 +0,0 @@
This directory contains archives of user uploads that are prepared on-demand
when a user wants to retrieve a copy of their uploaded content.
You can delete the files in here at will. They will just be regenerated if
requested again.

View File

@@ -1,6 +1,6 @@
'use strict';
module.exports = {
module.exports = {
extends: ['@commitlint/config-angular'],
rules: {
'header-max-length': [1, 'always', 72],

7
copy-non-ts-files.js Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
const fs = require('fs-extra');
fs.copy('config.json', 'build');
fs.copy('src/views', 'build/src/views');
fs.copy('install', 'build/install');

View File

@@ -1,15 +1,18 @@
'use strict';
const prompt = require('prompt');
const winston = require('winston');
import prompt from 'prompt';
import winston from 'winston';
import redis from '../src/database/redis';
import mongo from '../src/database/mongo';
import postgres from '../src/database/postgres';
const questions = {
redis: require('../src/database/redis').questions,
mongo: require('../src/database/mongo').questions,
postgres: require('../src/database/postgres').questions,
redis: redis.questions,
mongo: mongo.questions,
postgres: postgres.questions,
};
module.exports = async function (config) {
export default async function (config) {
winston.info(`\nNow configuring ${config.database} database:`);
const databaseConfig = await getDatabaseConfig(config);
return saveDatabaseConfig(config, databaseConfig);

View File

@@ -1,19 +1,19 @@
'use strict';
const winston = require('winston');
const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const path = require('path');
const childProcess = require('child_process');
const webpack = require('webpack');
const nconf = require('nconf');
const Benchpress = require('benchpressjs');
const mkdirp = require('mkdirp');
const { paths } = require('../src/constants');
const sass = require('../src/utils').getSass();
import winston from 'winston';
import express from 'express';
import bodyParser from 'body-parser';
import fs from 'fs';
import path from 'path';
import childProcess from 'child_process';
import webpack from 'webpack';
import nconf from 'nconf';
import Benchpress from 'benchpressjs';
import mkdirp from 'mkdirp';
import { paths } from '../src/constants';
import sass from '../src/utils';;
import util from 'util';
import webpackCfg from '../webpack.installer';
const app = express();
let server;
@@ -22,13 +22,15 @@ const formats = [
winston.format.colorize(),
];
const timestampFormat = winston.format((info) => {
const timestampFormat: any = winston.format((info) => {
const dateString = `${new Date().toISOString()} [${global.process.pid}]`;
info.level = `${dateString} - ${info.level}`;
return info;
});
formats.push(timestampFormat());
//@ts-ignore
formats.push(winston.format.splat());
//@ts-ignore
formats.push(winston.format.simple());
winston.configure({
@@ -45,7 +47,7 @@ winston.configure({
],
});
const web = module.exports;
const web = {} as any;
let installing = false;
let success = false;
let error = false;
@@ -80,14 +82,13 @@ web.install = async function (port) {
]);
setupRoutes();
launchExpress(port);
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
}
};
async function runWebpack() {
const util = require('util');
const webpackCfg = require('../webpack.installer');
const compiler = webpack(webpackCfg);
const webpackRun = util.promisify(compiler.run).bind(compiler);
await webpackRun();
@@ -202,7 +203,7 @@ async function launch(req, res) {
child = childProcess.exec(nconf.get('launchCmd'), {
detached: true,
stdio: ['ignore', 'ignore', 'ignore'],
});
} as any);
}
const filesToDelete = [
@@ -216,13 +217,13 @@ async function launch(req, res) {
filename => fs.promises.unlink(filename)
)
);
} catch (err) {
} catch (err: any) {
console.log(err.stack);
}
child.unref();
process.exit(0);
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
throw err;
}
@@ -258,7 +259,7 @@ async function compileSass() {
});
await fs.promises.writeFile(path.join(__dirname, '../public/installer.css'), scssOutput.css.toString());
} catch (err) {
} catch (err: any) {
winston.error(`Unable to compile SASS: \n${err.stack}`);
throw err;
}
@@ -276,7 +277,7 @@ async function loadDefaults() {
try {
// eslint-disable-next-line no-bitwise
await fs.promises.access(setupDefaultsPath, fs.constants.F_OK | fs.constants.R_OK);
} catch (err) {
} catch (err: any) {
// setup.json not found or inaccessible, proceed with no defaults
if (err.code !== 'ENOENT') {
throw err;
@@ -289,3 +290,5 @@ async function loadDefaults() {
file: setupDefaultsPath,
});
}
export default web;

View File

@@ -8,7 +8,7 @@ const { fork } = require('child_process');
const logrotate = require('logrotate-stream');
const mkdirp = require('mkdirp');
const file = require('./src/file');
const file = require('./build/src/file');
const pkg = require('./package.json');
const pathToConfig = path.resolve(__dirname, process.env.CONFIG || 'config.json');

3
nodebb
View File

@@ -2,4 +2,5 @@
'use strict';
require('./src/cli');
console.log('SERIOUSLY?');
require('./build/src/cli');

View File

@@ -11,7 +11,7 @@ let trackBottom;
let trackHeight;
let handleEl;
export default function init() {
module.exports = function init() {
const topicEl = document.querySelector('[component="topic"]');
const navigatorEl = document.querySelector('[component="topic/navigator"]');

View File

@@ -1,6 +1,6 @@
'use strict';
module.exports = function (utils, Benchpress, relative_path) {
module.exports = function (utils, Benchpress, relative_path) {
Benchpress.setGlobal('true', true);
Benchpress.setGlobal('false', false);

View File

@@ -5,7 +5,7 @@
if (typeof define === 'function' && define.amd) {
define('slugify', ['xregexp'], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require('xregexp'));
factory(require('xregexp'));
} else {
window.slugify = factory(XRegExp);
}

View File

@@ -1,6 +1,6 @@
'use strict';
module.exports = function (utils, load, warn) {
module.exports = function (utils, load, warn) {
const assign = Object.assign || jQuery.extend;
function escapeHTML(str) {

View File

@@ -82,4 +82,4 @@ utils.generateUUID = function () {
return uuid.split(/[:/]/g).pop().toLowerCase(); // remove prefixes
};
module.exports = utils;
module.exports = utils;

View File

@@ -1,3 +1,3 @@
for f in src/**/**/*.js; do
for f in src/user/**/*.js; do
git mv "$f" "${f%.js}.ts"
done

View File

@@ -4,6 +4,7 @@
// this allows plugins to use `require.main.require` to reference NodeBB modules
// without worrying about multiple parent modules
if (require.main !== module) {
//@ts-ignore
require.main.require = function (path) {
return require(path);
};

View File

@@ -1,13 +1,14 @@
'use strict';
const fs = require('fs');
const path = require('path');
const sanitizeHTML = require('sanitize-html');
const nconf = require('nconf');
const winston = require('winston');
import fs from 'fs';
import path from 'path';
import sanitizeHTML from 'sanitize-html';
import nconf from 'nconf';
import winston from 'winston';
import file from '../file';
import Translator from '../translator';
const file = require('../file');
const { Translator } = require('../translator');
function filterDirectories(directories) {
return directories.map(
@@ -113,7 +114,7 @@ async function buildNamespace(language, namespace) {
translations: `${str}\n${title}`,
title: title,
};
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
return {
namespace: namespace,
@@ -124,7 +125,7 @@ async function buildNamespace(language, namespace) {
const cache = {};
async function getDictionary(language) {
async function getLatestVersionDictionary(language) {
if (cache[language]) {
return cache[language];
}
@@ -134,9 +135,13 @@ async function getDictionary(language) {
return params;
}
module.exports.getDictionary = getDictionary;
module.exports.filterDirectories = filterDirectories;
module.exports.simplify = simplify;
module.exports.sanitize = sanitize;
const obj = {
getLatestVersionDictionary,
filterDirectories,
simplify,
sanitize
};
import promisify from '../promisify';
promisify(obj);
require('../promisify')(module.exports);
export default obj;

View File

@@ -1,15 +1,17 @@
'use strict';
const request = require('request');
import request from 'request';
const meta = require('../meta');
import meta from '../meta';
let versionCache = '';
let versionCacheLastModified = '';
import promisify from '../promisify';
const isPrerelease = /^v?\d+\.\d+\.\d+-.+$/;
function getLatestVersion(callback) {
export const isPrereleaseRegex = /^v?\d+\.\d+\.\d+-.+$/;
export function isPrerelease(callback) {
const headers = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': encodeURIComponent(`NodeBB Admin Control Panel/${meta.config.title}`),
@@ -46,7 +48,6 @@ function getLatestVersion(callback) {
});
}
exports.getLatestVersion = getLatestVersion;
exports.isPrerelease = isPrerelease;
promisify({ isPrerelease });
promisify({ isPrereleaseRegex });
require('../promisify')(exports);

View File

@@ -1,7 +1,7 @@
'use strict';
const { AsyncLocalStorage } = require('async_hooks');
import { AsyncLocalStorage } from 'async_hooks';
const asyncLocalStorage = new AsyncLocalStorage();
module.exports = asyncLocalStorage;
export default asyncLocalStorage;

View File

@@ -1,22 +1,23 @@
'use strict';
const cronJob = require('cron').CronJob;
const winston = require('winston');
const nconf = require('nconf');
const crypto = require('crypto');
const util = require('util');
const _ = require('lodash');
import { CronJob } from 'cron';
const cronJob = CronJob;import winston from 'winston';
import nconf from 'nconf';
import crypto from 'crypto';
import util from 'util';
import _ from 'lodash';
const sleep = util.promisify(setTimeout);
const db = require('./database');
const utils = require('./utils');
const plugins = require('./plugins');
const meta = require('./meta');
const pubsub = require('./pubsub');
const cacheCreate = require('./cache/lru');
import db from './database';
const Analytics = module.exports;
import utils from './utils';
import plugins from './plugins';
import meta from './meta';
import pubsub from './pubsub';
import cacheCreate from './cache/lru';
const Analytics = {} as any;
const secret = nconf.get('secret');
@@ -194,7 +195,7 @@ Analytics.writeData = async function () {
try {
await Promise.all(dbQueue);
} catch (err) {
} catch (err: any) {
winston.error(`[analytics] Encountered error while writing analytics to data store\n${err.stack}`);
}
};
@@ -298,4 +299,7 @@ Analytics.getBlacklistAnalytics = async function () {
});
};
require('./promisify')(Analytics);
import promisify from './promisify';
promisify(Analytics);
export default Analytics;

View File

@@ -1,12 +1,12 @@
'use strict';
const categories = require('../categories');
const events = require('../events');
const user = require('../user');
const groups = require('../groups');
const privileges = require('../privileges');
import categories from '../categories';
import events from '../events';
import user from '../user';
import groups from '../groups';
import privileges from '../privileges';
const categoriesAPI = module.exports;
const categoriesAPI = {} as any;
categoriesAPI.get = async function (caller, data) {
const [userPrivileges, category] = await Promise.all([
@@ -100,3 +100,5 @@ categoriesAPI.setPrivilege = async (caller, data) => {
target: data.member,
});
};
export default categoriesAPI;

View File

@@ -1,16 +1,15 @@
'use strict';
const validator = require('validator');
import validator from 'validator';
import user from '../user';
import meta from '../meta';
import messaging from '../messaging';
import plugins from '../plugins';
const user = require('../user');
const meta = require('../meta');
const messaging = require('../messaging');
const plugins = require('../plugins');
// const websockets from '../socket.io';
import socketHelpers from '../socket.io/helpers';
// const websockets = require('../socket.io');
const socketHelpers = require('../socket.io/helpers');
const chatsAPI = module.exports;
const chatsAPI = {} as any;
function rateLimitExceeded(caller) {
const session = caller.request ? caller.request.session : caller.session; // socket vs req
@@ -118,3 +117,5 @@ chatsAPI.kick = async (caller, data) => {
delete data.uids;
return chatsAPI.users(caller, data);
};
export default chatsAPI;

View File

@@ -1,9 +1,9 @@
'use strict';
const user = require('../user');
const flags = require('../flags');
import user from '../user';
import flags from '../flags';
const flagsApi = module.exports;
const flagsApi = {} as any;
flagsApi.create = async (caller, data) => {
const required = ['type', 'id', 'reason'];
@@ -49,7 +49,7 @@ flagsApi.appendNote = async (caller, data) => {
if (note.uid !== caller.uid) {
throw new Error('[[error:no-privileges]]');
}
} catch (e) {
} catch (e: any) {
// Okay if not does not exist in database
if (e.message !== '[[error:invalid-data]]') {
throw e;
@@ -82,3 +82,5 @@ flagsApi.deleteNote = async (caller, data) => {
]);
return { notes: notes, history: history };
};
export default flagsApi;

View File

@@ -1,16 +1,15 @@
'use strict';
const validator = require('validator');
import validator from 'validator';
import privileges from '../privileges';
import events from '../events';
import groups from '../groups';
import user from '../user';
import meta from '../meta';
import notifications from '../notifications';
import slugify from '../slugify';
const privileges = require('../privileges');
const events = require('../events');
const groups = require('../groups');
const user = require('../user');
const meta = require('../meta');
const notifications = require('../notifications');
const slugify = require('../slugify');
const groupsAPI = module.exports;
const groupsAPI = {} as any;
groupsAPI.create = async function (caller, data) {
if (!caller.uid) {
@@ -236,3 +235,5 @@ function logGroupEvent(caller, event, additional) {
...additional,
});
}
export default groupsAPI;

View File

@@ -1,24 +1,26 @@
'use strict';
const url = require('url');
const user = require('../user');
const topics = require('../topics');
const posts = require('../posts');
const privileges = require('../privileges');
const plugins = require('../plugins');
const socketHelpers = require('../socket.io/helpers');
const websockets = require('../socket.io');
const events = require('../events');
import url from 'url';
import user from '../user';
import topics from '../topics';
import posts from '../posts';
import privileges from '../privileges';
import plugins from '../plugins';
import socketHelpers from '../socket.io/helpers';
import websockets from '../socket.io';
import events from '../events';
exports.setDefaultPostData = function (reqOrSocket, data) {
export const setDefaultPostData = function (reqOrSocket, data) {
data.uid = reqOrSocket.uid;
data.req = exports.buildReqObject(reqOrSocket, { ...data });
data.req = buildReqObject(reqOrSocket, { ...data });
data.timestamp = Date.now();
data.fromQueue = false;
};
// creates a slimmed down version of the request object
exports.buildReqObject = (req, payload) => {
export const buildReqObject = (req, payload?) => {
req = req || {};
const headers = req.headers || (req.request && req.request.headers) || {};
const encrypted = req.connection ? !!req.connection.encrypted : false;
@@ -45,7 +47,7 @@ exports.buildReqObject = (req, payload) => {
};
};
exports.doTopicAction = async function (action, event, caller, { tids }) {
export const doTopicAction = async function (action, event, caller, { tids }: any) {
if (!Array.isArray(tids)) {
throw new Error('[[error:invalid-tid]]');
}
@@ -85,7 +87,7 @@ async function logTopicAction(action, req, tid, title) {
});
}
exports.postCommand = async function (caller, command, eventName, notification, data) {
export const postCommand = async function (caller, command, eventName, notification, data) {
if (!caller.uid) {
throw new Error('[[error:not-logged-in]]');
}

View File

@@ -1,11 +1,18 @@
'use strict';
import users from './users';
import groups from './groups';
import topics from './topics';
import posts from './posts';
import chats from './chats';
import categories from './categories';
import flags from './flags';
module.exports = {
users: require('./users'),
groups: require('./groups'),
topics: require('./topics'),
posts: require('./posts'),
chats: require('./chats'),
categories: require('./categories'),
flags: require('./flags'),
export default {
users,
groups,
topics,
posts,
chats,
categories,
flags,
};

View File

@@ -1,21 +1,20 @@
'use strict';
const validator = require('validator');
const _ = require('lodash');
import validator from 'validator';
import _ from 'lodash';
import utils from '../utils';
import user from '../user';
import posts from '../posts';
import topics from '../topics';
import groups from '../groups';
import meta from '../meta';
import events from '../events';
import privileges from '../privileges';
import * as apiHelpers from './helpers';
import websockets from '../socket.io';
import socketHelpers from '../socket.io/helpers';
const utils = require('../utils');
const user = require('../user');
const posts = require('../posts');
const topics = require('../topics');
const groups = require('../groups');
const meta = require('../meta');
const events = require('../events');
const privileges = require('../privileges');
const apiHelpers = require('./helpers');
const websockets = require('../socket.io');
const socketHelpers = require('../socket.io/helpers');
const postsAPI = module.exports;
const postsAPI = {} as any;
postsAPI.get = async function (caller, data) {
const [userPrivileges, post, voted] = await Promise.all([
@@ -333,3 +332,5 @@ postsAPI.restoreDiff = async (caller, data) => {
const edit = await posts.diffs.restore(data.pid, data.since, caller.uid, apiHelpers.buildReqObject(caller));
websockets.in(`topic_${edit.topic.tid}`).emit('event:post_edited', edit);
};
export default postsAPI;

View File

@@ -1,19 +1,20 @@
'use strict';
const user = require('../user');
const topics = require('../topics');
const posts = require('../posts');
const meta = require('../meta');
const privileges = require('../privileges');
import user from '../user';
import topics from '../topics';
import posts from '../posts';
import meta from '../meta';
const apiHelpers = require('./helpers');
import privileges from '../privileges';
import * as apiHelpers from './helpers';
const { doTopicAction } = apiHelpers;
const websockets = require('../socket.io');
const socketHelpers = require('../socket.io/helpers');
import websockets from '../socket.io';
import socketHelpers from '../socket.io/helpers';
const topicsAPI = module.exports;
const topicsAPI = {} as any;
topicsAPI.get = async function (caller, data) {
const [userPrivileges, topic] = await Promise.all([
@@ -152,3 +153,5 @@ topicsAPI.ignore = async function (caller, data) {
topicsAPI.unfollow = async function (caller, data) {
await topics.unfollow(data.tid, caller.uid);
};
export default topicsAPI;

View File

@@ -1,21 +1,21 @@
'use strict';
const validator = require('validator');
const winston = require('winston');
import validator from 'validator';
import winston from 'winston';
import db from '../database';
import user from '../user';
import groups from '../groups';
import meta from '../meta';
import child from 'child_process';
import flags from '../flags';
import privileges from '../privileges';
import notifications from '../notifications';
import plugins from '../plugins';
import events from '../events';
import translator from '../translator';
import sockets from '../socket.io';
const db = require('../database');
const user = require('../user');
const groups = require('../groups');
const meta = require('../meta');
const flags = require('../flags');
const privileges = require('../privileges');
const notifications = require('../notifications');
const plugins = require('../plugins');
const events = require('../events');
const translator = require('../translator');
const sockets = require('../socket.io');
const usersAPI = module.exports;
const usersAPI = {} as any;
usersAPI.create = async function (caller, data) {
if (!data) {
@@ -91,7 +91,7 @@ usersAPI.deleteAccount = async function (caller, { uid, password }) {
usersAPI.deleteMany = async function (caller, data) {
if (await canDeleteUids(data.uids)) {
await Promise.all(data.uids.map(uid => processDeletion({ uid, method: 'delete', caller })));
await Promise.all(data.uids.map(uid => processDeletion({ uid, method: 'delete', caller } as any)));
}
};
@@ -244,7 +244,7 @@ usersAPI.mute = async function (caller, data) {
uid: data.uid,
timestamp: now,
expire: data.until,
};
} as any;
if (data.reason) {
muteData.reason = reason;
}
@@ -448,16 +448,15 @@ usersAPI.generateExport = async (caller, { uid, type }) => {
if (count > 1) {
throw new Error('[[error:already-exporting]]');
}
const child = require('child_process').fork(`./src/user/jobs/export-${type}.js`, [], {
env: process.env,
(child as any).fork(`./src/user/jobs/export-${type}.js`, [], {
env: (process as any).env,
});
child.send({ uid });
child.on('error', async (err) => {
(child as any).send({ uid });
(child as any).on('error', async (err) => {
winston.error(err.stack);
await db.deleteObjectField('locks', `export:${uid}${type}`);
});
child.on('exit', async () => {
(child as any).on('exit', async () => {
await db.deleteObjectField('locks', `export:${uid}${type}`);
const { displayname } = await user.getUserFields(uid, ['username']);
const n = await notifications.create({
@@ -475,3 +474,5 @@ usersAPI.generateExport = async (caller, { uid, type }) => {
});
});
};
export default usersAPI;

View File

@@ -1,16 +1,19 @@
'use strict';
const util = require('util');
import util from 'util';
import db from './database';
import utils from './utils';
import promisify from './promisify';
const db = require('./database');
const utils = require('./utils');
const DEFAULT_BATCH_SIZE = 100;
const sleep = util.promisify(setTimeout);
exports.processSortedSet = async function (setKey, process, options) {
export const processSortedSet = async function (setKey, process, options , callback?) {
options = options || {};
if (typeof process !== 'function') {
@@ -35,7 +38,7 @@ exports.processSortedSet = async function (setKey, process, options) {
let start = 0;
let stop = options.batch - 1;
if (process && process.constructor && process.constructor.name !== 'AsyncFunction') {
if (process && (process as any).constructor && (process as any).constructor.name !== 'AsyncFunction') {
process = util.promisify(process);
}
@@ -56,7 +59,7 @@ exports.processSortedSet = async function (setKey, process, options) {
}
};
exports.processArray = async function (array, process, options) {
export const processArray = async function (array, process, options) {
options = options || {};
if (!Array.isArray(array) || !array.length) {
@@ -68,7 +71,7 @@ exports.processArray = async function (array, process, options) {
const batch = options.batch || DEFAULT_BATCH_SIZE;
let start = 0;
if (process && process.constructor && process.constructor.name !== 'AsyncFunction') {
if (process && (process as any).constructor && (process as any).constructor.name !== 'AsyncFunction') {
process = util.promisify(process);
}
@@ -89,4 +92,5 @@ exports.processArray = async function (array, process, options) {
}
};
require('./promisify')(exports);
promisify({ processArray });
promisify({ processSortedSet });

View File

@@ -1,8 +1,8 @@
'use strict';
const cacheCreate = require('./cache/lru');
import cacheCreate from './cache/lru';
module.exports = cacheCreate({
export default cacheCreate({
name: 'local',
max: 40000,
ttl: 0,

15
src/cache/lru.ts vendored
View File

@@ -1,12 +1,11 @@
'use strict';
module.exports = function (opts) {
const LRU = require('lru-cache');
const pubsub = require('../pubsub');
import LRU from 'lru-cache';
import pubsub from '../pubsub';
import winston from 'winston';
import chalk from 'chalk';
// lru-cache@7 deprecations
const winston = require('winston');
const chalk = require('chalk');
export default function (opts) {
// sometimes we kept passing in `length` with no corresponding `maxSize`.
// This is now enforced in v7; drop superfluous property
@@ -30,7 +29,7 @@ module.exports = function (opts) {
const lruCache = new LRU(opts);
const cache = {};
const cache = {} as any;
cache.name = opts.name;
cache.hits = 0;
cache.misses = 0;
@@ -61,7 +60,7 @@ module.exports = function (opts) {
if (!cache.enabled) {
return;
}
const opts = {};
const opts = {} as any;
if (ttl) {
opts.ttl = ttl;
}

11
src/cache/ttl.ts vendored
View File

@@ -1,12 +1,13 @@
'use strict';
module.exports = function (opts) {
const TTLCache = require('@isaacs/ttlcache');
const pubsub = require('../pubsub');
import TTLCache from '@isaacs/ttlcache';
import pubsub from '../pubsub';
export default function (opts) {
const ttlCache = new TTLCache(opts);
const cache = {};
const cache = {} as any;
cache.name = opts.name;
cache.hits = 0;
cache.misses = 0;
@@ -34,7 +35,7 @@ module.exports = function (opts) {
if (!cache.enabled) {
return;
}
const opts = {};
const opts = {} as any;
if (ttl) {
opts.ttl = ttl;
}

View File

@@ -1,3 +1,3 @@
'use strict';
module.exports = require('./cache/lru');
export * from './cache/lru';

View File

@@ -1,11 +1,10 @@
'use strict';
const _ = require('lodash');
import _ from 'lodash';
import posts from '../posts';
import db from '../database';
const posts = require('../posts');
const db = require('../database');
module.exports = function (Categories) {
export default function (Categories) {
Categories.getActiveUsers = async function (cids) {
if (!Array.isArray(cids)) {
cids = [cids];

View File

@@ -1,16 +1,15 @@
'use strict';
const async = require('async');
const _ = require('lodash');
import async from 'async';
import _ from 'lodash';
import db from '../database';
import plugins from '../plugins';
import privileges from '../privileges';
import utils from '../utils';
import slugify from '../slugify';
import cache from '../cache';
const db = require('../database');
const plugins = require('../plugins');
const privileges = require('../privileges');
const utils = require('../utils');
const slugify = require('../slugify');
const cache = require('../cache');
module.exports = function (Categories) {
export default function (Categories) {
Categories.create = async function (data) {
const parentCid = data.parentCid ? data.parentCid : 0;
const [cid, firstChild] = await Promise.all([
@@ -44,7 +43,7 @@ module.exports = function (Categories) {
imageClass: 'cover',
isSection: 0,
subCategoriesPerPage: 10,
};
} as any;
if (data.backgroundImage) {
category.backgroundImage = data.backgroundImage;

View File

@@ -1,11 +1,10 @@
'use strict';
const validator = require('validator');
const db = require('../database');
const meta = require('../meta');
const plugins = require('../plugins');
const utils = require('../utils');
import validator from 'validator';
import db from '../database';
import meta from '../meta';
import plugins from '../plugins';
import utils from '../utils';
const intFields = [
'cid', 'parentCid', 'disabled', 'isSection', 'order',
@@ -13,7 +12,7 @@ const intFields = [
'minTags', 'maxTags', 'postQueue', 'subCategoriesPerPage',
];
module.exports = function (Categories) {
export default function (Categories) {
Categories.getCategoriesFields = async function (cids, fields) {
if (!Array.isArray(cids) || !cids.length) {
return [];

View File

@@ -1,15 +1,15 @@
'use strict';
const async = require('async');
const db = require('../database');
const batch = require('../batch');
const plugins = require('../plugins');
const topics = require('../topics');
const groups = require('../groups');
const privileges = require('../privileges');
const cache = require('../cache');
import async from 'async';
import db from '../database';
import * as batch from '../batch';
import plugins from '../plugins';
import topics from '../topics';
import groups from '../groups';
import privileges from '../privileges';
import cache from '../cache';
module.exports = function (Categories) {
export default function (Categories) {
Categories.purge = async function (cid, uid) {
await batch.processSortedSet(`cid:${cid}:tids`, async (tids) => {
await async.eachLimit(tids, 10, async (tid) => {
@@ -60,7 +60,7 @@ module.exports = function (Categories) {
db.getSortedSetRange(`cid:${cid}:children`, 0, -1),
]);
const bulkAdd = [];
const bulkAdd = [] as any[];
const childrenKeys = children.map((cid) => {
bulkAdd.push(['cid:0:children', cid, cid]);
return `category:${cid}`;

View File

@@ -1,28 +1,38 @@
'use strict';
const _ = require('lodash');
import _ from 'lodash';
import db from '../database';
import user from '../user';
import groups from '../groups';
import plugins from '../plugins';
import privileges from '../privileges';
import cache from '../cache';
import meta from '../meta';
const db = require('../database');
const user = require('../user');
const groups = require('../groups');
const plugins = require('../plugins');
const privileges = require('../privileges');
const cache = require('../cache');
const meta = require('../meta');
const Categories = {} as any;
import data from './data';
import create from './create';
import deleteCategory from './delete';
import topics from './topics';
import unread from './unread';
import activeUsers from './activeusers';
import recentReplies from './recentreplies';
import update from './update';
import watch from './watch';
import search from './search';
import promisify from '../promisify';
const Categories = module.exports;
require('./data')(Categories);
require('./create')(Categories);
require('./delete')(Categories);
require('./topics')(Categories);
require('./unread')(Categories);
require('./activeusers')(Categories);
require('./recentreplies')(Categories);
require('./update')(Categories);
require('./watch')(Categories);
require('./search')(Categories);
data(Categories);
create(Categories);
deleteCategory(Categories);
topics(Categories);
unread(Categories);
activeUsers(Categories);
recentReplies(Categories);
update(Categories);
watch(Categories);
search(Categories);
Categories.exists = async function (cids) {
return await db.exists(
@@ -257,7 +267,7 @@ Categories.getParentCids = async function (currentCid) {
};
Categories.getChildrenCids = async function (rootCid) {
let allCids = [];
let allCids: number[] = [];
async function recursive(keys) {
let childrenCids = await db.getSortedSetRange(keys, 0, -1);
@@ -313,7 +323,7 @@ Categories.getTree = function (categories, parentCid) {
}
});
const tree = [];
const tree = [] as any[];
categories.forEach((category) => {
if (category) {
@@ -406,4 +416,5 @@ Categories.buildForSelectCategories = function (categories, fields, parentCid) {
return categoriesData.map(category => _.pick(category, pickFields));
};
require('../promisify')(Categories);
promisify(Categories);
export default Categories;

View File

@@ -1,17 +1,16 @@
'use strict';
const winston = require('winston');
const _ = require('lodash');
import winston from 'winston';
import _ from 'lodash';
import db from '../database';
import posts from '../posts';
import topics from '../topics';
import privileges from '../privileges';
import plugins from '../plugins';
import * as batch from '../batch';
const db = require('../database');
const posts = require('../posts');
const topics = require('../topics');
const privileges = require('../privileges');
const plugins = require('../plugins');
const batch = require('../batch');
module.exports = function (Categories) {
export default function (Categories) {
Categories.getRecentReplies = async function (cid, uid, start, stop) {
// backwards compatibility, treat start as count
if (stop === undefined && start > 0) {
@@ -71,7 +70,7 @@ module.exports = function (Categories) {
return;
}
const categoriesToLoad = categoryData.filter(c => c && c.numRecentReplies && parseInt(c.numRecentReplies, 10) > 0);
let keys = [];
let keys = [] as any[];
if (plugins.hooks.hasListeners('filter:categories.getRecentTopicReplies')) {
const result = await plugins.hooks.fire('filter:categories.getRecentTopicReplies', {
categories: categoriesToLoad,
@@ -144,7 +143,7 @@ module.exports = function (Categories) {
if (category.posts.length) {
return;
}
const posts = [];
const posts = [] as any[];
getPostsRecursive(category, posts);
posts.sort((a, b) => b.pid - a.pid);
@@ -174,8 +173,8 @@ module.exports = function (Categories) {
await batch.processArray(pids, async (pids) => {
const postData = await posts.getPostsFields(pids, ['pid', 'deleted', 'uid', 'timestamp', 'upvotes', 'downvotes']);
const bulkRemove = [];
const bulkAdd = [];
const bulkRemove = [] as any[];
const bulkAdd = [] as any[];
postData.forEach((post) => {
bulkRemove.push([`cid:${oldCid}:uid:${post.uid}:pids`, post.pid]);
bulkRemove.push([`cid:${oldCid}:uid:${post.uid}:pids:votes`, post.pid]);

View File

@@ -1,19 +1,18 @@
'use strict';
const _ = require('lodash');
import _ from 'lodash';
import privileges from '../privileges';
import plugins from '../plugins';
import db from '../database';
const privileges = require('../privileges');
const plugins = require('../plugins');
const db = require('../database');
module.exports = function (Categories) {
export default function (Categories) {
Categories.search = async function (data) {
const query = data.query || '';
const page = data.page || 1;
const uid = data.uid || 0;
const paginate = data.hasOwnProperty('paginate') ? data.paginate : true;
const startTime = process.hrtime();
const startTime = (process as any).hrtime();
let cids = await findCids(query, data.hardCap);
@@ -26,7 +25,7 @@ module.exports = function (Categories) {
const searchResult = {
matchCount: cids.length,
};
} as any;
if (paginate) {
const resultsPerPage = data.resultsPerPage || 50;
@@ -57,7 +56,7 @@ module.exports = function (Categories) {
}
return c1.order - c2.order;
});
searchResult.timing = (process.elapsedTimeSince(startTime) / 1000).toFixed(2);
searchResult.timing = ((process as any).elapsedTimeSince(startTime) / 1000).toFixed(2);
searchResult.categories = categoryData.filter(c => cids.includes(c.cid));
return searchResult;
};

View File

@@ -1,13 +1,13 @@
'use strict';
const db = require('../database');
const topics = require('../topics');
const plugins = require('../plugins');
const meta = require('../meta');
const privileges = require('../privileges');
const user = require('../user');
import db from '../database';
import topics from '../topics';
import plugins from '../plugins';
import meta from '../meta';
import privileges from '../privileges';
import user from '../user';
module.exports = function (Categories) {
export default function (Categories) {
Categories.getCategoryTopics = async function (data) {
let results = await plugins.hooks.fire('filter:category.topics.prepare', data);
const tids = await Categories.getTopicIds(results);
@@ -93,7 +93,7 @@ module.exports = function (Categories) {
Categories.buildTopicsSortedSet = async function (data) {
const { cid } = data;
let set = `cid:${cid}:tids`;
let set: any = `cid:${cid}:tids`;
const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest';
if (sort === 'most_posts') {

View File

@@ -1,8 +1,8 @@
'use strict';
const db = require('../database');
import db from '../database';
module.exports = function (Categories) {
export default function (Categories) {
Categories.markAsRead = async function (cids, uid) {
if (!Array.isArray(cids) || !cids.length || parseInt(uid, 10) <= 0) {
return;

View File

@@ -1,14 +1,14 @@
'use strict';
const db = require('../database');
const meta = require('../meta');
const utils = require('../utils');
const slugify = require('../slugify');
const translator = require('../translator');
const plugins = require('../plugins');
const cache = require('../cache');
import db from '../database';
import meta from '../meta';
import utils from '../utils';
import slugify from '../slugify';
import translator from '../translator';
import plugins from '../plugins';
import cache from '../cache';
module.exports = function (Categories) {
export default function (Categories) {
Categories.update = async function (modified) {
const cids = Object.keys(modified);
await Promise.all(cids.map(cid => updateCategory(cid, modified[cid])));

View File

@@ -1,9 +1,9 @@
'use strict';
const db = require('../database');
const user = require('../user');
import db from '../database';
import user from '../user';
module.exports = function (Categories) {
export default function (Categories) {
Categories.watchStates = {
ignoring: 1,
notwatching: 2,

View File

@@ -4,8 +4,8 @@
// to include color styling in the output
// so the CLI looks nice
const { Command } = require('commander');
const chalk = require('chalk');
import { Command } from 'commander';
import chalk from 'chalk';
const colors = [
// depth = 0, top-level command
@@ -31,7 +31,7 @@ function getControlCharacterSpaces(term) {
// get depth of command
// 0 = top, 1 = subcommand of top, etc
Command.prototype.depth = function () {
(Command.prototype as any).depth = function () {
if (this._depth === undefined) {
let depth = 0;
let { parent } = this;
@@ -42,7 +42,7 @@ Command.prototype.depth = function () {
return this._depth;
};
module.exports = {
export default {
commandUsage(cmd) {
const depth = cmd.depth();

View File

@@ -2,20 +2,47 @@
'use strict';
const fs = require('fs');
const path = require('path');
import * as prestart from '../prestart';
import yargs from 'yargs';
import fs from 'fs';
import path from 'path';
import { paths } from '../constants';
import nconf from 'nconf';
const opts = yargs((process as any).argv.slice(2)).help(false).exitProcess(false);
nconf.argv(opts).env({
separator: '__',
});
(process as any).env.NODE_ENV = (process as any).env.NODE_ENV || 'production';
(global as any).env = (process as any).env.NODE_ENV || 'production';
prestart.setupWinston();
// Alternate configuration file support
const configFile = path.resolve(paths.baseDir, nconf.get('config') || 'config.json');
const configExists = fs.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
prestart.loadConfig(configFile);
prestart.versionCheck();
// used for calling the file
require('../../require-main');
const packageInstall = require('./package-install');
const { paths } = require('../constants');
import packageInstall from './package-install';
import semver from 'semver';
//@ts-ignore
import defaultPackage from '../../install/package.json';
import chalk from 'chalk';
import { program } from 'commander';
import manage from './manage';
try {
fs.accessSync(paths.currentPackage, fs.constants.R_OK); // throw on missing package.json
try { // handle missing node_modules/ directory
fs.accessSync(paths.nodeModules, fs.constants.R_OK);
} catch (e) {
if (e.code === 'ENOENT') {
} catch (e: any) { if (e.code === 'ENOENT') {
// run package installation just to sync up node_modules/ with existing package.json
packageInstall.installAll();
} else {
@@ -24,13 +51,12 @@ try {
}
fs.accessSync(path.join(paths.nodeModules, 'semver/package.json'), fs.constants.R_OK);
const semver = require('semver');
const defaultPackage = require('../../install/package.json');
const checkVersion = function (packageName) {
const { version } = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, packageName, 'package.json'), 'utf8'));
if (!semver.satisfies(version, defaultPackage.dependencies[packageName])) {
const e = new TypeError(`Incorrect dependency version: ${packageName}`);
const e: any = new TypeError(`Incorrect dependency version: ${packageName}`);
e.code = 'DEP_WRONG_VERSION';
throw e;
}
@@ -42,7 +68,7 @@ try {
checkVersion('chalk');
checkVersion('lodash');
checkVersion('lru-cache');
} catch (e) {
} catch (e: any) {
if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) {
console.warn('Dependencies outdated or not yet installed.');
console.log('Installing them now...\n');
@@ -51,28 +77,18 @@ try {
packageInstall.preserveExtraneousPlugins();
packageInstall.installAll();
const chalk = require('chalk');
console.log(`${chalk.green('OK')}\n`);
} else {
throw e;
}
}
const chalk = require('chalk');
const nconf = require('nconf');
const { program } = require('commander');
const yargs = require('yargs');
const pkg = require('../../install/package.json');
const file = require('../file');
const prestart = require('../prestart');
program.configureHelp(require('./colors'));
program
.name('./nodebb')
.description('Welcome to NodeBB')
.version(pkg.version)
.version(defaultPackage.version)
.option('--json-logging', 'Output to logs in JSON format', false)
.option('--log-level <level>', 'Default logging level to use', 'info')
.option('--config <value>', 'Specify a config file', 'config.json')
@@ -82,29 +98,15 @@ program
// provide a yargs object ourselves
// otherwise yargs will consume `--help` or `help`
// and `nconf` will exit with useless usage info
const opts = yargs(process.argv.slice(2)).help(false).exitProcess(false);
nconf.argv(opts).env({
separator: '__',
});
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
global.env = process.env.NODE_ENV || 'production';
prestart.setupWinston();
// Alternate configuration file support
const configFile = path.resolve(paths.baseDir, nconf.get('config') || 'config.json');
const configExists = file.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
prestart.loadConfig(configFile);
prestart.versionCheck();
if (!configExists && process.argv[2] !== 'setup') {
if (!configExists && (process as any).argv[2] !== 'setup') {
require('./setup').webInstall();
// @ts-ignore
return;
}
process.env.CONFIG = configFile;
(process as any).env.CONFIG = configFile;
// running commands
program
@@ -127,8 +129,8 @@ program
})
.description('Start NodeBB in verbose development mode')
.action(() => {
process.env.NODE_ENV = 'development';
global.env = 'development';
(process as any).env.NODE_ENV = 'development';
(global as any).env = 'development';
require('./running').start({ ...program.opts(), dev: true });
});
program
@@ -162,11 +164,11 @@ program
.description('Run the NodeBB setup script, or setup with an initial config')
.option('--skip-build', 'Run setup without building assets')
.action((initConfig) => {
console.log('INIT CONFIG', initConfig);
if (initConfig) {
try {
initConfig = JSON.parse(initConfig);
} catch (e) {
console.warn(chalk.red('Invalid JSON passed as initial config value.'));
} catch (e: any) { console.warn(chalk.red('Invalid JSON passed as initial config value.'));
console.log('If you meant to pass in an initial config value, please try again.\n');
throw e;
@@ -181,7 +183,7 @@ program
.option('-f, --force', 'Force plugin installation even if it may be incompatible with currently installed NodeBB version')
.action((plugin, options) => {
if (plugin) {
require('./manage').install(plugin, options);
manage.install(plugin);
} else {
require('./setup').webInstall();
}
@@ -193,11 +195,12 @@ program
.option('-s, --series', 'Run builds in series without extra processes')
.option('-w, --webpack', 'Bundle assets with webpack', true)
.action((targets, options) => {
console.log('HEYYYYY!!!!!!!!!!!');
if (program.opts().dev) {
process.env.NODE_ENV = 'development';
global.env = 'development';
(process as any).env.NODE_ENV = 'development';
(global as any).env = 'development';
}
require('./manage').build(targets.length ? targets : true, options);
manage.buildWrapper(targets.length ? targets : true, options);
})
.on('--help', () => {
require('../meta/aliases').buildTargets();
@@ -206,25 +209,25 @@ program
.command('activate [plugin]')
.description('Activate a plugin for the next startup of NodeBB (nodebb-plugin- prefix is optional)')
.action((plugin) => {
require('./manage').activate(plugin);
manage.activate(plugin);
});
program
.command('plugins')
.action(() => {
require('./manage').listPlugins();
manage.listPlugins();
})
.description('List all installed plugins');
program
.command('events [count]')
.description('Outputs the most recent administrative events recorded by NodeBB')
.action((count) => {
require('./manage').listEvents(count);
manage.listEvents(count);
});
program
.command('info')
.description('Outputs various system info')
.action(() => {
require('./manage').info();
manage.info();
});
// reset
@@ -246,10 +249,10 @@ resetCommand
require('./reset').reset(options, (err) => {
if (err) {
return process.exit(1);
return (process as any).exit(1);
}
process.exit(0);
(process as any).exit(0);
});
});
@@ -277,8 +280,8 @@ program
})
.action((scripts, options) => {
if (program.opts().dev) {
process.env.NODE_ENV = 'development';
global.env = 'development';
(process as any).env.NODE_ENV = 'development';
(global as any).env = 'development';
}
require('./upgrade').upgrade(scripts.length ? scripts : true, options);
});
@@ -295,7 +298,7 @@ program
throw err;
}
console.log(chalk.green('OK'));
process.exit();
(process as any).exit();
});
});
@@ -307,7 +310,7 @@ program
return program.help();
}
const command = program.commands.find(command => command._name === name);
const command = program.commands.find(command => (command as any)._name === name);
if (command) {
command.help();
} else {
@@ -316,10 +319,10 @@ program
}
});
if (process.argv.length === 2) {
if ((process as any).argv.length === 2) {
program.help();
}
program.executables = false;
(program as any).executables = false;
program.parse();

View File

@@ -1,20 +1,22 @@
'use strict';
const winston = require('winston');
const childProcess = require('child_process');
const CliGraph = require('cli-graph');
const chalk = require('chalk');
const nconf = require('nconf');
import winston from 'winston';
import child from 'child_process';
import CliGraph from 'cli-graph';
import chalk from 'chalk';
import nconf from 'nconf';
import { build } from '../meta/build';
import db from '../database';
import plugins from '../plugins';
import events from '../events';
import analytics from '../analytics';
import * as reset from './reset';
import { pluginNamePattern, themeNamePattern, paths } from '../constants';
//@ts-ignore
import { version } from '../../package.json';
const build = require('../meta/build');
const db = require('../database');
const plugins = require('../plugins');
const events = require('../events');
const analytics = require('../analytics');
const reset = require('./reset');
const { pluginNamePattern, themeNamePattern, paths } = require('../constants');
async function install(plugin, options) {
async function install(plugin, options?) {
if (!options) {
options = {};
}
@@ -31,7 +33,7 @@ async function install(plugin, options) {
if (isInstalled) {
throw new Error('plugin already installed');
}
const nbbVersion = require(paths.currentPackage).version;
const nbbVersion = require(paths.currentPackage).default.version;
const suggested = await plugins.suggest(plugin, nbbVersion);
if (!suggested.version) {
if (!options.force) {
@@ -43,10 +45,10 @@ async function install(plugin, options) {
winston.info('Installing Plugin `%s@%s`', plugin, suggested.version);
await plugins.toggleInstall(plugin, suggested.version);
process.exit(0);
} catch (err) {
(process as any).exit(0);
} catch (err: any) {
winston.error(`An error occurred during plugin installation\n${err.stack}`);
process.exit(1);
(process as any).exit(1);
}
}
@@ -55,7 +57,7 @@ async function activate(plugin) {
await reset.reset({
theme: plugin,
});
process.exit();
(process as any).exit();
}
try {
await db.init();
@@ -73,11 +75,11 @@ async function activate(plugin) {
const isActive = await plugins.isActive(plugin);
if (isActive) {
winston.info('Plugin `%s` already active', plugin);
process.exit(0);
(process as any).exit(0);
}
if (nconf.get('plugins:active')) {
winston.error('Cannot activate plugins while plugin state configuration is set, please change your active configuration (config.json, environmental variables or terminal arguments) instead');
process.exit(1);
(process as any).exit(1);
}
const numPlugins = await db.sortedSetCard('plugins:active');
winston.info('Activating plugin `%s`', plugin);
@@ -87,10 +89,10 @@ async function activate(plugin) {
text: plugin,
});
process.exit(0);
} catch (err) {
(process as any).exit(0);
} catch (err: any) {
winston.error(`An error occurred during plugin activation\n${err.stack}`);
process.exit(1);
(process as any).exit(1);
}
}
@@ -116,16 +118,16 @@ async function listPlugins() {
combined.sort((a, b) => (a.id > b.id ? 1 : -1));
// Pretty output
process.stdout.write('Active plugins:\n');
(process as any).stdout.write('Active plugins:\n');
combined.forEach((plugin) => {
process.stdout.write(`\t* ${plugin.id}${plugin.version ? `@${plugin.version}` : ''} (`);
process.stdout.write(plugin.installed ? chalk.green('installed') : chalk.red('not installed'));
process.stdout.write(', ');
process.stdout.write(plugin.active ? chalk.green('enabled') : chalk.yellow('disabled'));
process.stdout.write(')\n');
(process as any).stdout.write(`\t* ${plugin.id}${plugin.version ? `@${plugin.version}` : ''} (`);
(process as any).stdout.write(plugin.installed ? chalk.green('installed') : chalk.red('not installed'));
(process as any).stdout.write(', ');
(process as any).stdout.write(plugin.active ? chalk.green('enabled') : chalk.yellow('disabled'));
(process as any).stdout.write(')\n');
});
process.exit();
(process as any).exit();
}
async function listEvents(count = 10) {
@@ -135,17 +137,16 @@ async function listEvents(count = 10) {
eventData.forEach((event) => {
console.log(` * ${chalk.green(String(event.timestampISO))} ${chalk.yellow(String(event.type))}${event.text ? ` ${event.text}` : ''} (uid: ${event.uid ? event.uid : 0})`);
});
process.exit();
(process as any).exit();
}
async function info() {
console.log('');
const { version } = require('../../package.json');
console.log(` version: ${version}`);
console.log(` Node ver: ${process.version}`);
const hash = childProcess.execSync('git rev-parse HEAD');
console.log(` Node ver: ${(process as any).version}`);
// @ts-ignore
const hash = child(process as any).execSync('git rev-parse HEAD');
console.log(` git hash: ${hash}`);
console.log(` database: ${nconf.get('database')}`);
@@ -182,28 +183,31 @@ async function info() {
const max = Math.max(...analyticsData);
analyticsData.forEach((point, idx) => {
// @ts-ignore
graph.addPoint(idx + 1, Math.round(point / max * 10));
});
console.log('');
console.log(graph.toString());
console.log(`Pageviews, last 24h (min: ${min} max: ${max})`);
process.exit();
(process as any).exit();
}
async function buildWrapper(targets, options) {
async function buildWrapper(targets, options?) {
try {
await build.build(targets, options);
process.exit(0);
} catch (err) {
await build(targets, options);
(process as any).exit(0);
} catch (err: any) {
winston.error(err.stack);
process.exit(1);
(process as any).exit(1);
}
}
exports.build = buildWrapper;
exports.install = install;
exports.activate = activate;
exports.listPlugins = listPlugins;
exports.listEvents = listEvents;
exports.info = info;
export default {
buildWrapper,
install,
activate,
listPlugins,
listEvents,
info
};

View File

@@ -1,13 +1,15 @@
'use strict';
const path = require('path');
import path from 'path';
import fs from 'fs';
import cproc from 'child_process';
import { paths, pluginNamePattern } from '../constants';
import nconf from 'nconf';
import _ from 'lodash';
const fs = require('fs');
const cproc = require('child_process');
const { paths, pluginNamePattern } = require('../constants');
const pkgInstall = module.exports;
const pkgInstall = {} as any;
function sortDependencies(dependencies) {
return Object.entries(dependencies)
@@ -23,8 +25,7 @@ pkgInstall.updatePackageFile = () => {
try {
oldPackageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
} catch (e) {
if (e.code !== 'ENOENT') {
} catch (e: any) { if (e.code !== 'ENOENT') {
throw e;
} else {
// No local package.json, copy from install/package.json
@@ -33,7 +34,6 @@ pkgInstall.updatePackageFile = () => {
}
}
const _ = require('lodash');
const defaultPackageContents = JSON.parse(fs.readFileSync(paths.installPackage, 'utf8'));
let dependencies = {};
@@ -70,7 +70,6 @@ pkgInstall.getPackageManager = () => {
return packageManager.groups.packageManager;
}
fs.accessSync(path.join(paths.nodeModules, 'nconf/package.json'), fs.constants.R_OK);
const nconf = require('nconf');
if (!Object.keys(nconf.stores).length) {
// Quick & dirty nconf setup for when you cannot rely on nconf having been required already
const configFile = path.resolve(__dirname, '../../', nconf.any(['config', 'CONFIG']) || 'config.json');
@@ -87,8 +86,7 @@ pkgInstall.getPackageManager = () => {
}
return nconf.get('package_manager') || 'npm';
} catch (e) {
// nconf not installed or other unexpected error/exception
} catch (e: any) { // nconf not installed or other unexpected error/exception
return getPackageManagerByLockfile() || 'npm';
}
};
@@ -103,10 +101,10 @@ function getPackageManagerByLockfile() {
}
pkgInstall.installAll = () => {
const prod = process.env.NODE_ENV !== 'development';
const prod = (process as any).env.NODE_ENV !== 'development';
let command = 'npm install';
const supportedPackageManagerList = exports.supportedPackageManager; // load config from src/cli/package-install.js
const supportedPackageManagerList = pkgInstall.supportedPackageManager; // load config from src/cli/package-install.js
const packageManager = pkgInstall.getPackageManager();
if (supportedPackageManagerList.indexOf(packageManager) >= 0) {
switch (packageManager) {
@@ -130,7 +128,7 @@ pkgInstall.installAll = () => {
cwd: path.join(__dirname, '../../'),
stdio: [0, 1, 2],
});
} catch (e) {
} catch (e: any) {
console.log('Error installing dependencies!');
console.log(`message: ${e.message}`);
console.log(`stdout: ${e.stdout}`);
@@ -143,8 +141,7 @@ pkgInstall.preserveExtraneousPlugins = () => {
// Skip if `node_modules/` is not found or inaccessible
try {
fs.accessSync(paths.nodeModules, fs.constants.R_OK);
} catch (e) {
return;
} catch (e: any) { return;
}
const packages = fs.readdirSync(paths.nodeModules)
@@ -172,3 +169,5 @@ pkgInstall.preserveExtraneousPlugins = () => {
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
};
export default pkgInstall;

View File

@@ -1,20 +1,19 @@
'use strict';
const path = require('path');
const winston = require('winston');
const fs = require('fs');
const chalk = require('chalk');
const nconf = require('nconf');
import path from 'path';
import winston from 'winston';
import fs from 'fs';
import chalk from 'chalk';
import nconf from 'nconf';
import db from '../database';
import events from '../events';
import meta from '../meta';
import plugins from '../plugins';
import widgets from '../widgets';
import privileges from '../privileges';
import { paths, pluginNamePattern, themeNamePattern } from '../constants';
const db = require('../database');
const events = require('../events');
const meta = require('../meta');
const plugins = require('../plugins');
const widgets = require('../widgets');
const privileges = require('../privileges');
const { paths, pluginNamePattern, themeNamePattern } = require('../constants');
exports.reset = async function (options) {
export const reset = async function (options) {
const map = {
theme: async function () {
let themeId = options.theme;
@@ -71,7 +70,7 @@ exports.reset = async function (options) {
' Prefix is optional, e.g. ./nodebb reset -p markdown, ./nodebb reset -t harmony',
].join('\n'));
process.exit(0);
(process as any).exit(0);
}
try {
@@ -81,10 +80,10 @@ exports.reset = async function (options) {
await task();
}
winston.info('[reset] Reset complete. Please run `./nodebb build` to rebuild assets.');
process.exit(0);
} catch (err) {
(process as any).exit(0);
} catch (err: any) {
winston.error(`[reset] Errors were encountered during reset -- ${err.message}`);
process.exit(1);
(process as any).exit(1);
}
};
@@ -97,7 +96,7 @@ async function resetSettings() {
async function resetTheme(themeId) {
try {
await fs.promises.access(path.join(paths.nodeModules, themeId, 'package.json'));
} catch (err) {
} catch (err: any) {
winston.warn('[reset] Theme `%s` is not installed on this forum', themeId);
throw new Error('theme-not-found');
}
@@ -117,11 +116,11 @@ async function resetThemeTo(themeId) {
winston.info(`[reset] Theme reset to ${themeId} and default skin`);
}
async function resetPlugin(pluginId) {
async function resetPlugin(pluginId?) {
try {
if (nconf.get('plugins:active')) {
winston.error('Cannot reset plugins while plugin state is set in the configuration (config.json, environmental variables or terminal arguments), please modify the configuration instead');
process.exit(1);
(process as any).exit(1);
}
const isActive = await db.isSortedSetMember('plugins:active', pluginId);
if (isActive) {
@@ -135,7 +134,7 @@ async function resetPlugin(pluginId) {
winston.warn('[reset] Plugin `%s` was not active on this forum', pluginId);
winston.info('[reset] No action taken.');
}
} catch (err) {
} catch (err: any) {
winston.error(`[reset] Could not disable plugin: ${pluginId} encountered error %s\n${err.stack}`);
throw err;
}
@@ -144,7 +143,7 @@ async function resetPlugin(pluginId) {
async function resetPlugins() {
if (nconf.get('plugins:active')) {
winston.error('Cannot reset plugins while plugin state is set in the configuration (config.json, environmental variables or terminal arguments), please modify the configuration instead');
process.exit(1);
(process as any).exit(1);
}
await db.delete('plugins:active');
winston.info('[reset] All Plugins De-activated');

View File

@@ -1,38 +1,35 @@
'use strict';
const fs = require('fs');
const childProcess = require('child_process');
const chalk = require('chalk');
const fork = require('../meta/debugFork');
const { paths } = require('../constants');
import fs from 'fs';
import chalk from 'chalk';
import fork from '../meta/debugFork';
import { paths } from '../constants';
const cwd = paths.baseDir;
function getRunningPid(callback) {
export function getRunningPid(callback) {
fs.readFile(paths.pidfile, {
encoding: 'utf-8',
}, (err, pid) => {
}, (err, pid: number | string) => {
if (err) {
return callback(err);
}
pid = parseInt(pid, 10);
pid = parseInt(pid as string, 10);
try {
process.kill(pid, 0);
(process as any).kill(pid, 0);
callback(null, pid);
} catch (e) {
callback(e);
} catch (e: any) { callback(e);
}
});
}
function start(options) {
export function start(options?) {
if (options.dev) {
process.env.NODE_ENV = 'development';
(process as any).env.NODE_ENV = 'development';
fork(paths.loader, ['--no-daemon', '--no-silent'], {
env: process.env,
env: (process as any).env,
stdio: 'inherit',
cwd,
});
@@ -55,12 +52,13 @@ function start(options) {
}
// Spawn a new NodeBB process
const child = fork(paths.loader, process.argv.slice(3), {
env: process.env,
const child = fork(paths.loader, (process as any).argv.slice(3), {
env: (process as any).env,
cwd,
});
if (options.log) {
childProcess.spawn('tail', ['-F', './logs/output.log'], {
// @ts-ignore
child(process as any).spawn('tail', ['-F', './logs/output.log'], {
stdio: 'inherit',
cwd,
});
@@ -69,10 +67,10 @@ function start(options) {
return child;
}
function stop() {
export function stop() {
getRunningPid((err, pid) => {
if (!err) {
process.kill(pid, 'SIGTERM');
(process as any).kill(pid, 'SIGTERM');
console.log('Stopping NodeBB. Goodbye!');
} else {
console.log('NodeBB is already stopped.');
@@ -84,7 +82,7 @@ function restart(options) {
getRunningPid((err, pid) => {
if (!err) {
console.log(chalk.bold('\nRestarting NodeBB'));
process.kill(pid, 'SIGTERM');
(process as any).kill(pid, 'SIGTERM');
options.silent = true;
start(options);
@@ -94,7 +92,7 @@ function restart(options) {
});
}
function status() {
export function status() {
getRunningPid((err, pid) => {
if (!err) {
console.log(`\n${[
@@ -110,16 +108,11 @@ function status() {
});
}
function log() {
export function log() {
console.log(`${chalk.red('\nHit ') + chalk.bold('Ctrl-C ') + chalk.red('to exit\n')}\n`);
childProcess.spawn('tail', ['-F', './logs/output.log'], {
stdio: 'inherit',
cwd,
});
// child(process as any).spawn('tail', ['-F', './logs/output.log'], {
// stdio: 'inherit',
// cwd,
// });
}
exports.start = start;
exports.stop = stop;
exports.restart = restart;
exports.status = status;
exports.log = log;

View File

@@ -1,17 +1,18 @@
'use strict';
const winston = require('winston');
const path = require('path');
const nconf = require('nconf');
import winston from 'winston';
import path from 'path';
import nconf from 'nconf';
import web from '../../install/web';
import { paths } from '../constants';
// import install from '../install';
import * as build from '../meta/build';
import * as prestart from '../prestart';
//@ts-ignore
import pkg from '../../package.json';
const { install } = require('../../install/web');
async function setup(initConfig?) {
async function setup(initConfig) {
const { paths } = require('../constants');
const install = require('../install');
const build = require('../meta/build');
const prestart = require('../prestart');
const pkg = require('../../package.json');
winston.info('NodeBB Setup Triggered via Command Line');
@@ -19,8 +20,8 @@ async function setup(initConfig) {
console.log('\nThis looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.');
console.log('Press enter to accept the default setting (shown in brackets).');
install.values = initConfig;
const data = await install.setup();
web.values = initConfig;
const data = await web.setup();
let configFile = paths.config;
if (nconf.get('config')) {
configFile = path.resolve(paths.baseDir, nconf.get('config'));
@@ -33,8 +34,8 @@ async function setup(initConfig) {
}
let separator = ' ';
if (process.stdout.columns > 10) {
for (let x = 0, cols = process.stdout.columns - 10; x < cols; x += 1) {
if ((process as any).stdout.columns > 10) {
for (let x = 0, cols = (process as any).stdout.columns - 10; x < cols; x += 1) {
separator += '=';
}
}
@@ -50,11 +51,15 @@ async function setup(initConfig) {
// If I am a child process, notify the parent of the returned data before exiting (useful for notifying
// hosts of auto-generated username/password during headless setups)
if (process.send) {
process.send(data);
if ((process as any).send) {
(process as any).send(data);
}
process.exit();
(process as any).exit();
}
exports.setup = setup;
exports.webInstall = install;
export default {
setup,
webInstall: web,
}

View File

@@ -1,30 +1,30 @@
'use strict';
const prompt = require('prompt');
const request = require('request-promise-native');
const cproc = require('child_process');
const semver = require('semver');
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
import prompt from 'prompt';
import request from 'request-promise-native';
import cproc from 'child_process';
import semver from 'semver';
import fs from 'fs';
import path from 'path';
import chalk from 'chalk';
import { paths, pluginNamePattern } from '../constants';
import pkgInstall from './package-install';
import * as batch from '../batch';
const { paths, pluginNamePattern } = require('../constants');
const pkgInstall = require('./package-install');
const packageManager = pkgInstall.getPackageManager();
let packageManagerExecutable = packageManager;
const packageManagerInstallArgs = packageManager === 'yarn' ? ['add'] : ['install', '--save'];
if (process.platform === 'win32') {
if ((process as any).platform === 'win32') {
packageManagerExecutable += '.cmd';
}
async function getModuleVersions(modules) {
const versionHash = {};
const batch = require('../batch');
await batch.processArray(modules, async (moduleNames) => {
await Promise.all(moduleNames.map(async (module) => {
let pkg = await fs.promises.readFile(
let pkg: any = await fs.promises.readFile(
path.join(paths.nodeModules, module, 'package.json'), { encoding: 'utf-8' }
);
pkg = JSON.parse(pkg);
@@ -41,7 +41,7 @@ async function getInstalledPlugins() {
let [deps, bundled] = await Promise.all([
fs.promises.readFile(paths.currentPackage, { encoding: 'utf-8' }),
fs.promises.readFile(paths.installPackage, { encoding: 'utf-8' }),
]);
]) as [any, any];
deps = Object.keys(JSON.parse(deps).dependencies)
.filter(pkgName => pluginNamePattern.test(pkgName));
@@ -59,8 +59,7 @@ async function getInstalledPlugins() {
try {
fs.accessSync(path.join(paths.nodeModules, pkgName, '.git'));
return false;
} catch (e) {
return true;
} catch (e: any) { return true;
}
});
@@ -68,7 +67,7 @@ async function getInstalledPlugins() {
}
async function getCurrentVersion() {
let pkg = await fs.promises.readFile(paths.installPackage, { encoding: 'utf-8' });
let pkg: any = await fs.promises.readFile(paths.installPackage, { encoding: 'utf-8' });
pkg = JSON.parse(pkg);
return pkg.version;
}
@@ -86,7 +85,7 @@ async function getSuggestedModules(nbbVersion, toCheck) {
}
async function checkPlugins() {
process.stdout.write('Checking installed plugins and themes for updates... ');
(process as any).stdout.write('Checking installed plugins and themes for updates... ');
const [plugins, nbbVersion] = await Promise.all([
getInstalledPlugins(),
getCurrentVersion(),
@@ -94,11 +93,11 @@ async function checkPlugins() {
const toCheck = Object.keys(plugins);
if (!toCheck.length) {
process.stdout.write(chalk.green(' OK'));
(process as any).stdout.write(chalk.green(' OK'));
return []; // no extraneous plugins installed
}
const suggestedModules = await getSuggestedModules(nbbVersion, toCheck);
process.stdout.write(chalk.green(' OK'));
(process as any).stdout.write(chalk.green(' OK'));
let current;
let suggested;
@@ -119,13 +118,13 @@ async function checkPlugins() {
return upgradable;
}
async function upgradePlugins() {
export const upgradePlugins = async function() {
try {
const found = await checkPlugins();
if (found && found.length) {
process.stdout.write(`\n\nA total of ${chalk.bold(String(found.length))} package(s) can be upgraded:\n\n`);
(process as any).stdout.write(`\n\nA total of ${chalk.bold(String(found.length))} package(s) can be upgraded:\n\n`);
found.forEach((suggestObj) => {
process.stdout.write(`${chalk.yellow(' * ') + suggestObj.name} (${chalk.yellow(suggestObj.current)} -> ${chalk.green(suggestObj.suggested)})\n`);
(process as any).stdout.write(`${chalk.yellow(' * ') + suggestObj.name} (${chalk.yellow(suggestObj.current)} -> ${chalk.green(suggestObj.suggested)})\n`);
});
} else {
console.log(chalk.green('\nAll packages up-to-date!'));
@@ -150,10 +149,9 @@ async function upgradePlugins() {
} else {
console.log(`${chalk.yellow('Package upgrades skipped')}. Check for upgrades at any time by running "${chalk.green('./nodebb upgrade -p')}".`);
}
} catch (err) {
} catch (err: any) {
console.log(`${chalk.yellow('Warning')}: An unexpected error occured when attempting to verify plugin upgradability`);
throw err;
}
}
exports.upgradePlugins = upgradePlugins;

View File

@@ -1,10 +1,13 @@
'use strict';
const nconf = require('nconf');
const chalk = require('chalk');
import nconf from 'nconf';
import chalk from 'chalk';
import packageInstall from './package-install';
import { upgradePlugins } from './upgrade-plugins';
import db from '../database';
import meta from '../meta';
import Upgrade from '../upgrade';
const packageInstall = require('./package-install');
const { upgradePlugins } = require('./upgrade-plugins');
const steps = {
package: {
@@ -12,13 +15,13 @@ const steps = {
handler: function () {
packageInstall.updatePackageFile();
packageInstall.preserveExtraneousPlugins();
process.stdout.write(chalk.green(' OK\n'));
(process as any).stdout.write(chalk.green(' OK\n'));
},
},
install: {
message: 'Bringing base dependencies up to date...',
handler: function () {
process.stdout.write(chalk.green(' started\n'));
(process as any).stdout.write(chalk.green(' started\n'));
packageInstall.installAll();
},
},
@@ -50,7 +53,7 @@ async function runSteps(tasks) {
for (let i = 0; i < tasks.length; i++) {
const step = steps[tasks[i]];
if (step && step.message && step.handler) {
process.stdout.write(`\n${chalk.bold(`${i + 1}. `)}${chalk.yellow(step.message)}`);
(process as any).stdout.write(`\n${chalk.bold(`${i + 1}. `)}${chalk.yellow(step.message)}`);
/* eslint-disable-next-line */
await step.handler();
}
@@ -58,19 +61,19 @@ async function runSteps(tasks) {
const message = 'NodeBB Upgrade Complete!';
// some consoles will return undefined/zero columns,
// so just use 2 spaces in upgrade script if we can't get our column count
const { columns } = process.stdout;
const { columns } = (process as any).stdout;
const spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : ' ';
console.log(`\n\n${spaces}${chalk.green.bold(message)}\n`);
process.exit();
} catch (err) {
(process as any).exit();
} catch (err: any) {
console.error(`Error occurred during upgrade: ${err.stack}`);
throw err;
}
}
async function runUpgrade(upgrades, options) {
async function runUpgrade(upgrades, options?) {
console.log(chalk.cyan('\nUpdating NodeBB...'));
options = options || {};
// disable mongo timeouts during upgrade
@@ -86,10 +89,10 @@ async function runUpgrade(upgrades, options) {
return;
}
await require('../database').init();
await require('../meta').configs.init();
await require('../upgrade').runParticular(upgrades);
process.exit(0);
db.init();
meta.configs.init();
Upgrade.runParticular(upgrades);
(process as any).exit(0);
}
exports.upgrade = runUpgrade;
export const upgrade = runUpgrade;

View File

@@ -1,8 +1,22 @@
'use strict';
const { Command, Option } = require('commander');
import user from '../user';
import groups from '../groups';
import privileges from '../privileges';
import privHelpers from '../privileges/helpers';
import utils from '../utils';
import winston from 'winston';
import * as webserver from '../webserver';
const viewsDir = nconf.get('views_dir');
import nconf from 'nconf';
import Benchpress from 'benchpressjs';
import meta from '../meta';
import emailer from '../emailer';
import db from '../database';
module.exports = () => {
import { Command, Option } from 'commander';
export default () => {
const userCmd = new Command('user')
.description('Manage users')
.arguments('[command]');
@@ -66,37 +80,21 @@ module.exports = () => {
return userCmd;
};
let db;
let user;
let groups;
let privileges;
let privHelpers;
let utils;
let winston;
async function init() {
db = require('../database');
await db.init();
user = require('../user');
groups = require('../groups');
privileges = require('../privileges');
privHelpers = require('../privileges/helpers');
utils = require('../utils');
winston = require('winston');
}
async function execute(cmd, args) {
await init();
try {
await cmd(...args);
} catch (err) {
} catch (err: any) {
const userError = err.name === 'UserError';
winston.error(`[userCmd/${cmd.name}] ${userError ? `${err.message}` : 'Command failed.'}`, userError ? '' : err);
process.exit(1);
(process as any).exit(1);
}
process.exit();
(process as any).exit();
}
function UserCmdHelpers() {
@@ -111,24 +109,17 @@ function UserCmdHelpers() {
}
async function setupApp() {
const nconf = require('nconf');
const Benchpress = require('benchpressjs');
const meta = require('../meta');
await meta.configs.init();
const webserver = require('../webserver');
const viewsDir = nconf.get('views_dir');
webserver.app.engine('tpl', (filepath, data, next) => {
filepath = filepath.replace(/\.tpl$/, '.js');
Benchpress.__express(filepath, data, next);
(Benchpress as any).__express(filepath, data, next);
});
webserver.app.set('view engine', 'tpl');
webserver.app.set('views', viewsDir);
const emailer = require('../emailer');
emailer.registerApp(webserver.app);
}

View File

@@ -1,17 +1,17 @@
'use strict';
const path = require('path');
import path from 'path';
const baseDir = path.join(__dirname, '../');
const loader = path.join(baseDir, 'loader.js');
const loader = path.join(baseDir, '../loader.js');
const app = path.join(baseDir, 'app.js');
const pidfile = path.join(baseDir, 'pidfile');
const config = path.join(baseDir, 'config.json');
const currentPackage = path.join(baseDir, 'package.json');
const config = path.join(baseDir, '../config.json');
const currentPackage = path.join(baseDir, '../package.json');
const installPackage = path.join(baseDir, 'install/package.json');
const nodeModules = path.join(baseDir, 'node_modules');
const nodeModules = path.join(baseDir, '../node_modules');
exports.paths = {
export const paths = {
baseDir,
loader,
app,
@@ -22,5 +22,5 @@ exports.paths = {
nodeModules,
};
exports.pluginNamePattern = /^(@[\w-]+\/)?nodebb-(theme|plugin|widget|rewards)-[\w-]+$/;
exports.themeNamePattern = /^(@[\w-]+\/)?nodebb-theme-[\w-]+$/;
export const pluginNamePattern = /^(@[\w-]+\/)?nodebb-(theme|plugin|widget|rewards)-[\w-]+$/;
export const themeNamePattern = /^(@[\w-]+\/)?nodebb-theme-[\w-]+$/;

View File

@@ -1,15 +1,13 @@
'use strict';
'use strict'
import nconf from 'nconf';
import winston from 'winston';
import validator from 'validator';
import meta from '../meta';
import plugins from '../plugins';
import middleware from '../middleware';
import helpers from '../middleware/helpers';
const nconf = require('nconf');
const winston = require('winston');
const validator = require('validator');
const meta = require('../meta');
const plugins = require('../plugins');
const middleware = require('../middleware');
const helpers = require('../middleware/helpers');
exports.handle404 = function handle404(req, res) {
export const handle404 = function handle404(req, res) {
const relativePath = nconf.get('relative_path');
const isClientScript = new RegExp(`^${relativePath}\\/assets\\/src\\/.+\\.js(\\?v=\\w+)?$`);
@@ -33,18 +31,18 @@ exports.handle404 = function handle404(req, res) {
meta.errors.log404(req.path || '');
res.sendStatus(404);
} else if (req.accepts('html')) {
if (process.env.NODE_ENV === 'development') {
if ((process as any).env.NODE_ENV === 'development') {
winston.warn(`Route requested but not found: ${req.url}`);
}
meta.errors.log404(req.path.replace(/^\/api/, '') || '');
exports.send404(req, res);
send404(req, res);
} else {
res.status(404).type('txt').send('Not found');
}
};
exports.send404 = async function (req, res) {
export const send404 = async function (req, res) {
res.status(404);
const path = String(req.path || '');
if (res.locals.isAPI) {

View File

@@ -1,20 +1,35 @@
'use strict';
import profile from './accounts/profile';
import edit from './accounts/edit';
import info from './accounts/info';
import categories from './accounts/categories';
import settings from './accounts/settings';
import groups from './accounts/groups';
import follow from './accounts/follow';
import posts from './accounts/posts';
import notifications from './accounts/notifications';
import chats from './accounts/chats';
import sessions from './accounts/sessions';
import blocks from './accounts/blocks';
import uploads from './accounts/uploads';
import consent from './accounts/consent';
const accountsController = {
profile: require('./accounts/profile'),
edit: require('./accounts/edit'),
info: require('./accounts/info'),
categories: require('./accounts/categories'),
settings: require('./accounts/settings'),
groups: require('./accounts/groups'),
follow: require('./accounts/follow'),
posts: require('./accounts/posts'),
notifications: require('./accounts/notifications'),
chats: require('./accounts/chats'),
sessions: require('./accounts/sessions'),
blocks: require('./accounts/blocks'),
uploads: require('./accounts/uploads'),
consent: require('./accounts/consent'),
profile,
edit,
info,
categories,
settings,
groups,
follow,
posts,
notifications,
chats,
sessions,
blocks,
uploads,
consent,
};
module.exports = accountsController;
export default accountsController;

View File

@@ -1,12 +1,12 @@
'use strict';
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
const pagination = require('../../pagination');
const user = require('../../user');
const plugins = require('../../plugins');
import helpers from '../helpers';
import accountHelpers from './helpers';
import pagination from '../../pagination';
import user from '../../user';
import plugins from '../../plugins';
const blocksController = module.exports;
const blocksController = {} as any;
blocksController.getBlocks = async function (req, res, next) {
const page = parseInt(req.query.page, 10) || 1;
@@ -37,3 +37,5 @@ blocksController.getBlocks = async function (req, res, next) {
res.render('account/blocks', userData);
};
export default blocksController;

View File

@@ -1,13 +1,13 @@
'use strict';
const user = require('../../user');
const categories = require('../../categories');
const accountHelpers = require('./helpers');
const helpers = require('../helpers');
const pagination = require('../../pagination');
const meta = require('../../meta');
import user from '../../user';
import categories from '../../categories';
import accountHelpers from './helpers';
import helpers from '../helpers';
import pagination from '../../pagination';
import meta from '../../meta';
const categoriesController = module.exports;
const categoriesController = {} as any;
categoriesController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -42,3 +42,5 @@ categoriesController.get = async function (req, res, next) {
userData.pagination = pagination.create(page, pageCount, req.query);
res.render('account/categories', userData);
};
export default categoriesController;

View File

@@ -1,12 +1,12 @@
'use strict';
const messaging = require('../../messaging');
const meta = require('../../meta');
const user = require('../../user');
const privileges = require('../../privileges');
const helpers = require('../helpers');
import messaging from '../../messaging';
import meta from '../../meta';
import user from '../../user';
import privileges from '../../privileges';
import helpers from '../helpers';
const chatsController = module.exports;
const chatsController = {} as any;
chatsController.get = async function (req, res, next) {
if (meta.config.disableChat) {
@@ -63,3 +63,5 @@ chatsController.redirectToChat = async function (req, res, next) {
const roomid = parseInt(req.params.roomid, 10);
helpers.redirect(res, `/user/${userslug}/chats${roomid ? `/${roomid}` : ''}`);
};
export default chatsController;

View File

@@ -1,11 +1,11 @@
'use strict';
const db = require('../../database');
const meta = require('../../meta');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
import db from '../../database';
import meta from '../../meta';
import helpers from '../helpers';
import accountHelpers from './helpers';
const consentController = module.exports;
const consentController = {} as any;
consentController.get = async function (req, res, next) {
if (!meta.config.gdpr_enabled) {
@@ -28,3 +28,5 @@ consentController.get = async function (req, res, next) {
res.render('account/consent', userData);
};
export default consentController;

View File

@@ -1,14 +1,14 @@
'use strict';
const user = require('../../user');
const meta = require('../../meta');
const helpers = require('../helpers');
const groups = require('../../groups');
const accountHelpers = require('./helpers');
const privileges = require('../../privileges');
const file = require('../../file');
import user from '../../user';
import meta from '../../meta';
import helpers from '../helpers';
import groups from '../../groups';
import accountHelpers from './helpers';
import privileges from '../../privileges';
import file from '../../file';
const editController = module.exports;
const editController = {} as any;
editController.get = async function (req, res, next) {
const [userData, canUseSignature] = await Promise.all([
@@ -100,7 +100,7 @@ editController.email = async function (req, res, next) {
};
async function renderRoute(name, req, res, next) {
const userData = await getUserData(req, next);
const userData = await getUserData(req);
if (!userData) {
return next();
}
@@ -161,9 +161,11 @@ editController.uploadPicture = async function (req, res, next) {
name: userPhoto.name,
url: image.url,
}]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
await file.delete(userPhoto.path);
}
};
export default editController;

View File

@@ -1,11 +1,11 @@
'use strict';
const user = require('../../user');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
const pagination = require('../../pagination');
import user from '../../user';
import helpers from '../helpers';
import accountHelpers from './helpers';
import pagination from '../../pagination';
const followController = module.exports;
const followController = {} as any;
followController.getFollowing = async function (req, res, next) {
await getFollow('account/following', 'following', req, res, next);
@@ -39,3 +39,5 @@ async function getFollow(tpl, name, req, res, next) {
res.render(tpl, userData);
}
export default followController;

View File

@@ -1,10 +1,10 @@
'use strict';
const groups = require('../../groups');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
import groups from '../../groups';
import helpers from '../helpers';
import accountHelpers from './helpers';
const groupsController = module.exports;
const groupsController = {} as any;
groupsController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -23,3 +23,5 @@ groupsController.get = async function (req, res, next) {
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[global:header.groups]]' }]);
res.render('account/groups', userData);
};
export default groupsController;

View File

@@ -1,20 +1,22 @@
'use strict';
const validator = require('validator');
const nconf = require('nconf');
import validator from 'validator';
import nconf from 'nconf';
import db from '../../database';
import user from '../../user';
import groups from '../../groups';
import plugins from '../../plugins';
import meta from '../../meta';
import utils from '../../utils';
import privileges from '../../privileges';
import translator from '../../translator';
import messaging from '../../messaging';
import categories from '../../categories';
import promisify from '../../promisify';
const db = require('../../database');
const user = require('../../user');
const groups = require('../../groups');
const plugins = require('../../plugins');
const meta = require('../../meta');
const utils = require('../../utils');
const privileges = require('../../privileges');
const translator = require('../../translator');
const messaging = require('../../messaging');
const categories = require('../../categories');
const helpers = module.exports;
const helpers = {} as any;
helpers.getUserDataByUserSlug = async function (userslug, callerUID, query = {}) {
const uid = await user.getUidByUserslug(userslug);
@@ -109,7 +111,7 @@ helpers.getUserDataByUserSlug = async function (userslug, callerUID, query = {})
if (userData['cover:url']) {
userData['cover:url'] = userData['cover:url'].startsWith('http') ? userData['cover:url'] : (nconf.get('relative_path') + userData['cover:url']);
} else {
userData['cover:url'] = require('../../coverPhoto').getDefaultProfileCover(userData.uid);
userData['cover:url'] = require('../../coverPhoto').default.getDefaultProfileCover(userData.uid);
}
userData['cover:position'] = validator.escape(String(userData['cover:position'] || '50% 50%'));
@@ -160,7 +162,7 @@ async function getCounts(userData, callerUID) {
best: Promise.all(cids.map(async c => db.sortedSetCount(`cid:${c}:uid:${uid}:pids:votes`, 1, '+inf'))),
controversial: Promise.all(cids.map(async c => db.sortedSetCount(`cid:${c}:uid:${uid}:pids:votes`, '-inf', -1))),
topics: db.sortedSetsCardSum(cids.map(c => `cid:${c}:uid:${uid}:tids`)),
};
} as any;
if (userData.isAdmin || userData.isSelf) {
promises.ignored = db.sortedSetCard(`uid:${uid}:ignored_tids`);
promises.watched = db.sortedSetCard(`uid:${uid}:followed_tids`);
@@ -267,4 +269,6 @@ function filterLinks(links, states) {
});
}
require('../../promisify')(helpers);
promisify(helpers);
export default helpers;

View File

@@ -1,12 +1,12 @@
'use strict';
const db = require('../../database');
const user = require('../../user');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
const pagination = require('../../pagination');
import db from '../../database';
import user from '../../user';
import helpers from '../helpers';
import accountHelpers from './helpers';
import pagination from '../../pagination';
const infoController = module.exports;
const infoController = {} as any;
infoController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -52,3 +52,5 @@ async function getNotes(userData, start, stop) {
]);
return { notes: notes, count: count };
}
export default infoController;

View File

@@ -1,11 +1,11 @@
'use strict';
const user = require('../../user');
const helpers = require('../helpers');
const plugins = require('../../plugins');
const pagination = require('../../pagination');
import user from '../../user';
import helpers from '../helpers';
import plugins from '../../plugins';
import pagination from '../../pagination';
const notificationsController = module.exports;
const notificationsController = {} as any;
notificationsController.get = async function (req, res, next) {
const regularFilters = [
@@ -70,3 +70,5 @@ notificationsController.get = async function (req, res, next) {
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:notifications]]' }]),
});
};
export default notificationsController;

View File

@@ -1,18 +1,18 @@
'use strict';
const db = require('../../database');
const user = require('../../user');
const posts = require('../../posts');
const topics = require('../../topics');
const categories = require('../../categories');
const privileges = require('../../privileges');
const pagination = require('../../pagination');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
const plugins = require('../../plugins');
const utils = require('../../utils');
import db from '../../database';
import user from '../../user';
import posts from '../../posts';
import topics from '../../topics';
import categories from '../../categories';
import privileges from '../../privileges';
import pagination from '../../pagination';
import helpers from '../helpers';
import accountHelpers from './helpers';
import plugins from '../../plugins';
import utils from '../../utils';
const postsController = module.exports;
const postsController = {} as any;
const templateToData = {
'account/bookmarks': {
@@ -252,3 +252,5 @@ async function getItemCount(sets, data, settings) {
}
return await db.sortedSetsCardSum(sets);
}
export default postsController;

View File

@@ -1,20 +1,19 @@
'use strict';
const nconf = require('nconf');
const _ = require('lodash');
import nconf from 'nconf';
import _ from 'lodash';
import db from '../../database';
import user from '../../user';
import posts from '../../posts';
import categories from '../../categories';
import plugins from '../../plugins';
import meta from '../../meta';
import privileges from '../../privileges';
import accountHelpers from './helpers';
import helpers from '../helpers';
import utils from '../../utils';
const db = require('../../database');
const user = require('../../user');
const posts = require('../../posts');
const categories = require('../../categories');
const plugins = require('../../plugins');
const meta = require('../../meta');
const privileges = require('../../privileges');
const accountHelpers = require('./helpers');
const helpers = require('../helpers');
const utils = require('../../utils');
const profileController = module.exports;
const profileController = {} as any;
profileController.get = async function (req, res, next) {
const lowercaseSlug = req.params.userslug.toLowerCase();
@@ -164,3 +163,5 @@ function addMetaTags(res, userData) {
);
}
}
export default profileController;

View File

@@ -1,10 +1,10 @@
'use strict';
const user = require('../../user');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
import user from '../../user';
import helpers from '../helpers';
import accountHelpers from './helpers';
const sessionController = module.exports;
const sessionController = {} as any;
sessionController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -18,3 +18,5 @@ sessionController.get = async function (req, res, next) {
res.render('account/sessions', userData);
};
export default sessionController;

View File

@@ -1,21 +1,20 @@
'use strict';
const nconf = require('nconf');
const winston = require('winston');
const _ = require('lodash');
const jwt = require('jsonwebtoken');
const util = require('util');
import nconf from 'nconf';
import winston from 'winston';
import _ from 'lodash';
import jwt from 'jsonwebtoken';
import util from 'util';
import user from '../../user';
import languages from '../../languages';
import meta from '../../meta';
import plugins from '../../plugins';
import notifications from '../../notifications';
import db from '../../database';
import helpers from '../helpers';
import accountHelpers from './helpers';
const user = require('../../user');
const languages = require('../../languages');
const meta = require('../../meta');
const plugins = require('../../plugins');
const notifications = require('../../notifications');
const db = require('../../database');
const helpers = require('../helpers');
const accountHelpers = require('./helpers');
const settingsController = module.exports;
const settingsController = {} as any;
settingsController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -129,7 +128,7 @@ const doUnsubscribe = async (payload) => {
settingsController.unsubscribe = async (req, res) => {
try {
const payload = await jwtVerifyAsync(req.params.token);
const payload: any = await jwtVerifyAsync(req.params.token);
if (!payload || !unsubscribable.includes(payload.template)) {
return;
}
@@ -137,7 +136,7 @@ settingsController.unsubscribe = async (req, res) => {
res.render('unsubscribe', {
payload,
});
} catch (err) {
} catch (err: any) {
res.render('unsubscribe', {
error: err.message,
});
@@ -151,13 +150,13 @@ settingsController.unsubscribePost = async function (req, res) {
if (!payload || !unsubscribable.includes(payload.template)) {
return res.sendStatus(404);
}
} catch (err) {
} catch (err: any) {
return res.sendStatus(403);
}
try {
await doUnsubscribe(payload);
res.sendStatus(200);
} catch (err) {
} catch (err: any) {
winston.error(`[settings/unsubscribe] One-click unsubscribe failed with error: ${err.message}`);
res.sendStatus(500);
}
@@ -227,3 +226,5 @@ async function getHomePageRoutes(userData) {
return routes;
}
export default settingsController;

View File

@@ -1,16 +1,14 @@
'use strict';
const path = require('path');
import path from 'path';
import nconf from 'nconf';
import db from '../../database';
import helpers from '../helpers';
import meta from '../../meta';
import pagination from '../../pagination';
import accountHelpers from './helpers';
const nconf = require('nconf');
const db = require('../../database');
const helpers = require('../helpers');
const meta = require('../../meta');
const pagination = require('../../pagination');
const accountHelpers = require('./helpers');
const uploadsController = module.exports;
const uploadsController = {} as any;
uploadsController.get = async function (req, res, next) {
const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
@@ -38,3 +36,5 @@ uploadsController.get = async function (req, res, next) {
userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[global:uploads]]' }]);
res.render('account/uploads', userData);
};
export default uploadsController;

View File

@@ -1,35 +1,52 @@
'use strict';
const privileges = require('../privileges');
const helpers = require('./helpers');
import privileges from '../privileges';
import helpers from './helpers';
import dashboard from './admin/dashboard';
import categories from './admin/categories';
import adminPrivileges from './admin/privileges';
import adminsMods from './admin/admins-mods';
import tags from './admin/tags';
import groups from './admin/groups';
import digest from './admin/digest';
import appearance from './admin/appearance';
import widgets from './admin/widgets';
import rewards from './admin/rewards';
import events from './admin/events';
import hooks from './admin/hooks';
import logs from './admin/logs';
import errors from './admin/errors';
import database from './admin/database';
import cache from './admin/cache';
import plugins from './admin/plugins';
import settings from './admin/settings';
import logger from './admin/logger';
import themes from './admin/themes';
import users from './admin/users';
import uploads from './admin/uploads';
import info from './admin/info';
const adminController = {
dashboard: require('./admin/dashboard'),
categories: require('./admin/categories'),
privileges: require('./admin/privileges'),
adminsMods: require('./admin/admins-mods'),
tags: require('./admin/tags'),
groups: require('./admin/groups'),
digest: require('./admin/digest'),
appearance: require('./admin/appearance'),
extend: {
widgets: require('./admin/widgets'),
rewards: require('./admin/rewards'),
},
events: require('./admin/events'),
hooks: require('./admin/hooks'),
logs: require('./admin/logs'),
errors: require('./admin/errors'),
database: require('./admin/database'),
cache: require('./admin/cache'),
plugins: require('./admin/plugins'),
settings: require('./admin/settings'),
logger: require('./admin/logger'),
themes: require('./admin/themes'),
users: require('./admin/users'),
uploads: require('./admin/uploads'),
info: require('./admin/info'),
};
dashboard,
categories,
privileges,
adminsMods,
groups,
digest,
appearance,
events,
hooks,
errors,
database,
plugins,
adminPrivileges,
settings,
logger,
themes,
users,
uploads,
info,
} as any;
adminController.routeIndex = async (req, res) => {
const privilegeSet = await privileges.admin.get(req.uid);
@@ -55,4 +72,4 @@ adminController.routeIndex = async (req, res) => {
return helpers.notAllowed(req, res);
};
module.exports = adminController;
export default adminController;

View File

@@ -1,16 +1,15 @@
'use strict';
const _ = require('lodash');
import _ from 'lodash';
import db from '../../database';
import groups from '../../groups';
import categories from '../../categories';
import user from '../../user';
import meta from '../../meta';
import pagination from '../../pagination';
import categoriesController from './categories';
const db = require('../../database');
const groups = require('../../groups');
const categories = require('../../categories');
const user = require('../../user');
const meta = require('../../meta');
const pagination = require('../../pagination');
const categoriesController = require('./categories');
const AdminsMods = module.exports;
const AdminsMods = {} as any;
AdminsMods.get = async function (req, res) {
const rootCid = parseInt(req.query.cid, 10) || 0;
@@ -59,3 +58,5 @@ async function getModeratorsOfCategories(categoryData) {
});
return categoryData;
}
export default AdminsMods;

View File

@@ -1,9 +1,11 @@
'use strict';
const appearanceController = module.exports;
const appearanceController = {} as any;
appearanceController.get = function (req, res) {
const term = req.params.term ? req.params.term : 'themes';
res.render(`admin/appearance/${term}`, {});
};
export default appearanceController;

View File

@@ -1,16 +1,15 @@
'use strict';
const cacheController = module.exports;
const cacheController = {} as any;
const utils = require('../../utils');
const plugins = require('../../plugins');
import utils from '../../utils';
import plugins from '../../plugins';
import postCache from '../../posts/cache';
import group from '../../groups';
import db from '../../database';
import localCache from '../../cache';
cacheController.get = async function (req, res) {
const postCache = require('../../posts/cache');
const groupCache = require('../../groups').cache;
const { objectCache } = require('../../database');
const localCache = require('../../cache');
function getInfo(cache) {
return {
length: cache.length,
@@ -29,11 +28,11 @@ cacheController.get = async function (req, res) {
}
let caches = {
post: postCache,
group: groupCache,
group: group.groupCache,
local: localCache,
};
if (objectCache) {
caches.object = objectCache;
} as any;
if (db.objectCache) {
caches.object = db.objectCache;
}
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
for (const [key, value] of Object.entries(caches)) {
@@ -45,10 +44,10 @@ cacheController.get = async function (req, res) {
cacheController.dump = async function (req, res, next) {
let caches = {
post: require('../../posts/cache'),
object: require('../../database').objectCache,
group: require('../../groups').cache,
local: require('../../cache'),
post: postCache,
object: db.objectCache,
group: group.groupCache,
local: localCache,
};
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
if (!caches[req.query.name]) {
@@ -65,3 +64,5 @@ cacheController.dump = async function (req, res, next) {
res.end();
});
};
export default cacheController;

View File

@@ -1,16 +1,16 @@
'use strict';
const _ = require('lodash');
const nconf = require('nconf');
const categories = require('../../categories');
const analytics = require('../../analytics');
const plugins = require('../../plugins');
const translator = require('../../translator');
const meta = require('../../meta');
const helpers = require('../helpers');
const pagination = require('../../pagination');
import _ from 'lodash';
import nconf from 'nconf';
import categories from '../../categories';
import analytics from '../../analytics';
import plugins from '../../plugins';
import translator from '../../translator';
import meta from '../../meta';
import helpers from '../helpers';
import pagination from '../../pagination';
const categoriesController = module.exports;
const categoriesController = {} as any;
categoriesController.get = async function (req, res, next) {
const [categoryData, parent, selectedData] = await Promise.all([
@@ -141,3 +141,5 @@ categoriesController.getAnalytics = async function (req, res) {
analytics: analyticsData,
});
};
export default categoriesController;

View File

@@ -1,22 +1,22 @@
'use strict';
import nconf from 'nconf';
import semver from 'semver';
import winston from 'winston';
import _ from 'lodash';
import validator from 'validator';
import * as versions from '../../admin/versions';
import db from '../../database';
import meta from '../../meta';
import analytics from '../../analytics';
import plugins from '../../plugins';
import user from '../../user';
import topics from '../../topics';
import utils from '../../utils';
import emailer from '../../emailer';
import cache from '../../cache';
const nconf = require('nconf');
const semver = require('semver');
const winston = require('winston');
const _ = require('lodash');
const validator = require('validator');
const versions = require('../../admin/versions');
const db = require('../../database');
const meta = require('../../meta');
const analytics = require('../../analytics');
const plugins = require('../../plugins');
const user = require('../../user');
const topics = require('../../topics');
const utils = require('../../utils');
const emailer = require('../../emailer');
const dashboardController = module.exports;
const dashboardController = {} as any;
dashboardController.get = async function (req, res) {
const [stats, notices, latestVersion, lastrestart, isAdmin, popularSearches] = await Promise.all([
@@ -34,10 +34,11 @@ dashboardController.get = async function (req, res) {
lookupFailed: latestVersion === null,
latestVersion: latestVersion,
upgradeAvailable: latestVersion && semver.gt(latestVersion, version),
// @ts-ignore
currentPrerelease: versions.isPrerelease.test(version),
notices: notices,
stats: stats,
canRestart: !!process.send,
canRestart: !!(process as any).send,
lastrestart: lastrestart,
showSystemControls: isAdmin,
popularSearches: popularSearches,
@@ -58,7 +59,7 @@ async function getNotices() {
tooltip: '[[admin/dashboard:search-plugin-tooltip]]',
link: '/admin/extend/plugins',
},
];
] as any[];
if (emailer.fallbackNotFound) {
notices.push({
@@ -67,7 +68,7 @@ async function getNotices() {
});
}
if (global.env !== 'production') {
if ((global as any).env !== 'production') {
notices.push({
done: false,
notDoneText: '[[admin/dashboard:running-in-development]]',
@@ -79,8 +80,9 @@ async function getNotices() {
async function getLatestVersion() {
try {
// @ts-ignore
return await versions.getLatestVersion();
} catch (err) {
} catch (err: any) {
winston.error(`[acp] Failed to fetch latest version\n${err.stack}`);
}
return null;
@@ -92,7 +94,7 @@ dashboardController.getAnalytics = async (req, res, next) => {
const validSets = ['uniquevisitors', 'pageviews', 'pageviews:registered', 'pageviews:bot', 'pageviews:guest'];
const until = req.query.until ? new Date(parseInt(req.query.until, 10)) : Date.now();
const count = req.query.count || (req.query.units === 'hours' ? 24 : 30);
if (isNaN(until) || !validUnits.includes(req.query.units)) {
if (isNaN(until as number) || !validUnits.includes(req.query.units)) {
return next(new Error('[[error:invalid-data]]'));
}
@@ -121,7 +123,6 @@ dashboardController.getAnalytics = async (req, res, next) => {
};
async function getStats() {
const cache = require('../../cache');
const cachedStats = cache.get('admin:stats');
if (cachedStats !== undefined) {
return cachedStats;
@@ -342,3 +343,5 @@ dashboardController.getSearches = async (req, res) => {
searches: searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })),
});
};
export default dashboardController;

View File

@@ -1,23 +1,27 @@
'use strict';
const nconf = require('nconf');
import nconf from 'nconf';
import rdb from '../../database/redis';
import mdb from '../../database/mongo';
import pdb from '../../database/postgres';
const databaseController = module.exports;
const databaseController = {} as any;
databaseController.get = async function (req, res) {
const results = {};
const results = {} as any;
if (nconf.get('redis')) {
const rdb = require('../../database/redis');
results.redis = await rdb.info(rdb.client);
}
if (nconf.get('mongo')) {
const mdb = require('../../database/mongo');
results.mongo = await mdb.info(mdb.client);
}
if (nconf.get('postgres')) {
const pdb = require('../../database/postgres');
results.postgres = await pdb.info(pdb.pool);
}
res.render('admin/advanced/database', results);
};
export default databaseController;

View File

@@ -1,10 +1,10 @@
'use strict';
const meta = require('../../meta');
const digest = require('../../user/digest');
const pagination = require('../../pagination');
import meta from '../../meta';
import digest from '../../user/digest';
import pagination from '../../pagination';
const digestController = module.exports;
const digestController = {} as any;
digestController.get = async function (req, res) {
const page = parseInt(req.query.page, 10) || 1;
@@ -21,3 +21,5 @@ digestController.get = async function (req, res) {
pagination: pagination.create(page, pageCount),
});
};
export default digestController;

View File

@@ -1,12 +1,11 @@
'use strict';
const json2csvAsync = require('json2csv').parseAsync;
import { parseAsync as json2csvAsync } from 'json2csv';
import meta from '../../meta';
import analytics from '../../analytics';
import utils from '../../utils';
const meta = require('../../meta');
const analytics = require('../../analytics');
const utils = require('../../utils');
const errorsController = module.exports;
const errorsController = {} as any;
errorsController.get = async function (req, res) {
const data = await utils.promiseParallel({
@@ -23,3 +22,5 @@ errorsController.export = async function (req, res) {
const csv = await json2csvAsync(data, opts);
res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="404.csv"').send(csv);
};
export default errorsController;

View File

@@ -1,10 +1,10 @@
'use strict';
const db = require('../../database');
const events = require('../../events');
const pagination = require('../../pagination');
import db from '../../database';
import events from '../../events';
import pagination from '../../pagination';
const eventsController = module.exports;
const eventsController = {} as any;
eventsController.get = async function (req, res) {
const page = parseInt(req.query.page, 10) || 1;
@@ -13,8 +13,8 @@ eventsController.get = async function (req, res) {
const stop = start + itemsPerPage - 1;
// Limit by date
let from = req.query.start ? new Date(req.query.start) || undefined : undefined;
let to = req.query.end ? new Date(req.query.end) || undefined : new Date();
let from: any = req.query.start ? new Date(req.query.start) || undefined : undefined;
let to: any = req.query.end ? new Date(req.query.end) || undefined : new Date();
from = from && from.setHours(0, 0, 0, 0); // setHours returns a unix timestamp (Number, not Date)
to = to && to.setHours(23, 59, 59, 999); // setHours returns a unix timestamp (Number, not Date)
@@ -42,3 +42,5 @@ eventsController.get = async function (req, res) {
query: req.query,
});
};
export default eventsController;

View File

@@ -1,17 +1,16 @@
'use strict';
const nconf = require('nconf');
const validator = require('validator');
import nconf from 'nconf';
import validator from 'validator';
import db from '../../database';
import user from '../../user';
import groups from '../../groups';
import meta from '../../meta';
import pagination from '../../pagination';
import events from '../../events';
import slugify from '../../slugify';
const db = require('../../database');
const user = require('../../user');
const groups = require('../../groups');
const meta = require('../../meta');
const pagination = require('../../pagination');
const events = require('../../events');
const slugify = require('../../slugify');
const groupsController = module.exports;
const groupsController = {} as any;
groupsController.list = async function (req, res) {
const page = parseInt(req.query.page, 10) || 1;
@@ -96,3 +95,5 @@ groupsController.getCSV = async function (req, res) {
res.setHeader('Content-Type', 'text/csv');
res.end(csvContent);
};
export default groupsController;

View File

@@ -1,9 +1,9 @@
'use strict';
const validator = require('validator');
const plugins = require('../../plugins');
import validator from 'validator';
import plugins from '../../plugins';
const hooksController = module.exports;
const hooksController = {} as any;
hooksController.get = function (req, res) {
const hooks = [];
@@ -30,3 +30,5 @@ hooksController.get = function (req, res) {
res.render('admin/advanced/hooks', { hooks: hooks });
};
export default hooksController;

View File

@@ -1,17 +1,17 @@
'use strict';
const os = require('os');
const winston = require('winston');
const nconf = require('nconf');
const { exec } = require('child_process');
import os from 'os';
import winston from 'winston';
import nconf from 'nconf';
import { exec } from 'child_process';
import pubsub from '../../pubsub';
import rooms from '../../socket.io/admin/rooms';
import { promisify } from 'util';
const pubsub = require('../../pubsub');
const rooms = require('../../socket.io/admin/rooms');
const infoController = module.exports;
const infoController = {} as any;
let info = {};
let previousUsage = process.cpuUsage();
let previousUsage = (process as any).cpuUsage();
let usageStartDate = Date.now();
infoController.get = function (req, res) {
@@ -53,7 +53,7 @@ pubsub.on('sync:node:info:start', async () => {
const data = await getNodeInfo();
data.id = `${os.hostname()}:${nconf.get('port')}`;
pubsub.publish('sync:node:info:end', { data: data, id: data.id });
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
}
});
@@ -66,11 +66,11 @@ async function getNodeInfo() {
const data = {
process: {
port: nconf.get('port'),
pid: process.pid,
title: process.title,
version: process.version,
memoryUsage: process.memoryUsage(),
uptime: process.uptime(),
pid: (process as any).pid,
title: (process as any).title,
version: (process as any).version,
memoryUsage: (process as any).memoryUsage(),
uptime: (process as any).uptime(),
cpuUsage: getCpuUsage(),
},
os: {
@@ -89,7 +89,7 @@ async function getNodeInfo() {
runJobs: nconf.get('runJobs'),
jobsDisabled: nconf.get('jobsDisabled'),
},
};
} as any;
data.process.memoryUsage.humanReadable = (data.process.memoryUsage.rss / (1024 * 1024 * 1024)).toFixed(3);
data.process.uptimeHumanReadable = humanReadableUptime(data.process.uptime);
@@ -106,7 +106,7 @@ async function getNodeInfo() {
}
function getCpuUsage() {
const newUsage = process.cpuUsage();
const newUsage = (process as any).cpuUsage();
const diff = (newUsage.user + newUsage.system) - (previousUsage.user + previousUsage.system);
const now = Date.now();
const result = diff / ((now - usageStartDate) * 1000) * 100;
@@ -135,10 +135,12 @@ async function getGitInfo() {
callback(null, stdout ? stdout.replace(/\n$/, '') : 'no-git-info');
});
}
const getAsync = require('util').promisify(get);
const getAsync = promisify(get);
const [hash, branch] = await Promise.all([
getAsync('git rev-parse HEAD'),
getAsync('git rev-parse --abbrev-ref HEAD'),
]);
]) as [any, any];
return { hash: hash, hashShort: hash.slice(0, 6), branch: branch };
}
export default infoController;

View File

@@ -1,7 +1,9 @@
'use strict';
const loggerController = module.exports;
const loggerController = {} as any;
loggerController.get = function (req, res) {
res.render('admin/development/logger', {});
};
export default loggerController;

View File

@@ -1,20 +1,21 @@
'use strict';
const validator = require('validator');
const winston = require('winston');
import validator from 'validator';
import winston from 'winston';
import meta from '../../meta';
const meta = require('../../meta');
const logsController = module.exports;
const logsController = {} as any;
logsController.get = async function (req, res) {
let logs = '';
try {
logs = await meta.logs.get();
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
}
res.render('admin/advanced/logs', {
data: validator.escape(logs),
});
};
export default logsController;

View File

@@ -1,11 +1,11 @@
'use strict';
const nconf = require('nconf');
const winston = require('winston');
const plugins = require('../../plugins');
const meta = require('../../meta');
import nconf from 'nconf';
import winston from 'winston';
import plugins from '../../plugins';
import meta from '../../meta';
const pluginsController = module.exports;
const pluginsController = {} as any;
pluginsController.get = async function (req, res) {
const [compatible, all, trending] = await Promise.all([
@@ -62,8 +62,10 @@ async function getPlugins(matching) {
try {
const pluginsData = await plugins.list(matching);
return pluginsData || [];
} catch (err) {
} catch (err: any) {
winston.error(err.stack);
return [];
}
}
export default pluginsController;

View File

@@ -1,9 +1,9 @@
'use strict';
const categories = require('../../categories');
const privileges = require('../../privileges');
import categories from '../../categories';
import privileges from '../../privileges';
const privilegesController = module.exports;
const privilegesController = {} as any;
privilegesController.get = async function (req, res) {
const cid = req.params.cid ? parseInt(req.params.cid, 10) || 0 : 0;
@@ -27,7 +27,7 @@ privilegesController.get = async function (req, res) {
}];
let selectedCategory;
categoriesData.forEach((category) => {
categoriesData.forEach((category: any) => {
if (category) {
category.selected = category.cid === (!isAdminPriv ? cid : 'admin');
@@ -50,3 +50,5 @@ privilegesController.get = async function (req, res) {
isAdminPriv,
});
};
export default privilegesController;

View File

@@ -1,10 +1,12 @@
'use strict';
const admin = require('../../rewards/admin');
import admin from '../../rewards/admin';
const rewardsController = module.exports;
const rewardsController = {} as any;
rewardsController.get = async function (req, res) {
const data = await admin.get();
res.render('admin/extend/rewards', data);
};
export default rewardsController;

View File

@@ -1,19 +1,17 @@
'use strict';
const validator = require('validator');
import validator from 'validator';
import meta from '../../meta';
import emailer from '../../emailer';
import notifications from '../../notifications';
import groups from '../../groups';
import languages from '../../languages';
import navigationAdmin from '../../navigation/admin';
import social from '../../social';
import helpers from '../helpers';
import translator from '../../translator';
const meta = require('../../meta');
const emailer = require('../../emailer');
const notifications = require('../../notifications');
const groups = require('../../groups');
const languages = require('../../languages');
const navigationAdmin = require('../../navigation/admin');
const social = require('../../social');
const helpers = require('../helpers');
const translator = require('../../translator');
const settingsController = module.exports;
const settingsController = {} as any;
settingsController.get = async function (req, res) {
const term = req.params.term || 'general';
@@ -108,3 +106,5 @@ settingsController.social = async function (req, res) {
posts: posts,
});
};
export default settingsController;

View File

@@ -1,10 +1,12 @@
'use strict';
const topics = require('../../topics');
import topics from '../../topics';
const tagsController = module.exports;
const tagsController = {} as any;
tagsController.get = async function (req, res) {
const tags = await topics.getTags(0, 199);
res.render('admin/manage/tags', { tags: tags });
};
export default tagsController;

View File

@@ -1,12 +1,11 @@
'use strict';
const path = require('path');
const fs = require('fs');
import path from 'path';
import fs from 'fs';
import file from '../../file';
import { paths } from '../../constants';
const file = require('../../file');
const { paths } = require('../../constants');
const themesController = module.exports;
const themesController = {} as any;
const defaultScreenshotPath = path.join(__dirname, '../../../public/images/themes/default.png');
@@ -18,7 +17,7 @@ themesController.get = async function (req, res, next) {
try {
themeConfig = await fs.promises.readFile(themeConfigPath, 'utf8');
themeConfig = JSON.parse(themeConfig);
} catch (err) {
} catch (err: any) {
if (err.code === 'ENOENT') {
return next(Error('invalid-data'));
}
@@ -29,3 +28,5 @@ themesController.get = async function (req, res, next) {
const exists = await file.exists(screenshotPath);
res.sendFile(exists ? screenshotPath : defaultScreenshotPath);
};
export default themesController;

View File

@@ -1,19 +1,18 @@
'use strict';
const path = require('path');
const nconf = require('nconf');
const fs = require('fs');
const meta = require('../../meta');
const posts = require('../../posts');
const file = require('../../file');
const image = require('../../image');
const plugins = require('../../plugins');
const pagination = require('../../pagination');
import path from 'path';
import nconf from 'nconf';
import fs from 'fs';
import meta from '../../meta';
import posts from '../../posts';
import file from '../../file';
import image from '../../image';
import plugins from '../../plugins';
import pagination from '../../pagination';
const allowedImageTypes = ['image/png', 'image/jpeg', 'image/pjpeg', 'image/jpg', 'image/gif', 'image/svg+xml'];
const uploadsController = module.exports;
const uploadsController = {} as any;
uploadsController.get = async function (req, res, next) {
const currentFolder = path.join(nconf.get('upload_path'), req.query.dir || '');
@@ -33,7 +32,7 @@ uploadsController.get = async function (req, res, next) {
files = await filesToData(currentFolder, files);
// Float directories to the top
files.sort((a, b) => {
files.sort((a: any, b: any) => {
if (a.isDirectory && !b.isDirectory) {
return -1;
} else if (!a.isDirectory && b.isDirectory) {
@@ -48,7 +47,7 @@ uploadsController.get = async function (req, res, next) {
// Add post usage info if in /files
if (['files', '/files', '/files/'].includes(req.query.dir)) {
const usage = await posts.uploads.getUsage(files);
files.forEach((file, idx) => {
files.forEach((file: any, idx) => {
file.inPids = usage[idx].map(pid => parseInt(pid, 10));
});
}
@@ -59,7 +58,7 @@ uploadsController.get = async function (req, res, next) {
breadcrumbs: buildBreadcrumbs(currentFolder),
pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query),
});
} catch (err) {
} catch (err: any) {
next(err);
}
};
@@ -113,8 +112,7 @@ uploadsController.uploadCategoryPicture = async function (req, res, next) {
try {
params = JSON.parse(req.body.params);
} catch (e) {
file.delete(uploadedFile.path);
} catch (e: any) { file.delete(uploadedFile.path);
return next(new Error('[[error:invalid-json]]'));
}
@@ -132,7 +130,7 @@ uploadsController.uploadFavicon = async function (req, res, next) {
try {
const imageObj = await file.saveFileToLocal('favicon.ico', 'system', uploadedFile.path);
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
file.delete(uploadedFile.path);
@@ -159,7 +157,7 @@ uploadsController.uploadTouchIcon = async function (req, res, next) {
});
}
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
file.delete(uploadedFile.path);
@@ -176,7 +174,7 @@ uploadsController.uploadMaskableIcon = async function (req, res, next) {
try {
const imageObj = await file.saveFileToLocal('maskableicon-orig.png', 'system', uploadedFile.path);
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
file.delete(uploadedFile.path);
@@ -193,15 +191,14 @@ uploadsController.uploadFile = async function (req, res, next) {
let params;
try {
params = JSON.parse(req.body.params);
} catch (e) {
file.delete(uploadedFile.path);
} catch (e: any) { file.delete(uploadedFile.path);
return next(new Error('[[error:invalid-json]]'));
}
try {
const data = await file.saveFileToLocal(uploadedFile.name, params.folder, uploadedFile.path);
res.json([{ url: data.url }]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
file.delete(uploadedFile.path);
@@ -265,9 +262,11 @@ async function uploadImage(filename, folder, uploadedFile, req, res, next) {
});
}
res.json([{ name: uploadedFile.name, url: imageData.url.startsWith('http') ? imageData.url : nconf.get('relative_path') + imageData.url }]);
} catch (err) {
} catch (err: any) {
next(err);
} finally {
file.delete(uploadedFile.path);
}
}
export default uploadsController;

View File

@@ -1,17 +1,19 @@
'use strict';
const validator = require('validator');
import validator from 'validator';
import user from '../../user';
import meta from '../../meta';
import db from '../../database';
import pagination from '../../pagination';
import events from '../../events';
import plugins from '../../plugins';
import privileges from '../../privileges';
import utils from '../../utils';
import path from 'path';
import * as constants from '../../constants';
const { paths: { baseDir } } = constants;
const user = require('../../user');
const meta = require('../../meta');
const db = require('../../database');
const pagination = require('../../pagination');
const events = require('../../events');
const plugins = require('../../plugins');
const privileges = require('../../privileges');
const utils = require('../../utils');
const usersController = module.exports;
const usersController = {} as any;
const userFields = [
'uid', 'username', 'userslug', 'email', 'postcount', 'joindate', 'banned',
@@ -260,8 +262,6 @@ usersController.getCSV = async function (req, res, next) {
uid: req.uid,
ip: req.ip,
});
const path = require('path');
const { baseDir } = require('../../constants').paths;
res.sendFile('users.csv', {
root: path.join(baseDir, 'build/export'),
headers: {
@@ -278,3 +278,5 @@ usersController.getCSV = async function (req, res, next) {
}
});
};
export default usersController;

View File

@@ -1,9 +1,11 @@
'use strict';
const widgetsController = module.exports;
const admin = require('../../widgets/admin');
const widgetsController = {} as any;
import admin from '../../widgets/admin';
widgetsController.get = async function (req, res) {
const data = await admin.get();
res.render('admin/extend/widgets', data);
};
export default widgetsController;

View File

@@ -1,16 +1,15 @@
'use strict';
const validator = require('validator');
const nconf = require('nconf');
import validator from 'validator';
import nconf from 'nconf';
import meta from '../meta';
import user from '../user';
import categories from '../categories';
import plugins from '../plugins';
import translator from '../translator';
import languages from '../languages';
const meta = require('../meta');
const user = require('../user');
const categories = require('../categories');
const plugins = require('../plugins');
const translator = require('../translator');
const languages = require('../languages');
const apiController = module.exports;
const apiController = {} as any;
const relative_path = nconf.get('relative_path');
const upload_url = nconf.get('upload_url');
@@ -84,7 +83,7 @@ apiController.loadConfig = async function (req) {
iconBackgrounds: await user.getIconBackgrounds(req.uid),
emailPrompt: meta.config.emailPrompt,
useragent: req.useragent,
};
} as any;
let settings = config;
let isAdminOrGlobalMod;
@@ -128,4 +127,7 @@ apiController.getModerators = async function (req, res) {
res.json({ moderators: moderators });
};
require('../promisify')(apiController, ['getConfig', 'getObject', 'getModerators']);
import promisify from '../promisify';
promisify(apiController, ['getConfig', 'getObject', 'getModerators']);
export default apiController;

Some files were not shown because too many files have changed in this diff Show More