MOBILE-3821 core: Configure lazy cache lifetime
parent
37bde23418
commit
1b24f0955d
|
@ -14,10 +14,11 @@
|
||||||
|
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { asyncInstance } from '@/core/utils/async-instance';
|
import { asyncInstance } from '@/core/utils/async-instance';
|
||||||
import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb';
|
import { SQLiteDBRecordValues } from '@classes/sqlitedb';
|
||||||
import { CoreConfig, CoreConfigProvider } from '@services/config';
|
import { CoreConfig, CoreConfigProvider } from '@services/config';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import {
|
import {
|
||||||
|
CoreDatabaseConfiguration,
|
||||||
CoreDatabaseReducer,
|
CoreDatabaseReducer,
|
||||||
CoreDatabaseTable,
|
CoreDatabaseTable,
|
||||||
CoreDatabaseConditions,
|
CoreDatabaseConditions,
|
||||||
|
@ -40,7 +41,8 @@ export class CoreDatabaseTableProxy<
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
||||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
||||||
|
|
||||||
protected config: CoreDatabaseConfiguration;
|
protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None;
|
||||||
|
|
||||||
protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>();
|
protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>();
|
||||||
protected environmentObserver?: CoreEventObserver;
|
protected environmentObserver?: CoreEventObserver;
|
||||||
protected targetConstructors: Record<
|
protected targetConstructors: Record<
|
||||||
|
@ -52,21 +54,12 @@ export class CoreDatabaseTableProxy<
|
||||||
[CoreDatabaseCachingStrategy.None]: CoreDatabaseTable,
|
[CoreDatabaseCachingStrategy.None]: CoreDatabaseTable,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
|
||||||
config: Partial<CoreDatabaseConfiguration>,
|
|
||||||
database: SQLiteDB,
|
|
||||||
tableName: string,
|
|
||||||
primaryKeyColumns?: PrimaryKeyColumn[],
|
|
||||||
) {
|
|
||||||
super(database, tableName, primaryKeyColumns);
|
|
||||||
|
|
||||||
this.config = { ...this.getConfigDefaults(), ...config };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
|
await super.initialize();
|
||||||
|
|
||||||
this.environmentObserver = CoreEvents.on(CoreConfigProvider.ENVIRONMENT_UPDATED, async () => {
|
this.environmentObserver = CoreEvents.on(CoreConfigProvider.ENVIRONMENT_UPDATED, async () => {
|
||||||
if (!(await this.shouldUpdateTarget())) {
|
if (!(await this.shouldUpdateTarget())) {
|
||||||
return;
|
return;
|
||||||
|
@ -82,9 +75,23 @@ export class CoreDatabaseTableProxy<
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async destroy(): Promise<void> {
|
async destroy(): Promise<void> {
|
||||||
|
await super.destroy();
|
||||||
|
|
||||||
this.environmentObserver?.off();
|
this.environmentObserver?.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
|
||||||
|
const thisDebug = this.config.debug ?? false;
|
||||||
|
const thisCachingStrategy = this.config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY;
|
||||||
|
const otherDebug = config.debug ?? false;
|
||||||
|
const otherCachingStrategy = config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY;
|
||||||
|
|
||||||
|
return super.matchesConfig(config) && thisDebug === otherDebug && thisCachingStrategy === otherCachingStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
@ -172,24 +179,12 @@ export class CoreDatabaseTableProxy<
|
||||||
return this.target.deleteByPrimaryKey(primaryKey);
|
return this.target.deleteByPrimaryKey(primaryKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get default configuration values.
|
|
||||||
*
|
|
||||||
* @returns Config defaults.
|
|
||||||
*/
|
|
||||||
protected getConfigDefaults(): CoreDatabaseConfiguration {
|
|
||||||
return {
|
|
||||||
cachingStrategy: CoreDatabaseCachingStrategy.None,
|
|
||||||
debug: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get database configuration to use at runtime.
|
* Get database configuration to use at runtime.
|
||||||
*
|
*
|
||||||
* @returns Database configuration.
|
* @returns Database configuration.
|
||||||
*/
|
*/
|
||||||
protected async getRuntimeConfig(): Promise<CoreDatabaseConfiguration> {
|
protected async getRuntimeConfig(): Promise<Partial<CoreDatabaseConfiguration>> {
|
||||||
await CoreConfig.ready();
|
await CoreConfig.ready();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -228,7 +223,8 @@ export class CoreDatabaseTableProxy<
|
||||||
const originalTarget = target instanceof CoreDebugDatabaseTable ? target.getTarget() : target;
|
const originalTarget = target instanceof CoreDebugDatabaseTable ? target.getTarget() : target;
|
||||||
|
|
||||||
return (config.debug && target === originalTarget)
|
return (config.debug && target === originalTarget)
|
||||||
|| originalTarget?.constructor !== this.targetConstructors[config.cachingStrategy];
|
|| originalTarget?.constructor !== this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY]
|
||||||
|
|| !originalTarget.matchesConfig(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,7 +234,7 @@ export class CoreDatabaseTableProxy<
|
||||||
*/
|
*/
|
||||||
protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
|
protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
|
||||||
const config = await this.getRuntimeConfig();
|
const config = await this.getRuntimeConfig();
|
||||||
const table = this.createTable(config.cachingStrategy);
|
const table = this.createTable(config);
|
||||||
|
|
||||||
return config.debug ? new CoreDebugDatabaseTable(table) : table;
|
return config.debug ? new CoreDebugDatabaseTable(table) : table;
|
||||||
}
|
}
|
||||||
|
@ -246,23 +242,29 @@ export class CoreDatabaseTableProxy<
|
||||||
/**
|
/**
|
||||||
* Create a database table using the given caching strategy.
|
* Create a database table using the given caching strategy.
|
||||||
*
|
*
|
||||||
* @param cachingStrategy Caching strategy.
|
* @param config Database configuration.
|
||||||
* @returns Database table.
|
* @returns Database table.
|
||||||
*/
|
*/
|
||||||
protected createTable(cachingStrategy: CoreDatabaseCachingStrategy): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
|
protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
|
||||||
const DatabaseTable = this.targetConstructors[cachingStrategy];
|
const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY];
|
||||||
|
|
||||||
return new DatabaseTable(this.database, this.tableName, this.primaryKeyColumns);
|
return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
declare module '@classes/database/database-table' {
|
||||||
* Database proxy configuration.
|
|
||||||
|
/**
|
||||||
|
* Augment CoreDatabaseConfiguration interface with data specific to this class.
|
||||||
|
*
|
||||||
|
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
||||||
*/
|
*/
|
||||||
export interface CoreDatabaseConfiguration {
|
export interface CoreDatabaseConfiguration {
|
||||||
cachingStrategy: CoreDatabaseCachingStrategy;
|
cachingStrategy: CoreDatabaseCachingStrategy;
|
||||||
debug: boolean;
|
debug: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,16 +24,30 @@ export class CoreDatabaseTable<
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
||||||
> {
|
> {
|
||||||
|
|
||||||
|
protected config: Partial<CoreDatabaseConfiguration>;
|
||||||
protected database: SQLiteDB;
|
protected database: SQLiteDB;
|
||||||
protected tableName: string;
|
protected tableName: string;
|
||||||
protected primaryKeyColumns: PrimaryKeyColumn[];
|
protected primaryKeyColumns: PrimaryKeyColumn[];
|
||||||
|
|
||||||
constructor(database: SQLiteDB, tableName: string, primaryKeyColumns?: PrimaryKeyColumn[]) {
|
constructor(
|
||||||
|
config: Partial<CoreDatabaseConfiguration>,
|
||||||
|
database: SQLiteDB,
|
||||||
|
tableName: string,
|
||||||
|
primaryKeyColumns?: PrimaryKeyColumn[],
|
||||||
|
) {
|
||||||
|
this.config = config;
|
||||||
this.database = database;
|
this.database = database;
|
||||||
this.tableName = tableName;
|
this.tableName = tableName;
|
||||||
this.primaryKeyColumns = primaryKeyColumns ?? ['id'] as PrimaryKeyColumn[];
|
this.primaryKeyColumns = primaryKeyColumns ?? ['id'] as PrimaryKeyColumn[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get database configuration.
|
||||||
|
*/
|
||||||
|
getConfig(): Partial<CoreDatabaseConfiguration> {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get database connection.
|
* Get database connection.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +89,17 @@ export class CoreDatabaseTable<
|
||||||
// Nothing to destroy by default, override this method if necessary.
|
// Nothing to destroy by default, override this method if necessary.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the table matches the given configuration for the values that concern it.
|
||||||
|
*
|
||||||
|
* @param config Database config.
|
||||||
|
* @returns Whether the table matches the given configuration.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get records matching the given conditions.
|
* Get records matching the given conditions.
|
||||||
*
|
*
|
||||||
|
@ -336,6 +361,13 @@ export class CoreDatabaseTable<
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database configuration.
|
||||||
|
*/
|
||||||
|
export interface CoreDatabaseConfiguration {
|
||||||
|
// This definition is augmented in subclasses.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CoreDatabaseTable constructor.
|
* CoreDatabaseTable constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -346,6 +378,7 @@ export type CoreDatabaseTableConstructor<
|
||||||
> = {
|
> = {
|
||||||
|
|
||||||
new (
|
new (
|
||||||
|
config: Partial<CoreDatabaseConfiguration>,
|
||||||
database: SQLiteDB,
|
database: SQLiteDB,
|
||||||
tableName: string,
|
tableName: string,
|
||||||
primaryKeyColumns?: PrimaryKeyColumn[]
|
primaryKeyColumns?: PrimaryKeyColumn[]
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class CoreDebugDatabaseTable<
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
|
|
||||||
constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>) {
|
constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>) {
|
||||||
super(target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
|
super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
|
||||||
|
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.logger = CoreLogger.getInstance(`CoreDatabase[${this.tableName}]`);
|
this.logger = CoreLogger.getInstance(`CoreDatabase[${this.tableName}]`);
|
||||||
|
@ -53,7 +53,9 @@ export class CoreDebugDatabaseTable<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
|
await super.initialize();
|
||||||
|
|
||||||
this.logger.log('initialize', this.target);
|
this.logger.log('initialize', this.target);
|
||||||
|
|
||||||
return this.target.initialize();
|
return this.target.initialize();
|
||||||
|
@ -62,7 +64,9 @@ export class CoreDebugDatabaseTable<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
destroy(): Promise<void> {
|
async destroy(): Promise<void> {
|
||||||
|
await super.destroy();
|
||||||
|
|
||||||
this.logger.log('destroy');
|
this.logger.log('destroy');
|
||||||
|
|
||||||
return this.target.destroy();
|
return this.target.destroy();
|
||||||
|
|
|
@ -40,6 +40,8 @@ export class CoreEagerDatabaseTable<
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
|
await super.initialize();
|
||||||
|
|
||||||
const records = await super.getMany();
|
const records = await super.getMany();
|
||||||
|
|
||||||
this.records = records.reduce((data, record) => {
|
this.records = records.reduce((data, record) => {
|
||||||
|
|
|
@ -14,7 +14,13 @@
|
||||||
|
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { SQLiteDBRecordValues } from '@classes/sqlitedb';
|
import { SQLiteDBRecordValues } from '@classes/sqlitedb';
|
||||||
import { CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey, CoreDatabaseQueryOptions } from './database-table';
|
import {
|
||||||
|
CoreDatabaseConfiguration,
|
||||||
|
CoreDatabaseTable,
|
||||||
|
CoreDatabaseConditions,
|
||||||
|
GetDBRecordPrimaryKey,
|
||||||
|
CoreDatabaseQueryOptions,
|
||||||
|
} from './database-table';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper used to improve performance by caching records that are used often for faster read operations.
|
* Wrapper used to improve performance by caching records that are used often for faster read operations.
|
||||||
|
@ -28,7 +34,38 @@ export class CoreLazyDatabaseTable<
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
||||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
||||||
|
|
||||||
|
protected readonly DEFAULT_CACHE_LIFETIME = 60000;
|
||||||
|
|
||||||
protected records: Record<string, DBRecord | null> = {};
|
protected records: Record<string, DBRecord | null> = {};
|
||||||
|
protected interval?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async initialize(): Promise<void> {
|
||||||
|
await super.initialize();
|
||||||
|
|
||||||
|
this.interval = window.setInterval(() => (this.records = {}), this.config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async destroy(): Promise<void> {
|
||||||
|
await super.destroy();
|
||||||
|
|
||||||
|
this.interval && window.clearInterval(this.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
matchesConfig(config: Partial<CoreDatabaseConfiguration>): boolean {
|
||||||
|
const thisCacheLifetime = this.config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME;
|
||||||
|
const otherCacheLifetime = config.lazyCacheLifetime ?? this.DEFAULT_CACHE_LIFETIME;
|
||||||
|
|
||||||
|
return super.matchesConfig(config) && thisCacheLifetime === otherCacheLifetime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -152,3 +189,16 @@ export class CoreLazyDatabaseTable<
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@classes/database/database-table' {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Augment CoreDatabaseConfiguration interface with data specific to this table.
|
||||||
|
*
|
||||||
|
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
||||||
|
*/
|
||||||
|
export interface CoreDatabaseConfiguration {
|
||||||
|
lazyCacheLifetime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -13,12 +13,8 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { mock, mockSingleton } from '@/testing/utils';
|
import { mock, mockSingleton } from '@/testing/utils';
|
||||||
import { CoreDatabaseSorting, CoreDatabaseTable } from '@classes/database/database-table';
|
import { CoreDatabaseConfiguration, CoreDatabaseSorting, CoreDatabaseTable } from '@classes/database/database-table';
|
||||||
import {
|
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
|
||||||
CoreDatabaseCachingStrategy,
|
|
||||||
CoreDatabaseConfiguration,
|
|
||||||
CoreDatabaseTableProxy,
|
|
||||||
} from '@classes/database/database-table-proxy';
|
|
||||||
import { SQLiteDB } from '@classes/sqlitedb';
|
import { SQLiteDB } from '@classes/sqlitedb';
|
||||||
import { CoreConfig } from '@services/config';
|
import { CoreConfig } from '@services/config';
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,8 @@ import { CoreAjaxError } from '@classes/errors/ajaxerror';
|
||||||
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
|
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
|
||||||
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
|
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CoreDatabaseTable } from '@classes/database/database-table';
|
import { CoreDatabaseConfiguration, CoreDatabaseTable } from '@classes/database/database-table';
|
||||||
import {
|
import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/database/database-table-proxy';
|
||||||
CoreDatabaseCachingStrategy,
|
|
||||||
CoreDatabaseConfiguration,
|
|
||||||
CoreDatabaseTableProxy,
|
|
||||||
} from '@classes/database/database-table-proxy';
|
|
||||||
import { asyncInstance, AsyncInstance } from '../utils/async-instance';
|
import { asyncInstance, AsyncInstance } from '../utils/async-instance';
|
||||||
import { CoreConfig } from './config';
|
import { CoreConfig } from './config';
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mai
|
||||||
import { CoreSitesDemoSiteData } from '@services/sites';
|
import { CoreSitesDemoSiteData } from '@services/sites';
|
||||||
import { OpenFileAction } from '@services/utils/utils';
|
import { OpenFileAction } from '@services/utils/utils';
|
||||||
import { CoreLoginSiteSelectorListMethod } from '@features/login/services/login-helper';
|
import { CoreLoginSiteSelectorListMethod } from '@features/login/services/login-helper';
|
||||||
import { CoreDatabaseConfiguration } from '@classes/database/database-table-proxy';
|
import { CoreDatabaseConfiguration } from '@classes/database/database-table';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue