@kotori-bot/loader
Advanced tools
Comparing version 1.2.0 to 1.3.0
export declare const DEV_FILE = ".ts"; | ||
export declare const BUILD_FILE = ".js"; | ||
export declare const DEV_CODE_DIRS = "./src/"; | ||
export declare const DEV_IMPORT = "./src/index.ts"; | ||
export declare const DEV_CODE_DIRS = "./src/"; | ||
export declare const BUILD_CONFIG_NAME = "kotori.yml"; | ||
export declare const DEV_CONFIG_NAME = "kotori.dev.yml"; | ||
export declare const SUPPORTS_VERSION: RegExp; | ||
export declare const SUPPORTS_HALF_VERSION: RegExp; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DEV_CODE_DIRS = exports.DEV_IMPORT = exports.BUILD_FILE = exports.DEV_FILE = void 0; | ||
exports.SUPPORTS_HALF_VERSION = exports.SUPPORTS_VERSION = exports.DEV_CONFIG_NAME = exports.BUILD_CONFIG_NAME = exports.DEV_IMPORT = exports.DEV_CODE_DIRS = exports.BUILD_FILE = exports.DEV_FILE = void 0; | ||
exports.DEV_FILE = '.ts'; | ||
exports.BUILD_FILE = '.js'; | ||
exports.DEV_IMPORT = './src/index.ts'; | ||
exports.DEV_CODE_DIRS = './src/'; | ||
exports.DEV_IMPORT = `${exports.DEV_CODE_DIRS}index.ts`; | ||
exports.BUILD_CONFIG_NAME = 'kotori.yml'; | ||
exports.DEV_CONFIG_NAME = 'kotori.dev.yml'; | ||
exports.SUPPORTS_VERSION = /(1\.1\.0)/; | ||
exports.SUPPORTS_HALF_VERSION = /(x\.x\.(.*?))/; |
@@ -1,2 +0,3 @@ | ||
import loader from './loader'; | ||
export default loader; | ||
export * from './loader'; | ||
export * from './consts'; | ||
export * from '@kotori-bot/logger'; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/* | ||
@@ -11,5 +7,21 @@ * @Author: Hotaru biyuehuya@gmail.com | ||
* @LastEditors: Hotaru biyuehuya@gmail.com | ||
* @LastEditTime: 2023-12-30 17:32:51 | ||
* @LastEditTime: 2024-02-06 19:03:21 | ||
*/ | ||
const loader_1 = __importDefault(require("./loader")); | ||
exports.default = loader_1.default; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./loader"), exports); | ||
__exportStar(require("./consts"), exports); | ||
__exportStar(require("@kotori-bot/logger"), exports); |
@@ -1,5 +0,25 @@ | ||
import { ContextInstance } from '@kotori-bot/core'; | ||
declare class Main extends ContextInstance { | ||
import { Container, Symbols } from '@kotori-bot/core'; | ||
import Logger from '@kotori-bot/logger'; | ||
import Runner from './runner'; | ||
declare module '@kotori-bot/core' { | ||
interface Context { | ||
readonly baseDir: Runner['baseDir']; | ||
readonly options: Runner['options']; | ||
readonly [Symbols.modules]: Runner[typeof Symbols.modules]; | ||
useAll(): void; | ||
watcher(): void; | ||
logger: Logger; | ||
} | ||
interface GlobalConfig { | ||
dirs: string[]; | ||
} | ||
} | ||
export declare class Loader extends Container { | ||
private ctx; | ||
constructor(); | ||
private loadCount; | ||
private failLoadCount; | ||
constructor(options?: { | ||
dir?: string; | ||
mode?: string; | ||
}); | ||
run(): void; | ||
@@ -10,5 +30,5 @@ private handleError; | ||
private loadAllModule; | ||
private loadAllAdapter; | ||
private loadAllService; | ||
private checkUpdate; | ||
} | ||
export default Main; | ||
export default Loader; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,2 +29,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Loader = void 0; | ||
/* | ||
@@ -12,30 +36,93 @@ * @Author: hotaru biyuehuya@gmail.com | ||
* @LastEditors: Hotaru biyuehuya@gmail.com | ||
* @LastEditTime: 2023-12-30 19:12:43 | ||
* @LastEditTime: 2024-02-06 21:05:17 | ||
*/ | ||
const core_1 = require("@kotori-bot/core"); | ||
const modules_1 = __importDefault(require("./modules")); | ||
const global_1 = require("./global"); | ||
const path_1 = __importDefault(require("path")); | ||
const fs_1 = __importDefault(require("fs")); | ||
const logger_1 = __importDefault(require("@kotori-bot/logger")); | ||
const runner_1 = __importStar(require("./runner")); | ||
const log_1 = __importDefault(require("./log")); | ||
const kotoriConfig = () => { | ||
let result = {}; | ||
const baseDir = (0, global_1.getBaseDir)(); | ||
result = { | ||
baseDir, | ||
config: (0, global_1.getGlobalConfig)(baseDir), | ||
options: { | ||
env: (0, global_1.isDev)() ? 'dev' : 'build', | ||
}, | ||
const consts_1 = require("./consts"); | ||
function getRunnerConfig(file, dir) { | ||
const handle = (baseDir) => { | ||
if (!fs_1.default.existsSync(baseDir.modules)) | ||
fs_1.default.mkdirSync(baseDir.modules); | ||
if (!fs_1.default.existsSync(baseDir.logs)) | ||
fs_1.default.mkdirSync(baseDir.logs); | ||
return baseDir; | ||
}; | ||
return result; | ||
}; | ||
class Main extends core_1.ContextInstance { | ||
const options = { | ||
mode: file === consts_1.DEV_CONFIG_NAME ? 'dev' : 'build' | ||
}; | ||
if (dir) | ||
return { | ||
baseDir: handle({ root: dir, modules: path_1.default.join(dir, 'modules'), logs: path_1.default.join(dir, 'logs') }), | ||
options | ||
}; | ||
let root = path_1.default.resolve(__dirname, '..').replace('loader', 'kotori'); | ||
let count = 0; | ||
while (!fs_1.default.existsSync(path_1.default.join(root, file))) { | ||
if (count > 5) { | ||
logger_1.default.fatal(`cannot find file ${file} `); | ||
process.exit(); | ||
} | ||
root = path_1.default.join(root, '..'); | ||
count += 1; | ||
} | ||
return { | ||
baseDir: handle({ root, modules: path_1.default.join(root, 'modules'), logs: path_1.default.join(root, 'logs') }), | ||
options | ||
}; | ||
} | ||
/* eslint consistent-return: 0 */ | ||
function getCoreConfig(file, baseDir) { | ||
try { | ||
const result1 = core_1.Tsu.Object({ | ||
global: core_1.Tsu.Object({ | ||
dirs: core_1.Tsu.Array(core_1.Tsu.String()).default([]), | ||
lang: runner_1.localeTypeSchema.default(core_1.DEFAULT_CORE_CONFIG.global.lang), | ||
'command-prefix': core_1.Tsu.String().default(core_1.DEFAULT_CORE_CONFIG.global['command-prefix']) | ||
}), | ||
plugin: core_1.Tsu.Object({}) | ||
.index(core_1.Tsu.Object({ | ||
filter: core_1.Tsu.Object({}).default({}) | ||
}).default({ filter: {} })) | ||
.default(core_1.DEFAULT_CORE_CONFIG.plugin) | ||
}) | ||
.default({ global: Object.assign(core_1.DEFAULT_CORE_CONFIG.global), plugin: core_1.DEFAULT_CORE_CONFIG.plugin }) | ||
.parse((0, core_1.loadConfig)(path_1.default.join(baseDir.root, file), 'yaml')); | ||
return core_1.Tsu.Object({ | ||
adapter: core_1.Tsu.Object({}) | ||
.index(core_1.Tsu.Object({ | ||
extends: core_1.Tsu.String(), | ||
master: core_1.Tsu.Union([core_1.Tsu.Number(), core_1.Tsu.String()]), | ||
lang: runner_1.localeTypeSchema.default(result1.global.lang), | ||
'command-prefix': core_1.Tsu.String().default(result1.global['command-prefix']) | ||
})) | ||
.default(core_1.DEFAULT_CORE_CONFIG.adapter) | ||
}).parse(result1); | ||
} | ||
catch (err) { | ||
if (!(err instanceof core_1.TsuError)) | ||
throw err; | ||
logger_1.default.fatal(`file ${file} format error: ${err.message}`); | ||
process.exit(); | ||
} | ||
} | ||
class Loader extends core_1.Container { | ||
ctx; | ||
constructor() { | ||
loadCount = 0; | ||
failLoadCount = 0; | ||
constructor(options) { | ||
super(); | ||
core_1.ContextInstance.setInstance(new modules_1.default(kotoriConfig())); | ||
this.ctx = core_1.ContextInstance.getInstance(); | ||
// 静态类型继续居然她妈是隔离的 | ||
const file = options && options.mode === 'dev' ? consts_1.DEV_CONFIG_NAME : consts_1.BUILD_CONFIG_NAME; | ||
const runnerConfig = getRunnerConfig(file, options?.dir); | ||
const ctx = new core_1.Core(getCoreConfig(file, runnerConfig.baseDir)); | ||
ctx.provide('runner', new runner_1.default(ctx, runnerConfig)); | ||
ctx.mixin('runner', ['baseDir', 'options', 'useAll', 'watcher']); | ||
core_1.Container.setInstance(ctx); | ||
this.ctx = core_1.Container.getInstance(); | ||
} | ||
run() { | ||
(0, log_1.default)(this.ctx.package, this.ctx); | ||
(0, log_1.default)(this.ctx.pkg, this.ctx); | ||
this.catchError(); | ||
@@ -47,87 +134,127 @@ this.listenMessage(); | ||
handleError(err, prefix) { | ||
const isKotoriError = err instanceof core_1.KotoriError; | ||
if (!isKotoriError) { | ||
this.ctx.logger.tag(prefix, 'default', prefix === 'UCE' ? 'cyanBG' : 'greenBG').error(err); | ||
if (!(err instanceof core_1.KotoriError)) { | ||
this.ctx.logger.label(prefix).error(err); | ||
return; | ||
} | ||
this.ctx.logger | ||
.tag(err.name.split('Error')[0].toUpperCase(), 'yellow', 'default')[err.level === 'normal' ? 'error' : err.level](err.message, err.stack); | ||
if (err.name !== 'CoreError') | ||
return; | ||
this.ctx.logger.tag('CORE', 'black', 'red').error(err.message); | ||
process.emit('SIGINT'); | ||
({ | ||
DatabaseError: () => this.ctx.logger.label('database').warn(err.message, err.stack), | ||
ModuleError: () => this.ctx.logger.label('module').error(err.message, err.stack), | ||
UnknownError: () => this.ctx.logger.error(err.name, err.stack), | ||
DevError: () => this.ctx.logger.label('error').debug(err.name, err.stack) | ||
})[err.name](); | ||
} | ||
catchError() { | ||
process.on('uncaughtExceptionMonitor', err => this.handleError(err, 'UCE')); | ||
process.on('unhandledRejection', err => this.handleError(err, 'UHR')); | ||
process.on('SIGINT', () => { | ||
process.exit(); | ||
}); | ||
this.ctx.logger.debug('Run info: develop with debuing...'); | ||
process.on('uncaughtExceptionMonitor', (err) => this.handleError(err, 'sync')); | ||
process.on('unhandledRejection', (err) => this.handleError(err, 'async')); | ||
process.on('SIGINT', () => process.exit()); | ||
this.ctx.logger.debug('run info: develop with debuing...'); | ||
} | ||
listenMessage() { | ||
const handleConnectInfo = (data) => { | ||
if (!data.info) | ||
this.ctx.on('connect', (data) => { | ||
const { type, mode, normal, address, adapter } = data; | ||
let msg; | ||
if (type === 'connect') { | ||
switch (mode) { | ||
case 'ws': | ||
msg = `${normal ? 'Connect' : 'Reconnect'} server to ${address}`; | ||
break; | ||
case 'ws-reverse': | ||
msg = `server ${normal ? 'start' : 'restart'} at ${address}`; | ||
break; | ||
default: | ||
msg = `ready completed about ${address}`; | ||
} | ||
} | ||
else { | ||
switch (mode) { | ||
case 'ws': | ||
msg = `disconnect server from ${address}${normal ? '' : ' unexpectedly'}`; | ||
break; | ||
case 'ws-reverse': | ||
msg = `server stop at ${address}${normal ? '' : ' unexpectedly'}`; | ||
break; | ||
default: | ||
msg = `dispose completed about ${address}`; | ||
} | ||
} | ||
this.ctx.logger.label([adapter.platform, adapter.identity])[normal ? 'info' : 'warn'](msg); | ||
}); | ||
this.ctx.on('status', (data) => { | ||
const { status, adapter } = data; | ||
this.ctx.logger.label([adapter.platform, adapter.identity]).info(status); | ||
}); | ||
this.ctx.on('ready_module', (data) => { | ||
if (!data.module || typeof data.module === 'string') | ||
return; | ||
this.ctx.logger[data.normal ? 'log' : 'warn'](`[${data.adapter.platform}]`, `${data.adapter.identity}:`, data.info); | ||
}; | ||
this.ctx.on('connect', handleConnectInfo); | ||
this.ctx.on('disconnect', handleConnectInfo); | ||
this.ctx.on('load_module', data => { | ||
if (!data.module) | ||
this.loadCount += 1; | ||
const { name, version, author } = data.module.pkg; | ||
if (data.error) { | ||
this.failLoadCount += 1; | ||
this.ctx.logger.warn(`failed to load module ${name}`); | ||
if (data.error instanceof core_1.KotoriError) { | ||
process.emit('uncaughtExceptionMonitor', data.error); | ||
} | ||
else { | ||
this.ctx.logger.warn(data.error); | ||
} | ||
} | ||
else { | ||
this.ctx.logger.info(`loaded module ${name} version: ${version} ${Array.isArray(author) ? `authors: ${author.join(',')}` : `author: ${author}`}`); | ||
} | ||
const requiredVersion = data.module.pkg.peerDependencies['kotori-bot']; | ||
if (!requiredVersion.includes('workspace') && | ||
(!consts_1.SUPPORTS_VERSION.exec(requiredVersion) || requiredVersion !== this.ctx.pkg.version)) { | ||
if (consts_1.SUPPORTS_HALF_VERSION.exec(requiredVersion)) { | ||
this.ctx.logger.warn(`incomplete supported module version: ${requiredVersion}`); | ||
} | ||
else { | ||
this.ctx.logger.error(`unsupported module version: ${requiredVersion}`); | ||
} | ||
} | ||
if (this.loadCount !== this.ctx.get('runner')[core_1.Symbols.modules].size) | ||
return; | ||
const { name, version, author } = data.module.package; | ||
this.ctx.logger.info(`Loaded ${data.moduleType} ${name} Version: ${version} ${Array.isArray(author) ? `Authors: ${author.join(',')}` : `Author: ${author}`}`); | ||
this.ctx.logger.info(`loaded ${this.loadCount - this.failLoadCount} modules successfully${this.failLoadCount > 0 ? `, failed to load ${this.failLoadCount} modules` : ''} `); | ||
this.loadAllService(); | ||
this.ctx.emit('ready'); | ||
}); | ||
this.ctx.on('load_all_module', data => { | ||
const failed = data.expected - data.reality; | ||
this.ctx.logger.info(`Loaded ${data.reality} modules (plugins)${failed > 0 ? `, failed to load ${failed} modules` : ''}`); | ||
this.loadAllAdapter(); | ||
}); | ||
} | ||
loadAllModule() { | ||
this.ctx.moduleAll(); | ||
if ((0, global_1.isDev)()) | ||
this.ctx.watchFile(); | ||
this.ctx.useAll(); | ||
} | ||
loadAllAdapter() { | ||
const adapters = this.ctx.internal.getAdapters(); | ||
Object.keys(this.ctx.config.adapter).forEach(botName => { | ||
loadAllService() { | ||
/* load database before adapters */ | ||
const adapters = this.ctx[core_1.Symbols.adapter]; | ||
Object.keys(this.ctx.config.adapter).forEach((botName) => { | ||
const botConfig = this.ctx.config.adapter[botName]; | ||
if (!(botConfig.extends in adapters)) { | ||
this.ctx.logger.warn(`Cannot find adapter '${botConfig.extends}' for ${botName}`); | ||
const array = adapters.get(botConfig.extends); | ||
if (!array) { | ||
this.ctx.logger.warn(`cannot find adapter '${botConfig.extends}' for ${botName}`); | ||
return; | ||
} | ||
const array = adapters[botConfig.extends]; | ||
const isSchema = array[1]?.parseSafe(botConfig); | ||
if (isSchema && !isSchema.value) { | ||
if (isSchema && !isSchema.value) | ||
return; | ||
} | ||
/* adapter donot support hot reload, so no extends for context */ | ||
const bot = new array[0](this.ctx, isSchema ? isSchema.data : botConfig, botName); | ||
// if (!(botConfig.extend in Adapter)) Adapter.apis[botConfig.extend] = []; // I dont know whats this | ||
// this.ctx.botStack[botConfig.extend].push(bot.api); | ||
bot.start(); | ||
}); /* | ||
const adapters: Adapter[] = []; | ||
Object.values(this.ctx.botStack).forEach(apis => { | ||
apis.forEach(api => adapters.push(api.adapter)); | ||
}); */ | ||
// this.ctx.emit({ type: 'adapters', adapters }); | ||
this.ctx.on('ready', () => bot.start()); | ||
}); | ||
/* load custom services after adapters */ | ||
} | ||
async checkUpdate() { | ||
const { version } = this.ctx.package; | ||
const { version } = this.ctx.pkg; | ||
const res = await this.ctx.http | ||
.get('https://hotaru.icu/api/agent/?url=https://raw.githubusercontent.com/kotorijs/kotori/master/packages/kotori/package.json') | ||
.catch(() => this.ctx.logger.error('Get update failed, please check your network')); | ||
.catch(() => this.ctx.logger.error('get update failed, please check your network')); | ||
if (!res || !core_1.Tsu.Object({ version: core_1.Tsu.String() }).check(res)) { | ||
this.ctx.logger.error(`Detection update failed`); | ||
this.ctx.logger.warn(`detection update failed`); | ||
} | ||
else if (version === res.version) { | ||
this.ctx.logger.log('Kotori is currently the latest version'); | ||
this.ctx.logger.info('kotori is currently the latest version'); | ||
} | ||
else { | ||
this.ctx.logger.warn(`The current version of Kotori is ${version}, and the latest version is ${res.version}. Please go to ${"https://github.com/kotorijs/kotori" /* GLOBAL.REPO */} to update`); | ||
this.ctx.logger.warn(`the current version of Kotori is ${version}, and the latest version is ${res.version}. please go to ${"https://github.com/kotorijs/kotori" /* GLOBAL.REPO */} to update`); | ||
} | ||
} | ||
} | ||
exports.default = Main; | ||
exports.Loader = Loader; | ||
exports.default = Loader; |
@@ -1,3 +0,3 @@ | ||
import type { Context, PackageInfo } from '@kotori-bot/core'; | ||
export declare function loadInfo(info: PackageInfo, ctx: Context): void; | ||
import type { Context } from '@kotori-bot/core'; | ||
export declare function loadInfo(info: Context['pkg'], ctx: Context): void; | ||
export default loadInfo; |
@@ -5,4 +5,4 @@ "use strict"; | ||
function loadInfo(info, ctx) { | ||
console.info('Kotori Bot is loading...'); | ||
console.info(` | ||
process.stdout.write('Kotori Bot is loading...'); | ||
process.stdout.write(` | ||
██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗ | ||
@@ -17,5 +17,5 @@ ██║ ██╔╝██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗██║ | ||
ctx.logger.info(`Kotori Bot By ${info.author}`); | ||
ctx.logger.info(`Copyright © 2023 ${info.author} All rights reserved.`); | ||
ctx.logger.info(`Copyright © 2023 - 2024 ${info.author} All rights reserved`); | ||
} | ||
exports.loadInfo = loadInfo; | ||
exports.default = loadInfo; |
{ | ||
"name": "@kotori-bot/loader", | ||
"version": "v1.2.0", | ||
"version": "v1.3.0", | ||
"description": "Loader For KotoriBot", | ||
@@ -9,11 +9,23 @@ "license": "GPL-3.0", | ||
"dependencies": { | ||
"@kotori-bot/core": "^v1.1.0" | ||
"@kotori-bot/core": "^v1.2.0", | ||
"@kotori-bot/logger": "^v1.1.1" | ||
}, | ||
"keywords": [ | ||
"kotori", | ||
"chatbot", | ||
"loader" | ||
], | ||
"files": [ | ||
"lib" | ||
"lib", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"devDependencies": { | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.1.3" | ||
} | ||
"bugs": { | ||
"url": "https://github.com/kotorijs/kotori/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/kotorijs/kotori.git" | ||
}, | ||
"homepage": "https://kotori.js.org" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
60367
0
573
0
0
1
6
2
2
13
+ Added@kotori-bot/logger@^v1.1.1
+ Added@kotori-bot/logger@1.3.2(transitive)
+ Addeddayjs@1.11.13(transitive)
+ Addedfast-safe-stringify@2.1.1(transitive)
Updated@kotori-bot/core@^v1.2.0