eslint, require-no-cache now deletes all requires from plugin directory from cache
This commit is contained in:
parent
f2af1891ee
commit
81b8e7581a
2
.eslintignore
Normal file
2
.eslintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.js
|
||||||
|
*.d.ts
|
46
.eslintrc.js
Normal file
46
.eslintrc.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
module.exports = {
|
||||||
|
'env': {
|
||||||
|
'es2021': true,
|
||||||
|
'node': true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended'
|
||||||
|
],
|
||||||
|
'parser': '@typescript-eslint/parser',
|
||||||
|
'parserOptions': {
|
||||||
|
'ecmaVersion': 13,
|
||||||
|
'sourceType': 'module',
|
||||||
|
'project': 'tsconfig.json',
|
||||||
|
'tsconfigRootDir': __dirname,
|
||||||
|
},
|
||||||
|
'plugins': [
|
||||||
|
'@typescript-eslint'
|
||||||
|
],
|
||||||
|
'rules': {
|
||||||
|
'no-empty': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'allowEmptyCatch': true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'indent': [
|
||||||
|
'error',
|
||||||
|
2
|
||||||
|
],
|
||||||
|
'linebreak-style': [
|
||||||
|
'error',
|
||||||
|
'unix'
|
||||||
|
],
|
||||||
|
'quotes': [
|
||||||
|
'error',
|
||||||
|
'single'
|
||||||
|
],
|
||||||
|
'semi': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
2772
package-lock.json
generated
2772
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@squeebot/core",
|
"name": "@squeebot/core",
|
||||||
"version": "3.3.5",
|
"version": "3.3.6",
|
||||||
"description": "Squeebot v3 core for the execution environment",
|
"description": "Squeebot v3 core for the execution environment",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
@ -23,7 +23,8 @@
|
|||||||
"@types/node": "^16.7.10",
|
"@types/node": "^16.7.10",
|
||||||
"@types/semver": "^7.3.8",
|
"@types/semver": "^7.3.8",
|
||||||
"@types/tar": "^4.0.5",
|
"@types/tar": "^4.0.5",
|
||||||
"tslint": "^6.1.3",
|
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
||||||
|
"eslint": "^8.4.1",
|
||||||
"typescript": "^4.4.2"
|
"typescript": "^4.4.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -15,7 +15,7 @@ const dirs: {[key: string]: string} = {
|
|||||||
* @param chroot Change bot root to this instead of the path in the environment
|
* @param chroot Change bot root to this instead of the path in the environment
|
||||||
* @returns Squeebot environment
|
* @returns Squeebot environment
|
||||||
*/
|
*/
|
||||||
export async function loadEnvironment(enviroFile: string = 'squeebot.env.json', chroot?: string): Promise<IEnvironment> {
|
export async function loadEnvironment(enviroFile = 'squeebot.env.json', chroot?: string): Promise<IEnvironment> {
|
||||||
if (!await fs.pathExists(enviroFile)) {
|
if (!await fs.pathExists(enviroFile)) {
|
||||||
throw new Error('Environment file does not exist.');
|
throw new Error('Environment file does not exist.');
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class Logger {
|
|||||||
const old = this.console[index];
|
const old = this.console[index];
|
||||||
this.console[index] = (...data: any[]): void => {
|
this.console[index] = (...data: any[]): void => {
|
||||||
rl.output.write('\x1b[2K\r');
|
rl.output.write('\x1b[2K\r');
|
||||||
old.apply(null, data);
|
old(...data);
|
||||||
rl.prompt(true);
|
rl.prompt(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ export class Logger {
|
|||||||
final = util.format(data[0], ...fargs);
|
final = util.format(data[0], ...fargs);
|
||||||
}
|
}
|
||||||
message.push(final);
|
message.push(final);
|
||||||
cfunc.apply(null, message);
|
cfunc(...message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,6 +102,6 @@ export class NPMExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private removeVersionWildcard(str: string): string {
|
private removeVersionWildcard(str: string): string {
|
||||||
return str.replace(/\^|\>|\=/, '');
|
return str.replace(/\^|>|=/, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* Declare this plugin as one that the user can configure.
|
* Declare this plugin as one that the user can configure.
|
||||||
* @param defconf Default configuration
|
* @param defconf Default configuration
|
||||||
*/
|
*/
|
||||||
export function Configurable(defconf: any): Function {
|
export function Configurable(defconf: any): (...arg: any[]) => any {
|
||||||
return (constructor: Function): void => {
|
return (constructor: (...arg: any[]) => any): void => {
|
||||||
constructor.prototype.__defconf = defconf;
|
constructor.prototype.__defconf = defconf;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* Declare this plugin as one that utilises services.
|
* Declare this plugin as one that utilises services.
|
||||||
* @param servtype Service class, usually a Protocol
|
* @param servtype Service class, usually a Protocol
|
||||||
*/
|
*/
|
||||||
export function InjectService(servtype: any): Function {
|
export function InjectService(servtype: any): (...arg: any[]) => any {
|
||||||
return (constructor: Function): void => {
|
return (constructor: (...arg: any[]) => any): void => {
|
||||||
constructor.prototype.__service = servtype;
|
constructor.prototype.__service = servtype;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ export class PluginMetaLoader {
|
|||||||
throw new Error('Plugin metadata does not specify a name, for some reason');
|
throw new Error('Plugin metadata does not specify a name, for some reason');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.name === 'squeebot' || !(/^[a-zA-Z0-9_\-]+$/.test(json.name))) {
|
if (json.name === 'squeebot' || !(/^[a-zA-Z0-9_-]+$/.test(json.name))) {
|
||||||
throw new Error('Illegal name.');
|
throw new Error('Illegal name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,12 +76,13 @@ export class PluginMetaLoader {
|
|||||||
public async loadAll(ignoreErrors = false): Promise<IPluginManifest[]> {
|
public async loadAll(ignoreErrors = false): Promise<IPluginManifest[]> {
|
||||||
const dirlist = await fs.readdir(this.env.pluginsPath);
|
const dirlist = await fs.readdir(this.env.pluginsPath);
|
||||||
const plugins: IPluginManifest[] = [];
|
const plugins: IPluginManifest[] = [];
|
||||||
|
|
||||||
for (const file of dirlist) {
|
for (const file of dirlist) {
|
||||||
// Ignore hidden files and non-directories
|
// Ignore hidden files and non-directories
|
||||||
const fpath = path.join(this.env.pluginsPath, file);
|
const fpath = path.join(this.env.pluginsPath, file);
|
||||||
if (file.indexOf('.') === 0 ||
|
const isDirectory = (await fs.lstat(fpath)).isDirectory();
|
||||||
file === 'node_modules' ||
|
|
||||||
!(await fs.lstat(fpath)).isDirectory()) {
|
if (!isDirectory || file.startsWith('.') || file === 'node_modules') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,12 +90,11 @@ export class PluginMetaLoader {
|
|||||||
const plugin = await this.load(file);
|
const plugin = await this.load(file);
|
||||||
plugins.push(plugin);
|
plugins.push(plugin);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (ignoreErrors) {
|
if (!ignoreErrors) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ export class PluginManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(/^[a-zA-Z0-9_\-]+$/.test(manifest.name))) {
|
if (!(/^[a-zA-Z0-9_-]+$/.test(manifest.name))) {
|
||||||
throw new Error('Illegal name for a plugin!');
|
throw new Error('Illegal name for a plugin!');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,8 +284,9 @@ export class PluginManager {
|
|||||||
/**
|
/**
|
||||||
* Restart a loaded plugin.
|
* Restart a loaded plugin.
|
||||||
* @param mf Plugin instance, plugin manifest or plugin name
|
* @param mf Plugin instance, plugin manifest or plugin name
|
||||||
|
* @param wait Waits for the plugin to be available before resolving
|
||||||
*/
|
*/
|
||||||
public async restart(mf: IPluginManifest | IPlugin | string): Promise<void> {
|
public async restart(mf: IPluginManifest | IPlugin | string, wait = false): Promise<void> {
|
||||||
let manifest;
|
let manifest;
|
||||||
if (typeof mf === 'string') {
|
if (typeof mf === 'string') {
|
||||||
manifest = this.getAvailableByName(mf);
|
manifest = this.getAvailableByName(mf);
|
||||||
@ -299,13 +300,34 @@ export class PluginManager {
|
|||||||
throw new Error('Plugin not found');
|
throw new Error('Plugin not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.getLoadedByName(manifest.name)) {
|
const pluginName = manifest.name;
|
||||||
|
if (!this.getLoadedByName(pluginName)) {
|
||||||
this.load(manifest);
|
this.load(manifest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.restartQueue.set(manifest.name, manifest);
|
this.restartQueue.set(pluginName, manifest);
|
||||||
this.stream.emitTo(manifest.name, 'pluginUnload', manifest.name);
|
this.stream.emitTo(pluginName, 'pluginUnload', pluginName);
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let retries = 0;
|
||||||
|
const checkInterval = setInterval(() => {
|
||||||
|
// Plugin has been loaded, resolve the promise
|
||||||
|
if (this.getLoadedByName(pluginName)) {
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
// Increment retry count and wait for next iteration
|
||||||
|
retries++;
|
||||||
|
if (retries >= 20) {
|
||||||
|
// Give up after 10 seconds
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
reject(new Error('Could not determine loaded status within a reasonable time frame.'));
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +24,7 @@ export class Plugin implements IPlugin {
|
|||||||
* Called when plugin first starts.
|
* Called when plugin first starts.
|
||||||
* Please use this instead of the constructor.
|
* Please use this instead of the constructor.
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
public initialize(): void {}
|
public initialize(): void {}
|
||||||
|
|
||||||
public get name(): string {
|
public get name(): string {
|
||||||
|
@ -163,7 +163,7 @@ export class RepositoryManager {
|
|||||||
throw new Error('Invalid metadata file for repository.');
|
throw new Error('Invalid metadata file for repository.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(/^[a-zA-Z0-9_\-\+]+$/.test(meta.name))) {
|
if (!(/^[a-zA-Z0-9_\-+]+$/.test(meta.name))) {
|
||||||
throw new Error('Illegal name for repository!');
|
throw new Error('Illegal name for repository!');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ export class RepositoryManager {
|
|||||||
throw new Error('Invalid repository file ' + rf);
|
throw new Error('Invalid repository file ' + rf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(/^[a-zA-Z0-9_\-\+]+$/.test(contents.name))) {
|
if (!(/^[a-zA-Z0-9_\-+]+$/.test(contents.name))) {
|
||||||
throw new Error(`"${rf}" is an illegal name for a repository!`);
|
throw new Error(`"${rf}" is an illegal name for a repository!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,12 @@ export class Configuration {
|
|||||||
const json = await fs.readJson(this.file);
|
const json = await fs.readJson(this.file);
|
||||||
this.config = json;
|
this.config = json;
|
||||||
|
|
||||||
|
// Assign default values to existing configuration and resave.
|
||||||
|
// Eliminates the need for plugins to overwrite the configuration file
|
||||||
|
// when exiting.
|
||||||
if (this.defaults) {
|
if (this.defaults) {
|
||||||
this.config = Object.assign({}, this.defaults, json);
|
this.config = Object.assign({}, this.defaults, json);
|
||||||
|
await this.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
import { EMessageType, IMessage } from './message';
|
import { EMessageType, IMessage } from './message';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export interface IMessageData {
|
|||||||
value: any;
|
value: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IMessageHandler = (data: IMessageData | string, reject: Function, next: IMessageHandler) => void;
|
export type IMessageHandler = (data: IMessageData | string, reject: (error: Error) => void, next: IMessageHandler) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Staged messaging handler
|
* Staged messaging handler
|
||||||
|
@ -10,9 +10,18 @@ export { IProcessData, spawnProcess, execProcess } from './run';
|
|||||||
*/
|
*/
|
||||||
export function requireNoCache(file: string): object | undefined {
|
export function requireNoCache(file: string): object | undefined {
|
||||||
const fullPath = path.resolve(file);
|
const fullPath = path.resolve(file);
|
||||||
|
// TODO: maybe use new "import" function?
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const mod = require(fullPath);
|
const mod = require(fullPath);
|
||||||
if (require.cache && require.cache[fullPath]) {
|
if (require.cache && require.cache[fullPath]) {
|
||||||
delete require.cache[fullPath];
|
delete require.cache[fullPath];
|
||||||
|
|
||||||
|
// Delete in-plugin-folder requires from cache as well
|
||||||
|
const dirname = path.dirname(fullPath);
|
||||||
|
const cacheEntries = Object.keys(require.cache).filter((entry) => entry.startsWith(dirname));
|
||||||
|
cacheEntries.forEach((entry) => {
|
||||||
|
delete require.cache[entry];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
122
tslint.json
122
tslint.json
@ -1,122 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tslint:recommended",
|
|
||||||
"rules": {
|
|
||||||
"align": {
|
|
||||||
"options": [
|
|
||||||
"parameters",
|
|
||||||
"statements"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"array-type": false,
|
|
||||||
"arrow-return-shorthand": true,
|
|
||||||
"curly": true,
|
|
||||||
"deprecation": {
|
|
||||||
"severity": "warning"
|
|
||||||
},
|
|
||||||
"eofline": true,
|
|
||||||
"import-spacing": true,
|
|
||||||
"indent": {
|
|
||||||
"options": [
|
|
||||||
"spaces"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"max-classes-per-file": false,
|
|
||||||
"max-line-length": [
|
|
||||||
true,
|
|
||||||
140
|
|
||||||
],
|
|
||||||
"member-ordering": [
|
|
||||||
true,
|
|
||||||
{
|
|
||||||
"order": [
|
|
||||||
"static-field",
|
|
||||||
"instance-field",
|
|
||||||
"static-method",
|
|
||||||
"instance-method"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-console": [
|
|
||||||
true,
|
|
||||||
"debug",
|
|
||||||
"info",
|
|
||||||
"time",
|
|
||||||
"timeEnd",
|
|
||||||
"trace"
|
|
||||||
],
|
|
||||||
"no-empty": false,
|
|
||||||
"no-inferrable-types": [
|
|
||||||
true,
|
|
||||||
"ignore-params"
|
|
||||||
],
|
|
||||||
"no-non-null-assertion": true,
|
|
||||||
"no-redundant-jsdoc": true,
|
|
||||||
"no-switch-case-fall-through": true,
|
|
||||||
"no-var-requires": false,
|
|
||||||
"object-literal-key-quotes": [
|
|
||||||
true,
|
|
||||||
"as-needed"
|
|
||||||
],
|
|
||||||
"quotemark": [
|
|
||||||
true,
|
|
||||||
"single"
|
|
||||||
],
|
|
||||||
"semicolon": {
|
|
||||||
"options": [
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"space-before-function-paren": {
|
|
||||||
"options": {
|
|
||||||
"anonymous": "never",
|
|
||||||
"asyncArrow": "always",
|
|
||||||
"constructor": "never",
|
|
||||||
"method": "never",
|
|
||||||
"named": "never"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"typedef": [
|
|
||||||
true,
|
|
||||||
"call-signature"
|
|
||||||
],
|
|
||||||
"forin": false,
|
|
||||||
"ban-types": {
|
|
||||||
"function": false
|
|
||||||
},
|
|
||||||
"typedef-whitespace": {
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"call-signature": "nospace",
|
|
||||||
"index-signature": "nospace",
|
|
||||||
"parameter": "nospace",
|
|
||||||
"property-declaration": "nospace",
|
|
||||||
"variable-declaration": "nospace"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"call-signature": "onespace",
|
|
||||||
"index-signature": "onespace",
|
|
||||||
"parameter": "onespace",
|
|
||||||
"property-declaration": "onespace",
|
|
||||||
"variable-declaration": "onespace"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"variable-name": {
|
|
||||||
"options": [
|
|
||||||
"ban-keywords",
|
|
||||||
"check-format",
|
|
||||||
"allow-pascal-case"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"whitespace": {
|
|
||||||
"options": [
|
|
||||||
"check-branch",
|
|
||||||
"check-decl",
|
|
||||||
"check-operator",
|
|
||||||
"check-separator",
|
|
||||||
"check-type",
|
|
||||||
"check-typecast"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user