MOBILE-4304 core: Return database records rowId
parent
b6f32dfddd
commit
869f08eee7
|
@ -18,7 +18,9 @@ import { CoreSiteSchema } from '@services/sites';
|
||||||
* Database variables for AddonModScormOfflineProvider.
|
* Database variables for AddonModScormOfflineProvider.
|
||||||
*/
|
*/
|
||||||
export const ATTEMPTS_TABLE_NAME = 'addon_mod_scorm_offline_attempts';
|
export const ATTEMPTS_TABLE_NAME = 'addon_mod_scorm_offline_attempts';
|
||||||
|
export const ATTEMPTS_TABLE_PRIMARY_KEYS = ['scormid', 'userid', 'attempt'] as const;
|
||||||
export const TRACKS_TABLE_NAME = 'addon_mod_scorm_offline_scos_tracks';
|
export const TRACKS_TABLE_NAME = 'addon_mod_scorm_offline_scos_tracks';
|
||||||
|
export const TRACKS_TABLE_PRIMARY_KEYS = ['scormid', 'userid', 'attempt', 'scoid', 'element'] as const;
|
||||||
export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
|
export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
|
||||||
name: 'AddonModScormOfflineProvider',
|
name: 'AddonModScormOfflineProvider',
|
||||||
version: 1,
|
version: 1,
|
||||||
|
@ -58,7 +60,7 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'TEXT',
|
type: 'TEXT',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['scormid', 'userid', 'attempt'],
|
primaryKeys: [...ATTEMPTS_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: TRACKS_TABLE_NAME,
|
name: TRACKS_TABLE_NAME,
|
||||||
|
@ -101,7 +103,7 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['scormid', 'userid', 'attempt', 'scoid', 'element'],
|
primaryKeys: [...TRACKS_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -125,6 +127,8 @@ export type AddonModScormAttemptDBRecord = AddonModScormOfflineDBCommonData & {
|
||||||
snapshot?: string | null;
|
snapshot?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AddonModScormAttemptDBPrimaryKeys = typeof ATTEMPTS_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SCORM track data.
|
* SCORM track data.
|
||||||
*/
|
*/
|
||||||
|
@ -135,3 +139,5 @@ export type AddonModScormTrackDBRecord = AddonModScormOfflineDBCommonData & {
|
||||||
timemodified: number;
|
timemodified: number;
|
||||||
synced: number;
|
synced: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AddonModScormTrackDBPrimaryKeys = typeof TRACKS_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
|
@ -22,11 +22,15 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import {
|
import {
|
||||||
|
AddonModScormAttemptDBPrimaryKeys,
|
||||||
AddonModScormAttemptDBRecord,
|
AddonModScormAttemptDBRecord,
|
||||||
AddonModScormOfflineDBCommonData,
|
AddonModScormOfflineDBCommonData,
|
||||||
|
AddonModScormTrackDBPrimaryKeys,
|
||||||
AddonModScormTrackDBRecord,
|
AddonModScormTrackDBRecord,
|
||||||
ATTEMPTS_TABLE_NAME,
|
ATTEMPTS_TABLE_NAME,
|
||||||
|
ATTEMPTS_TABLE_PRIMARY_KEYS,
|
||||||
TRACKS_TABLE_NAME,
|
TRACKS_TABLE_NAME,
|
||||||
|
TRACKS_TABLE_PRIMARY_KEYS,
|
||||||
} from './database/scorm';
|
} from './database/scorm';
|
||||||
import {
|
import {
|
||||||
AddonModScormDataEntry,
|
AddonModScormDataEntry,
|
||||||
|
@ -51,33 +55,41 @@ export class AddonModScormOfflineProvider {
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
|
|
||||||
protected tracksTables: LazyMap<
|
protected tracksTables: LazyMap<
|
||||||
AsyncInstance<CoreDatabaseTable<AddonModScormTrackDBRecord, 'scormid' | 'userid' | 'attempt' | 'scoid' | 'element'>>
|
AsyncInstance<CoreDatabaseTable<AddonModScormTrackDBRecord, AddonModScormTrackDBPrimaryKeys, never>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
protected attemptsTables: LazyMap<
|
protected attemptsTables: LazyMap<
|
||||||
AsyncInstance<CoreDatabaseTable<AddonModScormAttemptDBRecord, 'scormid' | 'userid' | 'attempt'>>
|
AsyncInstance<CoreDatabaseTable<AddonModScormAttemptDBRecord, AddonModScormAttemptDBPrimaryKeys, never>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger = CoreLogger.getInstance('AddonModScormOfflineProvider');
|
this.logger = CoreLogger.getInstance('AddonModScormOfflineProvider');
|
||||||
this.tracksTables = lazyMap(
|
this.tracksTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(TRACKS_TABLE_NAME, {
|
() => CoreSites.getSiteTable<AddonModScormTrackDBRecord, AddonModScormTrackDBPrimaryKeys, never>(
|
||||||
siteId,
|
TRACKS_TABLE_NAME,
|
||||||
primaryKeyColumns: ['scormid', 'userid', 'attempt', 'scoid', 'element'],
|
{
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
siteId,
|
||||||
onDestroy: () => delete this.tracksTables[siteId],
|
primaryKeyColumns: [...TRACKS_TABLE_PRIMARY_KEYS],
|
||||||
}),
|
rowIdColumn: null,
|
||||||
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
|
onDestroy: () => delete this.tracksTables[siteId],
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
this.attemptsTables = lazyMap(
|
this.attemptsTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(ATTEMPTS_TABLE_NAME, {
|
() => CoreSites.getSiteTable<AddonModScormAttemptDBRecord, AddonModScormAttemptDBPrimaryKeys, never>(
|
||||||
siteId,
|
ATTEMPTS_TABLE_NAME,
|
||||||
primaryKeyColumns: ['scormid', 'userid', 'attempt'],
|
{
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
siteId,
|
||||||
onDestroy: () => delete this.tracksTables[siteId],
|
primaryKeyColumns: [...ATTEMPTS_TABLE_PRIMARY_KEYS],
|
||||||
}),
|
rowIdColumn: null,
|
||||||
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
|
onDestroy: () => delete this.tracksTables[siteId],
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,16 +38,17 @@ import { CoreLazyDatabaseTable } from './lazy-database-table';
|
||||||
export class CoreDatabaseTableProxy<
|
export class CoreDatabaseTableProxy<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
|
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
|
|
||||||
protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None;
|
protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None;
|
||||||
|
|
||||||
protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>();
|
protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>>();
|
||||||
protected environmentObserver?: CoreEventObserver;
|
protected environmentObserver?: CoreEventObserver;
|
||||||
protected targetConstructors: Record<
|
protected targetConstructors: Record<
|
||||||
CoreDatabaseCachingStrategy,
|
CoreDatabaseCachingStrategy,
|
||||||
CoreDatabaseTableConstructor<DBRecord, PrimaryKeyColumn, PrimaryKey>
|
CoreDatabaseTableConstructor<DBRecord, PrimaryKeyColumn, RowIdColumn>
|
||||||
> = {
|
> = {
|
||||||
[CoreDatabaseCachingStrategy.Eager]: CoreEagerDatabaseTable,
|
[CoreDatabaseCachingStrategy.Eager]: CoreEagerDatabaseTable,
|
||||||
[CoreDatabaseCachingStrategy.Lazy]: CoreLazyDatabaseTable,
|
[CoreDatabaseCachingStrategy.Lazy]: CoreLazyDatabaseTable,
|
||||||
|
@ -154,7 +155,7 @@ export class CoreDatabaseTableProxy<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async insert(record: DBRecord): Promise<void> {
|
async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
|
||||||
return this.target.insert(record);
|
return this.target.insert(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +240,7 @@ export class CoreDatabaseTableProxy<
|
||||||
*
|
*
|
||||||
* @returns Target instance.
|
* @returns Target instance.
|
||||||
*/
|
*/
|
||||||
protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
|
protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>> {
|
||||||
const config = await this.getRuntimeConfig();
|
const config = await this.getRuntimeConfig();
|
||||||
const table = this.createTable(config);
|
const table = this.createTable(config);
|
||||||
|
|
||||||
|
@ -252,7 +253,7 @@ export class CoreDatabaseTableProxy<
|
||||||
* @param config Database configuration.
|
* @param config Database configuration.
|
||||||
* @returns Database table.
|
* @returns Database table.
|
||||||
*/
|
*/
|
||||||
protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> {
|
protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn> {
|
||||||
const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY];
|
const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY];
|
||||||
|
|
||||||
return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns);
|
return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns);
|
||||||
|
|
|
@ -21,13 +21,15 @@ import { SQLiteDB, SQLiteDBRecordValue, SQLiteDBRecordValues } from '@classes/sq
|
||||||
export class CoreDatabaseTable<
|
export class CoreDatabaseTable<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
> {
|
> {
|
||||||
|
|
||||||
protected config: Partial<CoreDatabaseConfiguration>;
|
protected config: Partial<CoreDatabaseConfiguration>;
|
||||||
protected database: SQLiteDB;
|
protected database: SQLiteDB;
|
||||||
protected tableName: string;
|
protected tableName: string;
|
||||||
protected primaryKeyColumns: PrimaryKeyColumn[];
|
protected primaryKeyColumns: PrimaryKeyColumn[];
|
||||||
|
protected rowIdColumn: RowIdColumn | null;
|
||||||
protected listeners: CoreDatabaseTableListener[] = [];
|
protected listeners: CoreDatabaseTableListener[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -35,11 +37,13 @@ export class CoreDatabaseTable<
|
||||||
database: SQLiteDB,
|
database: SQLiteDB,
|
||||||
tableName: string,
|
tableName: string,
|
||||||
primaryKeyColumns?: PrimaryKeyColumn[],
|
primaryKeyColumns?: PrimaryKeyColumn[],
|
||||||
|
rowIdColumn?: RowIdColumn | null,
|
||||||
) {
|
) {
|
||||||
this.config = config;
|
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[];
|
||||||
|
this.rowIdColumn = rowIdColumn === null ? null : (rowIdColumn ?? 'id') as RowIdColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,9 +257,12 @@ export class CoreDatabaseTable<
|
||||||
* Insert a new record.
|
* Insert a new record.
|
||||||
*
|
*
|
||||||
* @param record Database record.
|
* @param record Database record.
|
||||||
|
* @returns New record row id.
|
||||||
*/
|
*/
|
||||||
async insert(record: DBRecord): Promise<void> {
|
async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
|
||||||
await this.database.insertRecord(this.tableName, record);
|
const rowId = await this.database.insertRecord(this.tableName, record);
|
||||||
|
|
||||||
|
return rowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,7 +270,7 @@ export class CoreDatabaseTable<
|
||||||
*
|
*
|
||||||
* @param record Database record.
|
* @param record Database record.
|
||||||
*/
|
*/
|
||||||
syncInsert(record: DBRecord): void {
|
syncInsert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): void {
|
||||||
// The current database architecture does not support synchronous operations,
|
// The current database architecture does not support synchronous operations,
|
||||||
// so calling this method will mean that errors will be silenced. Because of that,
|
// so calling this method will mean that errors will be silenced. Because of that,
|
||||||
// this should only be called if using the asynchronous alternatives is not possible.
|
// this should only be called if using the asynchronous alternatives is not possible.
|
||||||
|
@ -423,15 +430,17 @@ export interface CoreDatabaseTableListener {
|
||||||
export type CoreDatabaseTableConstructor<
|
export type CoreDatabaseTableConstructor<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
> = {
|
> = {
|
||||||
|
|
||||||
new (
|
new (
|
||||||
config: Partial<CoreDatabaseConfiguration>,
|
config: Partial<CoreDatabaseConfiguration>,
|
||||||
database: SQLiteDB,
|
database: SQLiteDB,
|
||||||
tableName: string,
|
tableName: string,
|
||||||
primaryKeyColumns?: PrimaryKeyColumn[]
|
primaryKeyColumns?: PrimaryKeyColumn[],
|
||||||
): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>;
|
rowIdColumn?: RowIdColumn | null,
|
||||||
|
): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,14 @@ import {
|
||||||
export class CoreDebugDatabaseTable<
|
export class CoreDebugDatabaseTable<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
|
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
|
|
||||||
protected target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>;
|
protected target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>;
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
|
|
||||||
constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>) {
|
constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>) {
|
||||||
super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
|
super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
|
||||||
|
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
@ -48,7 +49,7 @@ export class CoreDebugDatabaseTable<
|
||||||
*
|
*
|
||||||
* @returns Table instance.
|
* @returns Table instance.
|
||||||
*/
|
*/
|
||||||
getTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
getTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
return this.target;
|
return this.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@ export class CoreDebugDatabaseTable<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
insert(record: DBRecord): Promise<void> {
|
insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
|
||||||
this.logger.log('insert', record);
|
this.logger.log('insert', record);
|
||||||
|
|
||||||
return this.target.insert(record);
|
return this.target.insert(record);
|
||||||
|
|
|
@ -31,8 +31,9 @@ import {
|
||||||
export class CoreEagerDatabaseTable<
|
export class CoreEagerDatabaseTable<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
|
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
|
|
||||||
protected records: Record<string, DBRecord> = {};
|
protected records: Record<string, DBRecord> = {};
|
||||||
|
|
||||||
|
@ -153,12 +154,10 @@ export class CoreEagerDatabaseTable<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async insert(record: DBRecord): Promise<void> {
|
async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
|
||||||
await super.insert(record);
|
const rowId = await this.insertAndRemember(record, this.records);
|
||||||
|
|
||||||
const primaryKey = this.serializePrimaryKey(this.getPrimaryKeyFromRecord(record));
|
return rowId;
|
||||||
|
|
||||||
this.records[primaryKey] = record;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,8 +26,9 @@ import { CoreDatabaseTable, GetDBRecordPrimaryKey } from './database-table';
|
||||||
export abstract class CoreInMemoryDatabaseTable<
|
export abstract class CoreInMemoryDatabaseTable<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
|
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
|
|
||||||
private static readonly ACTIVE_TABLES: WeakMap<SQLiteDB, Set<string>> = new WeakMap();
|
private static readonly ACTIVE_TABLES: WeakMap<SQLiteDB, Set<string>> = new WeakMap();
|
||||||
private static readonly LOGGER: CoreLogger = CoreLogger.getInstance('CoreInMemoryDatabaseTable');
|
private static readonly LOGGER: CoreLogger = CoreLogger.getInstance('CoreInMemoryDatabaseTable');
|
||||||
|
@ -70,4 +71,28 @@ export abstract class CoreInMemoryDatabaseTable<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new record and store it in the given object.
|
||||||
|
*
|
||||||
|
* @param record Database record.
|
||||||
|
* @param records Records object.
|
||||||
|
* @returns New record row id.
|
||||||
|
*/
|
||||||
|
protected async insertAndRemember(
|
||||||
|
record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>,
|
||||||
|
records: Record<string, DBRecord | null>,
|
||||||
|
): Promise<number> {
|
||||||
|
const rowId = await super.insert(record);
|
||||||
|
|
||||||
|
const completeRecord = (this.rowIdColumn && !(this.rowIdColumn in record))
|
||||||
|
? Object.assign({ [this.rowIdColumn]: rowId }, record) as DBRecord
|
||||||
|
: record as DBRecord;
|
||||||
|
|
||||||
|
const primaryKey = this.serializePrimaryKey(this.getPrimaryKeyFromRecord(completeRecord));
|
||||||
|
|
||||||
|
records[primaryKey] = completeRecord;
|
||||||
|
|
||||||
|
return rowId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,9 @@ import {
|
||||||
export class CoreLazyDatabaseTable<
|
export class CoreLazyDatabaseTable<
|
||||||
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
PrimaryKeyColumn extends keyof DBRecord = 'id',
|
||||||
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>
|
RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
|
||||||
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> {
|
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
|
||||||
|
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
|
||||||
|
|
||||||
protected readonly DEFAULT_CACHE_LIFETIME = 60000;
|
protected readonly DEFAULT_CACHE_LIFETIME = 60000;
|
||||||
|
|
||||||
|
@ -137,10 +138,10 @@ export class CoreLazyDatabaseTable<
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async insert(record: DBRecord): Promise<void> {
|
async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
|
||||||
await super.insert(record);
|
const rowId = await this.insertAndRemember(record, this.records);
|
||||||
|
|
||||||
this.records[this.serializePrimaryKey(this.getPrimaryKeyFromRecord(record))] = record;
|
return rowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,8 +42,10 @@ import { CoreDatabaseCachingStrategy } from '../database/database-table-proxy';
|
||||||
import {
|
import {
|
||||||
CONFIG_TABLE,
|
CONFIG_TABLE,
|
||||||
CoreSiteConfigDBRecord,
|
CoreSiteConfigDBRecord,
|
||||||
|
CoreSiteLastViewedDBPrimaryKeys,
|
||||||
CoreSiteLastViewedDBRecord,
|
CoreSiteLastViewedDBRecord,
|
||||||
CoreSiteWSCacheRecord,
|
CoreSiteWSCacheRecord,
|
||||||
|
LAST_VIEWED_PRIMARY_KEYS,
|
||||||
LAST_VIEWED_TABLE,
|
LAST_VIEWED_TABLE,
|
||||||
WS_CACHE_TABLE,
|
WS_CACHE_TABLE,
|
||||||
} from '@services/database/sites';
|
} from '@services/database/sites';
|
||||||
|
@ -65,8 +67,8 @@ export class CoreSite extends CoreAuthenticatedSite {
|
||||||
|
|
||||||
protected db!: SQLiteDB;
|
protected db!: SQLiteDB;
|
||||||
protected cacheTable: AsyncInstance<CoreDatabaseTable<CoreSiteWSCacheRecord>>;
|
protected cacheTable: AsyncInstance<CoreDatabaseTable<CoreSiteWSCacheRecord>>;
|
||||||
protected configTable: AsyncInstance<CoreDatabaseTable<CoreSiteConfigDBRecord, 'name'>>;
|
protected configTable: AsyncInstance<CoreDatabaseTable<CoreSiteConfigDBRecord, 'name', never>>;
|
||||||
protected lastViewedTable: AsyncInstance<CoreDatabaseTable<CoreSiteLastViewedDBRecord, 'component' | 'id'>>;
|
protected lastViewedTable: AsyncInstance<CoreDatabaseTable<CoreSiteLastViewedDBRecord, CoreSiteLastViewedDBPrimaryKeys>>;
|
||||||
protected lastAutoLogin = 0;
|
protected lastAutoLogin = 0;
|
||||||
protected tokenPluginFileWorks?: boolean;
|
protected tokenPluginFileWorks?: boolean;
|
||||||
protected tokenPluginFileWorksPromise?: Promise<boolean>;
|
protected tokenPluginFileWorksPromise?: Promise<boolean>;
|
||||||
|
@ -99,18 +101,19 @@ export class CoreSite extends CoreAuthenticatedSite {
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.configTable = asyncInstance(() => CoreSites.getSiteTable(CONFIG_TABLE, {
|
this.configTable = asyncInstance(() => CoreSites.getSiteTable<CoreSiteConfigDBRecord, 'name', never>(CONFIG_TABLE, {
|
||||||
siteId: this.getId(),
|
siteId: this.getId(),
|
||||||
database: this.getDb(),
|
database: this.getDb(),
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
primaryKeyColumns: ['name'],
|
primaryKeyColumns: ['name'],
|
||||||
|
rowIdColumn: null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.lastViewedTable = asyncInstance(() => CoreSites.getSiteTable(LAST_VIEWED_TABLE, {
|
this.lastViewedTable = asyncInstance(() => CoreSites.getSiteTable(LAST_VIEWED_TABLE, {
|
||||||
siteId: this.getId(),
|
siteId: this.getId(),
|
||||||
database: this.getDb(),
|
database: this.getDb(),
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
primaryKeyColumns: ['component', 'id'],
|
primaryKeyColumns: [...LAST_VIEWED_PRIMARY_KEYS],
|
||||||
}));
|
}));
|
||||||
this.setInfo(otherData.info);
|
this.setInfo(otherData.info);
|
||||||
this.calculateOfflineDisabled();
|
this.calculateOfflineDisabled();
|
||||||
|
|
|
@ -27,7 +27,12 @@ import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CoreCourseStatusDBRecord, CoreCourseViewedModulesDBRecord, COURSE_STATUS_TABLE, COURSE_VIEWED_MODULES_TABLE ,
|
CoreCourseStatusDBRecord,
|
||||||
|
CoreCourseViewedModulesDBPrimaryKeys,
|
||||||
|
CoreCourseViewedModulesDBRecord,
|
||||||
|
COURSE_STATUS_TABLE,
|
||||||
|
COURSE_VIEWED_MODULES_PRIMARY_KEYS,
|
||||||
|
COURSE_VIEWED_MODULES_TABLE,
|
||||||
} from './database/course';
|
} from './database/course';
|
||||||
import { CoreCourseOffline } from './course-offline';
|
import { CoreCourseOffline } from './course-offline';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
|
@ -121,7 +126,9 @@ export class CoreCourseProvider {
|
||||||
|
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
protected statusTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseStatusDBRecord>>>;
|
protected statusTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseStatusDBRecord>>>;
|
||||||
protected viewedModulesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseViewedModulesDBRecord, 'courseId' | 'cmId'>>>;
|
protected viewedModulesTables: LazyMap<
|
||||||
|
AsyncInstance<CoreDatabaseTable<CoreCourseViewedModulesDBRecord, CoreCourseViewedModulesDBPrimaryKeys, never>>
|
||||||
|
>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger = CoreLogger.getInstance('CoreCourseProvider');
|
this.logger = CoreLogger.getInstance('CoreCourseProvider');
|
||||||
|
@ -137,12 +144,16 @@ export class CoreCourseProvider {
|
||||||
|
|
||||||
this.viewedModulesTables = lazyMap(
|
this.viewedModulesTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(COURSE_VIEWED_MODULES_TABLE, {
|
() => CoreSites.getSiteTable<CoreCourseViewedModulesDBRecord, CoreCourseViewedModulesDBPrimaryKeys, never>(
|
||||||
siteId,
|
COURSE_VIEWED_MODULES_TABLE,
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
{
|
||||||
primaryKeyColumns: ['courseId', 'cmId'],
|
siteId,
|
||||||
onDestroy: () => delete this.viewedModulesTables[siteId],
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
}),
|
primaryKeyColumns: [...COURSE_VIEWED_MODULES_PRIMARY_KEYS],
|
||||||
|
rowIdColumn: null,
|
||||||
|
onDestroy: () => delete this.viewedModulesTables[siteId],
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { CoreSiteSchema } from '@services/sites';
|
||||||
*/
|
*/
|
||||||
export const COURSE_STATUS_TABLE = 'course_status';
|
export const COURSE_STATUS_TABLE = 'course_status';
|
||||||
export const COURSE_VIEWED_MODULES_TABLE = 'course_viewed_modules';
|
export const COURSE_VIEWED_MODULES_TABLE = 'course_viewed_modules';
|
||||||
|
export const COURSE_VIEWED_MODULES_PRIMARY_KEYS = ['courseId', 'cmId'] as const;
|
||||||
export const SITE_SCHEMA: CoreSiteSchema = {
|
export const SITE_SCHEMA: CoreSiteSchema = {
|
||||||
name: 'CoreCourseProvider',
|
name: 'CoreCourseProvider',
|
||||||
version: 2,
|
version: 2,
|
||||||
|
@ -75,7 +76,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['courseId', 'cmId'],
|
primaryKeys: [...COURSE_VIEWED_MODULES_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -133,6 +134,8 @@ export type CoreCourseViewedModulesDBRecord = {
|
||||||
sectionId?: number;
|
sectionId?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CoreCourseViewedModulesDBPrimaryKeys = typeof COURSE_VIEWED_MODULES_PRIMARY_KEYS[number];
|
||||||
|
|
||||||
export type CoreCourseManualCompletionDBRecord = {
|
export type CoreCourseManualCompletionDBRecord = {
|
||||||
cmid: number;
|
cmid: number;
|
||||||
completed: number;
|
completed: number;
|
||||||
|
|
|
@ -21,8 +21,10 @@ import { CoreSiteSchema } from '@services/sites';
|
||||||
* Keep "addon" in some names for backwards compatibility.
|
* Keep "addon" in some names for backwards compatibility.
|
||||||
*/
|
*/
|
||||||
export const BADGE_TABLE_NAME = 'addon_pushnotifications_badge';
|
export const BADGE_TABLE_NAME = 'addon_pushnotifications_badge';
|
||||||
|
export const BADGE_TABLE_PRIMARY_KEYS = ['siteid', 'addon'] as const;
|
||||||
export const PENDING_UNREGISTER_TABLE_NAME = 'addon_pushnotifications_pending_unregister';
|
export const PENDING_UNREGISTER_TABLE_NAME = 'addon_pushnotifications_pending_unregister';
|
||||||
export const REGISTERED_DEVICES_TABLE_NAME = 'addon_pushnotifications_registered_devices_2';
|
export const REGISTERED_DEVICES_TABLE_NAME = 'addon_pushnotifications_registered_devices_2';
|
||||||
|
export const REGISTERED_DEVICES_TABLE_PRIMARY_KEYS = ['appid', 'uuid'] as const;
|
||||||
export const APP_SCHEMA: CoreAppSchema = {
|
export const APP_SCHEMA: CoreAppSchema = {
|
||||||
name: 'CorePushNotificationsProvider',
|
name: 'CorePushNotificationsProvider',
|
||||||
version: 1,
|
version: 1,
|
||||||
|
@ -43,7 +45,7 @@ export const APP_SCHEMA: CoreAppSchema = {
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['siteid', 'addon'],
|
primaryKeys: [...BADGE_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: PENDING_UNREGISTER_TABLE_NAME,
|
name: PENDING_UNREGISTER_TABLE_NAME,
|
||||||
|
@ -109,7 +111,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'TEXT',
|
type: 'TEXT',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['appid', 'uuid'],
|
primaryKeys: [...REGISTERED_DEVICES_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
|
||||||
|
@ -129,6 +131,8 @@ export type CorePushNotificationsBadgeDBRecord = {
|
||||||
number: number; // eslint-disable-line id-blacklist
|
number: number; // eslint-disable-line id-blacklist
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CorePushNotificationsBadgeDBPrimaryKeys = typeof BADGE_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data stored in DB for pending unregisters.
|
* Data stored in DB for pending unregisters.
|
||||||
*/
|
*/
|
||||||
|
@ -152,3 +156,5 @@ export type CorePushNotificationsRegisteredDeviceDBRecord = {
|
||||||
pushid: string; // Push ID.
|
pushid: string; // Push ID.
|
||||||
publickey?: string; // Public key.
|
publickey?: string; // Public key.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CorePushNotificationsRegisteredDeviceDBPrimaryKeys = typeof REGISTERED_DEVICES_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
|
@ -36,6 +36,10 @@ import {
|
||||||
CorePushNotificationsPendingUnregisterDBRecord,
|
CorePushNotificationsPendingUnregisterDBRecord,
|
||||||
CorePushNotificationsRegisteredDeviceDBRecord,
|
CorePushNotificationsRegisteredDeviceDBRecord,
|
||||||
CorePushNotificationsBadgeDBRecord,
|
CorePushNotificationsBadgeDBRecord,
|
||||||
|
REGISTERED_DEVICES_TABLE_PRIMARY_KEYS,
|
||||||
|
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
|
||||||
|
CorePushNotificationsBadgeDBPrimaryKeys,
|
||||||
|
BADGE_TABLE_PRIMARY_KEYS,
|
||||||
} from './database/pushnotifications';
|
} from './database/pushnotifications';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreWSExternalWarning } from '@services/ws';
|
import { CoreWSExternalWarning } from '@services/ws';
|
||||||
|
@ -61,23 +65,38 @@ export class CorePushNotificationsProvider {
|
||||||
|
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
protected pushID?: string;
|
protected pushID?: string;
|
||||||
protected badgesTable = asyncInstance<CoreDatabaseTable<CorePushNotificationsBadgeDBRecord, 'siteid' | 'addon'>>();
|
protected badgesTable =
|
||||||
|
asyncInstance<CoreDatabaseTable<CorePushNotificationsBadgeDBRecord, CorePushNotificationsBadgeDBPrimaryKeys>>();
|
||||||
|
|
||||||
protected pendingUnregistersTable =
|
protected pendingUnregistersTable =
|
||||||
asyncInstance<CoreDatabaseTable<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>>();
|
asyncInstance<CoreDatabaseTable<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>>();
|
||||||
|
|
||||||
protected registeredDevicesTables:
|
protected registeredDevicesTables:
|
||||||
LazyMap<AsyncInstance<CoreDatabaseTable<CorePushNotificationsRegisteredDeviceDBRecord, 'appid' | 'uuid'>>>;
|
LazyMap<
|
||||||
|
AsyncInstance<
|
||||||
|
CoreDatabaseTable<
|
||||||
|
CorePushNotificationsRegisteredDeviceDBRecord,
|
||||||
|
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
|
||||||
|
never
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger = CoreLogger.getInstance('CorePushNotificationsProvider');
|
this.logger = CoreLogger.getInstance('CorePushNotificationsProvider');
|
||||||
this.registeredDevicesTables = lazyMap(
|
this.registeredDevicesTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(
|
() => CoreSites.getSiteTable<
|
||||||
|
CorePushNotificationsRegisteredDeviceDBRecord,
|
||||||
|
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
|
||||||
|
never
|
||||||
|
>(
|
||||||
REGISTERED_DEVICES_TABLE_NAME,
|
REGISTERED_DEVICES_TABLE_NAME,
|
||||||
{
|
{
|
||||||
siteId,
|
siteId,
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
|
||||||
primaryKeyColumns: ['appid', 'uuid'],
|
primaryKeyColumns: [...REGISTERED_DEVICES_TABLE_PRIMARY_KEYS],
|
||||||
|
rowIdColumn: null,
|
||||||
onDestroy: () => delete this.registeredDevicesTables[siteId],
|
onDestroy: () => delete this.registeredDevicesTables[siteId],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -190,11 +209,11 @@ export class CorePushNotificationsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
const database = CoreApp.getDB();
|
const database = CoreApp.getDB();
|
||||||
const badgesTable = new CoreDatabaseTableProxy<CorePushNotificationsBadgeDBRecord, 'siteid' | 'addon'>(
|
const badgesTable = new CoreDatabaseTableProxy<CorePushNotificationsBadgeDBRecord, CorePushNotificationsBadgeDBPrimaryKeys>(
|
||||||
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
database,
|
database,
|
||||||
BADGE_TABLE_NAME,
|
BADGE_TABLE_NAME,
|
||||||
['siteid', 'addon'],
|
[...BADGE_TABLE_PRIMARY_KEYS],
|
||||||
);
|
);
|
||||||
const pendingUnregistersTable = new CoreDatabaseTableProxy<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>(
|
const pendingUnregistersTable = new CoreDatabaseTableProxy<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>(
|
||||||
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
|
|
|
@ -49,7 +49,6 @@ export class CoreUserToursService {
|
||||||
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
CoreApp.getDB(),
|
CoreApp.getDB(),
|
||||||
USER_TOURS_TABLE_NAME,
|
USER_TOURS_TABLE_NAME,
|
||||||
['id'],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await table.initialize();
|
await table.initialize();
|
||||||
|
|
|
@ -19,8 +19,10 @@ import { CoreSiteSchema } from '@services/sites';
|
||||||
* Database variables for CoreFilepool service.
|
* Database variables for CoreFilepool service.
|
||||||
*/
|
*/
|
||||||
export const QUEUE_TABLE_NAME = 'filepool_files_queue'; // Queue of files to download.
|
export const QUEUE_TABLE_NAME = 'filepool_files_queue'; // Queue of files to download.
|
||||||
|
export const QUEUE_TABLE_PRIMARY_KEYS = ['siteId', 'fileId'] as const;
|
||||||
export const FILES_TABLE_NAME = 'filepool_files'; // Downloaded files.
|
export const FILES_TABLE_NAME = 'filepool_files'; // Downloaded files.
|
||||||
export const LINKS_TABLE_NAME = 'filepool_files_links'; // Links between downloaded files and components.
|
export const LINKS_TABLE_NAME = 'filepool_files_links'; // Links between downloaded files and components.
|
||||||
|
export const LINKS_TABLE_PRIMARY_KEYS = ['fileId', 'component', 'componentId'] as const;
|
||||||
export const PACKAGES_TABLE_NAME = 'filepool_packages'; // Downloaded packages (sets of files).
|
export const PACKAGES_TABLE_NAME = 'filepool_packages'; // Downloaded packages (sets of files).
|
||||||
export const APP_SCHEMA: CoreAppSchema = {
|
export const APP_SCHEMA: CoreAppSchema = {
|
||||||
name: 'CoreFilepoolProvider',
|
name: 'CoreFilepoolProvider',
|
||||||
|
@ -74,7 +76,7 @@ export const APP_SCHEMA: CoreAppSchema = {
|
||||||
type: 'TEXT',
|
type: 'TEXT',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['siteId', 'fileId'],
|
primaryKeys: [...QUEUE_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -146,7 +148,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'TEXT',
|
type: 'TEXT',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['fileId', 'component', 'componentId'],
|
primaryKeys: [...LINKS_TABLE_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: PACKAGES_TABLE_NAME,
|
name: PACKAGES_TABLE_NAME,
|
||||||
|
@ -241,7 +243,7 @@ export type CoreFilepoolFileEntry = CoreFilepoolFileOptions & {
|
||||||
/**
|
/**
|
||||||
* DB data for entry from file's queue.
|
* DB data for entry from file's queue.
|
||||||
*/
|
*/
|
||||||
export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & {
|
export type CoreFilepoolQueueDBRecord = CoreFilepoolFileOptions & {
|
||||||
/**
|
/**
|
||||||
* The site the file belongs to.
|
* The site the file belongs to.
|
||||||
*/
|
*/
|
||||||
|
@ -278,10 +280,12 @@ export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & {
|
||||||
links: string;
|
links: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CoreFilepoolQueueDBPrimaryKeys = typeof QUEUE_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry from the file's queue.
|
* Entry from the file's queue.
|
||||||
*/
|
*/
|
||||||
export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBEntry & {
|
export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBRecord & {
|
||||||
/**
|
/**
|
||||||
* File links (to link the file to components and componentIds).
|
* File links (to link the file to components and componentIds).
|
||||||
*/
|
*/
|
||||||
|
@ -356,8 +360,10 @@ export type CoreFilepoolComponentLink = {
|
||||||
/**
|
/**
|
||||||
* Links table record type.
|
* Links table record type.
|
||||||
*/
|
*/
|
||||||
export type CoreFilepoolLinksRecord = {
|
export type CoreFilepoolLinksDBRecord = {
|
||||||
fileId: string; // File Id.
|
fileId: string; // File Id.
|
||||||
component: string; // Component name.
|
component: string; // Component name.
|
||||||
componentId: number | string; // Component Id.
|
componentId: number | string; // Component Id.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CoreFilepoolLinksDBPrimaryKeys = typeof LINKS_TABLE_PRIMARY_KEYS[number];
|
||||||
|
|
|
@ -28,6 +28,7 @@ export const SCHEMA_VERSIONS_TABLE_NAME = 'schema_versions';
|
||||||
export const WS_CACHE_TABLE = 'wscache_2';
|
export const WS_CACHE_TABLE = 'wscache_2';
|
||||||
export const CONFIG_TABLE = 'core_site_config';
|
export const CONFIG_TABLE = 'core_site_config';
|
||||||
export const LAST_VIEWED_TABLE = 'core_site_last_viewed';
|
export const LAST_VIEWED_TABLE = 'core_site_last_viewed';
|
||||||
|
export const LAST_VIEWED_PRIMARY_KEYS = ['component', 'id'] as const;
|
||||||
|
|
||||||
// Schema to register in App DB.
|
// Schema to register in App DB.
|
||||||
export const APP_SCHEMA: CoreAppSchema = {
|
export const APP_SCHEMA: CoreAppSchema = {
|
||||||
|
@ -156,7 +157,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
|
||||||
type: 'INTEGER',
|
type: 'INTEGER',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primaryKeys: ['component', 'id'],
|
primaryKeys: [...LAST_VIEWED_PRIMARY_KEYS],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -214,3 +215,5 @@ export type CoreSiteLastViewedDBRecord = {
|
||||||
timeaccess: number;
|
timeaccess: number;
|
||||||
data?: string;
|
data?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CoreSiteLastViewedDBPrimaryKeys = typeof LAST_VIEWED_PRIMARY_KEYS[number];
|
||||||
|
|
|
@ -42,10 +42,14 @@ import {
|
||||||
CoreFilepoolFileEntry,
|
CoreFilepoolFileEntry,
|
||||||
CoreFilepoolComponentLink,
|
CoreFilepoolComponentLink,
|
||||||
CoreFilepoolFileOptions,
|
CoreFilepoolFileOptions,
|
||||||
CoreFilepoolLinksRecord,
|
CoreFilepoolLinksDBRecord,
|
||||||
CoreFilepoolPackageEntry,
|
CoreFilepoolPackageEntry,
|
||||||
CoreFilepoolQueueEntry,
|
CoreFilepoolQueueEntry,
|
||||||
CoreFilepoolQueueDBEntry,
|
CoreFilepoolQueueDBRecord,
|
||||||
|
CoreFilepoolLinksDBPrimaryKeys,
|
||||||
|
LINKS_TABLE_PRIMARY_KEYS,
|
||||||
|
CoreFilepoolQueueDBPrimaryKeys,
|
||||||
|
QUEUE_TABLE_PRIMARY_KEYS,
|
||||||
} from '@services/database/filepool';
|
} from '@services/database/filepool';
|
||||||
import { CoreFileHelper } from './file-helper';
|
import { CoreFileHelper } from './file-helper';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
|
@ -102,33 +106,39 @@ export class CoreFilepoolProvider {
|
||||||
// Variables to prevent downloading packages/files twice at the same time.
|
// Variables to prevent downloading packages/files twice at the same time.
|
||||||
protected packagesPromises: { [s: string]: { [s: string]: Promise<void> } } = {};
|
protected packagesPromises: { [s: string]: { [s: string]: Promise<void> } } = {};
|
||||||
protected filePromises: { [s: string]: { [s: string]: Promise<string> } } = {};
|
protected filePromises: { [s: string]: { [s: string]: Promise<string> } } = {};
|
||||||
protected filesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolFileEntry, 'fileId'>>>;
|
protected filesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolFileEntry, 'fileId', never>>>;
|
||||||
protected linksTables:
|
protected linksTables: LazyMap<
|
||||||
LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolLinksRecord, 'fileId' | 'component' | 'componentId'>>>;
|
AsyncInstance<CoreDatabaseTable<CoreFilepoolLinksDBRecord, CoreFilepoolLinksDBPrimaryKeys, never>>
|
||||||
|
>;
|
||||||
|
|
||||||
protected packagesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolPackageEntry>>>;
|
protected packagesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolPackageEntry>>>;
|
||||||
protected queueTable = asyncInstance<CoreDatabaseTable<CoreFilepoolQueueDBEntry, 'siteId' | 'fileId'>>();
|
protected queueTable = asyncInstance<CoreDatabaseTable<CoreFilepoolQueueDBRecord, CoreFilepoolQueueDBPrimaryKeys>>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger = CoreLogger.getInstance('CoreFilepoolProvider');
|
this.logger = CoreLogger.getInstance('CoreFilepoolProvider');
|
||||||
this.filesTables = lazyMap(
|
this.filesTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(FILES_TABLE_NAME, {
|
() => CoreSites.getSiteTable<CoreFilepoolFileEntry, 'fileId', never>(FILES_TABLE_NAME, {
|
||||||
siteId,
|
siteId,
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
||||||
primaryKeyColumns: ['fileId'],
|
primaryKeyColumns: ['fileId'],
|
||||||
|
rowIdColumn: null,
|
||||||
onDestroy: () => delete this.filesTables[siteId],
|
onDestroy: () => delete this.filesTables[siteId],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
this.linksTables = lazyMap(
|
this.linksTables = lazyMap(
|
||||||
siteId => asyncInstance(
|
siteId => asyncInstance(
|
||||||
() => CoreSites.getSiteTable(LINKS_TABLE_NAME, {
|
() => CoreSites.getSiteTable<CoreFilepoolLinksDBRecord, CoreFilepoolLinksDBPrimaryKeys, never>(
|
||||||
siteId,
|
LINKS_TABLE_NAME,
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
{
|
||||||
primaryKeyColumns: ['fileId', 'component', 'componentId'],
|
siteId,
|
||||||
onDestroy: () => delete this.linksTables[siteId],
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
||||||
}),
|
primaryKeyColumns: [...LINKS_TABLE_PRIMARY_KEYS],
|
||||||
|
rowIdColumn: null,
|
||||||
|
onDestroy: () => delete this.linksTables[siteId],
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
this.packagesTables = lazyMap(
|
this.packagesTables = lazyMap(
|
||||||
|
@ -168,11 +178,11 @@ export class CoreFilepoolProvider {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
const queueTable = new CoreDatabaseTableProxy<CoreFilepoolQueueDBEntry, 'siteId' | 'fileId'>(
|
const queueTable = new CoreDatabaseTableProxy<CoreFilepoolQueueDBRecord, CoreFilepoolQueueDBPrimaryKeys>(
|
||||||
{ cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
{ cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
|
||||||
CoreApp.getDB(),
|
CoreApp.getDB(),
|
||||||
QUEUE_TABLE_NAME,
|
QUEUE_TABLE_NAME,
|
||||||
['siteId','fileId'],
|
[...QUEUE_TABLE_PRIMARY_KEYS],
|
||||||
);
|
);
|
||||||
|
|
||||||
await queueTable.initialize();
|
await queueTable.initialize();
|
||||||
|
@ -406,7 +416,7 @@ export class CoreFilepoolProvider {
|
||||||
return this.addToQueue(siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link);
|
return this.addToQueue(siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newData: Partial<CoreFilepoolQueueDBEntry> = {};
|
const newData: Partial<CoreFilepoolQueueDBRecord> = {};
|
||||||
let foundLink = false;
|
let foundLink = false;
|
||||||
|
|
||||||
// We already have the file in queue, we update the priority and links.
|
// We already have the file in queue, we update the priority and links.
|
||||||
|
@ -1245,7 +1255,7 @@ export class CoreFilepoolProvider {
|
||||||
siteId: string | undefined,
|
siteId: string | undefined,
|
||||||
component: string,
|
component: string,
|
||||||
componentId?: string | number,
|
componentId?: string | number,
|
||||||
): Promise<CoreFilepoolLinksRecord[]> {
|
): Promise<CoreFilepoolLinksDBRecord[]> {
|
||||||
siteId = siteId ?? CoreSites.getCurrentSiteId();
|
siteId = siteId ?? CoreSites.getCurrentSiteId();
|
||||||
const conditions = {
|
const conditions = {
|
||||||
component,
|
component,
|
||||||
|
@ -1364,7 +1374,7 @@ export class CoreFilepoolProvider {
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
* @returns Promise resolved with the links.
|
* @returns Promise resolved with the links.
|
||||||
*/
|
*/
|
||||||
protected async getFileLinks(siteId: string, fileId: string): Promise<CoreFilepoolLinksRecord[]> {
|
protected async getFileLinks(siteId: string, fileId: string): Promise<CoreFilepoolLinksDBRecord[]> {
|
||||||
const items = await this.linksTables[siteId].getMany({ fileId });
|
const items = await this.linksTables[siteId].getMany({ fileId });
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
|
|
|
@ -93,7 +93,7 @@ export class CoreSitesProvider {
|
||||||
protected siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
protected siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
||||||
protected pluginsSiteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
protected pluginsSiteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
|
||||||
protected siteTables: Record<string, Record<string, CorePromisedValue<CoreDatabaseTable>>> = {};
|
protected siteTables: Record<string, Record<string, CorePromisedValue<CoreDatabaseTable>>> = {};
|
||||||
protected schemasTables: Record<string, AsyncInstance<CoreDatabaseTable<SchemaVersionsDBEntry, 'name'>>> = {};
|
protected schemasTables: Record<string, AsyncInstance<CoreDatabaseTable<SchemaVersionsDBEntry, 'name', never>>> = {};
|
||||||
protected sitesTable = asyncInstance<CoreDatabaseTable<SiteDBEntry>>();
|
protected sitesTable = asyncInstance<CoreDatabaseTable<SiteDBEntry>>();
|
||||||
|
|
||||||
constructor(@Optional() @Inject(CORE_SITE_SCHEMAS) siteSchemas: CoreSiteSchema[][] | null) {
|
constructor(@Optional() @Inject(CORE_SITE_SCHEMAS) siteSchemas: CoreSiteSchema[][] | null) {
|
||||||
|
@ -211,7 +211,8 @@ export class CoreSitesProvider {
|
||||||
*/
|
*/
|
||||||
async getSiteTable<
|
async getSiteTable<
|
||||||
DBRecord extends SQLiteDBRecordValues,
|
DBRecord extends SQLiteDBRecordValues,
|
||||||
PrimaryKeyColumn extends keyof DBRecord
|
PrimaryKeyColumn extends keyof DBRecord,
|
||||||
|
RowIdColumn extends PrimaryKeyColumn,
|
||||||
>(
|
>(
|
||||||
tableName: string,
|
tableName: string,
|
||||||
options: Partial<{
|
options: Partial<{
|
||||||
|
@ -219,9 +220,10 @@ export class CoreSitesProvider {
|
||||||
config: Partial<CoreDatabaseConfiguration>;
|
config: Partial<CoreDatabaseConfiguration>;
|
||||||
database: SQLiteDB;
|
database: SQLiteDB;
|
||||||
primaryKeyColumns: PrimaryKeyColumn[];
|
primaryKeyColumns: PrimaryKeyColumn[];
|
||||||
|
rowIdColumn: RowIdColumn | null;
|
||||||
onDestroy(): void;
|
onDestroy(): void;
|
||||||
}> = {},
|
}> = {},
|
||||||
): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
|
): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>> {
|
||||||
const siteId = options.siteId ?? this.getCurrentSiteId();
|
const siteId = options.siteId ?? this.getCurrentSiteId();
|
||||||
|
|
||||||
if (!(siteId in this.siteTables)) {
|
if (!(siteId in this.siteTables)) {
|
||||||
|
@ -231,11 +233,12 @@ export class CoreSitesProvider {
|
||||||
if (!(tableName in this.siteTables[siteId])) {
|
if (!(tableName in this.siteTables[siteId])) {
|
||||||
const promisedTable = this.siteTables[siteId][tableName] = new CorePromisedValue();
|
const promisedTable = this.siteTables[siteId][tableName] = new CorePromisedValue();
|
||||||
const database = options.database ?? await this.getSiteDb(siteId);
|
const database = options.database ?? await this.getSiteDb(siteId);
|
||||||
const table = new CoreDatabaseTableProxy<DBRecord, PrimaryKeyColumn>(
|
const table = new CoreDatabaseTableProxy<DBRecord, PrimaryKeyColumn, RowIdColumn>(
|
||||||
options.config ?? {},
|
options.config ?? {},
|
||||||
database,
|
database,
|
||||||
tableName,
|
tableName,
|
||||||
options.primaryKeyColumns,
|
options.primaryKeyColumns,
|
||||||
|
options.rowIdColumn,
|
||||||
);
|
);
|
||||||
|
|
||||||
options.onDestroy && table.addListener({ onDestroy: options.onDestroy });
|
options.onDestroy && table.addListener({ onDestroy: options.onDestroy });
|
||||||
|
@ -245,7 +248,7 @@ export class CoreSitesProvider {
|
||||||
promisedTable.resolve(table as unknown as CoreDatabaseTable);
|
promisedTable.resolve(table as unknown as CoreDatabaseTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.siteTables[siteId][tableName] as unknown as Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>;
|
return this.siteTables[siteId][tableName] as unknown as Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2033,6 +2036,7 @@ export class CoreSitesProvider {
|
||||||
database: site.getDb(),
|
database: site.getDb(),
|
||||||
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
|
||||||
primaryKeyColumns: ['name'],
|
primaryKeyColumns: ['name'],
|
||||||
|
rowIdColumn: null,
|
||||||
onDestroy: () => delete this.schemasTables[siteId],
|
onDestroy: () => delete this.schemasTables[siteId],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue