Compare commits

...

17 Commits

Author SHA1 Message Date
jacob
922567ff7b simplify, remove reply option 2023-11-02 15:16:12 -05:00
jacob
17eb701b5f decide not to support error handling for autocomplete 2023-11-02 14:19:43 -05:00
jacob
2b07bcc661 extract & refactor 2023-10-12 12:52:50 -05:00
jacob
a2b7158d24 Merge branch 'main' into feat/errors 2023-10-12 12:35:49 -05:00
Jacob Nguyen
56a74ab32a naive onError handling, not tested 2023-10-04 00:38:18 -05:00
Jacob Nguyen
f2218d02d4 progress on error handling 2023-10-02 22:01:15 -05:00
Jacob Nguyen
e954e2a399 fix merge 2023-10-02 11:07:13 -05:00
jacob
f3ed5354eb add command error builder 2023-09-28 19:42:36 -05:00
Jacob Nguyen
b1263c1c05 update error handling contract and wire more 2023-09-10 23:52:31 -05:00
Jacob Nguyen
0fbabea428 seems to work 2023-09-10 00:36:32 -05:00
Jacob Nguyen
fa66ff7471 wiring 2023-09-09 12:27:07 -05:00
Jacob Nguyen
c7ee2736b8 type alias 2023-09-09 11:39:04 -05:00
Jacob Nguyen
4591471e7e update onError to be record 2023-09-09 11:32:11 -05:00
Jacob Nguyen
374a12bb92 fix error callbacks not being stored 2023-09-09 01:08:56 -05:00
Jacob Nguyen
cafca503f9 wiring onError callback through module loader and resolver 2023-09-08 23:11:46 -05:00
Jacob Nguyen
59e7927816 Merge branch 'main' into feat/errors 2023-09-08 14:19:21 -05:00
jacob
a4848743c2 progress on better error handling 2023-08-29 18:09:31 -05:00
25 changed files with 209 additions and 961 deletions

View File

@@ -1,450 +0,0 @@
/** @type {import('dependency-cruiser').IConfiguration} */
module.exports = {
forbidden: [
/* rules from the 'recommended' preset: */
{
name: 'no-circular',
severity: 'warn',
comment:
'This dependency is part of a circular relationship. You might want to revise ' +
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
from: {},
to: {
circular: true,
},
},
{
name: 'no-orphans',
comment:
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
'add an exception for it in your dependency-cruiser configuration. By default ' +
'this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration ' +
'files (.d.ts), tsconfig.json and some of the babel and webpack configs.',
severity: 'warn',
from: {
orphan: true,
pathNot: [
'(^|/)\\.[^/]+\\.(js|cjs|mjs|ts|json)$', // dot files
'\\.d\\.ts$', // TypeScript declaration files
'(^|/)tsconfig\\.json$', // TypeScript config
'(^|/)(babel|webpack)\\.config\\.(js|cjs|mjs|ts|json)$', // other configs
],
},
to: {},
},
{
name: 'no-deprecated-core',
comment:
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
"bound to exist - node doesn't deprecate lightly.",
severity: 'warn',
from: {},
to: {
dependencyTypes: ['core'],
path: [
'^(v8/tools/codemap)$',
'^(v8/tools/consarray)$',
'^(v8/tools/csvparser)$',
'^(v8/tools/logreader)$',
'^(v8/tools/profile_view)$',
'^(v8/tools/profile)$',
'^(v8/tools/SourceMap)$',
'^(v8/tools/splaytree)$',
'^(v8/tools/tickprocessor-driver)$',
'^(v8/tools/tickprocessor)$',
'^(node-inspect/lib/_inspect)$',
'^(node-inspect/lib/internal/inspect_client)$',
'^(node-inspect/lib/internal/inspect_repl)$',
'^(async_hooks)$',
'^(punycode)$',
'^(domain)$',
'^(constants)$',
'^(sys)$',
'^(_linklist)$',
'^(_stream_wrap)$',
],
},
},
{
name: 'not-to-deprecated',
comment:
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
'version of that module, or find an alternative. Deprecated modules are a security risk.',
severity: 'warn',
from: {},
to: {
dependencyTypes: ['deprecated'],
},
},
{
name: 'no-non-package-json',
severity: 'error',
comment:
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
'available on live with an non-guaranteed version. Fix it by adding the package to the dependencies ' +
'in your package.json.',
from: {},
to: {
dependencyTypes: ['npm-no-pkg', 'npm-unknown'],
},
},
{
name: 'not-to-unresolvable',
comment:
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
'module: add it to your package.json. In all other cases you likely already know what to do.',
severity: 'error',
from: {},
to: {
couldNotResolve: true,
},
},
{
name: 'no-duplicate-dep-types',
comment:
"Likely this module depends on an external ('npm') package that occurs more than once " +
'in your package.json i.e. bot as a devDependencies and in dependencies. This will cause ' +
'maintenance problems later on.',
severity: 'warn',
from: {},
to: {
moreThanOneDependencyType: true,
// as it's pretty common to have a type import be a type only import
// _and_ (e.g.) a devDependency - don't consider type-only dependency
// types for this rule
dependencyTypesNot: ['type-only'],
},
},
/* rules you might want to tweak for your specific situation: */
{
name: 'not-to-test',
comment:
"This module depends on code within a folder that should only contain tests. As tests don't " +
"implement functionality this is odd. Either you're writing a test outside the test folder " +
"or there's something in the test folder that isn't a test.",
severity: 'error',
from: {
pathNot: '^(test)',
},
to: {
path: '^(test)',
},
},
{
name: 'not-to-spec',
comment:
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
severity: 'error',
from: {},
to: {
path: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$',
},
},
{
name: 'not-to-dev-dep',
severity: 'error',
comment:
"This module depends on an npm package from the 'devDependencies' section of your " +
'package.json. It looks like something that ships to production, though. To prevent problems ' +
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
'section of your package.json. If this module is development only - add it to the ' +
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
from: {
path: '^(src)',
pathNot: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$',
},
to: {
dependencyTypes: ['npm-dev'],
},
},
{
name: 'optional-deps-used',
severity: 'info',
comment:
'This module depends on an npm package that is declared as an optional dependency ' +
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
"If you're using an optional dependency here by design - add an exception to your" +
'dependency-cruiser configuration.',
from: {},
to: {
dependencyTypes: ['npm-optional'],
},
},
{
name: 'peer-deps-used',
comment:
'This module depends on an npm package that is declared as a peer dependency ' +
'in your package.json. This makes sense if your package is e.g. a plugin, but in ' +
'other cases - maybe not so much. If the use of a peer dependency is intentional ' +
'add an exception to your dependency-cruiser configuration.',
severity: 'warn',
from: {},
to: {
dependencyTypes: ['npm-peer'],
},
},
],
options: {
/* conditions specifying which files not to follow further when encountered:
- path: a regular expression to match
- dependencyTypes: see https://github.com/sverweij/dependency-cruiser/blob/main/doc/rules-reference.md#dependencytypes-and-dependencytypesnot
for a complete list
*/
doNotFollow: {
path: 'node_modules',
},
/* conditions specifying which dependencies to exclude
- path: a regular expression to match
- dynamic: a boolean indicating whether to ignore dynamic (true) or static (false) dependencies.
leave out if you want to exclude neither (recommended!)
*/
// exclude : {
// path: '',
// dynamic: true
// },
/* pattern specifying which files to include (regular expression)
dependency-cruiser will skip everything not matching this pattern
*/
// includeOnly : '',
/* dependency-cruiser will include modules matching against the focus
regular expression in its output, as well as their neighbours (direct
dependencies and dependents)
*/
// focus : '',
/* list of module systems to cruise */
// moduleSystems: ['amd', 'cjs', 'es6', 'tsd'],
/* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/develop/'
to open it on your online repo or `vscode://file/${process.cwd()}/` to
open it in visual studio code),
*/
// prefix: '',
/* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation
true: also detect dependencies that only exist before typescript-to-javascript compilation
"specify": for each dependency identify whether it only exists before compilation or also after
*/
tsPreCompilationDeps: true,
/*
list of extensions to scan that aren't javascript or compile-to-javascript.
Empty by default. Only put extensions in here that you want to take into
account that are _not_ parsable.
*/
// extraExtensionsToScan: [".json", ".jpg", ".png", ".svg", ".webp"],
/* if true combines the package.jsons found from the module up to the base
folder the cruise is initiated from. Useful for how (some) mono-repos
manage dependencies & dependency definitions.
*/
// combinedDependencies: false,
/* if true leave symlinks untouched, otherwise use the realpath */
// preserveSymlinks: false,
/* TypeScript project file ('tsconfig.json') to use for
(1) compilation and
(2) resolution (e.g. with the paths property)
The (optional) fileName attribute specifies which file to take (relative to
dependency-cruiser's current working directory). When not provided
defaults to './tsconfig.json'.
*/
tsConfig: {
fileName: 'tsconfig.json',
},
/* Webpack configuration to use to get resolve options from.
The (optional) fileName attribute specifies which file to take (relative
to dependency-cruiser's current working directory. When not provided defaults
to './webpack.conf.js'.
The (optional) `env` and `arguments` attributes contain the parameters to be passed if
your webpack config is a function and takes them (see webpack documentation
for details)
*/
// webpackConfig: {
// fileName: './webpack.config.js',
// env: {},
// arguments: {},
// },
/* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use
for compilation (and whatever other naughty things babel plugins do to
source code). This feature is well tested and usable, but might change
behavior a bit over time (e.g. more precise results for used module
systems) without dependency-cruiser getting a major version bump.
*/
// babelConfig: {
// fileName: './.babelrc'
// },
/* List of strings you have in use in addition to cjs/ es6 requires
& imports to declare module dependencies. Use this e.g. if you've
re-declared require, use a require-wrapper or use window.require as
a hack.
*/
// exoticRequireStrings: [],
/* options to pass on to enhanced-resolve, the package dependency-cruiser
uses to resolve module references to disk. You can set most of these
options in a webpack.conf.js - this section is here for those
projects that don't have a separate webpack config file.
Note: settings in webpack.conf.js override the ones specified here.
*/
enhancedResolveOptions: {
/* List of strings to consider as 'exports' fields in package.json. Use
['exports'] when you use packages that use such a field and your environment
supports it (e.g. node ^12.19 || >=14.7 or recent versions of webpack).
If you have an `exportsFields` attribute in your webpack config, that one
will have precedence over the one specified here.
*/
exportsFields: ['exports'],
/* List of conditions to check for in the exports field. e.g. use ['imports']
if you're only interested in exposed es6 modules, ['require'] for commonjs,
or all conditions at once `(['import', 'require', 'node', 'default']`)
if anything goes for you. Only works when the 'exportsFields' array is
non-empty.
If you have a 'conditionNames' attribute in your webpack config, that one will
have precedence over the one specified here.
*/
conditionNames: ['import', 'require', 'node', 'default'],
/*
The extensions, by default are the same as the ones dependency-cruiser
can access (run `npx depcruise --info` to see which ones that are in
_your_ environment. If that list is larger than what you need (e.g.
it contains .js, .jsx, .ts, .tsx, .cts, .mts - but you don't use
TypeScript you can pass just the extensions you actually use (e.g.
[".js", ".jsx"]). This can speed up the most expensive step in
dependency cruising (module resolution) quite a bit.
*/
// extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"],
/*
If your TypeScript project makes use of types specified in 'types'
fields in package.jsons of external dependencies, specify "types"
in addition to "main" in here, so enhanced-resolve (the resolver
dependency-cruiser uses) knows to also look there. You can also do
this if you're not sure, but still use TypeScript. In a future version
of dependency-cruiser this will likely become the default.
*/
mainFields: ['main', 'types'],
},
reporterOptions: {
dot: {
/* pattern of modules that can be consolidated in the detailed
graphical dependency graph. The default pattern in this configuration
collapses everything in node_modules to one folder deep so you see
the external modules, but not the innards your app depends upon.
*/
collapsePattern: 'node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
don't worry - dependency-cruiser will fall back to the default one.
*/
// theme: {
// graph: {
// /* use splines: "ortho" for straight lines. Be aware though
// graphviz might take a long time calculating ortho(gonal)
// routings.
// */
// splines: "true"
// },
// modules: [
// {
// criteria: { matchesFocus: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesFocus: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { matchesReaches: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesReaches: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { source: "^src/model" },
// attributes: { fillcolor: "#ccccff" }
// },
// {
// criteria: { source: "^src/view" },
// attributes: { fillcolor: "#ccffcc" }
// },
// ],
// dependencies: [
// {
// criteria: { "rules[0].severity": "error" },
// attributes: { fontcolor: "red", color: "red" }
// },
// {
// criteria: { "rules[0].severity": "warn" },
// attributes: { fontcolor: "orange", color: "orange" }
// },
// {
// criteria: { "rules[0].severity": "info" },
// attributes: { fontcolor: "blue", color: "blue" }
// },
// {
// criteria: { resolved: "^src/model" },
// attributes: { color: "#0000ff77" }
// },
// {
// criteria: { resolved: "^src/view" },
// attributes: { color: "#00770077" }
// }
// ]
// }
},
archi: {
/* pattern of modules that can be consolidated in the high level
graphical dependency graph. If you use the high level graphical
dependency graph reporter (`archi`) you probably want to tweak
this collapsePattern to your situation.
*/
collapsePattern:
'^(packages|src|lib|app|bin|test(s?)|spec(s?))/[^/]+|node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
for 'archi' dependency-cruiser will use the one specified in the
dot section (see above), if any, and otherwise use the default one.
*/
// theme: {
// },
},
text: {
highlightFocused: true,
},
},
},
};
// generated: dependency-cruiser@13.0.5 on 2023-07-08T03:48:00.632Z

View File

@@ -47,7 +47,6 @@
"@types/node": "^18.15.11",
"@typescript-eslint/eslint-plugin": "5.58.0",
"@typescript-eslint/parser": "5.59.1",
"dependency-cruiser": "^13.0.5",
"discord.js": "14.11.0",
"esbuild": "^0.17.0",
"eslint": "8.39.0",

View File

@@ -1,5 +1,9 @@
{
"extends": ["config:base", "helpers:pinGitHubActionDigests", "group:allNonMajor"],
"extends": [
"config:base",
"helpers:pinGitHubActionDigests",
"group:allNonMajor"
],
"major": {
"dependencyDashboardApproval": true,
"reviewers": ["EvolutionX-10", "jacoobes", "Murtatrxx"]

View File

@@ -1,21 +1,26 @@
import type { CommandModule,Processed, EventModule } from "../../types/core-modules";
/**
* @since 2.0.0
*/
export interface ErrorHandling {
/**
* Number of times the process should throw an error until crashing and exiting
*/
keepAlive: number;
/**
* @deprecated
* Version 4 will remove this method
*/
crash(err: Error): never;
/**
* A function that is called on every crash. Updates keepAlive.
* If keepAlive is 0, the process crashes.
* A function that is called on every throw,
* If and only if the command is not handled properly
* @param error
*/
updateAlive(error: Error): void;
/**
* This callback is called if a module
* handles onError with type 'fail'
*
*/
handleError(error: Error): void;
}

View File

@@ -3,16 +3,26 @@ import type {
CommandModule,
CommandModuleDefs,
Module,
OnError,
} from '../../types/core-modules';
import { CommandType } from '../structures';
/**
* @since 2.0.0
*/
export interface ModuleManager {
get(id: string): string | undefined;
interface MetadataAccess {
getMetadata(m: Module): CommandMeta | undefined;
setMetadata(m: Module, c: CommandMeta): void;
}
interface OnErrorAccess {
getErrorCallback(m: Module): OnError;
setErrorCallback(m: Module, c: NonNullable<OnError>): void;
}
/**
* @since 2.0.0
* @internal - direct access to the module manager will be removed in version 4
*/
export interface ModuleManager extends MetadataAccess, OnErrorAccess {
get(id: string): string | undefined;
set(id: string, path: string): void;
getPublishableCommands(): Promise<CommandModule[]>;
getByNameCommandType<T extends CommandType>(

View File

@@ -1,4 +1,4 @@
import type { CommandMeta, Module } from '../../types/core-modules';
import type { CommandMeta, Module, OnError } from '../../types/core-modules';
/**
* Represents a core module store that stores IDs mapped to file paths.
@@ -6,4 +6,5 @@ import type { CommandMeta, Module } from '../../types/core-modules';
export interface CoreModuleStore {
commands: Map<string, string>;
metadata: WeakMap<Module, CommandMeta>;
onError: WeakMap<Module, NonNullable<OnError>>;
}

View File

@@ -36,7 +36,7 @@ export function partitionPlugins(
export function treeSearch(
iAutocomplete: AutocompleteInteraction,
options: SernOptionsData[] | undefined,
): SernAutocompleteData | undefined {
): SernAutocompleteData & { parent?: string } | undefined {
if (options === undefined) return undefined;
//clone to prevent mutation of original command module
const _options = options.map(a => ({ ...a }));
@@ -68,11 +68,11 @@ export function treeSearch(
const parentAndOptionMatches =
subcommands.has(parent) && cur.name === choice.name;
if (parentAndOptionMatches) {
return cur;
return { ...cur, parent };
}
} else {
if (cur.name === choice.name) {
return cur;
return { ...cur, parent: undefined };
}
}
}

View File

@@ -5,7 +5,7 @@ import { basename, extname, join, resolve, parse } from 'path';
import assert from 'assert';
import { createRequire } from 'node:module';
import type { ImportPayload, Wrapper } from '../types/core';
import type { Module } from '../types/core-modules';
import type { Module, OnError } from '../types/core-modules';
export type ModuleResult<T> = Promise<ImportPayload<T>>;
@@ -23,21 +23,27 @@ export type ModuleResult<T> = Promise<ImportPayload<T>>;
* export default commandModule({})
*/
export async function importModule<T>(absPath: string) {
let module = await import(absPath).then(esm => esm.default);
let fileModule = await import(absPath);
assert(module, `Found no export for module at ${absPath}. Forgot to ignore with "!"? (!${basename(absPath)})?`);
if ('default' in module) {
module = module.default;
let commandModule = fileModule.default,
onError = fileModule.onError;
assert(commandModule , `Found no export @ ${absPath}. Forgot to ignore with "!"? (!${basename(absPath)})?`);
if ('default' in commandModule ) {
commandModule = commandModule.default;
}
return Result
.wrap(() => module.getInstance())
.unwrapOr(module) as T;
.wrap(() => ({ module: commandModule.getInstance(), onError }))
.unwrapOr({ module: commandModule, onError }) as T;
}
interface FileExtras {
onError : OnError
}
export async function defaultModuleLoader<T extends Module>(absPath: string): ModuleResult<T> {
let module = await importModule<T>(absPath);
let { onError, module } = await importModule<{ module: T } & FileExtras>(absPath);
assert(module, `Found an undefined module: ${absPath}`);
return { module, absPath };
return { module, absPath, onError };
}
export const fmtFileName = (fileName: string) => parse(fileName).name;
@@ -51,7 +57,8 @@ export const fmtFileName = (fileName: string) => parse(fileName).name;
export function buildModuleStream<T extends Module>(
input: ObservableInput<string>,
): Observable<ImportPayload<T>> {
return from(input).pipe(mergeMap(defaultModuleLoader<T>));
return from(input)
.pipe(mergeMap(defaultModuleLoader<T>));
}
export const getFullPathTree = (dir: string) => readPaths(resolve(dir));

View File

@@ -0,0 +1,6 @@
import type { Logging } from "../contracts";
export interface Response {
type: 'fail' | 'handled';
log?: { type: keyof Logging; message: unknown }
}

View File

@@ -11,8 +11,8 @@ import {
import { CoreContext } from '../structures/core-context';
import { Result, Ok, Err } from 'ts-results-es';
import * as assert from 'assert';
import { ReplyOptions } from '../../types/utility';
type ReplyOptions = string | Omit<InteractionReplyOptions, 'fetchReply'> | MessageReplyOptions;
/**
* @since 1.0.0
@@ -103,9 +103,9 @@ export class Context extends CoreContext<Message, ChatInputCommandInteraction> {
public async reply(content: ReplyOptions) {
return safeUnwrap(
this.ctx
.map(m => m.reply(content as string | MessageReplyOptions))
.map(m => m.reply(content as MessageReplyOptions))
.mapErr(i =>
i.reply(content as string | InteractionReplyOptions).then(() => i.fetchReply()),
i.reply(content as InteractionReplyOptions).then(() => i.fetchReply()),
),
);
}

View File

@@ -3,3 +3,4 @@ export * from './context';
export * from './sern-emitter';
export * from './services';
export * from './module-store';
export * as CommandError from './command-error';

View File

@@ -1,4 +1,4 @@
import { CommandMeta, Module } from '../../types/core-modules';
import { CommandMeta, Module, OnError } from '../../types/core-modules';
import { CoreModuleStore } from '../contracts';
/*
@@ -7,6 +7,7 @@ import { CoreModuleStore } from '../contracts';
* For interacting with modules, use the ModuleManager instead.
*/
export class ModuleStore implements CoreModuleStore {
onError = new WeakMap<Module, NonNullable<OnError>>();
metadata = new WeakMap<Module, CommandMeta>();
commands = new Map<string, string>();
}

View File

@@ -3,18 +3,18 @@ import { ErrorHandling } from '../../contracts';
/**
* @internal
* @since 2.0.0
* Version 4.0.0 will internalize this api. Please refrain from using ModuleStore!
* Version 4.0.0 will internalize this api. Please refrain from using the defaults!
*/
export class DefaultErrorHandling implements ErrorHandling {
crash(err: Error): never {
throw err;
}
keepAlive = 5;
#keepAlive = 5;
updateAlive(err: Error) {
this.keepAlive--;
if (this.keepAlive === 0) {
this.#keepAlive--;
if (this.#keepAlive === 0) {
throw err;
}
}

View File

@@ -1,7 +1,7 @@
import * as Id from '../../../core/id';
import { CoreModuleStore, ModuleManager } from '../../contracts';
import { Files } from '../../_internal';
import { CommandMeta, CommandModule, CommandModuleDefs, Module } from '../../../types/core-modules';
import { CommandMeta, CommandModule, CommandModuleDefs, Module, OnError } from '../../../types/core-modules';
import { CommandType } from '../enums';
/**
* @internal
@@ -11,6 +11,14 @@ import { CommandType } from '../enums';
export class DefaultModuleManager implements ModuleManager {
constructor(private moduleStore: CoreModuleStore) {}
getErrorCallback(m: Module): OnError {
return this.moduleStore.onError.get(m);
}
setErrorCallback(m: Module, c: NonNullable<OnError>): void {
this.moduleStore.onError.set(m, c);
}
getByNameCommandType<T extends CommandType>(name: string, commandType: T) {
const id = this.get(Id.create(name, commandType));
if (!id) {

View File

@@ -9,20 +9,11 @@ import {
SernError,
} from '../core/_internal';
import { createResultResolver } from './event-utils';
import { AutocompleteInteraction, BaseInteraction, Message } from 'discord.js';
import { BaseInteraction, Message } from 'discord.js';
import { CommandType, Context } from '../core';
import type { Args } from '../types/utility';
import type { BothCommand, CommandModule, Module, Processed } from '../types/core-modules';
import type { AnyFunction, Args } from '../types/utility';
import type { CommandModule, Module, OnError, Processed } from '../types/core-modules';
function dispatchInteraction<T extends CommandModule, V extends BaseInteraction | Message>(
payload: { module: Processed<T>; event: V },
createArgs: (m: typeof payload.event) => unknown[],
) {
return {
module: payload.module,
args: createArgs(payload.event),
};
}
//TODO: refactor dispatchers so that it implements a strategy for each different type of payload?
export function dispatchMessage(module: Processed<CommandModule>, args: [Context, Args]) {
return {
@@ -31,21 +22,6 @@ export function dispatchMessage(module: Processed<CommandModule>, args: [Context
};
}
function dispatchAutocomplete(payload: {
module: Processed<BothCommand>;
event: AutocompleteInteraction;
}) {
const option = treeSearch(payload.event, payload.module.options);
assert.ok(
option,
Error(SernError.NotSupportedInteraction + ` There is no autocomplete tag for this option`),
);
return {
module: option.command as Processed<Module>, //autocomplete is not a true "module" warning cast!
args: [payload.event],
};
}
export function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) {
const ctx = Context.wrap(wrappable);
const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options];
@@ -56,16 +32,16 @@ function interactionArg<T extends BaseInteraction>(interaction: T) {
return [interaction] as [T];
}
function intoPayload(module: Processed<Module>) {
function intoPayload(module: Processed<Module>, onError: AnyFunction|undefined) {
return pipe(
arrayifySource,
map(args => ({ module, args })),
map(args => ({ module, args, onError })),
);
}
const createResult = createResultResolver<
Processed<Module>,
{ module: Processed<Module>; args: unknown[] },
{ module: Processed<Module>; args: unknown[], onError: AnyFunction|undefined },
unknown[]
>({
createStream: ({ module, args }) => from(module.onEvent).pipe(callPlugin(args)),
@@ -76,14 +52,14 @@ const createResult = createResultResolver<
* @param module
* @param source
*/
export function eventDispatcher(module: Processed<Module>, source: unknown) {
export function eventDispatcher(module: Processed<Module>, onError: OnError, source: unknown) {
assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`);
const execute: OperatorFunction<unknown[], unknown> = concatMap(async args =>
module.execute(...args),
);
return fromEvent(source, module.name).pipe(
intoPayload(module),
intoPayload(module, onError),
concatMap(createResult),
execute,
);
@@ -92,6 +68,7 @@ export function eventDispatcher(module: Processed<Module>, source: unknown) {
export function createDispatcher(payload: {
module: Processed<CommandModule>;
event: BaseInteraction;
onError: OnError
}) {
assert.ok(
CommandType.Text !== payload.module.type,
@@ -101,17 +78,30 @@ export function createDispatcher(payload: {
case CommandType.Slash:
case CommandType.Both: {
if (isAutocomplete(payload.event)) {
/**
* Autocomplete is a special case that
* must be handled separately, since it's
* too different from regular command modules
* CAST SAFETY: payload is already guaranteed to be a slash command or both command
*/
return dispatchAutocomplete(payload as never);
const option = treeSearch(payload.event, payload.module.options);
assert.ok(
option,
Error(SernError.NotSupportedInteraction + ` There is no autocomplete tag for this option`),
);
const { command } = option;
return {
...payload,
module: command as Processed<Module>, //autocomplete is not a true "module" warning cast!
args: [payload.event],
onError: undefined
};
}
return dispatchInteraction(payload, contextArgs);
return {
args: contextArgs(payload.event),
...payload,
onError: payload.onError
};
}
default:
return dispatchInteraction(payload, interactionArg);
return {
args: interactionArg(payload.event),
...payload,
onError: payload.onError
}
}
}

View File

@@ -23,15 +23,16 @@ import {
VoidResult,
useContainerRaw,
} from '../core/_internal';
import { Emitter, ErrorHandling, Logging, ModuleManager } from '../core';
import { contextArgs, createDispatcher, dispatchMessage } from './dispatchers';
import { CommandError, Emitter, ErrorHandling, Logging, ModuleManager } from '../core';
import { contextArgs, createDispatcher } from './dispatchers';
import { ObservableInput, pipe } from 'rxjs';
import { SernEmitter } from '../core';
import { Err, Ok, Result } from 'ts-results-es';
import type { Awaitable } from '../types/utility';
import type { AnyFunction, Awaitable } from '../types/utility';
import type { ControlPlugin } from '../types/core-plugin';
import type { AnyModule, CommandModule, Module, Processed } from '../types/core-modules';
import type { AnyModule, CommandModule, Module, OnError, Processed } from '../types/core-modules';
import type { ImportPayload } from '../types/core';
import assert from 'node:assert';
function createGenericHandler<Source, Narrowed extends Source, Output>(
source: Observable<Source>,
@@ -78,8 +79,11 @@ export function createInteractionHandler<T extends Interaction>(
return Files
.defaultModuleLoader<Processed<CommandModule>>(fullPath)
.then(payload =>
Ok(createDispatcher({ module: payload.module, event }))
);
Ok(createDispatcher({
module: payload.module,
onError: payload.onError,
event,
})));
},
);
}
@@ -94,13 +98,13 @@ export function createMessageHandler(
const fullPath = mg.get(`${prefix}_A1`);
if(!fullPath) {
return Err('Possibly undefined behavior: could not find a static id to resolve ')
return Err('Possibly undefined behavior: could not find a static id to resolve')
}
return Files
.defaultModuleLoader<Processed<CommandModule>>(fullPath)
.then(payload => {
const args = contextArgs(event, rest);
return Ok(dispatchMessage(payload.module, args));
return Ok({ args, ...payload });
});
});
}
@@ -129,6 +133,13 @@ export function buildModules<T extends AnyModule>(
return Files.buildModuleStream<Processed<T>>(input).pipe(assignDefaults(moduleManager));
}
interface ExecutePayload {
module: Processed<Module>;
task: () => Awaitable<unknown>;
onError: AnyFunction|undefined
args: unknown[]
}
/**
* Wraps the task in a Result as a try / catch.
* if the task is ok, an event is emitted and the stream becomes empty
@@ -139,14 +150,36 @@ export function buildModules<T extends AnyModule>(
*/
export function executeModule(
emitter: Emitter,
logger: Logging|undefined,
errHandler: ErrorHandling,
{
module,
task,
}: {
module: Processed<Module>;
task: () => Awaitable<unknown>;
},
onError,
args
}: ExecutePayload,
) {
const onError$ = (err_msg: unknown) => {
if(!onError) {
return throwError(() => SernEmitter.failure(module, err));
}
//Could be promise
const err = onError(err_msg) as CommandError.Response
if(!err) {
const failure = SernEmitter.failure(module, "onError: returned undefined/null");
return throwError(() => failure);
}
if(err.log) {
const { type, message } = err.log;
logger?.[type]({ message });
};
if(err.type === 'fail') {
} else {
}
return EMPTY;
}
return of(module).pipe(
//converting the task into a promise so rxjs can resolve the Awaitable properly
concatMap(() => Result.wrapAsync(async () => task())),
@@ -154,9 +187,8 @@ export function executeModule(
if (result.isOk()) {
emitter.emit('module.activate', SernEmitter.success(module));
return EMPTY;
} else {
return throwError(() => SernEmitter.failure(module, result.error));
}
return onError$(result.error);
}),
);
}
@@ -172,7 +204,7 @@ export function executeModule(
*/
export function createResultResolver<
T extends { execute: (...args: any[]) => any; onEvent: ControlPlugin[] },
Args extends { module: T; [key: string]: unknown },
Args extends { module: T; onError: unknown, [key: string]: unknown },
Output,
>(config: {
onStop?: (module: T) => unknown;
@@ -205,9 +237,9 @@ export function callInitPlugins<T extends Processed<AnyModule>>(sernEmitter: Emi
SernEmitter.failure(module, SernError.PluginFailure),
);
},
onNext: ({ module }) => {
onNext: ({ module, onError }) => {
sernEmitter.emit('module.register', SernEmitter.success(module));
return module;
return { module, onError: onError as OnError };
},
}),
);
@@ -219,16 +251,24 @@ export function callInitPlugins<T extends Processed<AnyModule>>(sernEmitter: Emi
*/
export function makeModuleExecutor<
M extends Processed<Module>,
Args extends { module: M; args: unknown[] },
Args extends {
module: M;
args: unknown[];
onError: AnyFunction|undefined
},
>(onStop: (m: M) => unknown) {
const onNext = ({ args, module }: Args) => ({
const onNext = ({ args, module, onError }: Args) => ({
task: () => module.execute(...args),
module,
onError,
args
});
return concatMap(
createResultResolver({
onStop,
createStream: ({ args, module }) => from(module.onEvent).pipe(callPlugin(args)),
createStream: ({ args, module }) =>
from(module.onEvent)
.pipe(callPlugin(args)),
onNext,
}),
);

View File

@@ -13,7 +13,7 @@ import {
import { createInteractionHandler, executeModule, makeModuleExecutor } from './_internal';
import type { DependencyList } from '../types/ioc';
export function interactionHandler([emitter, , , modules, client]: DependencyList) {
export function interactionHandler([emitter, err, log, modules, client]: DependencyList) {
const interactionStream$ = sharedEventStream<Interaction>(client, 'interactionCreate');
const handle = createInteractionHandler(interactionStream$, modules);
@@ -28,6 +28,6 @@ export function interactionHandler([emitter, , , modules, client]: DependencyLis
filterTap(e => emitter.emit('warning', SernEmitter.warning(e))),
makeModuleExecutor(module =>
emitter.emit('module.activate', SernEmitter.failure(module, SernError.PluginFailure))),
concatMap(payload => executeModule(emitter, payload)),
concatMap(payload => executeModule(emitter, log, err, payload)),
);
}

View File

@@ -23,7 +23,7 @@ function hasPrefix(prefix: string, content: string) {
}
export function messageHandler(
[emitter, , log, modules, client]: DependencyList,
[emitter, err, log, modules, client]: DependencyList,
defaultPrefix: string | undefined,
) {
if (!defaultPrefix) {
@@ -42,6 +42,6 @@ export function messageHandler(
makeModuleExecutor(module => {
emitter.emit('module.activate', SernEmitter.failure(module, SernError.PluginFailure));
}),
concatMap(payload => executeModule(emitter, payload)),
concatMap(payload => executeModule(emitter, log, err, payload)),
);
}

View File

@@ -17,10 +17,9 @@ export function startReadyEvent(
return concat(ready$, buildModules<AnyModule>(allPaths, moduleManager))
.pipe(callInitPlugins(sEmitter))
.subscribe(module => {
register(moduleManager, module).expect(
SernError.InvalidModuleType + ' ' + util.inspect(module),
);
.subscribe(({ module }) => {
register(moduleManager, module)
.expect(SernError.InvalidModuleType + ' ' + util.inspect(module));
});
}

View File

@@ -4,21 +4,21 @@ import { SernError } from '../core/_internal';
import { buildModules, callInitPlugins, handleCrash, eventDispatcher } from './_internal';
import { Service } from '../core/ioc';
import type { DependencyList } from '../types/ioc';
import type { CommandModule, EventModule, Processed } from '../types/core-modules';
import type { EventModule, OnError, Processed } from '../types/core-modules';
export function eventsHandler(
[emitter, err, log, moduleManager, client]: DependencyList,
allPaths: ObservableInput<string>,
) {
//code smell
const intoDispatcher = (e: Processed<EventModule | CommandModule>) => {
switch (e.type) {
const intoDispatcher = (e: { module: Processed<EventModule>, onError: OnError }) => {
switch (e.module.type) {
case EventType.Sern:
return eventDispatcher(e, emitter);
return eventDispatcher(e.module, e.onError, emitter);
case EventType.Discord:
return eventDispatcher(e, client);
return eventDispatcher(e.module, e.onError, client);
case EventType.External:
return eventDispatcher(e, Service(e.emitter));
return eventDispatcher(e.module, e.onError, Service(e.module.emitter));
default:
throw Error(SernError.InvalidModuleType + ' while creating event handler');
}
@@ -31,7 +31,6 @@ export function eventsHandler(
* Where all events are turned on
*/
mergeAll(),
handleCrash(err, log),
)
handleCrash(err, log))
.subscribe();
}

View File

@@ -17,7 +17,10 @@ import type {
} from 'discord.js';
import { CommandType, Context, EventType } from '../../src/core';
import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin';
import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility';
import { Awaitable, Args, SlashOptions, SernEventsMapping, AnyFunction } from './utility';
export type OnError = AnyFunction|undefined
export interface CommandMeta {
fullPath: string;

View File

@@ -1,6 +1,9 @@
import { OnError } from "./core-modules";
export interface ImportPayload<T> {
module: T;
absPath: string;
onError: OnError
[key: string]: unknown;
}

View File

@@ -1,6 +1,6 @@
import { CommandInteractionOptionResolver } from 'discord.js';
import { PayloadType } from '../core';
import { AnyModule } from './core-modules';
import type { CommandInteractionOptionResolver, InteractionReplyOptions, MessageReplyOptions } from 'discord.js';
import type { PayloadType } from '../core';
import type { AnyModule } from './core-modules';
export type Awaitable<T> = PromiseLike<T> | T;
@@ -27,3 +27,7 @@ export type Payload =
| { type: PayloadType.Success; module: AnyModule }
| { type: PayloadType.Failure; module?: AnyModule; reason: string | Error }
| { type: PayloadType.Warning; reason: string };
export type ReplyOptions = string | Omit<InteractionReplyOptions, 'fetchReply'> | MessageReplyOptions;

View File

@@ -3,8 +3,6 @@
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"noImplicitAny": true,
"experimentalDecorators": true,
"strictNullChecks": true,
"moduleResolution": "node",
"skipLibCheck": true,

400
yarn.lock
View File

@@ -612,7 +612,6 @@ __metadata:
"@types/node": ^18.15.11
"@typescript-eslint/eslint-plugin": 5.58.0
"@typescript-eslint/parser": 5.59.1
dependency-cruiser: ^13.0.5
discord.js: 14.11.0
esbuild: ^0.17.0
eslint: 8.39.0
@@ -933,14 +932,7 @@ __metadata:
languageName: node
linkType: hard
"acorn-jsx-walk@npm:2.0.0":
version: 2.0.0
resolution: "acorn-jsx-walk@npm:2.0.0"
checksum: 49417eab5bb595c1cdc96d64205eda7cc58f32d655068826ba96ec7a4dc4f957d55ca9e62a299d0dbdeae71c6dc518be1378c21d3b720e741812f55f2a13c937
languageName: node
linkType: hard
"acorn-jsx@npm:5.3.2, acorn-jsx@npm:^5.3.2":
"acorn-jsx@npm:^5.3.2":
version: 5.3.2
resolution: "acorn-jsx@npm:5.3.2"
peerDependencies:
@@ -949,23 +941,14 @@ __metadata:
languageName: node
linkType: hard
"acorn-loose@npm:8.3.0":
version: 8.3.0
resolution: "acorn-loose@npm:8.3.0"
dependencies:
acorn: ^8.5.0
checksum: 3418a20bded1e74a20950dee8289fb87808c21a50d4065e4ec48230668ea77f4238be1dd1ee30b2116f469e496bcdaf937ccb86d469482e028052f8eec804c07
languageName: node
linkType: hard
"acorn-walk@npm:8.2.0, acorn-walk@npm:^8.2.0":
"acorn-walk@npm:^8.2.0":
version: 8.2.0
resolution: "acorn-walk@npm:8.2.0"
checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1
languageName: node
linkType: hard
"acorn@npm:8.10.0, acorn@npm:^8.10.0, acorn@npm:^8.5.0, acorn@npm:^8.9.0":
"acorn@npm:^8.10.0, acorn@npm:^8.9.0":
version: 8.10.0
resolution: "acorn@npm:8.10.0"
bin:
@@ -1002,18 +985,6 @@ __metadata:
languageName: node
linkType: hard
"ajv@npm:8.12.0":
version: 8.12.0
resolution: "ajv@npm:8.12.0"
dependencies:
fast-deep-equal: ^3.1.1
json-schema-traverse: ^1.0.0
require-from-string: ^2.0.2
uri-js: ^4.2.2
checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001
languageName: node
linkType: hard
"ajv@npm:^6.10.0, ajv@npm:^6.12.4":
version: 6.12.6
resolution: "ajv@npm:6.12.6"
@@ -1229,14 +1200,7 @@ __metadata:
languageName: node
linkType: hard
"chalk@npm:5.3.0":
version: 5.3.0
resolution: "chalk@npm:5.3.0"
checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80
languageName: node
linkType: hard
"chalk@npm:^4.0.0, chalk@npm:^4.1.0":
"chalk@npm:^4.0.0":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
dependencies:
@@ -1311,13 +1275,6 @@ __metadata:
languageName: node
linkType: hard
"commander@npm:11.0.0":
version: 11.0.0
resolution: "commander@npm:11.0.0"
checksum: 6621954e1e1d078b4991c1f5bbd9439ad37aa7768d6ab4842de1dbd4d222c8a27e1b8e62108b3a92988614af45031d5bb2a2aaa92951f4d0c934d1a1ac564bb4
languageName: node
linkType: hard
"commander@npm:^4.0.0":
version: 4.1.1
resolution: "commander@npm:4.1.1"
@@ -1385,47 +1342,6 @@ __metadata:
languageName: node
linkType: hard
"dependency-cruiser@npm:^13.0.5":
version: 13.1.5
resolution: "dependency-cruiser@npm:13.1.5"
dependencies:
acorn: 8.10.0
acorn-jsx: 5.3.2
acorn-jsx-walk: 2.0.0
acorn-loose: 8.3.0
acorn-walk: 8.2.0
ajv: 8.12.0
chalk: 5.3.0
commander: 11.0.0
enhanced-resolve: 5.15.0
figures: 5.0.0
glob: 10.3.3
ignore: 5.2.4
indent-string: 5.0.0
interpret: ^3.1.1
is-installed-globally: 0.4.0
json5: 2.2.3
lodash: 4.17.21
prompts: 2.4.2
rechoir: ^0.8.0
safe-regex: 2.1.1
semver: ^7.5.4
semver-try-require: 6.2.3
teamcity-service-messages: 0.1.14
tsconfig-paths-webpack-plugin: 4.1.0
watskeburt: 1.0.1
wrap-ansi: 8.1.0
bin:
depcruise: bin/dependency-cruise.mjs
depcruise-baseline: bin/depcruise-baseline.mjs
depcruise-fmt: bin/depcruise-fmt.mjs
depcruise-wrap-stream-in-html: bin/wrap-stream-in-html.mjs
dependency-cruise: bin/dependency-cruise.mjs
dependency-cruiser: bin/dependency-cruise.mjs
checksum: a1f2b1dbc97e6fecffbcf2637535231c7df9fbf62520ec0ca9becd3a6c8d9827973af1386a9af77896445fa30608e601b060d649f7ab06b9159b8b5ae9ed2ce6
languageName: node
linkType: hard
"diff-sequences@npm:^29.4.3":
version: 29.6.3
resolution: "diff-sequences@npm:29.6.3"
@@ -1517,16 +1433,6 @@ __metadata:
languageName: node
linkType: hard
"enhanced-resolve@npm:5.15.0, enhanced-resolve@npm:^5.7.0":
version: 5.15.0
resolution: "enhanced-resolve@npm:5.15.0"
dependencies:
graceful-fs: ^4.2.4
tapable: ^2.2.0
checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11
languageName: node
linkType: hard
"env-paths@npm:^2.2.0":
version: 2.2.1
resolution: "env-paths@npm:2.2.1"
@@ -1702,13 +1608,6 @@ __metadata:
languageName: node
linkType: hard
"escape-string-regexp@npm:^5.0.0":
version: 5.0.0
resolution: "escape-string-regexp@npm:5.0.0"
checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e
languageName: node
linkType: hard
"eslint-scope@npm:^5.1.1":
version: 5.1.1
resolution: "eslint-scope@npm:5.1.1"
@@ -1903,16 +1802,6 @@ __metadata:
languageName: node
linkType: hard
"figures@npm:5.0.0":
version: 5.0.0
resolution: "figures@npm:5.0.0"
dependencies:
escape-string-regexp: ^5.0.0
is-unicode-supported: ^1.2.0
checksum: e6e8b6d1df2f554d4effae4a5ceff5d796f9449f6d4e912d74dab7d5f25916ecda6c305b9084833157d56485a0c78b37164430ddc5675bcee1330e346710669e
languageName: node
linkType: hard
"file-entry-cache@npm:^6.0.1":
version: 6.0.1
resolution: "file-entry-cache@npm:6.0.1"
@@ -2024,13 +1913,6 @@ __metadata:
languageName: node
linkType: hard
"function-bind@npm:^1.1.1":
version: 1.1.1
resolution: "function-bind@npm:1.1.1"
checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a
languageName: node
linkType: hard
"gauge@npm:^4.0.3":
version: 4.0.4
resolution: "gauge@npm:4.0.4"
@@ -2079,21 +1961,6 @@ __metadata:
languageName: node
linkType: hard
"glob@npm:10.3.3":
version: 10.3.3
resolution: "glob@npm:10.3.3"
dependencies:
foreground-child: ^3.1.0
jackspeak: ^2.0.3
minimatch: ^9.0.1
minipass: ^5.0.0 || ^6.0.2 || ^7.0.0
path-scurry: ^1.10.1
bin:
glob: dist/cjs/src/bin.js
checksum: 29190d3291f422da0cb40b77a72fc8d2c51a36524e99b8bf412548b7676a6627489528b57250429612b6eec2e6fe7826d328451d3e694a9d15e575389308ec53
languageName: node
linkType: hard
"glob@npm:7.1.6":
version: 7.1.6
resolution: "glob@npm:7.1.6"
@@ -2137,15 +2004,6 @@ __metadata:
languageName: node
linkType: hard
"global-dirs@npm:^3.0.0":
version: 3.0.1
resolution: "global-dirs@npm:3.0.1"
dependencies:
ini: 2.0.0
checksum: 70147b80261601fd40ac02a104581432325c1c47329706acd773f3a6ce99bb36d1d996038c85ccacd482ad22258ec233c586b6a91535b1a116b89663d49d6438
languageName: node
linkType: hard
"globals@npm:^13.19.0":
version: 13.21.0
resolution: "globals@npm:13.21.0"
@@ -2169,7 +2027,7 @@ __metadata:
languageName: node
linkType: hard
"graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6":
"graceful-fs@npm:^4.2.6":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7
@@ -2197,15 +2055,6 @@ __metadata:
languageName: node
linkType: hard
"has@npm:^1.0.3":
version: 1.0.3
resolution: "has@npm:1.0.3"
dependencies:
function-bind: ^1.1.1
checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792
languageName: node
linkType: hard
"http-cache-semantics@npm:^4.1.1":
version: 4.1.1
resolution: "http-cache-semantics@npm:4.1.1"
@@ -2266,7 +2115,7 @@ __metadata:
languageName: node
linkType: hard
"ignore@npm:5.2.4, ignore@npm:^5.2.0":
"ignore@npm:^5.2.0":
version: 5.2.4
resolution: "ignore@npm:5.2.4"
checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef
@@ -2290,13 +2139,6 @@ __metadata:
languageName: node
linkType: hard
"indent-string@npm:5.0.0":
version: 5.0.0
resolution: "indent-string@npm:5.0.0"
checksum: e466c27b6373440e6d84fbc19e750219ce25865cb82d578e41a6053d727e5520dc5725217d6eb1cc76005a1bb1696a0f106d84ce7ebda3033b963a38583fb3b3
languageName: node
linkType: hard
"indent-string@npm:^4.0.0":
version: 4.0.0
resolution: "indent-string@npm:4.0.0"
@@ -2321,20 +2163,6 @@ __metadata:
languageName: node
linkType: hard
"ini@npm:2.0.0":
version: 2.0.0
resolution: "ini@npm:2.0.0"
checksum: e7aadc5fb2e4aefc666d74ee2160c073995a4061556b1b5b4241ecb19ad609243b9cceafe91bae49c219519394bbd31512516cb22a3b1ca6e66d869e0447e84e
languageName: node
linkType: hard
"interpret@npm:^3.1.1":
version: 3.1.1
resolution: "interpret@npm:3.1.1"
checksum: 35cebcf48c7351130437596d9ab8c8fe131ce4038da4561e6d665f25640e0034702a031cf7e3a5cea60ac7ac548bf17465e0571ede126f3d3a6933152171ac82
languageName: node
linkType: hard
"ip@npm:^2.0.0":
version: 2.0.0
resolution: "ip@npm:2.0.0"
@@ -2351,15 +2179,6 @@ __metadata:
languageName: node
linkType: hard
"is-core-module@npm:^2.13.0":
version: 2.13.0
resolution: "is-core-module@npm:2.13.0"
dependencies:
has: ^1.0.3
checksum: 053ab101fb390bfeb2333360fd131387bed54e476b26860dc7f5a700bbf34a0ec4454f7c8c4d43e8a0030957e4b3db6e16d35e1890ea6fb654c833095e040355
languageName: node
linkType: hard
"is-extglob@npm:^2.1.1":
version: 2.1.1
resolution: "is-extglob@npm:2.1.1"
@@ -2383,16 +2202,6 @@ __metadata:
languageName: node
linkType: hard
"is-installed-globally@npm:0.4.0":
version: 0.4.0
resolution: "is-installed-globally@npm:0.4.0"
dependencies:
global-dirs: ^3.0.0
is-path-inside: ^3.0.2
checksum: 3359840d5982d22e9b350034237b2cda2a12bac1b48a721912e1ab8e0631dd07d45a2797a120b7b87552759a65ba03e819f1bd63f2d7ab8657ec0b44ee0bf399
languageName: node
linkType: hard
"is-lambda@npm:^1.0.1":
version: 1.0.1
resolution: "is-lambda@npm:1.0.1"
@@ -2407,7 +2216,7 @@ __metadata:
languageName: node
linkType: hard
"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3":
"is-path-inside@npm:^3.0.3":
version: 3.0.3
resolution: "is-path-inside@npm:3.0.3"
checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9
@@ -2421,13 +2230,6 @@ __metadata:
languageName: node
linkType: hard
"is-unicode-supported@npm:^1.2.0":
version: 1.3.0
resolution: "is-unicode-supported@npm:1.3.0"
checksum: 20a1fc161afafaf49243551a5ac33b6c4cf0bbcce369fcd8f2951fbdd000c30698ce320de3ee6830497310a8f41880f8066d440aa3eb0a853e2aa4836dd89abc
languageName: node
linkType: hard
"isexe@npm:^2.0.0":
version: 2.0.0
resolution: "isexe@npm:2.0.0"
@@ -2496,13 +2298,6 @@ __metadata:
languageName: node
linkType: hard
"json-schema-traverse@npm:^1.0.0":
version: 1.0.0
resolution: "json-schema-traverse@npm:1.0.0"
checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad
languageName: node
linkType: hard
"json-stable-stringify-without-jsonify@npm:^1.0.1":
version: 1.0.1
resolution: "json-stable-stringify-without-jsonify@npm:1.0.1"
@@ -2510,15 +2305,6 @@ __metadata:
languageName: node
linkType: hard
"json5@npm:2.2.3, json5@npm:^2.2.2":
version: 2.2.3
resolution: "json5@npm:2.2.3"
bin:
json5: lib/cli.js
checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349
languageName: node
linkType: hard
"jsonc-parser@npm:^3.2.0":
version: 3.2.0
resolution: "jsonc-parser@npm:3.2.0"
@@ -2535,13 +2321,6 @@ __metadata:
languageName: node
linkType: hard
"kleur@npm:^3.0.3":
version: 3.0.3
resolution: "kleur@npm:3.0.3"
checksum: df82cd1e172f957bae9c536286265a5cdbd5eeca487cb0a3b2a7b41ef959fc61f8e7c0e9aeea9c114ccf2c166b6a8dd45a46fd619c1c569d210ecd2765ad5169
languageName: node
linkType: hard
"levn@npm:^0.4.1":
version: 0.4.1
resolution: "levn@npm:0.4.1"
@@ -2610,7 +2389,7 @@ __metadata:
languageName: node
linkType: hard
"lodash@npm:4.17.21, lodash@npm:^4.17.21":
"lodash@npm:^4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7
@@ -2730,13 +2509,6 @@ __metadata:
languageName: node
linkType: hard
"minimist@npm:^1.2.6":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0
languageName: node
linkType: hard
"minipass-collect@npm:^1.0.2":
version: 1.0.2
resolution: "minipass-collect@npm:1.0.2"
@@ -3062,13 +2834,6 @@ __metadata:
languageName: node
linkType: hard
"path-parse@npm:^1.0.7":
version: 1.0.7
resolution: "path-parse@npm:1.0.7"
checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a
languageName: node
linkType: hard
"path-scurry@npm:^1.10.1":
version: 1.10.1
resolution: "path-scurry@npm:1.10.1"
@@ -3205,16 +2970,6 @@ __metadata:
languageName: node
linkType: hard
"prompts@npm:2.4.2":
version: 2.4.2
resolution: "prompts@npm:2.4.2"
dependencies:
kleur: ^3.0.3
sisteransi: ^1.0.5
checksum: d8fd1fe63820be2412c13bfc5d0a01909acc1f0367e32396962e737cb2fc52d004f3302475d5ce7d18a1e8a79985f93ff04ee03007d091029c3f9104bffc007d
languageName: node
linkType: hard
"punycode@npm:^2.1.0":
version: 2.3.0
resolution: "punycode@npm:2.3.0"
@@ -3265,31 +3020,6 @@ __metadata:
languageName: node
linkType: hard
"rechoir@npm:^0.8.0":
version: 0.8.0
resolution: "rechoir@npm:0.8.0"
dependencies:
resolve: ^1.20.0
checksum: ad3caed8afdefbc33fbc30e6d22b86c35b3d51c2005546f4e79bcc03c074df804b3640ad18945e6bef9ed12caedc035655ec1082f64a5e94c849ff939dc0a788
languageName: node
linkType: hard
"regexp-tree@npm:~0.1.1":
version: 0.1.27
resolution: "regexp-tree@npm:0.1.27"
bin:
regexp-tree: bin/regexp-tree
checksum: 129aebb34dae22d6694ab2ac328be3f99105143737528ab072ef624d599afecbcfae1f5c96a166fa9e5f64fa1ecf30b411c4691e7924c3e11bbaf1712c260c54
languageName: node
linkType: hard
"require-from-string@npm:^2.0.2":
version: 2.0.2
resolution: "require-from-string@npm:2.0.2"
checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b
languageName: node
linkType: hard
"resolve-from@npm:^4.0.0":
version: 4.0.0
resolution: "resolve-from@npm:4.0.0"
@@ -3304,32 +3034,6 @@ __metadata:
languageName: node
linkType: hard
"resolve@npm:^1.20.0":
version: 1.22.4
resolution: "resolve@npm:1.22.4"
dependencies:
is-core-module: ^2.13.0
path-parse: ^1.0.7
supports-preserve-symlinks-flag: ^1.0.0
bin:
resolve: bin/resolve
checksum: 23f25174c2736ce24c6d918910e0d1f89b6b38fefa07a995dff864acd7863d59a7f049e691f93b4b2ee29696303390d921552b6d1b841ed4a8101f517e1d0124
languageName: node
linkType: hard
"resolve@patch:resolve@^1.20.0#~builtin<compat/resolve>":
version: 1.22.4
resolution: "resolve@patch:resolve@npm%3A1.22.4#~builtin<compat/resolve>::version=1.22.4&hash=c3c19d"
dependencies:
is-core-module: ^2.13.0
path-parse: ^1.0.7
supports-preserve-symlinks-flag: ^1.0.0
bin:
resolve: bin/resolve
checksum: c45f2545fdc4d21883861b032789e20aa67a2f2692f68da320cc84d5724cd02f2923766c5354b3210897e88f1a7b3d6d2c7c22faeead8eed7078e4c783a444bc
languageName: node
linkType: hard
"retry@npm:^0.12.0":
version: 0.12.0
resolution: "retry@npm:0.12.0"
@@ -3394,15 +3098,6 @@ __metadata:
languageName: node
linkType: hard
"safe-regex@npm:2.1.1":
version: 2.1.1
resolution: "safe-regex@npm:2.1.1"
dependencies:
regexp-tree: ~0.1.1
checksum: 5d734e2193c63ef0cb00f60c0244e0f8a30ecb31923633cd34636808d6a7c4c206d650017953ae1db8bc33967c2f06af33488dea6f038f4e38212beb7bed77b4
languageName: node
linkType: hard
"safer-buffer@npm:>= 2.1.2 < 3.0.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
@@ -3410,16 +3105,7 @@ __metadata:
languageName: node
linkType: hard
"semver-try-require@npm:6.2.3":
version: 6.2.3
resolution: "semver-try-require@npm:6.2.3"
dependencies:
semver: ^7.5.3
checksum: 891ef070f0817342f84692c2ed015f04ab49758722a51261f634d13a426bda899c89dce3b6bb7593b33c5b47283d2bf273fe0649807813fe814466e1017af523
languageName: node
linkType: hard
"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.5.4":
"semver@npm:^7.3.5, semver@npm:^7.3.7":
version: 7.5.4
resolution: "semver@npm:7.5.4"
dependencies:
@@ -3474,13 +3160,6 @@ __metadata:
languageName: node
linkType: hard
"sisteransi@npm:^1.0.5":
version: 1.0.5
resolution: "sisteransi@npm:1.0.5"
checksum: aba6438f46d2bfcef94cf112c835ab395172c75f67453fe05c340c770d3c402363018ae1ab4172a1026a90c47eaccf3af7b6ff6fa749a680c2929bd7fa2b37a4
languageName: node
linkType: hard
"slash@npm:^3.0.0":
version: 3.0.0
resolution: "slash@npm:3.0.0"
@@ -3611,13 +3290,6 @@ __metadata:
languageName: node
linkType: hard
"strip-bom@npm:^3.0.0":
version: 3.0.0
resolution: "strip-bom@npm:3.0.0"
checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b
languageName: node
linkType: hard
"strip-final-newline@npm:^2.0.0":
version: 2.0.0
resolution: "strip-final-newline@npm:2.0.0"
@@ -3678,20 +3350,6 @@ __metadata:
languageName: node
linkType: hard
"supports-preserve-symlinks-flag@npm:^1.0.0":
version: 1.0.0
resolution: "supports-preserve-symlinks-flag@npm:1.0.0"
checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae
languageName: node
linkType: hard
"tapable@npm:^2.2.0":
version: 2.2.1
resolution: "tapable@npm:2.2.1"
checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51
languageName: node
linkType: hard
"tar@npm:^6.1.11, tar@npm:^6.1.2":
version: 6.1.15
resolution: "tar@npm:6.1.15"
@@ -3706,13 +3364,6 @@ __metadata:
languageName: node
linkType: hard
"teamcity-service-messages@npm:0.1.14":
version: 0.1.14
resolution: "teamcity-service-messages@npm:0.1.14"
checksum: b4f91d81158df1f977bdf10312779dc1bb47b3268dbdbab7cdf1e9d99591d2d4916af975fe059f62481bff1e7938dff1b46c05ba53545d53fd486de079879d9b
languageName: node
linkType: hard
"text-table@npm:^0.2.0":
version: 0.2.0
resolution: "text-table@npm:0.2.0"
@@ -3817,28 +3468,6 @@ __metadata:
languageName: node
linkType: hard
"tsconfig-paths-webpack-plugin@npm:4.1.0":
version: 4.1.0
resolution: "tsconfig-paths-webpack-plugin@npm:4.1.0"
dependencies:
chalk: ^4.1.0
enhanced-resolve: ^5.7.0
tsconfig-paths: ^4.1.2
checksum: f6e9a8a407e1a405b0f2531184296d9f033cb4fe5837282b757ab4a2f4cd82a3117e62c4b86d56c7d47749c7f1345aa438ec6417dbf64a0ec74a292fe9eae44d
languageName: node
linkType: hard
"tsconfig-paths@npm:^4.1.2":
version: 4.2.0
resolution: "tsconfig-paths@npm:4.2.0"
dependencies:
json5: ^2.2.2
minimist: ^1.2.6
strip-bom: ^3.0.0
checksum: 28c5f7bbbcabc9dabd4117e8fdc61483f6872a1c6b02a4b1c4d68c5b79d06896c3cc9547610c4c3ba64658531caa2de13ead1ea1bf321c7b53e969c4752b98c7
languageName: node
linkType: hard
"tslib@npm:^1.8.1":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
@@ -4116,15 +3745,6 @@ __metadata:
languageName: node
linkType: hard
"watskeburt@npm:1.0.1":
version: 1.0.1
resolution: "watskeburt@npm:1.0.1"
bin:
watskeburt: dist/cli.js
checksum: 8fe0212c23485f2ad9c33aaee49f1c4adf2691e3f860dd985b0c7567e4483935ec072e0f94056a86691041c79bdfe631009838ec18db5fc47c7288b4faee3dea
languageName: node
linkType: hard
"webidl-conversions@npm:^4.0.2":
version: 4.0.2
resolution: "webidl-conversions@npm:4.0.2"
@@ -4186,7 +3806,7 @@ __metadata:
languageName: node
linkType: hard
"wrap-ansi@npm:8.1.0, wrap-ansi@npm:^8.1.0":
"wrap-ansi@npm:^8.1.0":
version: 8.1.0
resolution: "wrap-ansi@npm:8.1.0"
dependencies: