From a49a26da48822fdeca93ef22e90888ef0ca84f2e Mon Sep 17 00:00:00 2001 From: garrettmills Date: Thu, 27 Feb 2020 00:31:07 -0600 Subject: [PATCH] Start adding state classes; update dependencies --- app/classes/logical/services/ServiceConfig.js | 5 + app/classes/state/Routine.js | 11 ++ app/classes/state/fs/DirectoryState.js | 2 + app/classes/state/fs/FileContentState.js | 64 ----------- app/classes/state/fs/FileState.js | 6 ++ .../state/os/PackageCacheClearedState.js | 28 +++++ app/classes/state/os/PackageState.js | 24 +++++ .../state/os/ServiceDaemonReloadState.js | 28 +++++ app/classes/state/os/ServiceRestartState.js | 29 +++++ app/classes/state/os/ServiceState.js | 29 +++++ app/classes/state/os/UpdateState.js | 29 +++++ app/services/states.service.js | 50 +++++++++ package.json | 8 +- yarn.lock | 100 +++++++++++++++--- 14 files changed, 333 insertions(+), 80 deletions(-) create mode 100644 app/classes/state/Routine.js delete mode 100644 app/classes/state/fs/FileContentState.js create mode 100644 app/classes/state/os/PackageCacheClearedState.js create mode 100644 app/classes/state/os/PackageState.js create mode 100644 app/classes/state/os/ServiceDaemonReloadState.js create mode 100644 app/classes/state/os/ServiceRestartState.js create mode 100644 app/classes/state/os/ServiceState.js create mode 100644 app/classes/state/os/UpdateState.js create mode 100644 app/services/states.service.js diff --git a/app/classes/logical/services/ServiceConfig.js b/app/classes/logical/services/ServiceConfig.js index 94e9e7c..c4654c9 100644 --- a/app/classes/logical/services/ServiceConfig.js +++ b/app/classes/logical/services/ServiceConfig.js @@ -13,6 +13,11 @@ class ServiceConfig extends Injectable { install_to: 'multi-user.target', } + constructor(merge_data = {}) { + super() + this._data = {...this._data, ...merge_data} + } + name(set) { return this._get_or_set('name', set) } description(set) { return this._get_or_set('description', set) } diff --git a/app/classes/state/Routine.js b/app/classes/state/Routine.js new file mode 100644 index 0000000..31a38b5 --- /dev/null +++ b/app/classes/state/Routine.js @@ -0,0 +1,11 @@ +class Routine { + constructor(steps) { + this.steps = steps + } + + apply_to(host) { + // TODO + } +} + +module.exports = exports = Routine diff --git a/app/classes/state/fs/DirectoryState.js b/app/classes/state/fs/DirectoryState.js index f5539b8..495d798 100644 --- a/app/classes/state/fs/DirectoryState.js +++ b/app/classes/state/fs/DirectoryState.js @@ -5,6 +5,8 @@ class DirectoryState extends State { if ( !(await this.check()) ) { const path = await this._path() await path.touch(true) + + // TODO directories } } diff --git a/app/classes/state/fs/FileContentState.js b/app/classes/state/fs/FileContentState.js deleted file mode 100644 index e795388..0000000 --- a/app/classes/state/fs/FileContentState.js +++ /dev/null @@ -1,64 +0,0 @@ -const State = require('../State') -const UniversalPath = require('../../logical/UniversalPath') - -class FileContentState extends State { - static get services() { - return [...super.services, 'hosts'] - } - - async apply() { - const target_path = await this._target() - if ( target_path.is_valid() ) { - - } - - if ( this._config.source ) { - const source_path = await this._source() - await source_path.copy_to(target_path) - } else { - await target_path.echo(this._config.contents) - } - } - - async check() { - if ( this._config.source ) { - const source_path = await this._source() - const source_hash = await source_path.hash() - - const target_path = await this._target() - if ( !target_path.is_file() ) return false - const target_hash = await target_path.hash() - - return source_hash === target_hash - } else { - const localhost = this.hosts.get('localhost') - const temp_path = await localhost.get_temp_file() - await temp_path.echo(this._config.contents) - const source_hash = await temp_path.hash() - - const target_path = await this._target() - if ( !target_path.is_file() ) return false - const target_hash = await target_path.hash() - - return source_hash === target_hash - } - } - - async reverse() { - await (await this._target()).echo('') - } - - async _target() { - if ( typeof this._config.target === 'string' ) { - return UniversalPath.fromString(this._config.target) - } else return this._config.target - } - - async _source() { - if ( typeof this._config.target === 'string' ) { - return UniversalPath.fromString(this._config.target) - } else return this._config.target - } -} - -module.exports = exports = FileContentState diff --git a/app/classes/state/fs/FileState.js b/app/classes/state/fs/FileState.js index 0a445f3..51d33b4 100644 --- a/app/classes/state/fs/FileState.js +++ b/app/classes/state/fs/FileState.js @@ -5,6 +5,12 @@ class FileState extends State { if ( !(await this.check()) ) { const path = await this._path() await path.touch() + + if ( this._config.contents ) { + await path.echo(this._config.contents) + } else if ( this._config.template ) { + await path.copy_from(this._config.template) + } } } diff --git a/app/classes/state/os/PackageCacheClearedState.js b/app/classes/state/os/PackageCacheClearedState.js new file mode 100644 index 0000000..23bbd09 --- /dev/null +++ b/app/classes/state/os/PackageCacheClearedState.js @@ -0,0 +1,28 @@ +const State = require('../State') + +class PackageCacheClearedState extends State { + static get services() { + return [...super.services, 'output'] + } + + constructor(host, config) { + if ( !host.packages ) { + throw new Error(`Cannot apply package state to host ${host.name}: missing package manager API.`) + } + super(host, config) + } + + async apply() { + return this._host.packages.clear_cache() + } + + async check() { + return false + } + + async reverse() { + this.output.warn(`Package cache cleared state does not currently support reversal. (Host: ${this._host.name})`) + } +} + +module.exports = exports = PackageCacheClearedState diff --git a/app/classes/state/os/PackageState.js b/app/classes/state/os/PackageState.js new file mode 100644 index 0000000..5ef27e7 --- /dev/null +++ b/app/classes/state/os/PackageState.js @@ -0,0 +1,24 @@ +const State = require('../State') + +class PackageState extends State { + constructor(host, config) { + if ( !host.packages ) { + throw new Error(`Cannot apply package state to host ${host.name}: missing package manager API.`) + } + super(host, config) + } + + async apply() { + return this._host.packages.install(this._config.package) + } + + async check() { + return this._host.packages.is_installed(this._config.package) + } + + async reverse() { + return this._host.packages.uninstall(this._config.package) + } +} + +module.exports = exports = PackageState diff --git a/app/classes/state/os/ServiceDaemonReloadState.js b/app/classes/state/os/ServiceDaemonReloadState.js new file mode 100644 index 0000000..e494b0e --- /dev/null +++ b/app/classes/state/os/ServiceDaemonReloadState.js @@ -0,0 +1,28 @@ +const State = require('../State') + +class ServiceDaemonReloadState extends State { + static get services() { + return [...super.services, 'output'] + } + + constructor(host, config) { + if ( !host.services ) { + throw new Error(`Cannot apply service state to host ${host.name}: missing service manager API.`) + } + super(host, config) + } + + async apply() { + return this._host.services.daemon_reload() + } + + async check() { + return false + } + + async reverse() { + this.output.warn(`Service daemon reload state does not currently support reversal. (Host: ${this._host.name})`) + } +} + +module.exports = exports = ServiceDaemonReloadState diff --git a/app/classes/state/os/ServiceRestartState.js b/app/classes/state/os/ServiceRestartState.js new file mode 100644 index 0000000..7e583d3 --- /dev/null +++ b/app/classes/state/os/ServiceRestartState.js @@ -0,0 +1,29 @@ +const State = require('../State') + +class ServiceRestartState extends State { + static get services() { + return [...super.services, 'output'] + } + + constructor(host, config) { + if ( !host.services ) { + throw new Error(`Cannot apply service state to host ${host.name}: missing service manager API.`) + } + super(host, config) + } + + async apply() { + const services = Array.isArray(this._config.service) ? this._config.service : [this._config.service] + return this._host.services.restart(...services) + } + + async check() { + return false + } + + async reverse() { + this.output.warn(`Service restart state does not currently support reversal. (Host: ${this._host.name})`) + } +} + +module.exports = exports = ServiceRestartState diff --git a/app/classes/state/os/ServiceState.js b/app/classes/state/os/ServiceState.js new file mode 100644 index 0000000..22a5872 --- /dev/null +++ b/app/classes/state/os/ServiceState.js @@ -0,0 +1,29 @@ +const State = require('../State') + +class ServiceState extends State { + constructor(host, config) { + if ( !host.services ) { + throw new Error(`Cannot apply service state to host ${host.name}: missing service manager API.`) + } + super(host, config) + } + + async apply() { + const services = Array.isArray(this._config.service) ? this._config.service : [this._config.service] + return this._host.services.start(...services) + } + + async check() { + const services = Array.isArray(this._config.service) ? this._config.service : [this._config.service] + let states = await this._host.services.status(...services) + if ( !Array.isArray(states) ) states = [states] + return states.every(x => x.status === 'running') + } + + async reverse() { + const services = Array.isArray(this._config.service) ? this._config.service : [this._config.service] + return this._host.services.stop(...services) + } +} + +module.exports = exports = ServiceState diff --git a/app/classes/state/os/UpdateState.js b/app/classes/state/os/UpdateState.js new file mode 100644 index 0000000..1b0d59a --- /dev/null +++ b/app/classes/state/os/UpdateState.js @@ -0,0 +1,29 @@ +const State = require('../State') + +class UpdateState extends State { + static get services() { + return [...super.services, 'output'] + } + + constructor(host, config) { + if ( !host.packages ) { + throw new Error(`Cannot apply update state to host ${host.name}: missing package manager API.`) + } + super(host, config) + } + + async apply() { + const packages = (await this._host.packages.list_updates()).map(x => x.name) + await this._host.packages.update(...packages) + } + + async check() { + return (await this._host.packages.list_updates()).length === 0 + } + + async reverse() { + this.output.warn(`Update state does not currently support reversing package updates. (Host: ${this._host.name})`) + } +} + +module.exports = exports = UpdateState diff --git a/app/services/states.service.js b/app/services/states.service.js new file mode 100644 index 0000000..0d446df --- /dev/null +++ b/app/services/states.service.js @@ -0,0 +1,50 @@ +const { Service } = require('flitter-di') + +/* + * states Service + * ------------------------------------------------------------- + * This is a service file that will be made available through Flitter's + * dependency injector to the rest of the application based on its given + * canonical name. + * + * e.g. app.di().service("states") + */ +class StatesService extends Service { + static #state_map = { + // TODO apache and nginx states - virtual host, reverse proxy + // TODO file/directory permissions state - chmod & chown + // TODO file download state + // TODO file unpack state - zips, tarballs + // TODO package repository states - import keys, install repository + // TODO service manager states - service enabled, service installed + // TODO git states - clone repo, ref checked out + + 'fs.file': require('../classes/state/fs/FileState'), + 'fs.directory': require('../classes/state/fs/DirectoryState'), + + 'package.present': require('../classes/state/os/PackageState'), + 'package.updates': require('../classes/state/os/UpdateState'), + 'package.cache.clear': require('../classes/state/os/PackageCacheClearedState'), + + 'service.running': require('../classes/state/os/ServiceState'), + 'service.restarted': require('../classes/state/os/ServiceRestartState'), + 'service.daemon.reloaded': require('../classes/state/os/ServiceDaemonReloadState'), + } + + static get services() { + return [...super.services, 'app', 'configs'] + } + + from_config(host, state_config) { + const type = state_config.type + delete state_config.type + + const StepClass = this.constructor.#state_map[type] + this.app.di().make(StepClass) + if ( !StepClass ) throw new Error(`Invalid or unknown step type: ${type}`) + + return new StepClass(host, state_config) + } +} + +module.exports = exports = StatesService diff --git a/package.json b/package.json index 65dd196..714441d 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,12 @@ "cross-zip": "^2.1.6", "flitter-agenda": "^0.5.0", "flitter-auth": "^0.15.1", - "flitter-cli": "^0.15.1", - "flitter-di": "^0.4.0", - "flitter-flap": "^0.5.1", + "flitter-cli": "^0.15.2", + "flitter-di": "^0.4.1", + "flitter-flap": "^0.5.2", "flitter-forms": "^0.8.0", "flitter-upload": "^0.7.6", - "libflitter": "^0.44.0", + "libflitter": "^0.46.8", "moment": "^2.24.0", "scp": "^0.0.3", "ssh2": "^0.8.7", diff --git a/yarn.lock b/yarn.lock index 7e3fb3f..8c79d5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -399,6 +399,14 @@ bcrypt@^3.0.4: nan "2.13.2" node-pre-gyp "0.12.0" +bl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.0.tgz#e1a574cdf528e4053019bb800b041c0ac88da493" + integrity sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + bluebird@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -768,6 +776,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +denque@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" + integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1030,10 +1043,10 @@ flitter-auth@^0.15.1: uuid "^3.3.2" validator "^10.11.0" -flitter-cli@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/flitter-cli/-/flitter-cli-0.15.1.tgz#21aed6154c248e9e271918af8b5d5a986a98eb95" - integrity sha512-7Hnecf8YJN9vR0PZggk68KhD7dKX/YXup3nbThq5DAJmGewwdakTa8/wNUGnZoR5CAtyynSKxaIsJ4M/iwledw== +flitter-cli@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/flitter-cli/-/flitter-cli-0.15.2.tgz#67a299711debccb3902a398301d2130ac31b00dc" + integrity sha512-xHt6c0QwLghBs54o4qWnq6drwwvTppMfM7ZlUJ3IBaqx9cxM59bipP8FMXLVUTm8gxH7AekJPSROCDK89ij+eA== dependencies: command-line-args "^5.0.2" es6-promisify "^6.0.1" @@ -1045,6 +1058,11 @@ flitter-di@^0.4.0: resolved "https://registry.yarnpkg.com/flitter-di/-/flitter-di-0.4.0.tgz#d4845e07624c06d178403cdfb79f0e400c1483aa" integrity sha512-Zgsqct2dpdXPHCeQHZZQ3qoLjM7aTx/WspgoSrQjleZZPkMynov+TMFntkzkrdkKtIySq7BjJUW3e48MLS9v4Q== +flitter-di@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/flitter-di/-/flitter-di-0.4.1.tgz#c77c40807aea5d3a3cc4f8f5eb2338b63108428d" + integrity sha512-Px1tJYCpeCV/Tl9EjUX202+Y9mpIkZfDpBNmKkgBLkcmBvuAXN4eGTUlBUxWUiTlv1zhePzoxRe9vEEiCzQ4aQ== + flitter-flap@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.4.0.tgz#ab1cdfc5b9ffe0b5b9fe2e3a8bdc87e9aac82c0e" @@ -1055,10 +1073,10 @@ flitter-flap@^0.4.0: node-migration "^1.0.1" touch "^3.1.0" -flitter-flap@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.5.1.tgz#35f0c5eaca21c6704ec671930b68ca98fa7f905a" - integrity sha512-syxaLdvoDI8zx/HDoKsj1bM1DQKYDQLxHWS7uC3eGXbCv/fvcbYHoTkSKCJu1io4jVPi8BzGuhkwEmhEvMBuzw== +flitter-flap@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.5.2.tgz#eeca4dfdfc32b79da46fb64b58a156b052c09239" + integrity sha512-hM605+tynZqmrlD3BnvXdEF6fe3ZXX48awRTKCouMSLdCWW5Ycx9leb87QgTLitKQpWXB+eMXvZUu+6Q4KjzHA== dependencies: del "^4.1.0" js-beautify "^1.10.2" @@ -1074,6 +1092,17 @@ flitter-forms@^0.8.0: recursive-readdir "^2.2.2" validator "^10.11.0" +flitter-orm@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/flitter-orm/-/flitter-orm-0.2.4.tgz#539f7631fd286955b01ce6034a0bb68142540f5d" + integrity sha512-7yhwwzzBpPIyW4VC9nHY+Pe9pM+EFYwljYKkK1BEMy8XNk6JADhcLiwZGJmxK38vQ8D7SEdFpZiux3fB68uVnQ== + dependencies: + flitter-di "^0.4.0" + json-stringify-safe "^5.0.1" + mongodb "^3.5.1" + object-hash "^2.0.1" + uuid "^3.4.0" + flitter-upload@^0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/flitter-upload/-/flitter-upload-0.7.6.tgz#eeae6c2cf63609e84670be1ea2c3af78ed935f99" @@ -1451,6 +1480,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + json5@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" @@ -1536,10 +1570,10 @@ leven@^1.0.2: resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3" integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM= -libflitter@^0.44.0: - version "0.44.0" - resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.44.0.tgz#f3674d0a3a639fc14efbfdbf37a9388e35d74adb" - integrity sha512-Dp/TXRNzeiiwvP+TxagdGX5aIzKXF6wU98xc5hObCoRkrqPGHMpaNJylxgU5fVopgwT1Li0gC317nApXOcxcmA== +libflitter@^0.46.8: + version "0.46.8" + resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.46.8.tgz#1500d70956628ff1db9719ff4086a8b0b313aa6e" + integrity sha512-ZAo4iUeTLz+6crqQG9UUJyliT6L7+kuZyTB39q8FC8qIdwtLd6C28Jkx82sBcYp9JZ5qJsbNYjSlF42Yt/msbg== dependencies: colors "^1.3.3" connect-mongodb-session "^2.2.0" @@ -1551,6 +1585,7 @@ libflitter@^0.44.0: express-graphql "^0.9.0" express-session "^1.15.6" flitter-di "^0.4.0" + flitter-orm "^0.2.4" graphql "^14.5.4" http-status "^1.4.2" mongo-schematic-class "^1.0.3" @@ -1796,6 +1831,19 @@ mongodb@3.3.3: optionalDependencies: saslprep "^1.0.0" +mongodb@^3.5.1: + version "3.5.4" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.5.4.tgz#f7609cfa9f8c56c35e844b4216ddc3a1b1ec5bef" + integrity sha512-xGH41Ig4dkSH5ROGezkgDbsgt/v5zbNUwE3TcFsSbDc6Qn3Qil17dhLsESSDDPTiyFDCPJRpfd4887dtsPgKtA== + dependencies: + bl "^2.2.0" + bson "^1.1.1" + denque "^1.4.1" + require_optional "^1.0.1" + safe-buffer "^5.1.2" + optionalDependencies: + saslprep "^1.0.0" + mongodb@~3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.4.1.tgz#0d15e57e0ea0fc85b7a4fb9291b374c2e71652dc" @@ -2030,6 +2078,11 @@ object-assign@^4.0.1, object-assign@^4.1.0: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-hash@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" + integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -2381,6 +2434,19 @@ readable-stream@^2.0.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^2.3.5: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + recast@0.10.33: version "0.10.33" resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.33.tgz#942808f7aa016f1fa7142c461d7e5704aaa8d697" @@ -2543,6 +2609,11 @@ safe-buffer@5.1.2, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + safe-json-parse@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" @@ -2956,6 +3027,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +uuid@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + uuid@latest: version "3.3.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"