From ade35d0a8bf992c37496c8d99ebb047f5a536487 Mon Sep 17 00:00:00 2001 From: Kyra Date: Sun, 11 Nov 2018 11:22:51 +0100 Subject: [PATCH] src: GatewayDriver#register changes (#480) * refactor: Convert GatewayDriver into a Collection (#467) * refactor: Convert GatewayDriver into a Collection * fix: Better error message for gateway existence in register Co-Authored-By: kyranet * refactor: Upgrade API for Settings#update (#426) * refactor: No more _update * cleanup: More re-organization * src: More refactors * Settings#{list,resolveString} -> Settings#display * style: Rename constant name * refactor: Re-add Conf#check and reduce duplicated code in Settings#reset * fix: _resolveUpdateOverloads not parsing reset args correctly * fix: Synchronize the Settings entry on update or reset instead of returning wrong results * typings: Fixed QB types and updated everything * docs: Added missing jsdocs and refactored Settings#get * fix: conf and userconf always throwing on empty values * fix: Better Schema#get * fix: Settings#show using Map[key] instead of Map#get(key) * fix: Settings#_resolveUpdateOverloads not checking for the lack of a key * fix: conf command not passing all args for check * fix: Fixed multiple things * docs: Update guides to reflect latest changes * pr: Update changelog * fix: Collection not being destructured from discord.js Now it's the time when I run and hide for such a silly mistake. * Settings rewrite (#471) * wip: Settings rewrite * design: Chain SettingsFolder#get instead of recursing, remove '*' wildcard * refactor: Made SettingsFolder#get use Array#reduce * src: Add Settings#init * src: Added SettingsFolder#display * src: Remove Settings and all traces of it * src: Update Gateway, move SettingsFolder#existenceStatus to Settings * docs: Documented all methods and properties of Settings and SettingsFolder * naming: Gateway#type -> Gateway#name * src: Change all occurrences of Settings[key] to Settings.get(key) * src: SettingsUpdateOptions#{action|avoidUnconfigurable} -> {arrayAction|onlyConfigurable} * src: guildSettings[key] -> guildSettings.get(key) * typings: GatewayStorage#type -> GatewayStorage#name * refactor: Faster Schema#get * typings: Fix Settings class typings * typings: Iterable -> IterableIterator * docs: Fixed util docs * fix: Use Map#call instead of inherited SettingsFolder#get and Schema * fix: Settings#init deepCloning the wrong value * fix: KlasaGuild#language using Settings[key] instead of Settings.get(key) * inspection: Make Settings#{id|base} non-enumerable * fix: Sandbox Schema#get to mimic previous functionality * fix: Better errors for Settings#{reset,update} * fix: Fixed SettingsFolder#display * docs: Added comments to justify the usage of Map.prototype.get.call * fix: SettingsFolder#display not getting the right path * fix: Revert change to commandHandler's mention only check * docs: Justify the prefix.length in commandHandler's mentionOnly * feat: SettingsFolder#pluck * fix: Updated providers helpers for the new Gateway results * fix: SettingsFolder#update not overloading well * fix: Settings and SettingsFolder trying to access client * fix: Fixed updating not patching correctly * fix: settingsUpdateEntry event receiving a SettingsFolder instead of the Settings instance * src: Better relative path parsing, fixed update inserting full values into db * fix: JSON provider not parsing create queries * fix: Configuration commands not checking correctly * src: Added Settings#target, Gateway#{create,acquire}, removed create in get * fix: Init schedule before pieces (but after SG) * i18n,fix: Default guild option in Settings#{update,reset}, i18n all errors * refactor: Better guild resolving for Settings#{reset,update} * fix: resolveGuild calls without client * fix: SQLProvider accessing to the gateway wrongly * changelog: Updated for the PR * fix: Settings#clone not working as expected * misc: Make Settings#{id,gateway,target} enumerable * revert: Settings#{gateway,target} enumerability * cleanup: Remove GatewayStorage#defaults * misc: Make Schema#defaults a property * fix: Call this.init() in destroy instead of patching * docs: Updated changelog * lint: Fixed lint * docs: Fixed jsdocs * src: Reorganize files * style: Remove optional property in Settings#id * memory: Deepclone patch, not init * fix: Access to undefined * fix: Settings#update not serializing arrays correctly * src: Remove all usage of deepClone in SettingsGateway * misc: Make Schema#defaults a SettingsFolder instance * docs: Finished changelog * misc: Remove guild option from the conf command * docs: Forgot to mention arrayPosition->arrayIndex in CHANGELOG * perf: Optimize Gateway#sync to the clouds for empty schemas * feat: Added `KlasaClient#settingsSync` event. (#475) * feat: Added `KlasaClient#settingsSyncEntry` event. * docs: Correct PR number in CHANGELOG * src: Emit settingsSyncEntry on broadcastEval * fix: Entry settings not setting their existence status to true in shards * misc: Renamed `KlasaClient#{settingsUpdateEntry,settingsDeleteEntry,settingsCreateEntry}` to `KlasaClient#{settingsUpdate,settingsDelete,settingsCreate}`. * misc: Rename prefix settingsUpdate core event to... coreSettingsUpdate * fix: coreSettingsUpdate is not an once event * fix: Old typings, patch before emitting events * fix: Settings delete core event (#477) * fix: Added core event handler for settingsDelete * docs: Updated IncludedEvents * docs: Correct changelog PR number * fix: Don't check this.client.shard in both core settings event handlers * misc: Add IS support for both core settings events handlers * misc: Much better and faster shard check for both settings events * src: GatewayDriver#register changes * fix: I missed this * misc: Requested changes * src: Requested change * fix: Who did this * fix: settings is not defined in the evals --- CHANGELOG.md | 2 + src/commands/Admin/transfer.js | 2 +- src/events/coreSettingsDelete.js | 2 +- src/events/coreSettingsUpdate.js | 2 +- src/lib/Client.js | 7 +-- src/lib/settings/gateway/Gateway.js | 19 +++----- src/lib/settings/gateway/GatewayDriver.js | 19 +++----- src/lib/settings/gateway/GatewayStorage.js | 10 +++-- typings/index.d.ts | 50 ++++++++-------------- 9 files changed, 48 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51ba4d18c9..b169a30a99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -132,6 +132,7 @@ NOTE: For the contributors, you add new entries to this document following this ### Changed +- [[#480](https://github.com/dirigeants/klasa/pull/480)] Changed the entire mechanism for `GatewayDriver#register` to take a `GatewayStorage` instance. (kyranet) - [[#475](https://github.com/dirigeants/klasa/pull/475)] Renamed `KlasaClient#{settingsUpdateEntry,settingsDeleteEntry,settingsCreateEntry}` to `KlasaClient#{settingsUpdate,settingsDelete,settingsCreate}`. (kyranet) - [[#471](https://github.com/dirigeants/klasa/pull/471)] Modified `Schema#defaults` type from Object literal to a `SettingsFolder` instance. (kyranet) - [[#471](https://github.com/dirigeants/klasa/pull/471)] Modified `Schema#defaults` to be a property instead of a getter. (kyranet) @@ -254,6 +255,7 @@ NOTE: For the contributors, you add new entries to this document following this ### Removed +- [[#480](https://github.com/dirigeants/klasa/pull/480)] Removed `Gateway#store`. (kyranet) - [[#471](https://github.com/dirigeants/klasa/pull/471)] Removed `Gateway#defaults`. Refer to `Schema#defaults` instead. (kyranet) - [[#426](https://github.com/dirigeants/klasa/pull/426)] Removed `Gateway#getPath`. They're now resolved inside Settings. (kyranet) - [[#401](https://github.com/dirigeants/klasa/pull/401)] Removed `Settings#waitSync` in favor of `Settings#sync(?false);`. (kyranet) diff --git a/src/commands/Admin/transfer.js b/src/commands/Admin/transfer.js index 85767b595b..ecac597502 100644 --- a/src/commands/Admin/transfer.js +++ b/src/commands/Admin/transfer.js @@ -22,7 +22,7 @@ module.exports = class extends Command { piece.store.load(piece.store.userDirectory, piece.file); if (this.client.shard) { await this.client.shard.broadcastEval(` - if (String(this.shard.id) !== '${this.client.shard.id}') this.${piece.store}.load(${piece.store.userDirectory}, ${JSON.stringify(piece.file)}); + if (String(this.shard.id) !== '${this.client.shard.id}') this.${piece.store}.load('${piece.store.userDirectory}', ${JSON.stringify(piece.file)}); `); } return message.sendLocale('COMMAND_TRANSFER_SUCCESS', [piece.type, piece.name]); diff --git a/src/events/coreSettingsDelete.js b/src/events/coreSettingsDelete.js index 4a51d8ea60..15b87a351e 100644 --- a/src/events/coreSettingsDelete.js +++ b/src/events/coreSettingsDelete.js @@ -13,7 +13,7 @@ module.exports = class extends Event { if (String(this.shard.id) !== '${this.client.shard.id}') { const entry = this.gateways.get('${settings.gateway.name}').get('${settings.id}'); if (entry && entry.existenceStatus) { - this.emit('settingsDelete', settings); + this.emit('settingsDelete', entry); entry.init(entry, entry.schema); entry.existenceStatus = false; } diff --git a/src/events/coreSettingsUpdate.js b/src/events/coreSettingsUpdate.js index 8d7bfc1674..cab705b6e6 100644 --- a/src/events/coreSettingsUpdate.js +++ b/src/events/coreSettingsUpdate.js @@ -15,7 +15,7 @@ module.exports = class extends Event { if (entry) { entry._patch(${JSON.stringify(settings)}); entry.existenceStatus = true; - this.emit('settingsSync', settings); + this.emit('settingsSync', entry); } } `); diff --git a/src/lib/Client.js b/src/lib/Client.js index b4b973d776..240969e68a 100644 --- a/src/lib/Client.js +++ b/src/lib/Client.js @@ -25,6 +25,7 @@ const TaskStore = require('./structures/TaskStore'); const GatewayDriver = require('./settings/gateway/GatewayDriver'); // lib/settings/schema +const Gateway = require('./settings/gateway/Gateway'); const Schema = require('./settings/schema/Schema'); // lib/util @@ -267,9 +268,9 @@ class KlasaClient extends Discord.Client { // Register default gateways this.gateways - .register('guilds', { ...guilds, schema: guildSchema }) - .register('users', { ...users, schema: userSchema }) - .register('clientStorage', { ...clientStorage, schema: clientSchema }); + .register(new Gateway(this, 'guilds', { schema: guildSchema, ...this.options.gateways.guilds || {} })) + .register(new Gateway(this, 'users', { schema: userSchema, ...this.options.gateways.users || {} })) + .register(new Gateway(this, 'clientStorage', { schema: clientSchema, ...this.options.gateways.clientStorage || {} })); /** * The Settings instance that handles this client's settings diff --git a/src/lib/settings/gateway/Gateway.js b/src/lib/settings/gateway/Gateway.js index 1fc3f0af6c..31ca4c8d38 100644 --- a/src/lib/settings/gateway/Gateway.js +++ b/src/lib/settings/gateway/Gateway.js @@ -1,5 +1,6 @@ const GatewayStorage = require('./GatewayStorage'); const Settings = require('../Settings'); +const Schema = require('../schema/Schema'); const { Collection } = require('discord.js'); /** @@ -12,20 +13,14 @@ class Gateway extends GatewayStorage { /** * @since 0.0.1 - * @param {GatewayDriver} store The GatewayDriver instance which initiated this instance + * @param {KlasaClient} client The KlasaClient instance which initiated this instance * @param {string} name The name of this Gateway - * @param {Schema} schema The schema for this gateway - * @param {string} provider The provider's name for this gateway + * @param {Object} [options = {}] The options for this gateway + * @param {Schema} [options.schema = new Schema()] The schema for this gateway + * @param {string} [options.provider = this.client.options.providers.default] The provider's name for this gateway */ - constructor(store, name, schema, provider) { - super(store.client, name, schema, provider); - - /** - * The GatewayDriver that manages this Gateway - * @since 0.0.1 - * @type {GatewayDriver} - */ - this.store = store; + constructor(client, name, { schema = new Schema(), provider = client.options.providers.default } = {}) { + super(client, name, schema, provider); /** * The cached entries for this Gateway or the external datastore to get the settings from diff --git a/src/lib/settings/gateway/GatewayDriver.js b/src/lib/settings/gateway/GatewayDriver.js index 9bd4317739..4e62451c72 100644 --- a/src/lib/settings/gateway/GatewayDriver.js +++ b/src/lib/settings/gateway/GatewayDriver.js @@ -1,5 +1,5 @@ -const Gateway = require('./Gateway'); -const Schema = require('../schema/Schema'); +const GatewayStorage = require('./GatewayStorage'); +const Type = require('../../util/Type'); const { Collection } = require('discord.js'); /** @@ -53,19 +53,14 @@ class GatewayDriver extends Collection { /** * Registers a new Gateway. * @since 0.5.0 - * @param {string} name The name for the new gateway - * @param {GatewayDriverRegisterOptions} [options = {}] The options for the new gateway + * @param {GatewayStorage} gateway The gateway to register * @returns {this} * @chainable */ - register(name, { provider = this.client.options.providers.default, schema = new Schema() } = {}) { - if (typeof name !== 'string') throw new TypeError('You must pass a name for your new gateway and it must be a string.'); - if (!(schema instanceof Schema)) throw new TypeError('Schema must be a valid Schema instance.'); - if (this.has(name)) throw new Error(`The key '${name}' is taken by another Gateway.`); - - if (!(name in this.client.options.gateways)) this.client.options.gateways[name] = {}; - const gateway = new Gateway(this, name, schema, provider); - this.set(name, gateway); + register(gateway) { + if (!(gateway instanceof GatewayStorage)) throw new TypeError(`You must pass a GatewayStorage instance, received: ${new Type(gateway)}`); + if (!(gateway.name in this.client.options.gateways)) this.client.options.gateways[gateway.name] = {}; + this.set(gateway.name, gateway); return this; } diff --git a/src/lib/settings/gateway/GatewayStorage.js b/src/lib/settings/gateway/GatewayStorage.js index 2afecb99ab..92ec0d9d48 100644 --- a/src/lib/settings/gateway/GatewayStorage.js +++ b/src/lib/settings/gateway/GatewayStorage.js @@ -3,7 +3,7 @@ class GatewayStorage { /** * @typedef {Object} GatewayJSON * @property {string} name The name of this gateway - * @property {GatewayDriverRegisterOptions} options The options for this gateway + * @property {string} provider The provider's name * @property {Object} schema The current schema */ @@ -42,13 +42,15 @@ class GatewayStorage { * @type {string} * @readonly */ - Object.defineProperty(this, 'providerName', { value: provider || this.client.options.providers.default }); + Object.defineProperty(this, 'providerName', { value: provider }); /** * @since 0.5.0 + * @name GatewayStorage#schema * @type {Schema} + * @readonly */ - this.schema = schema; + Object.defineProperty(this, 'schema', { value: schema, enumerable: true }); /** * @since 0.5.0 @@ -118,7 +120,7 @@ class GatewayStorage { toJSON() { return { name: this.name, - options: { provider: this.providerName }, + provider: this.providerName, schema: this.schema.toJSON() }; } diff --git a/typings/index.d.ts b/typings/index.d.ts index 150e743a37..10b4a943a6 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -242,9 +242,21 @@ declare module 'klasa' { private init(folder: SettingsFolder, schema: SchemaFolder): void; } + export class GatewayDriver extends Collection { + private constructor(client: KlasaClient); + public readonly client: KlasaClient; + public ready: boolean; + + public register(gateway: GatewayStorage): this; + public init(): Promise; + public sync(input?: string[] | string): Promise>; + + public toJSON(): GatewayDriverJSON; + public toString(): string; + } + export class Gateway extends GatewayStorage { - public constructor(store: GatewayDriver, name: string, schema: Schema, options: GatewayOptions); - public store: GatewayDriver; + public constructor(client: KlasaClient, name: string, options?: { schema?: Schema, provider?: string }); public syncQueue: WeakMap>; public readonly Settings: Settings; private cache: Collection & { settings: Settings }>; @@ -265,27 +277,14 @@ declare module 'klasa' { private readonly _datatypes: ObjectLiteral>; } - export class GatewayDriver extends Collection { - private constructor(client: KlasaClient); - public readonly client: KlasaClient; - public ready: boolean; - - public register(name: string, options?: GatewayDriverRegisterOptions): this; - public init(): Promise; - public sync(input?: string[] | string): Promise>; - - public toJSON(): GatewayDriverJSON; - public toString(): string; - } - export abstract class GatewayStorage { - public constructor(client: KlasaClient, name: string, schema: Schema, provider?: string); + public constructor(client: KlasaClient, name: string, schema?: Schema, provider?: string); public readonly client: KlasaClient; public readonly provider: Provider | null; public readonly providerName: string; public readonly name: string; + public readonly schema: SchemaFolder; public ready: boolean; - public schema: SchemaFolder; public init(): Promise; public toJSON(): GatewayJSON; @@ -1310,11 +1309,7 @@ declare module 'klasa' { default?: string; } & ObjectLiteral; - export type KlasaGatewaysOptions = { - clientStorage?: GatewayDriverRegisterOptions; - guilds?: GatewayDriverRegisterOptions; - users?: GatewayDriverRegisterOptions; - } & ObjectLiteral; + export type KlasaGatewaysOptions = Record; // Parsers export type ArgResolverCustomMethod = (arg: string, possible: Possible, message: KlasaMessage, params: string[]) => any; @@ -1464,9 +1459,9 @@ declare module 'klasa' { }; export type GatewayJSON = { - options: GatewayOptions; - schema: SchemaFolderAddOptions; name: string; + provider: string; + schema: SchemaFolderAddOptions; }; export type QueryBuilderDatatypeOptions = { @@ -1483,12 +1478,6 @@ declare module 'klasa' { | GuildChannel | Snowflake; - export type GatewayDriverRegisterOptions = { - provider?: string; - schema?: Schema; - syncArg?: string[] | string | true; - }; - export type SchemaFolderAddOptions = SchemaFolderOptions | SchemaPieceOptions; export type SchemaPieceOptions = { @@ -1512,7 +1501,6 @@ declare module 'klasa' { clientStorage: GatewayJSON; guilds: GatewayJSON; users: GatewayJSON; - keys: string[]; ready: boolean; } & ObjectLiteral;