Merge pull request 'gulpfile refactor and removed unused code' (#294) from 2266_refactor_gulpfile_docker into dev
gitea/salix/pipeline/head There was a failure building this commit Details

Reviewed-by: Juan Ferrer <juan@verdnatura.es>
This commit is contained in:
Carlos Jimenez Ruiz 2020-06-11 10:10:38 +00:00
commit a66cc4a36d
8 changed files with 278 additions and 346 deletions

2
Jenkinsfile vendored
View File

@ -68,7 +68,7 @@ pipeline {
stage('Backend') {
steps {
nodejs('node-lts') {
sh 'gulp backTestDockerOnce --junit --random'
sh 'gulp backTestOnce --ci'
}
}
}

View File

@ -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/)

166
db/docker.js Normal file
View File

@ -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
});
}
});
});
}
};

View File

@ -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();

View File

@ -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);
});
});

View File

@ -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,13 +69,25 @@ 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);
dataSources = JSON.parse(JSON.stringify(dataSources));
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) => {
@ -92,7 +100,7 @@ async function backTestOnce() {
}
};
if (argv.junit) {
if (argv.ci) {
const reporters = require('jasmine-reporters');
options.reporter = new reporters.JUnitXmlReporter();
}
@ -109,42 +117,16 @@ async function backTestOnce() {
.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,
};

57
package-lock.json generated
View File

@ -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": {

View File

@ -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",