diff --git a/Jenkinsfile b/Jenkinsfile index 1fa6a49ea4..9af09b3060 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -68,7 +68,7 @@ pipeline { stage('Backend') { steps { nodejs('node-lts') { - sh 'gulp backTestDockerOnce --junit --random' + sh 'gulp backTestOnce --ci' } } } diff --git a/README.md b/README.md index 52f854b6e9..82f7497659 100644 --- a/README.md +++ b/README.md @@ -8,18 +8,12 @@ Salix is also the scientific name of a beautifull tree! :) Required applications. -* Visual Studio Code * Node.js = 12.17.0 LTS * Docker -In Visual Studio Code we use the ESLint extension. Open Visual Studio Code, press Ctrl+P and paste the following command. -``` -ext install dbaeumer.vscode-eslint -``` - You will need to install globally the following items. ``` -# sudo npm install -g jest gulp-cli nodemon +# sudo npm install -g jest gulp-cli ``` ## Linux Only Prerequisites @@ -65,6 +59,15 @@ For end-to-end tests run from project's root. $ gulp e2e ``` +## Recommended tools + +* Visual Studio Code + +In Visual Studio Code we use the ESLint extension. Open Visual Studio Code, press Ctrl+P and paste the following command. +``` +ext install dbaeumer.vscode-eslint +``` + ## Built With * [angularjs](https://angularjs.org/) @@ -75,4 +78,4 @@ $ gulp e2e * [gulp.js](https://gulpjs.com/) * [jest](https://jestjs.io/) * [Jasmine](https://jasmine.github.io/) -* [Nightmare](http://www.nightmarejs.org/) +* [Puppeteer](https://pptr.dev/) diff --git a/db/docker.js b/db/docker.js new file mode 100644 index 0000000000..849cf182cc --- /dev/null +++ b/db/docker.js @@ -0,0 +1,166 @@ +const exec = require('child_process').exec; +const log = require('fancy-log'); +const dataSources = require('../loopback/server/datasources.json'); + +module.exports = class Docker { + constructor(name) { + Object.assign(this, { + id: name, + name, + isRandom: name == null, + dbConf: Object.assign({}, dataSources.vn) + }); + } + + /** + * Builds the database image and runs a container. It only rebuilds the + * image when fixtures have been modified or when the day on which the + * image was built is different to today. Some workarounds have been used + * to avoid a bug with OverlayFS driver on MacOS. + * + * @param {Boolean} ci continuous integration environment argument + */ + async run(ci) { + let d = new Date(); + let pad = v => v < 10 ? '0' + v : v; + let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; + await this.execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`); + + let dockerArgs; + + if (this.isRandom) + dockerArgs = '-p 3306'; + else { + try { + await this.rm(); + } catch (e) {} + dockerArgs = `--name ${this.name} -p 3306:${this.dbConf.port}`; + } + + let runChown = process.platform != 'linux'; + + let container = await this.execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`); + this.id = container.stdout; + + try { + if (this.isRandom) { + let inspect = await this.execP(`docker inspect -f "{{json .NetworkSettings}}" ${this.id}`); + let netSettings = JSON.parse(inspect.stdout); + + if (ci) + this.dbConf.host = netSettings.Gateway; + + this.dbConf.port = netSettings.Ports['3306/tcp'][0]['HostPort']; + } + + if (runChown) await this.wait(); + } catch (err) { + if (this.isRandom) + await this.rm(); + throw err; + } + } + + /** + * Does the minium effort to start the database container, if it doesn't exists + * calls the 'docker' task, if it is started does nothing. Keep in mind that when + * you do not rebuild the docker you may be using an outdated version of it. + * See the 'docker' task for more info. + */ + async start() { + let state; + try { + let result = await this.execP(`docker inspect -f "{{json .State}}" ${this.id}`); + state = JSON.parse(result.stdout); + } catch (err) { + return await this.run(); + } + + switch (state.Status) { + case 'running': + return; + case 'exited': + await this.execP(`docker start ${this.id}`); + await this.wait(); + return; + default: + throw new Error(`Unknown docker status: ${state.Status}`); + } + } + + wait() { + return new Promise((resolve, reject) => { + const mysql = require('mysql2'); + + let interval = 100; + let elapsedTime = 0; + let maxInterval = 4 * 60 * 1000; + + let myConf = { + user: this.dbConf.username, + password: this.dbConf.password, + host: this.dbConf.host, + port: this.dbConf.port + }; + + log('Waiting for MySQL init process...'); + + async function checker() { + elapsedTime += interval; + let state; + + try { + let result = await this.execP(`docker container inspect -f "{{json .State}}" ${this.id}`); + state = JSON.parse(result.stdout); + } catch (err) { + return reject(new Error(err.message)); + } + + if (state.Status === 'exited') + return reject(new Error('Docker exited, please see the docker logs for more info')); + + let conn = mysql.createConnection(myConf); + conn.on('error', () => {}); + conn.connect(err => { + conn.destroy(); + if (!err) { + log('MySQL process ready.'); + return resolve(); + } + + if (elapsedTime >= maxInterval) + reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`)); + else + setTimeout(bindedChecker, interval); + }); + } + let bindedChecker = checker.bind(this); + bindedChecker(); + }); + } + + rm() { + return this.execP(`docker rm -fv ${this.id}`); + } + + /** + * Promisified version of exec(). + * + * @param {String} command The exec command + * @return {Promise} The promise + */ + execP(command) { + return new Promise((resolve, reject) => { + exec(command, (err, stdout, stderr) => { + if (err) + reject(err); + else { + resolve({ + stdout: stdout, + stderr: stderr + }); + } + }); + }); + } +}; diff --git a/e2e/smokes-tests.js b/e2e/smokes-tests.js deleted file mode 100644 index 7b4e16edfb..0000000000 --- a/e2e/smokes-tests.js +++ /dev/null @@ -1,35 +0,0 @@ -require('babel-core/register')({presets: ['es2015']}); - -process.on('warning', warning => { - console.log(warning.name); - console.log(warning.message); - console.log(warning.stack); -}); - -let verbose = false; - -if (process.argv[2] === '--v') - verbose = true; - -let Jasmine = require('jasmine'); -let jasmine = new Jasmine(); -let SpecReporter = require('jasmine-spec-reporter').SpecReporter; - -jasmine.loadConfig({ - spec_files: [ - `${__dirname}/smokes/**/*[sS]pec.js`, - `${__dirname}/helpers/extensions.js` - ], - helpers: [] -}); - -jasmine.addReporter(new SpecReporter({ - spec: { - // displayStacktrace: 'summary', - displaySuccessful: verbose, - displayFailedSpec: true, - displaySpecDuration: true - } -})); - -jasmine.execute(); diff --git a/e2e/smokes/01_client_path.spec.js b/e2e/smokes/01_client_path.spec.js deleted file mode 100644 index 6c106b2eb2..0000000000 --- a/e2e/smokes/01_client_path.spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import selectors from '../../helpers/selectors.js'; -import getBrowser from '../../helpers/puppeteer'; - -describe('create client path', () => { - let browser; - let page; - beforeAll(async() => { - browser = await getBrowser(); - page = browser.page; - await page.loginAndModule('employee', 'client'); - }); - - afterAll(async() => { - await browser.close(); - }); - - it('should access to the create client view by clicking the create-client floating button', async() => { - await page.waitToClick(selectors.clientsIndex.createClientButton); - let url = await page.expectURL('#!/client/create'); - - expect(url).toBe(true); - }); - - it('should cancel the client creation to go back to clients index', async() => { - await page.waitToClick(selectors.globalItems.applicationsMenuButton); - await page.waitToClick(selectors.globalItems.clientsButton); - let url = await page.expectURL('#!/client/index'); - - expect(url).toBe(true); - }); -}); diff --git a/gulpfile.js b/gulpfile.js index ff6c71aa4e..678fda5271 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,11 +1,11 @@ require('require-yaml'); const gulp = require('gulp'); -const exec = require('child_process').exec; const PluginError = require('plugin-error'); const argv = require('minimist')(process.argv.slice(2)); const log = require('fancy-log'); const request = require('request'); const e2eConfig = require('./e2e/helpers/config.js'); +const Docker = require('./db/docker.js'); // Configuration @@ -18,10 +18,6 @@ let langs = ['es', 'en']; let srcDir = './front'; let modulesDir = './modules'; let buildDir = 'dist'; -let containerId = 'salix-db'; - -let dataSources = require('./loopback/server/datasources.json'); -let dbConf = dataSources.vn; let backSources = [ '!node_modules', @@ -63,7 +59,7 @@ function backWatch(done) { done: done }); } -backWatch.description = `Starts backend in waching mode`; +backWatch.description = `Starts backend in watcher mode`; const back = gulp.series(dockerStart, backWatch); back.description = `Starts backend and database service`; @@ -73,78 +69,64 @@ defaultTask.description = `Starts all application services`; // Backend tests -async function backTestOnce() { - let bootOptions; +async function backTestOnce(done) { + let err; + let dataSources = require('./loopback/server/datasources.json'); - if (argv['random']) - bootOptions = {dataSources}; + const container = new Docker(); + await container.run(argv.ci); - let app = require(`./loopback/server/server`); - app.boot(bootOptions); + dataSources = JSON.parse(JSON.stringify(dataSources)); - await new Promise((resolve, reject) => { - const jasmine = require('gulp-jasmine'); - - let options = { - errorOnFail: false, - config: { - random: false - } - }; - - if (argv.junit) { - const reporters = require('jasmine-reporters'); - options.reporter = new reporters.JUnitXmlReporter(); - } - - let backSpecFiles = [ - 'back/**/*.spec.js', - 'loopback/**/*.spec.js', - 'modules/*/back/**/*.spec.js' - ]; - - gulp.src(backSpecFiles) - .pipe(jasmine(options)) - .on('end', resolve) - .on('error', reject) - .resume(); + Object.assign(dataSources.vn, { + host: container.dbConf.host, + port: container.dbConf.port }); + let bootOptions = {dataSources}; + + let app = require(`./loopback/server/server`); + + try { + app.boot(bootOptions); + + await new Promise((resolve, reject) => { + const jasmine = require('gulp-jasmine'); + + let options = { + errorOnFail: false, + config: { + random: false + } + }; + + if (argv.ci) { + const reporters = require('jasmine-reporters'); + options.reporter = new reporters.JUnitXmlReporter(); + } + + let backSpecFiles = [ + 'back/**/*.spec.js', + 'loopback/**/*.spec.js', + 'modules/*/back/**/*.spec.js' + ]; + + gulp.src(backSpecFiles) + .pipe(jasmine(options)) + .on('end', resolve) + .on('error', reject) + .resume(); + }); + } catch (e) { + err = e; + } await app.disconnect(); + await container.rm(); + done(); + if (err) + throw err; } -backTestOnce.description = `Runs the backend tests once, can receive --junit arg to save reports on a xml file`; - -async function backTestDockerOnce() { - let containerId = await docker(); - let err; - - try { - await backTestOnce(); - } catch (e) { - err = e; - } - - if (argv['random']) - await execP(`docker rm -fv ${containerId}`); - if (err) throw err; -} -backTestDockerOnce.description = `Runs backend tests using in site container once`; - -async function backTestDocker() { - let containerId = await docker(); - let err; - - try { - await backTest(); - } catch (e) { - err = e; - } - - if (argv['random']) - await execP(`docker rm -fv ${containerId}`); - if (err) throw err; -} -backTestDocker.description = `Runs backend tests restoring fixtures first`; +backTestOnce.description = `Runs the backend tests once using a random container, can receive --ci arg to save reports on a xml file`; function backTest(done) { const nodemon = require('gulp-nodemon'); @@ -208,7 +190,14 @@ function e2eSingleRun() { ] })); } -e2eSingleRun.description = `Runs the e2e tests just once`; + +e2e = gulp.series(docker, async function isBackendReady() { + const attempts = await backendStatus(); + log(`Backend ready after ${attempts} attempt(s)`); + + return attempts; +}, e2eSingleRun); +e2e.description = `Restarts database and runs the e2e tests`; async function backendStatus() { const milliseconds = 250; @@ -231,24 +220,6 @@ async function backendStatus() { } backendStatus.description = `Performs a simple requests to check the backend status`; -e2e = gulp.series(docker, async function isBackendReady() { - const attempts = await backendStatus(); - log(`Backend ready after ${attempts} attempt(s)`); - - return attempts; -}, e2eSingleRun); -e2e.description = `Restarts database and runs the e2e tests`; - -function smokesOnly() { - const jasmine = require('gulp-jasmine'); - return gulp.src('./e2e/smokes-tests.js') - .pipe(jasmine({reporter: 'none'})); -} -smokesOnly.description = `Runs the smokes tests only`; - -smokes = gulp.series(docker, smokesOnly); -smokes.description = `Restarts database and runs the smokes tests`; - function install() { const install = require('gulp-install'); const print = require('gulp-print'); @@ -414,156 +385,17 @@ function watch(done) { watch.description = `Watches for changes in routes and locale files`; // Docker - -/** - * Builds the database image and runs a container. It only rebuilds the - * image when fixtures have been modified or when the day on which the - * image was built is different to today. Some workarounds have been used - * to avoid a bug with OverlayFS driver on MacOS. - */ -async function docker() { - let d = new Date(); - let pad = v => v < 10 ? '0' + v : v; - let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; - await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`); - - let dockerArgs = `--name ${containerId} -p 3306:${dbConf.port}`; - - if (argv['random']) - dockerArgs = '-p 3306'; - else { - try { - await execP(`docker rm -fv ${containerId}`); - } catch (e) {} - } - - let runChown = process.platform != 'linux'; - if (argv['run-chown']) runChown = true; - - let result = await execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`); - containerId = result.stdout; - - try { - if (argv['random']) { - let inspect = await execP(`docker inspect -f "{{json .NetworkSettings}}" ${containerId}`); - let netSettings = JSON.parse(inspect.stdout); - - dbConf.host = netSettings.Gateway; - dbConf.port = netSettings.Ports['3306/tcp'][0]['HostPort']; - } - - if (runChown) await dockerWait(); - } catch (err) { - if (argv['random']) - await execP(`docker rm -fv ${containerId}`); - throw err; - } - - return containerId; -} -docker.description = `Builds the database image and runs a container`; - -/** - * Does the minium effort to start the database container, if it doesn't exists - * calls the 'docker' task, if it is started does nothing. Keep in mind that when - * you do not rebuild the docker you may be using an outdated version of it. - * See the 'docker' task for more info. - */ async function dockerStart() { - let state; - try { - let result = await execP(`docker inspect -f "{{json .State}}" ${containerId}`); - state = JSON.parse(result.stdout); - } catch (err) { - return await docker(); - } - - switch (state.Status) { - case 'running': - return; - case 'exited': - await execP(`docker start ${containerId}`); - await dockerWait(); - return; - default: - throw new Error(`Unknown docker status: ${state.Status}`); - } + const container = new Docker('salix-db'); + await container.start(); } -dockerStart.description = `Starts the database container`; +dockerStart.description = `Starts the salix-db container`; -function dockerWait() { - return new Promise((resolve, reject) => { - const mysql = require('mysql2'); - - let interval = 100; - let elapsedTime = 0; - let maxInterval = 4 * 60 * 1000; - - let myConf = { - user: dbConf.username, - password: dbConf.password, - host: dbConf.host, - port: dbConf.port - }; - - log('Waiting for MySQL init process...'); - checker(); - - async function checker() { - elapsedTime += interval; - let state; - - try { - let result = await execP(`docker container inspect -f "{{json .State}}" ${containerId}`); - state = JSON.parse(result.stdout); - } catch (err) { - return reject(new Error(err.message)); - } - - if (state.Status === 'exited') - return reject(new Error('Docker exited, please see the docker logs for more info')); - - let conn = mysql.createConnection(myConf); - conn.on('error', () => {}); - conn.connect(err => { - conn.destroy(); - if (!err) { - log('MySQL process ready.'); - return resolve(); - } - - if (elapsedTime >= maxInterval) - reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`)); - else - setTimeout(checker, interval); - }); - } - }); -} -dockerWait.description = `Waits until database service is ready`; - -// Helpers - -/** - * Promisified version of exec(). - * - * @param {String} command The exec command - * @return {Promise} The promise - */ -function execP(command) { - return new Promise((resolve, reject) => { - exec(command, (err, stdout, stderr) => { - if (err) - reject(err); - else { - resolve({ - stdout: stdout, - stderr: stderr - }); - } - }); - }); +async function docker() { + const container = new Docker('salix-db'); + await container.run(); } +docker.description = `Runs the salix-db container`; module.exports = { default: defaultTask, @@ -572,13 +404,8 @@ module.exports = { backOnly, backWatch, backTestOnce, - backTestDockerOnce, backTest, - backTestDocker, e2e, - e2eSingleRun, - smokes, - smokesOnly, i, install, build, @@ -590,7 +417,5 @@ module.exports = { localesRoutes, watch, docker, - dockerStart, - dockerWait, backendStatus, }; diff --git a/package-lock.json b/package-lock.json index 4668175599..d2464eaa18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3265,7 +3265,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -4081,7 +4081,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -4532,7 +4532,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -4544,7 +4544,7 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -4604,7 +4604,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -4674,7 +4674,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { @@ -4813,7 +4813,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -5899,7 +5899,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "requires": { "is-obj": "^1.0.0" } @@ -6856,7 +6856,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -7813,7 +7813,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -8023,7 +8023,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -10201,7 +10201,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" @@ -10563,7 +10563,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", "dev": true, "requires": { "colors": "1.1.2" @@ -10740,7 +10740,8 @@ }, "yargs-parser": { "version": "13.1.1", - "resolved": "", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -12568,7 +12569,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { @@ -13209,7 +13210,7 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } @@ -13359,7 +13360,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -13826,7 +13827,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, @@ -14999,7 +15000,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -15386,7 +15387,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -15578,7 +15579,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -15930,7 +15931,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", @@ -15981,7 +15982,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -16265,7 +16266,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -17509,7 +17510,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", "dev": true, "requires": { "nopt": "~1.0.10" @@ -18753,7 +18754,7 @@ }, "globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { @@ -18766,7 +18767,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -19227,7 +19228,7 @@ }, "xmlbuilder": { "version": "9.0.7", - "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, "xmlcreate": { diff --git a/package.json b/package.json index d92ff59a64..dafe4d7565 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ "type": "git", "url": "https://gitea.verdnatura.es/verdnatura/salix" }, + "engines": { + "node": ">=12" + }, "dependencies": { "compression": "^1.7.3", "fs-extra": "^5.0.0",