Skip to content
This repository has been archived by the owner on Nov 29, 2020. It is now read-only.

feat: First step at the rewrite #1

Merged
merged 46 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c49f1ed
feat: First step at the rewrite
kyranet Nov 10, 2019
2a0d373
feat: Added more progress
kyranet Nov 10, 2019
eaff9ba
feat: Added more things
kyranet Nov 11, 2019
85398f7
git: Why do we not ignore yarn-error.log?
kyranet Nov 11, 2019
dfe163c
refactor: Move code around and finished Settings and GatewayDriver
kyranet Nov 11, 2019
968058f
misc: Deleted yarn-error.log
kyranet Nov 11, 2019
95d30e5
feat: Added all structures
kyranet Nov 11, 2019
fd50d31
lint: Fixed several ESLint warnings
kyranet Nov 11, 2019
869a33e
build: Resolved all build errors
kyranet Nov 11, 2019
5978f15
fix: Resovled circular references
kyranet Nov 11, 2019
a8ac06f
tests: Added first mock classes and fixed a few things
kyranet Nov 11, 2019
ed6ab6f
tests: Add a bunch of tests and fixed a few things
kyranet Nov 29, 2019
d8e46a5
misc: More tests, finalized SG and fixed bugs
kyranet Nov 29, 2019
abd34f8
polyfill: Added ObjectFromEntries for Node.js v10 compatibility
kyranet Nov 29, 2019
0065363
misc: Fixed SchemaEntry#edit, added examples and tests
kyranet Nov 30, 2019
181716f
docs: I heard you liked examples
kyranet Nov 30, 2019
7eb7def
docs: Added more examples
kyranet Nov 30, 2019
4668d66
misc: Finalized SchemaEntry's tests, documented more, moved resolve m…
kyranet Nov 30, 2019
9761129
fix: Better `_checkSchemaFolder` and freeze SchemaEntry instances
kyranet Nov 30, 2019
5aae670
misc: Refactor code and added more tests
kyranet Dec 3, 2019
b857e36
tests: Fixed Settings tests
kyranet Dec 5, 2019
135e209
misc: Resolved bug in Settings upsert code, added more tests
kyranet Dec 5, 2019
73e7b6c
chore: Update all dependencies
kyranet Dec 6, 2019
b45dcc1
build: Enable declarationMap
kyranet Dec 6, 2019
a222327
ci: Use Crawl's action and Node.js 12
kyranet Dec 6, 2019
8a9bced
fix: Resolved several bugs and added more tests
kyranet Dec 6, 2019
0a2f808
tests: Removed snapshot testing
kyranet Dec 6, 2019
10ace57
tests: Added a lot of SettingsFolder#reset tests, fixed several things
kyranet Dec 6, 2019
60babae
tests: Finalize SettingsFolder#reset's tests
kyranet Dec 6, 2019
6d7c095
fix: Resolved several bugs and added some SF#update tests
kyranet Dec 8, 2019
c44bf95
fix: Resolved type issues and another bug
kyranet Dec 8, 2019
c9ae1f7
test: Added more SF#update tests and more hooks for Serializer
kyranet Dec 8, 2019
565a99e
tests: Added array action tests
kyranet Dec 9, 2019
e682de8
tests: Added ArrayIndex tests
kyranet Dec 9, 2019
69cf148
docs: Added LOTS OF DOCS
kyranet Dec 9, 2019
9e43f9d
docs: Added CHANGELOG
kyranet Dec 9, 2019
c8495ba
fix: Generate TS compiler error to stop unexpected behaviour.
kyranet Dec 9, 2019
74a4085
misc: Resolved code review by @vladfrangu
kyranet Dec 9, 2019
b4ec819
misc: Resolved code review by @Favna
kyranet Dec 9, 2019
105d652
git: Ignore all .xml and .log files
kyranet Dec 9, 2019
4df9f91
chore: Update all dependencies
kyranet Dec 9, 2019
5af9b29
package: Update the name, description, and repository.url
kyranet Dec 9, 2019
16e431a
npm: Add .github and remove unused/inexistent files
kyranet Dec 9, 2019
fc0ef32
Update src/lib/schema/Schema.ts
kyranet Dec 9, 2019
c6da24b
misc: Resolved all requested changes from @vladfrangu and @Favna
kyranet Dec 9, 2019
f7b38ca
style: Re-add `_` prefix to methods users are not supposed to use
kyranet Dec 9, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/codequality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ jobs:
steps:
- name: Checkout Project
uses: actions/checkout@v1
- name: Use Node.js 10
- name: Use Node.js 12
uses: actions/setup-node@v1
with:
node-version: 10
node-version: 12
- name: Restore CI Cache
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.os }}-10-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-12-${{ hashFiles('**/yarn.lock') }}
- name: Install Dependencies
run: yarn
- name: Run ESLint
uses: discordjs/action-eslint@v1
uses: icrawl/action-eslint@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand All @@ -38,15 +38,15 @@ jobs:
steps:
- name: Checkout Project
uses: actions/checkout@v1
- name: Use Node.js 10
- name: Use Node.js 12
uses: actions/setup-node@v1
with:
node-version: 10
node-version: 12
- name: Restore CI Cache
uses: actions/cache@v1
with:
path: node_modules
key: ${{ runner.os }}-10-${{ hashFiles('**/yarn.lock') }}
key: ${{ runner.os }}-12-${{ hashFiles('**/yarn.lock') }}
- name: Install Dependencies
run: yarn
- name: Run TSC
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ coverage/
.nyc_output/
dist/
docs/
test-results.xml
**/*.xml
**/*.log
18 changes: 4 additions & 14 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
# .npmignore
.get/
.github/
coverage/
node_modules/
test/
docs/
scripts/
src/
.docstrap.json
test/
.eslintrc.json
tslint.json
.travis.yml
appveyor.yml
tsconfig.json
package-lock.json
README.md
tsconfig.json
yarn.lock
coverage/
.nyc_output/
azure-pipelines.yml
test-results.xml
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Change Log

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

<!--
NOTE: For the contributors, you add new entries to this document following this format:
- [[#PRNUMBER](https://github.com/dirigeants/settings-gateway/pull/PRNUMBER)] The change that has been made. (Author's Github name)
-->

## 0.0.1

### Added

- [[#1][]] Added Unit Testing. (kyranet)
- [[#1][]] Added examples for a large set of methods. (kyranet)
- [[#1][]] Added bare `null` as an option to reset a key in `SettingsFolder`#{`update`}. (kyranet)
- [[#1][]] Added `Serializer`#{`validate`,`resolve`} to allow further control on how SettingsGateway handles the data. (kyranet)
- [[#1][]] Added `context` to the `settingsUpdate` and `settingsCreate` events, they contain the raw changes, guild, language, etc. (kyranet)
- [[#1][]] Added `extraContext` to the `SettingsFolderResetOptions` type, this value is pased in all places (`Serializer`#`validate`, `SchemaEntry`#`filter`, `settingsUpdate` and `settingsCreate` events, and more). (kyranet)

### Changed

- [[#1][]] Tweaked `Serializer`#`deserialize`'s arguments to (`SerializableValue`, `SerializerUpdateContext`). (kyranet)
- [[#1][]] Renamed `SchemaEntry`#{`min`,`max`} to `SchemaEntry`#{`minimum`,`maximum`}. (kyranet)
- [[#1][]] Tweaked `SettingsFolder`'s value type to be more accurate. (kyranet)
- [[#1][]] Tweaked `SettingsFolderUpdateOptions`'s option to produce a TypeScript compiler error when `arrayAction` is set to `'overwrite'` and `arrayIndex` is defined. (kyranet)
- [[#1][]] Tweaked `SettingsFolder`#`client` to throw an error when it's uninitialized. (kyranet)
- [[#1][]] Tweaked `SettingsFolder`#{`reset`,`update`} to return a much more useful struct. (kyranet)
- [[#1][]] When specifying `arrayIndex` in `SettingsFolder`#`update` and `arrayAction` is defined as `add`, all entries will be inserted at given index. (kyranet)
- [[#1][]] When specifying `arrayIndex` in `SettingsFolder`#`update` and `arrayAction` is defined as `remove`, as many entries as given will be removed from given index. (kyranet)
- [[#1][]] When specifying `arrayIndex` in `SettingsFolder`#`update` and `arrayAction` is not defined or defined as `auto`, all entries will replace the existing ones. (kyranet)

### Removed

- [[#1][]] Removed `throwOnError` option in `SettingsFolder`#{`reset`,`update`}, they will now always throw when they encounter an error. (kyranet)

### Fixed

- [[#1][]] Resolved bug where `Schema`#`get` would throw an error if a path did not exist. (kyranet)
- [[#1][]] Resolved bug where `Schema`#{`add`,`remove`} was still callable even after being initialized. (kyranet)
- [[#1][]] Resolved bug where `SettingsFolder`#`get` would throw an error if a path did not exist. (kyranet)
- [[#1][]] Resolved type bug in `SettingsFolder`#`pluck`. (kyranet)
- [[#1][]] Resolved bug in `SettingsFolder`#`resolve` not resolving into objects when specifying a folder path. (kyranet)
- [[#1][]] Resolved bug in `SettingsFolder`#`reset` where database conditions were not handled correctly. (kyranet)
- [[#1][]] Resolved bug in `SettingsFolder`#`update` where options would sometimes type error. (kyranet)
- [[#1][]] Resolved bug in `SettingsFolder`'s patch function not allowing non-literal objects to be used. (kyranet)
- [[#1][]] Resolved bug in `SettingsFolder`#{`reset`,`update`} patching after emit. (kyranet)
- [[#1][]] Fixed the types from the `Provider` and `SQLProvider` classes. (kyranet)

<!-- References, they're to shorten lines -->
[#1]: https://github.com/dirigeants/settings-gateway/pull/1
30 changes: 21 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@klasa/util",
"name": "@klasa/settings-gateway",
"version": "0.0.1",
"description": "some util thing.",
"description": "The centralized settings system designed for the Klasa framework.",
"main": "dist/index.js",
"scripts": {
"prepublishOnly": "yarn build",
Expand All @@ -17,20 +17,26 @@
"engines": {
"node": ">=10.1.0"
},
"peerDependencies": {
"klasa": "dirigeants/klasa"
},
"devDependencies": {
"@types/node": "^12.7.3",
"@typescript-eslint/eslint-plugin": "^2.0.0",
"@typescript-eslint/parser": "^2.0.0",
"@types/node": "^12.12.15",
"@types/ws": "^6.0.4",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"ava": "^2.3.0",
"eslint": "^6.3.0",
"discord.js": "discordjs/discord.js",
"eslint": "^6.7.2",
"eslint-config-klasa": "dirigeants/klasa-lint",
"klasa": "dirigeants/klasa#875/head",
"source-map-support": "^0.5.13",
"ts-node": "^8.3.0",
"typescript": "^3.6.2"
"ts-node": "^8.5.4",
"typescript": "^3.7.3"
},
"repository": {
"type": "git",
"url": "https://github.com/dirigeants/util"
"url": "https://github.com/dirigeants/settings-gateway"
},
"ava": {
"compileEnhancements": false,
Expand All @@ -45,5 +51,11 @@
"ts-node/register",
"source-map-support/register"
]
},
"dependencies": {
"@discordjs/collection": "^0.1.3",
"@klasa/querybuilder": "^0.0.1",
"@klasa/request-handler": "^0.0.3",
"@klasa/utils": "^0.0.4"
}
}
17 changes: 14 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
export default function foo(): string {
return 'bar';
}
export * from './lib/gateway/Gateway';
export * from './lib/gateway/GatewayDriver';
export * from './lib/gateway/GatewayStorage';
export * from './lib/schema/Schema';
export * from './lib/schema/SchemaEntry';
export * from './lib/schema/SchemaFolder';
kyranet marked this conversation as resolved.
Show resolved Hide resolved
export * from './lib/settings/Settings';
export * from './lib/settings/SettingsFolder';
export * from './lib/structures/Provider';
export * from './lib/structures/SQLProvider';
export * from './lib/structures/ProviderStore';
export * from './lib/structures/Serializer';
export * from './lib/structures/SerializerStore';
export * from './lib/types';
98 changes: 98 additions & 0 deletions src/lib/gateway/Gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { RequestHandler, IdKeyed } from '@klasa/request-handler';
import Collection from '@discordjs/collection';
import { GatewayStorage } from './GatewayStorage';
import { Settings } from '../settings/Settings';
import { Client } from '../types';

export class Gateway extends GatewayStorage {

/* eslint-disable no-invalid-this */
/**
* The cached entries for this Gateway or the external datastore to get the settings from.
*/
kyranet marked this conversation as resolved.
Show resolved Hide resolved
public cache: ProxyMap = (this.name in this.client) && (this.client[this.name as keyof Client] instanceof Map) ?
this.client[this.name as keyof Client] as ProxyMap :
new Collection<string, ProxyMapEntry>();

/**
* The request handler that manages the synchronization queue.
*/
public requestHandler = new RequestHandler(
(id: string): Promise<IdKeyed<string>> => {
const { provider } = this;
return provider === null ?
Promise.reject(new Error('Cannot run requests without a provider available.')) :
provider.get(this.name, id) as Promise<IdKeyed<string>>;
}, (ids: string[]): Promise<IdKeyed<string>[]> => {
const { provider } = this;
return provider === null ?
Promise.reject(new Error('Cannot run requests without a provider available.')) :
provider.getAll(this.name, ids) as Promise<IdKeyed<string>[]>;
}
);
/* eslint-enable no-invalid-this */

/**
* Gets an entry from the cache or creates one if it does not exist
* @param target The target that holds a Settings instance of the holder for the new one
* @param id The settings' identificator
* @example
* // Retrieve a members gateway
kyranet marked this conversation as resolved.
Show resolved Hide resolved
* const gateway = this.client.gateways.get('members');
*
* // Acquire a settings instance belonging to a member
* gateway.acquire(message.member);
kyranet marked this conversation as resolved.
Show resolved Hide resolved
*/
public acquire(target: IdKeyed<string>, id = target.id): Settings {
return this.get(id) || this.create(target, id);
}

/**
* Get an entry from the cache.
* @param id The key to get from the cache
* @example
* // Retrieve a members gateway
* const gateway = this.client.gateways.get('members');
*
* // Retrieve a settings instance belonging to a member's id
* const settings = gateway.get(someMemberID);
*
* // Do something with it, be careful as it can return null
* if (settings === null) {
* // settings is null
* } else {
* // console.log(settings);
* }
*/
public get(id: string): Settings | null {
const entry = this.cache.get(id);
return (entry && entry.settings) || null;
}

/**
* Create a new Settings instance for this gateway.
* @param target The target that will hold this instance alive
* @param id The settings' identificator
*/
public create(target: IdKeyed<string>, id = target.id): Settings {
const settings = new Settings(this, target, id);
if (this.schema.size !== 0) settings.sync(true).catch(err => this.client.emit('error', err));
return settings;
}

/**
* Runs a synchronization task for the gateway.
*/
public async sync(): Promise<this> {
await this.requestHandler.wait();
return this;
}

}

export interface ProxyMapEntry {
settings: Settings;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
kyranet marked this conversation as resolved.
Show resolved Hide resolved
export interface ProxyMap extends Map<string, ProxyMapEntry> { }
kyranet marked this conversation as resolved.
Show resolved Hide resolved
67 changes: 67 additions & 0 deletions src/lib/gateway/GatewayDriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { GatewayStorage, GatewayStorageJson } from './GatewayStorage';
import { Client } from '../types';
import { fromEntries } from '../polyfills';
import Collection from '@discordjs/collection';

export class GatewayDriver extends Collection<string, GatewayStorage> {

/**
* The client this GatewayDriver was created with.
*/
kyranet marked this conversation as resolved.
Show resolved Hide resolved
public readonly client: Client;

/**
* Constructs a new instance of GatewayDriver.
* @param client The client that manages this instance
*/
public constructor(client: Client) {
super();
this.client = client;
}

/**
* Registers a new gateway.
* @param gateway The gateway to register
* @example
* // Import Client and Gateway from klasa
* const { Client, Gateway } = require('klasa');
*
* // Construct the client and register a gateway named channels
* const client = new Client();
* client.register(new Gateway(client, 'channels'));
*
* @example
* // Import Client and Gateway from klasa
* const { Client, Gateway } = require('klasa');
* const client = new Client();
*
* // register calls can be chained
* client
* .register(new Gateway(client, 'channels'))
* .register(new GatewayStorage(client, 'moderations', { provider: 'postgres' }));
*/
public register(gateway: GatewayStorage): this {
if (typeof this.client.options.settings.gateways === 'undefined') this.client.options.settings.gateways = { [gateway.name]: {} };
if (!(gateway.name in this.client.options.settings.gateways)) this.client.options.settings.gateways[gateway.name] = {};
this.set(gateway.name, gateway);
return this;
kyranet marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Initializes all gateways.
*/
public async init(): Promise<void> {
await Promise.all([...this.values()].map(gateway => gateway.init()));
}

/**
* The gateway driver with all serialized gateways.
*/
public toJSON(): GatewayDriverJson {
return fromEntries([...this.entries()].map(([key, value]) => [key, value.toJSON()]));
}

}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
kyranet marked this conversation as resolved.
Show resolved Hide resolved
export interface GatewayDriverJson extends Record<string, GatewayStorageJson> { }
kyranet marked this conversation as resolved.
Show resolved Hide resolved