From bc1d0ee338fb79f2ff837052a39199bb5a7867eb Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 1 Feb 2021 17:27:28 +0100 Subject: [PATCH] MOBILE-3689 config: Migrate config build to gulp --- .gitignore | 5 +- .travis.yml | 1 - .vscode/settings.json | 4 +- angular.json | 15 ++-- config/webpack.config.js | 40 ---------- gulp/task-build-env.js | 41 ++++++++++ gulpfile.js | 9 ++- config/config.json => moodle.config.json | 0 ...example.json => moodle.example.config.json | 5 +- package-lock.json | 79 ++++++------------- package.json | 10 +-- config/utils.js => scripts/env-utils.js | 4 +- src/core/constants.ts | 54 ++++++++++++- src/core/services/groups.ts | 1 - src/testing/setup.ts | 9 --- src/types/global.d.ts | 62 +-------------- 16 files changed, 150 insertions(+), 189 deletions(-) delete mode 100644 config/webpack.config.js create mode 100644 gulp/task-build-env.js rename config/config.json => moodle.config.json (100%) rename config/config.example.json => moodle.example.config.json (61%) rename config/utils.js => scripts/env-utils.js (88%) diff --git a/.gitignore b/.gitignore index 3e8297b04..73624db7a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,5 +29,8 @@ npm-debug.log* /plugins /www -/config/config.*.json +/moodle.*.config.json +!/moodle.example.config.json + /src/assets/lang/* +/src/assets/env.json diff --git a/.travis.yml b/.travis.yml index 3cefd498a..64da6f723 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,3 @@ script: - npm run lint - npm run test:ci - npm run build:prod - diff --git a/.vscode/settings.json b/.vscode/settings.json index cf9b6ae4c..d8b699e18 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,8 @@ { "files.associations": { - "config.json": "jsonc", - "config.*.json": "jsonc", + "moodle.config.json": "jsonc", + "moodle.*.config.json": "jsonc", }, } diff --git a/angular.json b/angular.json index 7caa291e1..a1ffa0962 100644 --- a/angular.json +++ b/angular.json @@ -12,7 +12,7 @@ "schematics": {}, "architect": { "build": { - "builder": "@angular-builders/custom-webpack:browser", + "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "www", "index": "src/index.html", @@ -36,10 +36,7 @@ "input": "src/theme/global.scss" } ], - "scripts": [], - "customWebpackConfig": { - "path": "./config/webpack.config.js" - } + "scripts": [] }, "configurations": { "production": { @@ -66,7 +63,7 @@ } }, "serve": { - "builder": "@angular-builders/custom-webpack:dev-server", + "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "app:build" }, @@ -89,9 +86,9 @@ "builder": "@angular-eslint/builder:lint", "options": { "lintFilePatterns": [ - "src/**/*.ts", - "src/core/**/*.html", - "src/addons/**/*.html" + "src/**/*.ts", + "src/core/**/*.html", + "src/addons/**/*.html" ] } }, diff --git a/config/webpack.config.js b/config/webpack.config.js deleted file mode 100644 index 27266089c..000000000 --- a/config/webpack.config.js +++ /dev/null @@ -1,40 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -const webpack = require('webpack'); -const { getConfig, getBuild } = require('./utils'); -const { resolve } = require('path'); - -module.exports = config => { - config.resolve.alias['@'] = resolve('src'); - config.resolve.alias['@classes'] = resolve('src/core/classes'); - config.resolve.alias['@components'] = resolve('src/core/components'); - config.resolve.alias['@directives'] = resolve('src/core/directives'); - config.resolve.alias['@features'] = resolve('src/core/features'); - config.resolve.alias['@guards'] = resolve('src/core/guards'); - config.resolve.alias['@pipes'] = resolve('src/core/pipes'); - config.resolve.alias['@services'] = resolve('src/core/services'); - config.resolve.alias['@singletons'] = resolve('src/core/singletons'); - - config.plugins.push( - new webpack.DefinePlugin({ - 'window.MoodleApp': { - CONFIG: JSON.stringify(getConfig(process.env.NODE_ENV || 'development')), - BUILD: JSON.stringify(getBuild(process.env.NODE_ENV || 'development')), - }, - }), - ); - - return config; -}; diff --git a/gulp/task-build-env.js b/gulp/task-build-env.js new file mode 100644 index 000000000..b96005906 --- /dev/null +++ b/gulp/task-build-env.js @@ -0,0 +1,41 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const { getConfig, getBuild } = require('../scripts/env-utils'); +const { resolve } = require('path'); +const { writeFile } = require('fs'); + +/** + * Task to build an env file depending on the current environment. + */ +class BuildEnvTask { + + /** + * Run the task. + * + * @param done Function to call when done. + */ + run(done) { + const envFile = resolve(__dirname, '../src/assets/env.json'); + const env = { + CONFIG: getConfig(process.env.NODE_ENV || 'development'), + BUILD: getBuild(process.env.NODE_ENV || 'development'), + }; + + writeFile(envFile, JSON.stringify(env), done); + } + +} + +module.exports = BuildEnvTask; diff --git a/gulpfile.js b/gulpfile.js index 739e799c2..2115bad2e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -13,6 +13,7 @@ // limitations under the License. const BuildLangTask = require('./gulp/task-build-lang'); +const BuildEnvTask = require('./gulp/task-build-env'); const PushTask = require('./gulp/task-push'); const Utils = require('./gulp/utils'); const gulp = require('gulp'); @@ -34,12 +35,18 @@ gulp.task('lang', (done) => { new BuildLangTask().run(paths.lang, done); }); +// Build an env file depending on the current environment. +gulp.task('env', (done) => { + new BuildEnvTask().run(done); +}); + gulp.task('push', (done) => { new PushTask().run(args, done); }); -gulp.task('default', gulp.parallel('lang')); +gulp.task('default', gulp.parallel(['lang', 'env'])); gulp.task('watch', () => { gulp.watch(paths.lang, { interval: 500 }, gulp.parallel('lang')); + gulp.watch(['./moodle.config.json', './moodle.*.config.json'], { interval: 500 }, gulp.parallel('env')); }); diff --git a/config/config.json b/moodle.config.json similarity index 100% rename from config/config.json rename to moodle.config.json diff --git a/config/config.example.json b/moodle.example.config.json similarity index 61% rename from config/config.example.json rename to moodle.example.config.json index d160714af..a94e15ea6 100644 --- a/config/config.example.json +++ b/moodle.example.config.json @@ -1,9 +1,8 @@ /** * Application config. * - * You can create your own environment files such as "config.prod.json" and "config.dev.json" - * to override some values. The values will be merged, so you don't need to duplicate everything - * in this file. + * You can create your own environment files such as "moodle.config.prod.json" and "moodle.config.dev.json" + * to override some values. The values will be merged, so you don't need to duplicate everything in this file. */ { diff --git a/package-lock.json b/package-lock.json index dba0c97bf..977dd2cfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,58 +4,29 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@angular-builders/custom-webpack": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-10.0.1.tgz", - "integrity": "sha512-YDy5zEKVwXdoXLjmbsY6kGaEbmunQxaPipxrwLUc9hIjRLU2WcrX9vopf1R9Pgj4POad73IPBNGu+ibqNRFIEQ==", - "dev": true, - "requires": { - "@angular-devkit/architect": ">=0.1000.0 < 0.1100.0", - "@angular-devkit/build-angular": ">=0.1000.0 < 0.1100.0", - "@angular-devkit/core": "^10.0.0", - "lodash": "^4.17.15", - "ts-node": "^9.0.0", - "webpack-merge": "^4.2.2" - }, - "dependencies": { - "ts-node": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", - "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - } - } - }, "@angular-devkit/architect": { - "version": "0.1001.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1001.4.tgz", - "integrity": "sha512-0U/w+61vWxnEe9Ln/hNOH6O27FVcU+s/sbJAuPREbP875R4bQzK2PX0eYRlISzkDtQyw16GzlsikLWOoJ3vjTA==", + "version": "0.1101.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1101.2.tgz", + "integrity": "sha512-MLmBfHiiyPhbFSSAX4oMecPjEuBauOui5uBpI6BKNnk/7783fznbkbAKjXlOco7M81gkNeEoHMR8c+mOfcvv7g==", "dev": true, "requires": { - "@angular-devkit/core": "10.1.4", - "rxjs": "6.6.2" + "@angular-devkit/core": "11.1.2", + "rxjs": "6.6.3" }, "dependencies": { "rxjs": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", - "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -249,22 +220,22 @@ } }, "@angular-devkit/core": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-10.1.4.tgz", - "integrity": "sha512-B1cwVcfChBvmEacydE2uqZ1UC2ez1G+KY0GyVnCQKpAb/DdfDgtaYjTx9JLvGQjE/BlVklEj8YCKDjVV0WPE5g==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.1.2.tgz", + "integrity": "sha512-V7zOMqL2l56JcwXVyswkG+7+t67r9XtkrVzRcG2Z5ZYwafU+iKWMwg5kBFZr1SX7fM1M9E4MpskxqtagQeUKng==", "dev": true, "requires": { - "ajv": "6.12.4", + "ajv": "6.12.6", "fast-json-stable-stringify": "2.1.0", "magic-string": "0.25.7", - "rxjs": "6.6.2", + "rxjs": "6.6.3", "source-map": "0.7.3" }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -274,18 +245,18 @@ } }, "rxjs": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", - "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } diff --git a/package.json b/package.json index 6bef0195a..07da98963 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,10 @@ "start": "ionic serve", "build": "ionic build", "build:prod": "ionic build --prod", - "test": "jest --verbose", - "test:ci": "jest -ci --runInBand --verbose", - "test:watch": "jest --watch", - "test:coverage": "jest --coverage", + "test": "NODE_ENV=testing gulp && jest --verbose", + "test:ci": "NODE_ENV=testing gulp && jest -ci --runInBand --verbose", + "test:watch": "NODE_ENV=testing gulp watch & jest --watch", + "test:coverage": "NODE_ENV=testing gulp && jest --coverage", "lint": "ng lint", "ionic:serve:before": "gulp", "ionic:serve": "gulp watch & ng serve", @@ -119,7 +119,7 @@ "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-builders/custom-webpack": "^10.0.1", + "@angular-devkit/architect": "^0.1101.2", "@angular-devkit/build-angular": "~0.1000.0", "@angular-eslint/builder": "0.5.0-beta.2", "@angular-eslint/eslint-plugin": "0.5.0-beta.2", diff --git a/config/utils.js b/scripts/env-utils.js similarity index 88% rename from config/utils.js rename to scripts/env-utils.js index e2d482c8f..39944ac00 100644 --- a/config/utils.js +++ b/scripts/env-utils.js @@ -23,9 +23,9 @@ function getConfig(environment) { development: ['dev', 'development'], production: ['prod', 'production'], }; - const config = parseJsonc(readFileSync(resolve('config/config.json')).toString()); + const config = parseJsonc(readFileSync(resolve(__dirname, '../moodle.config.json')).toString()); const envSuffixes = (envSuffixesMap[environment] || []); - const envConfigPath = envSuffixes.map(suffix => resolve(`config/config.${suffix}.json`)).find(existsSync); + const envConfigPath = envSuffixes.map(suffix => resolve(__dirname, `../moodle.${suffix}.config.json`)).find(existsSync); if (envConfigPath) { const envConfig = parseJsonc(readFileSync(envConfigPath).toString()); diff --git a/src/core/constants.ts b/src/core/constants.ts index b4bd8c42a..0f43c62e3 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -12,6 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +/* eslint-disable @typescript-eslint/naming-convention */ + +import { CoreColorScheme } from '@features/settings/services/settings-helper'; +import { CoreSitesDemoSiteData } from '@services/sites'; +import envJson from '@/assets/env.json'; + /** * Context levels enumeration. */ @@ -114,7 +120,51 @@ export class CoreConstants { static readonly MOD_ARCHETYPE_SYSTEM = 3; // System (not user-addable) module archetype. // Config & environment constants. - static readonly CONFIG = (window as unknown as MoodleAppWindow).MoodleApp.CONFIG; // Data parsed from config.json files. - static readonly BUILD = (window as unknown as MoodleAppWindow).MoodleApp.BUILD; // Environment info. + 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. } + +type EnvironmentConfig = { + app_id: string; + appname: string; + versioncode: number; + versionname: string; + cache_update_frequency_usually: number; + cache_update_frequency_often: number; + cache_update_frequency_sometimes: number; + cache_update_frequency_rarely: number; + default_lang: string; + languages: Record; + wsservice: string; + wsextservice: string; + demo_sites: Record; + font_sizes: number[]; + customurlscheme: string; + siteurl: string; + sitename: string; + multisitesdisplay: string; + sitefindersettings: Record; + onlyallowlistedsites: boolean; + skipssoconfirmation: boolean; + forcedefaultlanguage: boolean; + privacypolicy: string; + notificoncolor: string; + enableanalytics: boolean; + enableonboarding: boolean; + forceColorScheme: CoreColorScheme; + forceLoginLogo: boolean; + ioswebviewscheme: string; + appstores: Record; + displayqroncredentialscreen?: boolean; + displayqronsitescreen?: boolean; + forceOpenLinksIn: 'app' | 'browser'; +}; + +type EnvironmentBuild = { + isProduction: boolean; + isTesting: boolean; + isDevelopment: boolean; + lastCommitHash: string; + compilationTime: number; +}; diff --git a/src/core/services/groups.ts b/src/core/services/groups.ts index f38c1efa2..39541f9df 100644 --- a/src/core/services/groups.ts +++ b/src/core/services/groups.ts @@ -19,7 +19,6 @@ import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { CoreError } from '@classes/errors/error'; import { makeSingleton, Translate } from '@singletons'; import { CoreWSExternalWarning } from '@services/ws'; -import { CoreCourseBase } from '@/types/global'; const ROOT_CACHE_KEY = 'mmGroups:'; diff --git a/src/testing/setup.ts b/src/testing/setup.ts index 0a2d9049f..aba69b950 100644 --- a/src/testing/setup.ts +++ b/src/testing/setup.ts @@ -12,13 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* eslint-disable @typescript-eslint/naming-convention */ - import 'jest-preset-angular'; - -import { getConfig, getBuild } from '../../config/utils'; - -(window as unknown as MoodleAppWindow).MoodleApp = { - CONFIG: getConfig('testing'), - BUILD: getBuild('testing'), -}; diff --git a/src/types/global.d.ts b/src/types/global.d.ts index cbd429038..f8d2f8031 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -13,69 +13,13 @@ // limitations under the License. /* eslint-disable @typescript-eslint/naming-convention */ - -import { CoreColorScheme } from '@features/settings/services/settings-helper'; -import { CoreSitesDemoSiteData } from '@services/sites'; - -declare global { - - interface Window { - __Zone_disable_customElements: boolean; - } - - type MoodleAppWindow = { - MoodleApp: { - CONFIG: { - app_id: string; - appname: string; - versioncode: number; - versionname: string; - cache_update_frequency_usually: number; - cache_update_frequency_often: number; - cache_update_frequency_sometimes: number; - cache_update_frequency_rarely: number; - default_lang: string; - languages: Record; - wsservice: string; - wsextservice: string; - demo_sites: Record; - font_sizes: number[]; - customurlscheme: string; - siteurl: string; - sitename: string; - multisitesdisplay: string; - sitefindersettings: Record; - onlyallowlistedsites: boolean; - skipssoconfirmation: boolean; - forcedefaultlanguage: boolean; - privacypolicy: string; - notificoncolor: string; - enableanalytics: boolean; - enableonboarding: boolean; - forceColorScheme: CoreColorScheme; - forceLoginLogo: boolean; - ioswebviewscheme: string; - appstores: Record; - displayqroncredentialscreen?: boolean; - displayqronsitescreen?: boolean; - forceOpenLinksIn: 'app' | 'browser'; - }; - - BUILD: { - isProduction: boolean; - isTesting: boolean; - isDevelopment: boolean; - lastCommitHash: string; - compilationTime: number; - }; - }; - }; - +interface Window { + __Zone_disable_customElements: boolean; } /** * Course base definition. */ -export type CoreCourseBase = { +type CoreCourseBase = { id: number; // Course Id. };