MOBILE-3833 core: Improve dev config overrides

main
Noel De Martin 2022-02-10 10:43:06 +01:00
parent 4df8dc3c64
commit f24b35de61
7 changed files with 88 additions and 13 deletions

View File

@ -15,7 +15,7 @@
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 { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb';
import { CoreConfigProvider } from '@services/config'; import { CoreConfig, CoreConfigProvider } from '@services/config';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreDatabaseReducer, CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey } from './database-table'; import { CoreDatabaseReducer, CoreDatabaseTable, CoreDatabaseConditions, GetDBRecordPrimaryKey } from './database-table';
import { CoreDebugDatabaseTable } from './debug-database-table'; import { CoreDebugDatabaseTable } from './debug-database-table';
@ -144,7 +144,9 @@ export class CoreDatabaseTableProxy<
* *
* @returns Database configuration. * @returns Database configuration.
*/ */
protected getRuntimeConfig(): CoreDatabaseConfiguration { protected async getRuntimeConfig(): Promise<CoreDatabaseConfiguration> {
await CoreConfig.ready();
return { return {
...this.config, ...this.config,
...CoreConstants.CONFIG.databaseOptimizations, ...CoreConstants.CONFIG.databaseOptimizations,
@ -157,7 +159,7 @@ export class CoreDatabaseTableProxy<
*/ */
protected async updateTarget(): Promise<void> { protected async updateTarget(): Promise<void> {
const oldTarget = this.target.instance; const oldTarget = this.target.instance;
const newTarget = this.createTarget(); const newTarget = await this.createTarget();
if (oldTarget) { if (oldTarget) {
await oldTarget.destroy(); await oldTarget.destroy();
@ -175,8 +177,8 @@ export class CoreDatabaseTableProxy<
* *
* @returns Target instance. * @returns Target instance.
*/ */
protected createTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> { protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> {
const config = this.getRuntimeConfig(); const config = await this.getRuntimeConfig();
const table = this.createTable(config.cachingStrategy); const table = this.createTable(config.cachingStrategy);
return config.debug ? new CoreDebugDatabaseTable(table) : table; return config.debug ? new CoreDebugDatabaseTable(table) : table;

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { mock } from '@/testing/utils'; import { mock, mockSingleton } from '@/testing/utils';
import { CoreDatabaseTable } from '@classes/database/database-table'; import { CoreDatabaseTable } from '@classes/database/database-table';
import { import {
CoreDatabaseCachingStrategy, CoreDatabaseCachingStrategy,
@ -20,6 +20,7 @@ import {
CoreDatabaseTableProxy, CoreDatabaseTableProxy,
} from '@classes/database/database-table-proxy'; } from '@classes/database/database-table-proxy';
import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb'; import { SQLiteDB, SQLiteDBRecordValues } from '@classes/sqlitedb';
import { CoreConfig } from '@services/config';
interface User extends SQLiteDBRecordValues { interface User extends SQLiteDBRecordValues {
id: number; id: number;
@ -66,6 +67,8 @@ function prepareStubs(config: Partial<CoreDatabaseConfiguration> = {}): [User[],
}); });
const table = new CoreDatabaseTableProxy<User>(config, database, 'users'); const table = new CoreDatabaseTableProxy<User>(config, database, 'users');
mockSingleton(CoreConfig, { isReady: () => Promise.resolve() });
return [records, database, table]; return [records, database, table];
} }

View File

@ -145,6 +145,17 @@ export class CoreConstants {
static readonly CONFIG = { ...envJson.config } as unknown as EnvironmentConfig; // Data parsed from config.json files. static readonly CONFIG = { ...envJson.config } as unknown as EnvironmentConfig; // Data parsed from config.json files.
static readonly BUILD = envJson.build as unknown as EnvironmentBuild; // Build info. static readonly BUILD = envJson.build as unknown as EnvironmentBuild; // Build info.
/**
* Check whether devtools should be enabled.
*
* @returns Whether devtools should be enabled.
*/
static enableDevTools(): boolean {
// @todo [4.0] This is not the proper way to check for development tools, we should rely only on the BUILD variable.
return this.BUILD.isDevelopment
|| this.CONFIG.versionname.includes('-dev');
}
} }
interface EnvironmentBuild { interface EnvironmentBuild {

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { CoreConfig } from '@services/config';
import { CoreFilepool } from '@services/filepool'; import { CoreFilepool } from '@services/filepool';
import { CoreLang } from '@services/lang'; import { CoreLang } from '@services/lang';
import { CoreLocalNotifications } from '@services/local-notifications'; import { CoreLocalNotifications } from '@services/local-notifications';
@ -20,6 +21,7 @@ import { CoreUpdateManager } from '@services/update-manager';
export default async function(): Promise<void> { export default async function(): Promise<void> {
await Promise.all([ await Promise.all([
CoreConfig.initialize(),
CoreFilepool.initialize(), CoreFilepool.initialize(),
CoreSites.initialize(), CoreSites.initialize(),
CoreLang.initialize(), CoreLang.initialize(),

View File

@ -12,22 +12,21 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { EnvironmentConfig } from '@/types/config'; import { CoreConfig, CoreConfigProvider } from '@services/config';
import { CoreConstants } from '../constants'; import { CoreConstants } from '../constants';
type DevelopmentWindow = Window & { type DevelopmentWindow = Window & {
coreConstantsConfig?: EnvironmentConfig; configProvider?: CoreConfigProvider;
}; };
function exportData(window: DevelopmentWindow) { function initializeDevelopmentWindow(window: DevelopmentWindow) {
window.coreConstantsConfig = CoreConstants.CONFIG; window.configProvider = CoreConfig.instance;
} }
export default function(): void { export default function(): void {
if (!CoreConstants.CONFIG.versionname.includes('-dev')) { if (!CoreConstants.enableDevTools()) {
// Only export data in development.
return; return;
} }
exportData(window); initializeDevelopmentWindow(window);
} }

View File

@ -22,6 +22,8 @@ import { CoreConstants } from '../constants';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { CoreDatabaseTable } from '@classes/database/database-table'; import { CoreDatabaseTable } from '@classes/database/database-table';
import { asyncInstance } from '../utils/async-instance'; import { asyncInstance } from '../utils/async-instance';
import { CorePromisedValue } from '@classes/promised-value';
import { CoreUtils } from './utils/utils';
declare module '@singletons/events' { declare module '@singletons/events' {
@ -47,6 +49,23 @@ export class CoreConfigProvider {
protected table = asyncInstance<CoreDatabaseTable<ConfigDBEntry, 'name'>>(); protected table = asyncInstance<CoreDatabaseTable<ConfigDBEntry, 'name'>>();
protected defaultEnvironment?: EnvironmentConfig; protected defaultEnvironment?: EnvironmentConfig;
protected isReady = new CorePromisedValue<void>();
/**
* Wait until configuration is ready for use.
*/
ready(): Promise<void> {
return this.isReady;
}
/**
* Initialize.
*/
async initialize(): Promise<void> {
this.loadDevelopmentConfig();
this.isReady.resolve();
}
/** /**
* Initialize database. * Initialize database.
@ -139,6 +158,17 @@ export class CoreConfigProvider {
CoreEvents.trigger(CoreConfigProvider.ENVIRONMENT_UPDATED, CoreConstants.CONFIG); CoreEvents.trigger(CoreConfigProvider.ENVIRONMENT_UPDATED, CoreConstants.CONFIG);
} }
/**
* Load development config overrides.
*/
protected loadDevelopmentConfig(): void {
if (!CoreConstants.enableDevTools() || !CoreUtils.hasCookie('MoodleAppConfig')) {
return;
}
this.patchEnvironment(JSON.parse(CoreUtils.getCookie('MoodleAppConfig') ?? '{}'));
}
} }
export const CoreConfig = makeSingleton(CoreConfigProvider); export const CoreConfig = makeSingleton(CoreConfigProvider);

View File

@ -1748,6 +1748,34 @@ export class CoreUtilsProvider {
return CoreApp.isIOS() && openFileAction == OpenFileAction.OPEN_WITH; return CoreApp.isIOS() && openFileAction == OpenFileAction.OPEN_WITH;
} }
/**
* Check whether the given cookie is set.
*
* @param name Cookie name.
* @returns Whether the cookie is set.
*/
hasCookie(name: string): boolean {
return new RegExp(`(\\s|;|^)${name}=`).test(document.cookie ?? '');
}
/**
* Read a cookie.
*
* @param name Cookie name.
* @return Cookie value.
*/
getCookie(name: string): string | null {
const cookies = (document.cookie ?? '').split(';').reduce((cookies, cookie) => {
const [name, value] = cookie.trim().split('=');
cookies[name] = value;
return cookies;
}, {});
return cookies[name] ?? null;
}
} }
export const CoreUtils = makeSingleton(CoreUtilsProvider); export const CoreUtils = makeSingleton(CoreUtilsProvider);