diff --git a/src/util/Config.ts b/src/util/Config.ts
index 9b2b9600..1e29508b 100644
--- a/src/util/Config.ts
+++ b/src/util/Config.ts
@@ -368,55 +368,53 @@ const createPlainObject = <T = unknown>(): T => {
type Serialize<T> = (value: T) => string;
type Deserialize<T> = (text: string) => T;
-
-class Config<T extends Record<string, any> = Record<string, unknown>> implements Iterable<[keyof T, T[keyof T]]> {
- readonly path: string;
- readonly #validator?: ValidateFunction;
- readonly #defaultOptions: Partial<T> = {};
-
- constructor() {
-
- const ajv = new Ajv();
-
- ajvFormats(ajv);
-
- this.#validator = ajv.compile(schema);
-
- const base = envPaths('fosscord', {suffix: ""}).config;
-
- this.path = path.resolve(base, 'api.json');
+function getConfigPath(): string {
+ const configEnvPath = envPaths('fosscord', {suffix: ""}).config;
+ const configPath = path.resolve(configEnvPath, 'api.json');
+ return configPath
+}
- const fileStore = this.store;
- const store = Object.assign(createPlainObject<T>(), fileStore);
- this._validate(store);
-
- try {
- assert.deepStrictEqual(fileStore, store);
- } catch {
- this.store = store;
+class Store<T extends Record<string, any> = Record<string, unknown>> implements Iterable<[keyof T, T[keyof T]]>{
+ readonly path: string;
+ readonly validator: ValidateFunction;
+ constructor(path: string, validator: ValidateFunction) {
+ this.validator = validator;
+ if (fs.existsSync(path)) {
+ this.path = path
+ } else {
+ this._ensureDirectory()
}
}
- private _has<Key extends keyof T>(key: Key | string): boolean {
- return dotProp.has(this.store, key as string);
+ private _ensureDirectory(): void {
+ fs.mkdirSync(path.dirname(this.path), {recursive: true})
}
- private _validate(data: T | unknown): void {
- if (!this.#validator) {
- return;
- }
-
- const valid = this.#validator(data);
- if (valid || !this.#validator.errors) {
+ protected _validate(data: T | unknown): void {
+ const valid = this.validator(data);
+ if (valid || !this.validator.errors) {
return;
}
- const errors = this.#validator.errors.map(({ instancePath, message = '' }) => `\`${instancePath.slice(1)}\` ${message}`);
+ const errors = this.validator.errors.map(({ instancePath, message = '' }) => `\`${instancePath.slice(1)}\` ${message}`);
throw new Error('The config schema was violated!: ' + errors.join('; '));
}
- get store(): T {
+ private _write(value: T): void {
+ let data: string | Buffer = this._serialize(value);
+
+ try {
+ atomically.writeFileSync(this.path, data);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private readonly _serialize: Serialize<T> = value => JSON.stringify(value, undefined, '\t');
+ private readonly _deserialize: Deserialize<T> = value => JSON.parse(value);
+
+ public get store(): T {
try {
const data = fs.readFileSync(this.path).toString();
const deserializedData = this._deserialize(data);
@@ -425,41 +423,67 @@ class Config<T extends Record<string, any> = Record<string, unknown>> implements
} catch (error) {
if (error.code == 'ENOENT') {
this._ensureDirectory();
- return createPlainObject();
-
+ return Object.create(null);
}
throw error;
}
}
- private _ensureDirectory(): void {
- fs.mkdirSync(path.dirname(this.path), { recursive: true })
- }
-
- set store(value: T) {
+ public set store(value: T) {
this._validate(value);
this._write(value);
}
- private readonly _deserialize: Deserialize<T> = value => JSON.parse(value);
- private readonly _serialize: Serialize<T> = value => JSON.stringify(value, undefined, '\t')
+ *[Symbol.iterator](): IterableIterator<[keyof T, T[keyof T]]>{
+ for (const [key, value] of Object.entries(this.store)) {
+ yield [key, value]
+ }
+ }
+}
+
+interface Options {
+ path: string;
+ schemaValidator: ValidateFunction;
+}
+
+class Config<T extends Record<string, any> = Record<string, unknown>> extends Store<T> implements Iterable<[keyof T, T[keyof T]]> {
+ readonly path: string;
+
+ constructor(options: Readonly<Partial<Options>> = {}) {
+ super(options.path!, options.schemaValidator!);
+
+
+ const fileStore = this.store;
+ const store = Object.assign(createPlainObject<T>(), fileStore);
+ this._validate(store);
+
+ try {
+ assert.deepStrictEqual(fileStore, store);
+ } catch {
+ this.store = store;
+ }
+ }
- get<Key extends keyof T>(key: Key): T[Key];
- get<Key extends keyof T>(key: Key, defaultValue: Required<T>[Key]): Required<T>[Key];
- get<Key extends string, Value = unknown>(key: Exclude<Key, keyof T>, defaultValue?: Value): Value;
- get(key: string, defaultValue?: unknown): unknown {
+ public get<Key extends keyof T>(key: Key): T[Key];
+ public get<Key extends keyof T>(key: Key, defaultValue: Required<T>[Key]): Required<T>[Key];
+ public get<Key extends string, Value = unknown>(key: Exclude<Key, keyof T>, defaultValue?: Value): Value;
+ public get(key: string, defaultValue?: unknown): unknown {
return this._get(key, defaultValue);
}
+ private _has<Key extends keyof T>(key: Key | string): boolean {
+ return dotProp.has(this.store, key as string);
+ }
+
public getAll(): DefaultOptions {
return this.store as unknown as DefaultOptions
}
- private _get<Key extends keyof T>(key: Key): T[Key] | undefined;
- private _get<Key extends keyof T, Default = unknown>(key: Key, defaultValue: Default): T[Key] | Default;
- private _get<Key extends keyof T, Default = unknown>(key: Key | string, defaultValue?: Default): Default | undefined {
+ _get<Key extends keyof T>(key: Key): T[Key] | undefined;
+ _get<Key extends keyof T, Default = unknown>(key: Key, defaultValue: Default): T[Key] | Default;
+ _get<Key extends keyof T, Default = unknown>(key: Key | string, defaultValue?: Default): Default | undefined {
if (!this._has(key)) {
throw new Error("Tried to acess a non existant property in the config");
}
@@ -467,26 +491,18 @@ class Config<T extends Record<string, any> = Record<string, unknown>> implements
return dotProp.get<T[Key] | undefined>(this.store, key as string, defaultValue as T[Key]);
}
- *[Symbol.iterator](): IterableIterator<[keyof T, T[keyof T]]> {
+ * [Symbol.iterator](): IterableIterator<[keyof T, T[keyof T]]> {
for (const [key, value] of Object.entries(this.store)) {
yield [key, value];
}
}
- private _write(value: T): void {
- let data: string | Buffer = this._serialize(value);
+}
- try {
- atomically.writeFileSync(this.path, data);
- } catch (error) {
- if (error.code == 'EXDEV') {
- fs.writeFileSync(this.path, data)
- return
- }
+const ajv = new Ajv();
+const validator = ajv.compile(schema);
- throw error;
- }
- }
-}
+const configPath = getConfigPath()
+console.log(configPath)
-export const apiConfig = new Config();
\ No newline at end of file
+export const apiConfig = new Config({path: configPath, schemaValidator: validator});
\ No newline at end of file
|