mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-10 01:23:04 +01:00
recommended CLI startup / bootstrap changes
This commit is contained in:
@@ -139,6 +139,7 @@
|
||||
"timeago": "1.6.7",
|
||||
"tinycon": "0.6.8",
|
||||
"toobusy-js": "0.5.1",
|
||||
"typescript": "4.9.4",
|
||||
"validator": "13.7.0",
|
||||
"webpack": "5.75.0",
|
||||
"webpack-merge": "5.8.0",
|
||||
|
||||
2
nodebb
2
nodebb
@@ -3,4 +3,4 @@
|
||||
'use strict';
|
||||
|
||||
console.log('SERIOUSLY?');
|
||||
require('./build/src/cli');
|
||||
require('./src/cli/bootstrap');
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// 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);
|
||||
};
|
||||
94
src/cli/bootstrap.js
vendored
Normal file
94
src/cli/bootstrap.js
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/* eslint-disable import/order */
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
require('../../require-main');
|
||||
|
||||
const packageInstall = require('./package-install');
|
||||
const { paths } = require('../constants');
|
||||
|
||||
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') {
|
||||
// run package installation just to sync up node_modules/ with existing package.json
|
||||
packageInstall.installAll();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (defaultPackage.dependencies[packageName] == null) {
|
||||
const e = new TypeError(`Attempt to \`checkVersion('${packageName}')\`, but no "${packageName}" dependency entry in 'install/package.json'.`);
|
||||
e.code = 'DEP_NOT_DEFINED';
|
||||
throw e;
|
||||
}
|
||||
|
||||
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}`);
|
||||
e.code = 'DEP_WRONG_VERSION';
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
checkVersion('nconf');
|
||||
checkVersion('async');
|
||||
checkVersion('commander');
|
||||
checkVersion('chalk');
|
||||
checkVersion('lodash');
|
||||
checkVersion('lru-cache');
|
||||
checkVersion('typescript');
|
||||
} catch (e) {
|
||||
if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) {
|
||||
console.info(e);
|
||||
|
||||
console.warn('Dependencies outdated or not yet installed.');
|
||||
console.log('Installing them now...\n');
|
||||
|
||||
packageInstall.updatePackageFile();
|
||||
packageInstall.preserveExtraneousPlugins();
|
||||
packageInstall.installAll();
|
||||
|
||||
const chalk = require('chalk');
|
||||
console.log(`${chalk.green('OK')}\n`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Running typescript to transpile files...');
|
||||
|
||||
const child_process = require('child_process');
|
||||
const chalk = require('chalk');
|
||||
|
||||
const tsc = path.join(paths.nodeModules, '.bin/tsc');
|
||||
|
||||
try {
|
||||
child_process.execFileSync(tsc, [
|
||||
'--skipLibCheck',
|
||||
'--noResolve',
|
||||
'--noLib',
|
||||
], {
|
||||
cwd: paths.baseDir,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.status == null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`${chalk.green('OK')}\n`);
|
||||
|
||||
require('../../build/src/cli');
|
||||
139
src/cli/index.ts
139
src/cli/index.ts
@@ -2,93 +2,22 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
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');
|
||||
|
||||
import packageInstall from './package-install';
|
||||
import semver from 'semver';
|
||||
//@ts-ignore
|
||||
import defaultPackage from '../../install/package.json';
|
||||
import chalk from 'chalk';
|
||||
import nconf from 'nconf';
|
||||
import { program } from 'commander';
|
||||
import manage from './manage';
|
||||
import yargs from 'yargs';
|
||||
|
||||
|
||||
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: any) { if (e.code === 'ENOENT') {
|
||||
// run package installation just to sync up node_modules/ with existing package.json
|
||||
packageInstall.installAll();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
fs.accessSync(path.join(paths.nodeModules, 'semver/package.json'), fs.constants.R_OK);
|
||||
|
||||
|
||||
|
||||
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: any = new TypeError(`Incorrect dependency version: ${packageName}`);
|
||||
e.code = 'DEP_WRONG_VERSION';
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
checkVersion('nconf');
|
||||
checkVersion('async');
|
||||
checkVersion('commander');
|
||||
checkVersion('chalk');
|
||||
checkVersion('lodash');
|
||||
checkVersion('lru-cache');
|
||||
} 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');
|
||||
|
||||
packageInstall.updatePackageFile();
|
||||
packageInstall.preserveExtraneousPlugins();
|
||||
packageInstall.installAll();
|
||||
|
||||
console.log(`${chalk.green('OK')}\n`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
import pkg from '../../../install/package.json';
|
||||
import file from '../file';
|
||||
import * as prestart from '../prestart';
|
||||
|
||||
program.configureHelp(require('./colors'));
|
||||
|
||||
program
|
||||
.name('./nodebb')
|
||||
.description('Welcome to NodeBB')
|
||||
.version(defaultPackage.version)
|
||||
.version(pkg.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')
|
||||
@@ -98,15 +27,29 @@ 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';
|
||||
|
||||
if (!configExists && (process as any).argv[2] !== 'setup') {
|
||||
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') {
|
||||
require('./setup').webInstall();
|
||||
// @ts-ignore
|
||||
return;
|
||||
}
|
||||
|
||||
(process as any).env.CONFIG = configFile;
|
||||
process.env.CONFIG = configFile;
|
||||
|
||||
// running commands
|
||||
program
|
||||
@@ -129,8 +72,8 @@ program
|
||||
})
|
||||
.description('Start NodeBB in verbose development mode')
|
||||
.action(() => {
|
||||
(process as any).env.NODE_ENV = 'development';
|
||||
(global as any).env = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
global.env = 'development';
|
||||
require('./running').start({ ...program.opts(), dev: true });
|
||||
});
|
||||
program
|
||||
@@ -183,7 +126,7 @@ program
|
||||
.option('-f, --force', 'Force plugin installation even if it may be incompatible with currently installed NodeBB version')
|
||||
.action((plugin, options) => {
|
||||
if (plugin) {
|
||||
manage.install(plugin);
|
||||
require('./manage').install(plugin, options);
|
||||
} else {
|
||||
require('./setup').webInstall();
|
||||
}
|
||||
@@ -197,10 +140,10 @@ program
|
||||
.action((targets, options) => {
|
||||
console.log('HEYYYYY!!!!!!!!!!!');
|
||||
if (program.opts().dev) {
|
||||
(process as any).env.NODE_ENV = 'development';
|
||||
(global as any).env = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
global.env = 'development';
|
||||
}
|
||||
manage.buildWrapper(targets.length ? targets : true, options);
|
||||
require('./manage').build(targets.length ? targets : true, options);
|
||||
})
|
||||
.on('--help', () => {
|
||||
require('../meta/aliases').buildTargets();
|
||||
@@ -209,25 +152,25 @@ program
|
||||
.command('activate [plugin]')
|
||||
.description('Activate a plugin for the next startup of NodeBB (nodebb-plugin- prefix is optional)')
|
||||
.action((plugin) => {
|
||||
manage.activate(plugin);
|
||||
require('./manage').activate(plugin);
|
||||
});
|
||||
program
|
||||
.command('plugins')
|
||||
.action(() => {
|
||||
manage.listPlugins();
|
||||
require('./manage').listPlugins();
|
||||
})
|
||||
.description('List all installed plugins');
|
||||
program
|
||||
.command('events [count]')
|
||||
.description('Outputs the most recent administrative events recorded by NodeBB')
|
||||
.action((count) => {
|
||||
manage.listEvents(count);
|
||||
require('./manage').listEvents(count);
|
||||
});
|
||||
program
|
||||
.command('info')
|
||||
.description('Outputs various system info')
|
||||
.action(() => {
|
||||
manage.info();
|
||||
require('./manage').info();
|
||||
});
|
||||
|
||||
// reset
|
||||
@@ -249,10 +192,10 @@ resetCommand
|
||||
|
||||
require('./reset').reset(options, (err) => {
|
||||
if (err) {
|
||||
return (process as any).exit(1);
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -280,8 +223,8 @@ program
|
||||
})
|
||||
.action((scripts, options) => {
|
||||
if (program.opts().dev) {
|
||||
(process as any).env.NODE_ENV = 'development';
|
||||
(global as any).env = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
global.env = 'development';
|
||||
}
|
||||
require('./upgrade').upgrade(scripts.length ? scripts : true, options);
|
||||
});
|
||||
@@ -298,7 +241,7 @@ program
|
||||
throw err;
|
||||
}
|
||||
console.log(chalk.green('OK'));
|
||||
(process as any).exit();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -310,7 +253,7 @@ program
|
||||
return program.help();
|
||||
}
|
||||
|
||||
const command = program.commands.find(command => (command as any)._name === name);
|
||||
const command = program.commands.find(command => command._name === name);
|
||||
if (command) {
|
||||
command.help();
|
||||
} else {
|
||||
@@ -319,10 +262,10 @@ program
|
||||
}
|
||||
});
|
||||
|
||||
if ((process as any).argv.length === 2) {
|
||||
if (process.argv.length === 2) {
|
||||
program.help();
|
||||
}
|
||||
|
||||
(program as any).executables = false;
|
||||
program.executables = false;
|
||||
|
||||
program.parse();
|
||||
|
||||
@@ -5,18 +5,17 @@ import child from 'child_process';
|
||||
import CliGraph from 'cli-graph';
|
||||
import chalk from 'chalk';
|
||||
import nconf from 'nconf';
|
||||
import { build } from '../meta/build';
|
||||
import { build as metaBuild } 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';
|
||||
// @ts-ignore
|
||||
import { version } from '../../../package.json';
|
||||
|
||||
|
||||
async function install(plugin, options?) {
|
||||
export async function install(plugin, options?) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
@@ -45,19 +44,19 @@ async function install(plugin, options?) {
|
||||
winston.info('Installing Plugin `%s@%s`', plugin, suggested.version);
|
||||
await plugins.toggleInstall(plugin, suggested.version);
|
||||
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
} catch (err: any) {
|
||||
winston.error(`An error occurred during plugin installation\n${err.stack}`);
|
||||
(process as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function activate(plugin) {
|
||||
export async function activate(plugin) {
|
||||
if (themeNamePattern.test(plugin)) {
|
||||
await reset.reset({
|
||||
theme: plugin,
|
||||
});
|
||||
(process as any).exit();
|
||||
process.exit();
|
||||
}
|
||||
try {
|
||||
await db.init();
|
||||
@@ -75,11 +74,11 @@ async function activate(plugin) {
|
||||
const isActive = await plugins.isActive(plugin);
|
||||
if (isActive) {
|
||||
winston.info('Plugin `%s` already active', plugin);
|
||||
(process as any).exit(0);
|
||||
process.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 as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
const numPlugins = await db.sortedSetCard('plugins:active');
|
||||
winston.info('Activating plugin `%s`', plugin);
|
||||
@@ -89,14 +88,14 @@ async function activate(plugin) {
|
||||
text: plugin,
|
||||
});
|
||||
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
} catch (err: any) {
|
||||
winston.error(`An error occurred during plugin activation\n${err.stack}`);
|
||||
(process as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function listPlugins() {
|
||||
export async function listPlugins() {
|
||||
await db.init();
|
||||
const installed = await plugins.showInstalled();
|
||||
const installedList = installed.map(plugin => plugin.name);
|
||||
@@ -118,35 +117,35 @@ async function listPlugins() {
|
||||
combined.sort((a, b) => (a.id > b.id ? 1 : -1));
|
||||
|
||||
// Pretty output
|
||||
(process as any).stdout.write('Active plugins:\n');
|
||||
process.stdout.write('Active plugins:\n');
|
||||
combined.forEach((plugin) => {
|
||||
(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.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).exit();
|
||||
process.exit();
|
||||
}
|
||||
|
||||
async function listEvents(count = 10) {
|
||||
export async function listEvents(count = 10) {
|
||||
await db.init();
|
||||
const eventData = await events.getEvents('', 0, count - 1);
|
||||
console.log(chalk.bold(`\nDisplaying last ${count} administrative events...`));
|
||||
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 as any).exit();
|
||||
process.exit();
|
||||
}
|
||||
|
||||
async function info() {
|
||||
export async function info() {
|
||||
console.log('');
|
||||
console.log(` version: ${version}`);
|
||||
|
||||
console.log(` Node ver: ${(process as any).version}`);
|
||||
console.log(` Node ver: ${process.version}`);
|
||||
// @ts-ignore
|
||||
const hash = child(process as any).execSync('git rev-parse HEAD');
|
||||
const hash = childprocess.execSync('git rev-parse HEAD');
|
||||
console.log(` git hash: ${hash}`);
|
||||
|
||||
console.log(` database: ${nconf.get('database')}`);
|
||||
@@ -190,24 +189,15 @@ async function info() {
|
||||
console.log('');
|
||||
console.log(graph.toString());
|
||||
console.log(`Pageviews, last 24h (min: ${min} max: ${max})`);
|
||||
(process as any).exit();
|
||||
process.exit();
|
||||
}
|
||||
|
||||
async function buildWrapper(targets, options?) {
|
||||
export async function build(targets, options?) {
|
||||
try {
|
||||
await build(targets, options);
|
||||
(process as any).exit(0);
|
||||
await metaBuild(targets, options);
|
||||
process.exit(0);
|
||||
} catch (err: any) {
|
||||
winston.error(err.stack);
|
||||
(process as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
buildWrapper,
|
||||
install,
|
||||
activate,
|
||||
listPlugins,
|
||||
listEvents,
|
||||
info
|
||||
};
|
||||
174
src/cli/package-install.js
Normal file
174
src/cli/package-install.js
Normal file
@@ -0,0 +1,174 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const fs = require('fs');
|
||||
const cproc = require('child_process');
|
||||
|
||||
const { paths, pluginNamePattern } = require('../constants');
|
||||
|
||||
const pkgInstall = module.exports;
|
||||
|
||||
function sortDependencies(dependencies) {
|
||||
return Object.entries(dependencies)
|
||||
.sort((a, b) => (a < b ? -1 : 1))
|
||||
.reduce((memo, pkg) => {
|
||||
memo[pkg[0]] = pkg[1];
|
||||
return memo;
|
||||
}, {});
|
||||
}
|
||||
|
||||
pkgInstall.updatePackageFile = () => {
|
||||
let oldPackageContents;
|
||||
|
||||
try {
|
||||
oldPackageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT') {
|
||||
throw e;
|
||||
} else {
|
||||
// No local package.json, copy from install/package.json
|
||||
fs.copyFileSync(paths.installPackage, paths.currentPackage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const _ = require('lodash');
|
||||
const defaultPackageContents = JSON.parse(fs.readFileSync(paths.installPackage, 'utf8'));
|
||||
|
||||
let dependencies = {};
|
||||
Object.entries(oldPackageContents.dependencies || {}).forEach(([dep, version]) => {
|
||||
if (pluginNamePattern.test(dep)) {
|
||||
dependencies[dep] = version;
|
||||
}
|
||||
});
|
||||
|
||||
const { devDependencies } = defaultPackageContents;
|
||||
|
||||
// Sort dependencies alphabetically
|
||||
dependencies = sortDependencies({ ...dependencies, ...defaultPackageContents.dependencies });
|
||||
|
||||
const packageContents = { ..._.merge(oldPackageContents, defaultPackageContents), dependencies, devDependencies };
|
||||
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
|
||||
};
|
||||
|
||||
pkgInstall.supportedPackageManager = [
|
||||
'npm',
|
||||
'cnpm',
|
||||
'pnpm',
|
||||
'yarn',
|
||||
];
|
||||
|
||||
pkgInstall.getPackageManager = () => {
|
||||
try {
|
||||
const packageContents = require(paths.currentPackage);
|
||||
// This regex technically allows invalid values:
|
||||
// cnpm isn't supported by corepack and it doesn't enforce a version string being present
|
||||
const pmRegex = new RegExp(`^(?<packageManager>${pkgInstall.supportedPackageManager.join('|')})@?[\\d\\w\\.\\-]*$`);
|
||||
const packageManager = packageContents.packageManager ? packageContents.packageManager.match(pmRegex) : false;
|
||||
if (packageManager) {
|
||||
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');
|
||||
nconf.env().file({ // not sure why adding .argv() causes the process to terminate
|
||||
file: configFile,
|
||||
});
|
||||
}
|
||||
if (nconf.get('package_manager') && !pkgInstall.supportedPackageManager.includes(nconf.get('package_manager'))) {
|
||||
nconf.clear('package_manager');
|
||||
}
|
||||
|
||||
if (!nconf.get('package_manager')) {
|
||||
nconf.set('package_manager', getPackageManagerByLockfile());
|
||||
}
|
||||
|
||||
return nconf.get('package_manager') || 'npm';
|
||||
} catch (e) {
|
||||
// nconf not installed or other unexpected error/exception
|
||||
return getPackageManagerByLockfile() || 'npm';
|
||||
}
|
||||
};
|
||||
|
||||
function getPackageManagerByLockfile() {
|
||||
for (const [packageManager, lockfile] of Object.entries({ npm: 'package-lock.json', yarn: 'yarn.lock', pnpm: 'pnpm-lock.yaml' })) {
|
||||
try {
|
||||
fs.accessSync(path.resolve(__dirname, `../../${lockfile}`), fs.constants.R_OK);
|
||||
return packageManager;
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
pkgInstall.installAll = () => {
|
||||
const prod = process.env.NODE_ENV !== 'development';
|
||||
let command = 'npm install';
|
||||
|
||||
const supportedPackageManagerList = exports.supportedPackageManager; // load config from src/cli/package-install.js
|
||||
const packageManager = pkgInstall.getPackageManager();
|
||||
if (supportedPackageManagerList.indexOf(packageManager) >= 0) {
|
||||
switch (packageManager) {
|
||||
case 'yarn':
|
||||
command = `yarn${prod ? ' --production' : ''}`;
|
||||
break;
|
||||
case 'pnpm':
|
||||
command = 'pnpm install'; // pnpm checks NODE_ENV
|
||||
break;
|
||||
case 'cnpm':
|
||||
command = `cnpm install ${prod ? ' --production' : ''}`;
|
||||
break;
|
||||
default:
|
||||
command += prod ? ' --omit=dev' : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
cproc.execSync(command, {
|
||||
cwd: paths.baseDir,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Error installing dependencies!');
|
||||
console.log(`message: ${e.message}`);
|
||||
console.log(`stdout: ${e.stdout}`);
|
||||
console.log(`stderr: ${e.stderr}`);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
pkgInstall.preserveExtraneousPlugins = () => {
|
||||
// Skip if `node_modules/` is not found or inaccessible
|
||||
try {
|
||||
fs.accessSync(paths.nodeModules, fs.constants.R_OK);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
const packages = fs.readdirSync(paths.nodeModules)
|
||||
.filter(pkgName => pluginNamePattern.test(pkgName));
|
||||
|
||||
const packageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
|
||||
|
||||
const extraneous = packages
|
||||
// only extraneous plugins (ones not in package.json) which are not links
|
||||
.filter((pkgName) => {
|
||||
const extraneous = !packageContents.dependencies.hasOwnProperty(pkgName);
|
||||
const isLink = fs.lstatSync(path.join(paths.nodeModules, pkgName)).isSymbolicLink();
|
||||
|
||||
return extraneous && !isLink;
|
||||
})
|
||||
// reduce to a map of package names to package versions
|
||||
.reduce((map, pkgName) => {
|
||||
const pkgConfig = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, pkgName, 'package.json'), 'utf8'));
|
||||
map[pkgName] = pkgConfig.version;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Add those packages to package.json
|
||||
packageContents.dependencies = sortDependencies({ ...packageContents.dependencies, ...extraneous });
|
||||
|
||||
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
|
||||
};
|
||||
@@ -1,173 +1 @@
|
||||
'use strict';
|
||||
|
||||
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 pkgInstall = {} as any;
|
||||
|
||||
function sortDependencies(dependencies) {
|
||||
return Object.entries(dependencies)
|
||||
.sort((a, b) => (a < b ? -1 : 1))
|
||||
.reduce((memo, pkg) => {
|
||||
memo[pkg[0]] = pkg[1];
|
||||
return memo;
|
||||
}, {});
|
||||
}
|
||||
|
||||
pkgInstall.updatePackageFile = () => {
|
||||
let oldPackageContents;
|
||||
|
||||
try {
|
||||
oldPackageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
|
||||
} catch (e: any) { if (e.code !== 'ENOENT') {
|
||||
throw e;
|
||||
} else {
|
||||
// No local package.json, copy from install/package.json
|
||||
fs.copyFileSync(paths.installPackage, paths.currentPackage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultPackageContents = JSON.parse(fs.readFileSync(paths.installPackage, 'utf8'));
|
||||
|
||||
let dependencies = {};
|
||||
Object.entries(oldPackageContents.dependencies || {}).forEach(([dep, version]) => {
|
||||
if (pluginNamePattern.test(dep)) {
|
||||
dependencies[dep] = version;
|
||||
}
|
||||
});
|
||||
|
||||
const { devDependencies } = defaultPackageContents;
|
||||
|
||||
// Sort dependencies alphabetically
|
||||
dependencies = sortDependencies({ ...dependencies, ...defaultPackageContents.dependencies });
|
||||
|
||||
const packageContents = { ..._.merge(oldPackageContents, defaultPackageContents), dependencies, devDependencies };
|
||||
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
|
||||
};
|
||||
|
||||
pkgInstall.supportedPackageManager = [
|
||||
'npm',
|
||||
'cnpm',
|
||||
'pnpm',
|
||||
'yarn',
|
||||
];
|
||||
|
||||
pkgInstall.getPackageManager = () => {
|
||||
try {
|
||||
const packageContents = require(paths.currentPackage);
|
||||
// This regex technically allows invalid values:
|
||||
// cnpm isn't supported by corepack and it doesn't enforce a version string being present
|
||||
const pmRegex = new RegExp(`^(?<packageManager>${pkgInstall.supportedPackageManager.join('|')})@?[\\d\\w\\.\\-]*$`);
|
||||
const packageManager = packageContents.packageManager ? packageContents.packageManager.match(pmRegex) : false;
|
||||
if (packageManager) {
|
||||
return packageManager.groups.packageManager;
|
||||
}
|
||||
fs.accessSync(path.join(paths.nodeModules, 'nconf/package.json'), fs.constants.R_OK);
|
||||
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');
|
||||
nconf.env().file({ // not sure why adding .argv() causes the process to terminate
|
||||
file: configFile,
|
||||
});
|
||||
}
|
||||
if (nconf.get('package_manager') && !pkgInstall.supportedPackageManager.includes(nconf.get('package_manager'))) {
|
||||
nconf.clear('package_manager');
|
||||
}
|
||||
|
||||
if (!nconf.get('package_manager')) {
|
||||
nconf.set('package_manager', getPackageManagerByLockfile());
|
||||
}
|
||||
|
||||
return nconf.get('package_manager') || 'npm';
|
||||
} catch (e: any) { // nconf not installed or other unexpected error/exception
|
||||
return getPackageManagerByLockfile() || 'npm';
|
||||
}
|
||||
};
|
||||
|
||||
function getPackageManagerByLockfile() {
|
||||
for (const [packageManager, lockfile] of Object.entries({ npm: 'package-lock.json', yarn: 'yarn.lock', pnpm: 'pnpm-lock.yaml' })) {
|
||||
try {
|
||||
fs.accessSync(path.resolve(__dirname, `../../${lockfile}`), fs.constants.R_OK);
|
||||
return packageManager;
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
pkgInstall.installAll = () => {
|
||||
const prod = (process as any).env.NODE_ENV !== 'development';
|
||||
let command = 'npm install';
|
||||
|
||||
const supportedPackageManagerList = pkgInstall.supportedPackageManager; // load config from src/cli/package-install.js
|
||||
const packageManager = pkgInstall.getPackageManager();
|
||||
if (supportedPackageManagerList.indexOf(packageManager) >= 0) {
|
||||
switch (packageManager) {
|
||||
case 'yarn':
|
||||
command = `yarn${prod ? ' --production' : ''}`;
|
||||
break;
|
||||
case 'pnpm':
|
||||
command = 'pnpm install'; // pnpm checks NODE_ENV
|
||||
break;
|
||||
case 'cnpm':
|
||||
command = `cnpm install ${prod ? ' --production' : ''}`;
|
||||
break;
|
||||
default:
|
||||
command += prod ? ' --omit=dev' : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
cproc.execSync(command, {
|
||||
cwd: path.join(__dirname, '../../'),
|
||||
stdio: [0, 1, 2],
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.log('Error installing dependencies!');
|
||||
console.log(`message: ${e.message}`);
|
||||
console.log(`stdout: ${e.stdout}`);
|
||||
console.log(`stderr: ${e.stderr}`);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
pkgInstall.preserveExtraneousPlugins = () => {
|
||||
// Skip if `node_modules/` is not found or inaccessible
|
||||
try {
|
||||
fs.accessSync(paths.nodeModules, fs.constants.R_OK);
|
||||
} catch (e: any) { return;
|
||||
}
|
||||
|
||||
const packages = fs.readdirSync(paths.nodeModules)
|
||||
.filter(pkgName => pluginNamePattern.test(pkgName));
|
||||
|
||||
const packageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
|
||||
|
||||
const extraneous = packages
|
||||
// only extraneous plugins (ones not in package.json) which are not links
|
||||
.filter((pkgName) => {
|
||||
const extraneous = !packageContents.dependencies.hasOwnProperty(pkgName);
|
||||
const isLink = fs.lstatSync(path.join(paths.nodeModules, pkgName)).isSymbolicLink();
|
||||
|
||||
return extraneous && !isLink;
|
||||
})
|
||||
// reduce to a map of package names to package versions
|
||||
.reduce((map, pkgName) => {
|
||||
const pkgConfig = JSON.parse(fs.readFileSync(path.join(paths.nodeModules, pkgName, 'package.json'), 'utf8'));
|
||||
map[pkgName] = pkgConfig.version;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// Add those packages to package.json
|
||||
packageContents.dependencies = sortDependencies({ ...packageContents.dependencies, ...extraneous });
|
||||
|
||||
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
|
||||
};
|
||||
|
||||
export default pkgInstall;
|
||||
export * from '../../../src/cli/package-install';
|
||||
|
||||
@@ -70,7 +70,7 @@ export const reset = async function (options) {
|
||||
' Prefix is optional, e.g. ./nodebb reset -p markdown, ./nodebb reset -t harmony',
|
||||
].join('\n'));
|
||||
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -80,10 +80,10 @@ export const reset = async function (options) {
|
||||
await task();
|
||||
}
|
||||
winston.info('[reset] Reset complete. Please run `./nodebb build` to rebuild assets.');
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
} catch (err: any) {
|
||||
winston.error(`[reset] Errors were encountered during reset -- ${err.message}`);
|
||||
(process as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +120,7 @@ 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 as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
const isActive = await db.isSortedSetMember('plugins:active', pluginId);
|
||||
if (isActive) {
|
||||
@@ -143,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 as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
await db.delete('plugins:active');
|
||||
winston.info('[reset] All Plugins De-activated');
|
||||
|
||||
@@ -18,7 +18,7 @@ export function getRunningPid(callback) {
|
||||
pid = parseInt(pid as string, 10);
|
||||
|
||||
try {
|
||||
(process as any).kill(pid, 0);
|
||||
process.kill(pid, 0);
|
||||
callback(null, pid);
|
||||
} catch (e: any) { callback(e);
|
||||
}
|
||||
@@ -27,9 +27,9 @@ export function getRunningPid(callback) {
|
||||
|
||||
export function start(options?) {
|
||||
if (options.dev) {
|
||||
(process as any).env.NODE_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
fork(paths.loader, ['--no-daemon', '--no-silent'], {
|
||||
env: (process as any).env,
|
||||
env: process.env,
|
||||
stdio: 'inherit',
|
||||
cwd,
|
||||
});
|
||||
@@ -52,13 +52,13 @@ export function start(options?) {
|
||||
}
|
||||
|
||||
// Spawn a new NodeBB process
|
||||
const child = fork(paths.loader, (process as any).argv.slice(3), {
|
||||
env: (process as any).env,
|
||||
const child = fork(paths.loader, process.argv.slice(3), {
|
||||
env: process.env,
|
||||
cwd,
|
||||
});
|
||||
if (options.log) {
|
||||
// @ts-ignore
|
||||
child(process as any).spawn('tail', ['-F', './logs/output.log'], {
|
||||
childprocess.spawn('tail', ['-F', './logs/output.log'], {
|
||||
stdio: 'inherit',
|
||||
cwd,
|
||||
});
|
||||
@@ -70,7 +70,7 @@ export function start(options?) {
|
||||
export function stop() {
|
||||
getRunningPid((err, pid) => {
|
||||
if (!err) {
|
||||
(process as any).kill(pid, 'SIGTERM');
|
||||
process.kill(pid, 'SIGTERM');
|
||||
console.log('Stopping NodeBB. Goodbye!');
|
||||
} else {
|
||||
console.log('NodeBB is already stopped.');
|
||||
@@ -82,7 +82,7 @@ function restart(options) {
|
||||
getRunningPid((err, pid) => {
|
||||
if (!err) {
|
||||
console.log(chalk.bold('\nRestarting NodeBB'));
|
||||
(process as any).kill(pid, 'SIGTERM');
|
||||
process.kill(pid, 'SIGTERM');
|
||||
|
||||
options.silent = true;
|
||||
start(options);
|
||||
@@ -110,7 +110,7 @@ export function status() {
|
||||
|
||||
export function log() {
|
||||
console.log(`${chalk.red('\nHit ') + chalk.bold('Ctrl-C ') + chalk.red('to exit\n')}\n`);
|
||||
// child(process as any).spawn('tail', ['-F', './logs/output.log'], {
|
||||
// childprocess.spawn('tail', ['-F', './logs/output.log'], {
|
||||
// stdio: 'inherit',
|
||||
// cwd,
|
||||
// });
|
||||
|
||||
@@ -34,8 +34,8 @@ async function setup(initConfig?) {
|
||||
}
|
||||
|
||||
let separator = ' ';
|
||||
if ((process as any).stdout.columns > 10) {
|
||||
for (let x = 0, cols = (process as any).stdout.columns - 10; x < cols; x += 1) {
|
||||
if (process.stdout.columns > 10) {
|
||||
for (let x = 0, cols = process.stdout.columns - 10; x < cols; x += 1) {
|
||||
separator += '=';
|
||||
}
|
||||
}
|
||||
@@ -51,10 +51,10 @@ 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 as any).send) {
|
||||
(process as any).send(data);
|
||||
if (process.send) {
|
||||
process.send(data);
|
||||
}
|
||||
(process as any).exit();
|
||||
process.exit();
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -16,7 +16,7 @@ const packageManager = pkgInstall.getPackageManager();
|
||||
let packageManagerExecutable = packageManager;
|
||||
const packageManagerInstallArgs = packageManager === 'yarn' ? ['add'] : ['install', '--save'];
|
||||
|
||||
if ((process as any).platform === 'win32') {
|
||||
if (process.platform === 'win32') {
|
||||
packageManagerExecutable += '.cmd';
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ async function getSuggestedModules(nbbVersion, toCheck) {
|
||||
}
|
||||
|
||||
async function checkPlugins() {
|
||||
(process as any).stdout.write('Checking installed plugins and themes for updates... ');
|
||||
process.stdout.write('Checking installed plugins and themes for updates... ');
|
||||
const [plugins, nbbVersion] = await Promise.all([
|
||||
getInstalledPlugins(),
|
||||
getCurrentVersion(),
|
||||
@@ -93,11 +93,11 @@ async function checkPlugins() {
|
||||
|
||||
const toCheck = Object.keys(plugins);
|
||||
if (!toCheck.length) {
|
||||
(process as any).stdout.write(chalk.green(' OK'));
|
||||
process.stdout.write(chalk.green(' OK'));
|
||||
return []; // no extraneous plugins installed
|
||||
}
|
||||
const suggestedModules = await getSuggestedModules(nbbVersion, toCheck);
|
||||
(process as any).stdout.write(chalk.green(' OK'));
|
||||
process.stdout.write(chalk.green(' OK'));
|
||||
|
||||
let current;
|
||||
let suggested;
|
||||
@@ -122,9 +122,9 @@ export const upgradePlugins = async function() {
|
||||
try {
|
||||
const found = await checkPlugins();
|
||||
if (found && found.length) {
|
||||
(process as any).stdout.write(`\n\nA total of ${chalk.bold(String(found.length))} package(s) can be upgraded:\n\n`);
|
||||
process.stdout.write(`\n\nA total of ${chalk.bold(String(found.length))} package(s) can be upgraded:\n\n`);
|
||||
found.forEach((suggestObj) => {
|
||||
(process as any).stdout.write(`${chalk.yellow(' * ') + suggestObj.name} (${chalk.yellow(suggestObj.current)} -> ${chalk.green(suggestObj.suggested)})\n`);
|
||||
process.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!'));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import nconf from 'nconf';
|
||||
import chalk from 'chalk';
|
||||
import packageInstall from './package-install';
|
||||
import { upgradePlugins } from './upgrade-plugins';
|
||||
import { upgradePlugins } from './upgrade-plugins';
|
||||
import db from '../database';
|
||||
import meta from '../meta';
|
||||
import Upgrade from '../upgrade';
|
||||
@@ -15,13 +15,13 @@ const steps = {
|
||||
handler: function () {
|
||||
packageInstall.updatePackageFile();
|
||||
packageInstall.preserveExtraneousPlugins();
|
||||
(process as any).stdout.write(chalk.green(' OK\n'));
|
||||
process.stdout.write(chalk.green(' OK\n'));
|
||||
},
|
||||
},
|
||||
install: {
|
||||
message: 'Bringing base dependencies up to date...',
|
||||
handler: function () {
|
||||
(process as any).stdout.write(chalk.green(' started\n'));
|
||||
process.stdout.write(chalk.green(' started\n'));
|
||||
packageInstall.installAll();
|
||||
},
|
||||
},
|
||||
@@ -53,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 as any).stdout.write(`\n${chalk.bold(`${i + 1}. `)}${chalk.yellow(step.message)}`);
|
||||
process.stdout.write(`\n${chalk.bold(`${i + 1}. `)}${chalk.yellow(step.message)}`);
|
||||
/* eslint-disable-next-line */
|
||||
await step.handler();
|
||||
}
|
||||
@@ -61,12 +61,12 @@ 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 as any).stdout;
|
||||
const { columns } = process.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 as any).exit();
|
||||
process.exit();
|
||||
} catch (err: any) {
|
||||
console.error(`Error occurred during upgrade: ${err.stack}`);
|
||||
throw err;
|
||||
@@ -92,7 +92,7 @@ async function runUpgrade(upgrades, options?) {
|
||||
db.init();
|
||||
meta.configs.init();
|
||||
Upgrade.runParticular(upgrades);
|
||||
(process as any).exit(0);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
export const upgrade = runUpgrade;
|
||||
|
||||
@@ -91,10 +91,10 @@ async function execute(cmd, args) {
|
||||
} catch (err: any) {
|
||||
const userError = err.name === 'UserError';
|
||||
winston.error(`[userCmd/${cmd.name}] ${userError ? `${err.message}` : 'Command failed.'}`, userError ? '' : err);
|
||||
(process as any).exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
(process as any).exit();
|
||||
process.exit();
|
||||
}
|
||||
|
||||
function UserCmdHelpers() {
|
||||
|
||||
26
src/constants.js
Normal file
26
src/constants.js
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const baseDir = path.join(__dirname, '../');
|
||||
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 installPackage = path.join(baseDir, 'install/package.json');
|
||||
const nodeModules = path.join(baseDir, 'node_modules');
|
||||
|
||||
exports.paths = {
|
||||
baseDir,
|
||||
loader,
|
||||
app,
|
||||
pidfile,
|
||||
config,
|
||||
currentPackage,
|
||||
installPackage,
|
||||
nodeModules,
|
||||
};
|
||||
|
||||
exports.pluginNamePattern = /^(@[\w-]+\/)?nodebb-(theme|plugin|widget|rewards)-[\w-]+$/;
|
||||
exports.themeNamePattern = /^(@[\w-]+\/)?nodebb-theme-[\w-]+$/;
|
||||
@@ -1,26 +1 @@
|
||||
'use strict';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
const baseDir = path.join(__dirname, '../');
|
||||
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 installPackage = path.join(baseDir, 'install/package.json');
|
||||
const nodeModules = path.join(baseDir, '../node_modules');
|
||||
|
||||
export const paths = {
|
||||
baseDir,
|
||||
loader,
|
||||
app,
|
||||
pidfile,
|
||||
config,
|
||||
currentPackage,
|
||||
installPackage,
|
||||
nodeModules,
|
||||
};
|
||||
|
||||
export const pluginNamePattern = /^(@[\w-]+\/)?nodebb-(theme|plugin|widget|rewards)-[\w-]+$/;
|
||||
export const themeNamePattern = /^(@[\w-]+\/)?nodebb-theme-[\w-]+$/;
|
||||
export * from '../../src/constants';
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"target": "ES2019", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
@@ -78,13 +78,13 @@
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
"strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
"strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
"noImplicitThis": false, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
"noImplicitThis": false, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
"alwaysStrict": false, /* Ensure 'use strict' is always emitted. */
|
||||
"alwaysStrict": false, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
|
||||
Reference in New Issue
Block a user