mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-15 05:41:51 +00:00
Typing fixes; show last reload time in !about
This commit is contained in:
parent
2ff93f71db
commit
3e0498f96b
26 changed files with 154 additions and 75 deletions
|
@ -21,7 +21,7 @@ export class AutoReactionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private onMessageCreateFn;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_manage: false,
|
||||
|
|
|
@ -10,10 +10,11 @@ import { IPluginOptions } from "knub";
|
|||
import { GuildLogs } from "../data/GuildLogs";
|
||||
import { LogType } from "../data/LogType";
|
||||
import * as t from "io-ts";
|
||||
import { tNullable } from "../utils";
|
||||
|
||||
const ConfigSchema = t.type({
|
||||
log_automatic_actions: t.boolean,
|
||||
case_log_channel: t.string,
|
||||
case_log_channel: tNullable(t.string),
|
||||
});
|
||||
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||
|
||||
|
@ -50,7 +51,7 @@ export class CasesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected archives: GuildArchives;
|
||||
protected logs: GuildLogs;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
log_automatic_actions: true,
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
getInviteCodesInString,
|
||||
getUrlsInString,
|
||||
stripObjectToScalars,
|
||||
tNullable,
|
||||
} from "../utils";
|
||||
import { ZalgoRegex } from "../data/Zalgo";
|
||||
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||
|
@ -20,17 +21,17 @@ import * as t from "io-ts";
|
|||
const ConfigSchema = t.type({
|
||||
filter_zalgo: t.boolean,
|
||||
filter_invites: t.boolean,
|
||||
invite_guild_whitelist: t.array(t.string),
|
||||
invite_guild_blacklist: t.array(t.string),
|
||||
invite_code_whitelist: t.array(t.string),
|
||||
invite_code_blacklist: t.array(t.string),
|
||||
invite_guild_whitelist: tNullable(t.array(t.string)),
|
||||
invite_guild_blacklist: tNullable(t.array(t.string)),
|
||||
invite_code_whitelist: tNullable(t.array(t.string)),
|
||||
invite_code_blacklist: tNullable(t.array(t.string)),
|
||||
allow_group_dm_invites: t.boolean,
|
||||
filter_domains: t.boolean,
|
||||
domain_whitelist: t.array(t.string),
|
||||
domain_blacklist: t.array(t.string),
|
||||
blocked_tokens: t.array(t.string),
|
||||
blocked_words: t.array(t.string),
|
||||
blocked_regex: t.array(t.string),
|
||||
domain_whitelist: tNullable(t.array(t.string)),
|
||||
domain_blacklist: tNullable(t.array(t.string)),
|
||||
blocked_tokens: tNullable(t.array(t.string)),
|
||||
blocked_words: tNullable(t.array(t.string)),
|
||||
blocked_regex: tNullable(t.array(t.string)),
|
||||
});
|
||||
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||
|
||||
|
@ -43,7 +44,7 @@ export class CensorPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
private onMessageCreateFn;
|
||||
private onMessageUpdateFn;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
filter_zalgo: false,
|
||||
|
|
|
@ -25,7 +25,7 @@ export class CompanionChannelPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
companionChannels: Map<string, TCompanionChannel> = new Map();
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
channels: {},
|
||||
|
|
|
@ -75,7 +75,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private clearTriggers: () => void;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
events: {},
|
||||
|
|
|
@ -23,7 +23,7 @@ export class LocatePlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
private outdatedAlertsTimeout;
|
||||
private usersWithAlerts: string[] = [];
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_where: false,
|
||||
|
|
|
@ -71,7 +71,7 @@ export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private excludedUserProps = ["user", "member", "mod"];
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
channels: {},
|
||||
|
|
|
@ -16,7 +16,7 @@ export class MessageSaverPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
protected savedMessages: GuildSavedMessages;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_manage: false,
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
NotifyUserStatus,
|
||||
stripObjectToScalars,
|
||||
successMessage,
|
||||
tNullable,
|
||||
trimLines,
|
||||
ucfirst,
|
||||
UnknownUser,
|
||||
|
@ -35,12 +36,12 @@ const ConfigSchema = t.type({
|
|||
message_on_warn: t.boolean,
|
||||
message_on_kick: t.boolean,
|
||||
message_on_ban: t.boolean,
|
||||
message_channel: t.string,
|
||||
warn_message: t.string,
|
||||
kick_message: t.string,
|
||||
ban_message: t.string,
|
||||
message_channel: tNullable(t.string),
|
||||
warn_message: tNullable(t.string),
|
||||
kick_message: tNullable(t.string),
|
||||
ban_message: tNullable(t.string),
|
||||
alert_on_rejoin: t.boolean,
|
||||
alert_channel: t.string,
|
||||
alert_channel: tNullable(t.string),
|
||||
can_note: t.boolean,
|
||||
can_warn: t.boolean,
|
||||
can_mute: t.boolean,
|
||||
|
@ -84,7 +85,7 @@ export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
this.ignoredEvents = [];
|
||||
}
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
dm_on_warn: true,
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
NotifyUserStatus,
|
||||
stripObjectToScalars,
|
||||
successMessage,
|
||||
tNullable,
|
||||
ucfirst,
|
||||
UnknownUser,
|
||||
} from "../utils";
|
||||
|
@ -28,14 +29,14 @@ import { Case } from "../data/entities/Case";
|
|||
import * as t from "io-ts";
|
||||
|
||||
const ConfigSchema = t.type({
|
||||
mute_role: t.string,
|
||||
move_to_voice_channel: t.string,
|
||||
mute_role: tNullable(t.string),
|
||||
move_to_voice_channel: tNullable(t.string),
|
||||
|
||||
dm_on_mute: t.boolean,
|
||||
message_on_mute: t.boolean,
|
||||
message_channel: t.string,
|
||||
mute_message: t.string,
|
||||
timed_mute_message: t.string,
|
||||
message_channel: tNullable(t.string),
|
||||
mute_message: tNullable(t.string),
|
||||
timed_mute_message: tNullable(t.string),
|
||||
|
||||
can_view_list: t.boolean,
|
||||
can_cleanup: t.boolean,
|
||||
|
@ -70,7 +71,7 @@ export class MutesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected serverLogs: GuildLogs;
|
||||
private muteClearIntervalId: NodeJS.Timer;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
mute_role: null,
|
||||
|
@ -366,7 +367,7 @@ export class MutesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
if (!member) {
|
||||
if (!bannedIds) {
|
||||
const bans = await this.guild.getBans();
|
||||
bannedIds = bans.map(u => u.id);
|
||||
bannedIds = bans.map(u => u.user.id);
|
||||
}
|
||||
|
||||
muteWithDetails.banned = bannedIds.includes(mute.user_id);
|
||||
|
|
|
@ -18,7 +18,7 @@ export class NameHistoryPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected nicknameHistory: GuildNicknameHistory;
|
||||
protected usernameHistory: UsernameHistory;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_view: false,
|
||||
|
|
|
@ -22,7 +22,7 @@ export class PersistPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected persistedData: GuildPersistedData;
|
||||
protected logs: GuildLogs;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
persisted_roles: [],
|
||||
|
|
|
@ -21,7 +21,7 @@ export class PingableRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected cache: Map<string, PingableRole[]>;
|
||||
protected timeouts: Map<string, any>;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_manage: false,
|
||||
|
|
|
@ -58,7 +58,7 @@ export class PostPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
clearTimeout(this.scheduledPostLoopTimeout);
|
||||
}
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_post: false,
|
||||
|
|
|
@ -55,7 +55,7 @@ export class ReactionRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private autoRefreshTimeout;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
auto_refresh_interval: MIN_AUTO_REFRESH,
|
||||
|
|
|
@ -32,7 +32,7 @@ export class RemindersPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
private postRemindersTimeout;
|
||||
private unloaded = false;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_use: false,
|
||||
|
|
|
@ -18,7 +18,7 @@ export class SelfGrantableRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
protected selfGrantableRoles: GuildSelfGrantableRoles;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_manage: false,
|
||||
|
|
|
@ -42,7 +42,7 @@ export class SlowmodePlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private onMessageCreateFn;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
use_native_slowmode: true,
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
getUserMentions,
|
||||
noop,
|
||||
stripObjectToScalars,
|
||||
tNullable,
|
||||
trimLines,
|
||||
} from "../utils";
|
||||
import { LogType } from "../data/LogType";
|
||||
|
@ -23,30 +24,26 @@ import { MuteResult, MutesPlugin } from "./Mutes";
|
|||
import { CasesPlugin } from "./Cases";
|
||||
import * as t from "io-ts";
|
||||
|
||||
const BaseSingleSpamConfig = t.intersection([
|
||||
t.type({
|
||||
interval: t.number,
|
||||
count: t.number,
|
||||
}),
|
||||
t.partial({
|
||||
mute: t.boolean,
|
||||
mute_time: t.number,
|
||||
clean: t.boolean,
|
||||
}),
|
||||
]);
|
||||
const BaseSingleSpamConfig = t.type({
|
||||
interval: t.number,
|
||||
count: t.number,
|
||||
mute: tNullable(t.boolean),
|
||||
mute_time: tNullable(t.number),
|
||||
clean: tNullable(t.boolean),
|
||||
});
|
||||
type TBaseSingleSpamConfig = t.TypeOf<typeof BaseSingleSpamConfig>;
|
||||
|
||||
const ConfigSchema = t.type({
|
||||
max_censor: BaseSingleSpamConfig,
|
||||
max_messages: BaseSingleSpamConfig,
|
||||
max_mentions: BaseSingleSpamConfig,
|
||||
max_links: BaseSingleSpamConfig,
|
||||
max_attachments: BaseSingleSpamConfig,
|
||||
max_emojis: BaseSingleSpamConfig,
|
||||
max_newlines: BaseSingleSpamConfig,
|
||||
max_duplicates: BaseSingleSpamConfig,
|
||||
max_characters: BaseSingleSpamConfig,
|
||||
max_voice_moves: BaseSingleSpamConfig,
|
||||
max_censor: tNullable(BaseSingleSpamConfig),
|
||||
max_messages: tNullable(BaseSingleSpamConfig),
|
||||
max_mentions: tNullable(BaseSingleSpamConfig),
|
||||
max_links: tNullable(BaseSingleSpamConfig),
|
||||
max_attachments: tNullable(BaseSingleSpamConfig),
|
||||
max_emojis: tNullable(BaseSingleSpamConfig),
|
||||
max_newlines: tNullable(BaseSingleSpamConfig),
|
||||
max_duplicates: tNullable(BaseSingleSpamConfig),
|
||||
max_characters: tNullable(BaseSingleSpamConfig),
|
||||
max_voice_moves: tNullable(BaseSingleSpamConfig),
|
||||
});
|
||||
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||
|
||||
|
@ -99,7 +96,7 @@ export class SpamPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private expiryInterval;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
max_censor: null,
|
||||
|
|
|
@ -32,7 +32,7 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
private onMessageDeleteFn;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_manage: false,
|
||||
|
|
|
@ -34,7 +34,7 @@ export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
protected tagFunctions;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
prefix: "!!",
|
||||
|
|
|
@ -90,8 +90,9 @@ export class UtilityPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
protected archives: GuildArchives;
|
||||
|
||||
protected lastFullMemberRefresh = 0;
|
||||
protected lastReload;
|
||||
|
||||
getDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
protected static getStaticDefaultOptions(): IPluginOptions<TConfigSchema> {
|
||||
return {
|
||||
config: {
|
||||
can_roles: false,
|
||||
|
@ -142,6 +143,8 @@ export class UtilityPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
this.savedMessages = GuildSavedMessages.getGuildInstance(this.guildId);
|
||||
this.archives = GuildArchives.getGuildInstance(this.guildId);
|
||||
|
||||
this.lastReload = Date.now();
|
||||
|
||||
if (activeReloads && activeReloads.has(this.guildId)) {
|
||||
activeReloads.get(this.guildId).createMessage(successMessage("Reloaded!"));
|
||||
activeReloads.delete(this.guildId);
|
||||
|
@ -1003,8 +1006,14 @@ export class UtilityPlugin extends ZeppelinPlugin<TConfigSchema> {
|
|||
|
||||
const shard = this.bot.shards.get(this.bot.guildShardMap[this.guildId]);
|
||||
|
||||
const lastReload = humanizeDuration(Date.now() - this.lastReload, {
|
||||
largest: 2,
|
||||
round: true,
|
||||
});
|
||||
|
||||
const basicInfoRows = [
|
||||
["Uptime", prettyUptime],
|
||||
["Last reload", `${lastReload} ago`],
|
||||
["Last update", moment(lastCommit.committer.date, "X").format("LL [at] H:mm [(UTC)]")],
|
||||
["Version", lastCommit.shortHash],
|
||||
["API latency", `${shard.latency}ms`],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IBasePluginConfig, IPluginOptions, logger, Plugin } from "knub";
|
||||
import { IBasePluginConfig, IPluginOptions, logger, Plugin, configUtils } from "knub";
|
||||
import { PluginRuntimeError } from "../PluginRuntimeError";
|
||||
import * as t from "io-ts";
|
||||
import { pipe } from "fp-ts/lib/pipeable";
|
||||
|
@ -29,19 +29,47 @@ export class ZeppelinPlugin<TConfig extends {} = IBasePluginConfig> extends Plug
|
|||
return ourLevel > memberLevel;
|
||||
}
|
||||
|
||||
protected static getStaticDefaultOptions() {
|
||||
// Implemented by plugin
|
||||
return {};
|
||||
}
|
||||
|
||||
protected getDefaultOptions(): IPluginOptions<TConfig> {
|
||||
return (this.constructor as typeof ZeppelinPlugin).getStaticDefaultOptions() as IPluginOptions<TConfig>;
|
||||
}
|
||||
|
||||
public static validateOptions(options: any): string[] | null {
|
||||
// Validate config values
|
||||
if (this.configSchema) {
|
||||
if (options.config) {
|
||||
const errors = validateStrict(this.configSchema, options.config);
|
||||
if (errors) return errors;
|
||||
const merged = configUtils.mergeConfig(
|
||||
{},
|
||||
(this.getStaticDefaultOptions() as any).config || {},
|
||||
options.config,
|
||||
);
|
||||
const errors = validateStrict(this.configSchema, merged);
|
||||
if (errors) {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.overrides) {
|
||||
for (const override of options.overrides) {
|
||||
for (const [i, override] of options.overrides.entries()) {
|
||||
if (override.config) {
|
||||
const errors = validateStrict(this.configSchema, override.config);
|
||||
if (errors) return errors;
|
||||
// For type checking overrides, apply default config + supplied config + any overrides preceding this override + finally this override
|
||||
// Exhaustive type checking would require checking against all combinations of preceding overrides but that's... costy. This will do for now.
|
||||
// TODO: Override default config retrieval functions and do some sort of memoized checking there?
|
||||
const merged = configUtils.mergeConfig(
|
||||
{},
|
||||
(this.getStaticDefaultOptions() as any).config || {},
|
||||
options.config || {},
|
||||
...options.overrides.slice(0, i),
|
||||
override.config,
|
||||
);
|
||||
const errors = validateStrict(this.configSchema, merged);
|
||||
if (errors) {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +83,7 @@ export class ZeppelinPlugin<TConfig extends {} = IBasePluginConfig> extends Plug
|
|||
const mergedOptions = this.getMergedOptions();
|
||||
const validationErrors = ((this.constructor as unknown) as typeof ZeppelinPlugin).validateOptions(mergedOptions);
|
||||
if (validationErrors) {
|
||||
throw new Error(`Invalid options:\n${validationErrors.join("\n")}`);
|
||||
throw new Error(validationErrors.join("\n"));
|
||||
}
|
||||
|
||||
return super.runLoad();
|
||||
|
|
|
@ -25,6 +25,7 @@ import { GuildInfoSaverPlugin } from "./GuildInfoSaver";
|
|||
import { LogServerPlugin } from "./LogServer";
|
||||
import { CompanionChannelPlugin } from "./CompanionChannels";
|
||||
import { LocatePlugin } from "./LocateUser";
|
||||
import { GuildConfigReloader } from "./GuildConfigReloader";
|
||||
|
||||
/**
|
||||
* Plugins available to be loaded for individual guilds
|
||||
|
@ -70,4 +71,4 @@ export const basePlugins = [
|
|||
/**
|
||||
* Available global plugins (can't be loaded per-guild, only globally)
|
||||
*/
|
||||
export const availableGlobalPlugins = [BotControlPlugin, UsernameSaver, LogServerPlugin];
|
||||
export const availableGlobalPlugins = [BotControlPlugin, UsernameSaver, LogServerPlugin, GuildConfigReloader];
|
||||
|
|
|
@ -11,7 +11,8 @@ import {
|
|||
} from "eris";
|
||||
import url from "url";
|
||||
import tlds from "tlds";
|
||||
import emojiRegex from "emoji-regex/es2015/text";
|
||||
import emojiRegex from "emoji-regex/text";
|
||||
import * as t from "io-ts";
|
||||
|
||||
import fs from "fs";
|
||||
const fsp = fs.promises;
|
||||
|
@ -28,6 +29,10 @@ const delayStringMultipliers = {
|
|||
s: 1000,
|
||||
};
|
||||
|
||||
export function tNullable(type: t.Mixed) {
|
||||
return t.union([type, t.undefined, t.null]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a "delay string" such as "1h30m" to milliseconds
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,42 @@
|
|||
import * as t from "io-ts";
|
||||
import { pipe } from "fp-ts/lib/pipeable";
|
||||
import { fold } from "fp-ts/lib/Either";
|
||||
import { PathReporter } from "io-ts/lib/PathReporter";
|
||||
import { noop } from "./utils";
|
||||
|
||||
// From io-ts/lib/PathReporter
|
||||
function stringify(v) {
|
||||
if (typeof v === "function") {
|
||||
return t.getFunctionName(v);
|
||||
}
|
||||
if (typeof v === "number" && !isFinite(v)) {
|
||||
if (isNaN(v)) {
|
||||
return "NaN";
|
||||
}
|
||||
return v > 0 ? "Infinity" : "-Infinity";
|
||||
}
|
||||
return JSON.stringify(v);
|
||||
}
|
||||
|
||||
// From io-ts/lib/PathReporter
|
||||
// tslint:disable
|
||||
function getContextPath(context) {
|
||||
return context
|
||||
.map(function(_a) {
|
||||
var key = _a.key,
|
||||
type = _a.type;
|
||||
return key + ": " + type.name;
|
||||
})
|
||||
.join("/");
|
||||
}
|
||||
// tslint:enable
|
||||
|
||||
const report = fold((errors: any) => {
|
||||
return errors.map(err => {
|
||||
if (err.message) return err.message;
|
||||
const context = err.context.map(c => c.key).filter(k => k && !k.startsWith("{"));
|
||||
return `Invalid value <${stringify(err.value)}> supplied to <${context.join("/")}>`;
|
||||
});
|
||||
}, noop);
|
||||
|
||||
/**
|
||||
* Validates the given value against the given schema while also disallowing extra properties
|
||||
|
@ -12,7 +47,7 @@ export function validateStrict(schema: t.Type<any, any, any>, value: any): strin
|
|||
return pipe(
|
||||
validationResult,
|
||||
fold(
|
||||
err => PathReporter.report(validationResult),
|
||||
err => report(validationResult),
|
||||
result => {
|
||||
// Make sure there are no extra properties
|
||||
if (JSON.stringify(value) !== JSON.stringify(result)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue