diff --git a/packages/builder/src/builderStore/store.js b/packages/builder/src/builderStore/store.js index 49f6c0308a..bd95c2249f 100644 --- a/packages/builder/src/builderStore/store.js +++ b/packages/builder/src/builderStore/store.js @@ -344,17 +344,13 @@ const saveDerivedComponent = store => (derivedComponent) => { s.derivedComponents = derivedComponents; - const forSave = pipe(derivedComponents, [ - cloneDeep, - keyBy("_name") - ]); - - for(let c of forSave) { - delete c._name; - } - - s.pages.derivedComponents = forSave; - savePackage(store, s); + fetch(`/_builder/api/${s.appname}/derivedcomponent`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(derivedComponent), + }); return s; }) diff --git a/packages/builder/src/userInterface/UserInterfaceRoot.svelte b/packages/builder/src/userInterface/UserInterfaceRoot.svelte index 5ad9d7a3fa..5172758f57 100644 --- a/packages/builder/src/userInterface/UserInterfaceRoot.svelte +++ b/packages/builder/src/userInterface/UserInterfaceRoot.svelte @@ -4,8 +4,17 @@ import ComingSoon from "../common/ComingSoon.svelte"; - +
+
+ +
+
\ No newline at end of file diff --git a/packages/builder/src/userInterface/pagesParsing/defaultPagesObject.js b/packages/builder/src/userInterface/pagesParsing/defaultPagesObject.js index 4fbeb98a86..1510cbcc05 100644 --- a/packages/builder/src/userInterface/pagesParsing/defaultPagesObject.js +++ b/packages/builder/src/userInterface/pagesParsing/defaultPagesObject.js @@ -11,6 +11,5 @@ export const defaultPagesObject = () => ({ }, appBody: "bbapp.unauthenticated.json" }, - componentLibraries: ["./components"], - derivedComponents:[] + componentLibraries: ["./components"] }); \ No newline at end of file diff --git a/packages/server/appPackages/master/main.js b/packages/server/appPackages/master/main.js index 62403902f6..4c9c291293 100644 --- a/packages/server/appPackages/master/main.js +++ b/packages/server/appPackages/master/main.js @@ -5,7 +5,7 @@ const { take, takeRight, last } = require("lodash/fp"); const { splitKey, $, joinKey } = require("budibase-core").common; const { unzipTarGzPackageToRuntime } = require("../../utilities/targzAppPackage"); const { getRuntimePackageDirectory } = require("../../utilities/runtimePackages"); -const { exists } = require("../../utilities/fsawait"); +const { pathExists } = require("fs-extra"); const createInstanceDb = require("../../initialise/createInstanceDb"); const { createWriteStream } = require("fs"); const { applictionVersionPackage } = require("../../utilities/createAppPackage"); @@ -33,7 +33,7 @@ module.exports = (context) => { application.name, versionId); - if(!await exists(runtimeDir)) + if(!await pathExists(runtimeDir)) await downloadAppPackage(apis, instance, application.name, versionId); const dbConfig = await createInstanceDb( diff --git a/packages/server/appPackages/testApp/components/newTextBox.json b/packages/server/appPackages/testApp/components/newTextBox.json new file mode 100644 index 0000000000..f5de87bb1e --- /dev/null +++ b/packages/server/appPackages/testApp/components/newTextBox.json @@ -0,0 +1 @@ +{"_name":"newTextBox","_component":"./customComponents/textbox","label":"something else"} diff --git a/packages/server/appPackages/testApp/components/undefined.json b/packages/server/appPackages/testApp/components/undefined.json new file mode 100644 index 0000000000..0a3036fd00 --- /dev/null +++ b/packages/server/appPackages/testApp/components/undefined.json @@ -0,0 +1 @@ +{"oldname":"newTextBox","newName":"anotherSubFolder/newTextBox"} diff --git a/packages/server/appPackages/testApp/dist/package.tar.gz b/packages/server/appPackages/testApp/dist/package.tar.gz index 1af8254fa4..c6821cf947 100644 Binary files a/packages/server/appPackages/testApp/dist/package.tar.gz and b/packages/server/appPackages/testApp/dist/package.tar.gz differ diff --git a/packages/server/initialise/initialiseBudibase.js b/packages/server/initialise/initialiseBudibase.js index 9775c87409..c26c56835f 100644 --- a/packages/server/initialise/initialiseBudibase.js +++ b/packages/server/initialise/initialiseBudibase.js @@ -2,7 +2,7 @@ const create = require("./createMasterDb"); const argv = require("yargs").argv const readline = require('readline'); const { promisify } = require('util'); -const { mkdir, rimraf } = require("../utilities/fsawait"); +const { mkdir, remove } = require("fs-extra"); const budibaseConfig = require("../config"); const buildAppContext = require("../initialise/buildAppContext"); @@ -61,7 +61,7 @@ const question = async (q) => { if(cleanDev) { try { - await rimraf(rootconfig.rootPath); + await remove(rootconfig.rootPath); } catch(_){} await mkdir(rootconfig.rootPath); diff --git a/packages/server/initialise/initialiseRuntimePackages.js b/packages/server/initialise/initialiseRuntimePackages.js index 0387e2873e..4a3d9619bd 100644 --- a/packages/server/initialise/initialiseRuntimePackages.js +++ b/packages/server/initialise/initialiseRuntimePackages.js @@ -1,11 +1,10 @@ -const { ncp } = require('ncp'); const { masterAppPackage } = require("../utilities/createAppPackage"); -const { mkdir, rimraf, exists } = require("../utilities/fsawait"); +const { mkdir, remove, pathExists, copy } = require("fs-extra"); const { runtimePackagesDirectory } = require("../utilities/runtimePackages"); const copyfolder = (source, destination) => new Promise((resolve, reject) => { - ncp(source, destination, function (err) { + copy(source, destination, function (err) { if (err) { reject(err); } else { @@ -19,9 +18,9 @@ module.exports = async (context, bbMaster, latestAppsFolder) => { // create runtime folder // copy master into /master/latest - if(await exists(runtimePackagesDirectory)) { + if(await pathExists(runtimePackagesDirectory)) { try { - await rimraf(runtimePackagesDirectory); + await remove(runtimePackagesDirectory); } catch(err) { console.log(err); } diff --git a/packages/server/middleware/routers.js b/packages/server/middleware/routers.js index 2c496e0754..387624b323 100644 --- a/packages/server/middleware/routers.js +++ b/packages/server/middleware/routers.js @@ -4,8 +4,14 @@ const StatusCodes = require("../utilities/statusCodes"); const fs = require("fs"); const { resolve } = require("path"); const send = require('koa-send'); -const { getPackageForBuilder, getRootComponents: getComponents, - savePackage, getApps } = require("../utilities/builder"); +const { + getPackageForBuilder, + getRootComponents, + savePackage, + getApps, + saveDerivedComponent, + renameDerivedComponent +} = require("../utilities/builder"); const builderPath = resolve(__dirname, "../builder"); @@ -119,23 +125,11 @@ module.exports = (config, app) => { ctx.response.status = StatusCodes.OK; }) .get("/_builder/api/apps", async (ctx) => { - if(!config.dev) { - ctx.response.status = StatusCodes.FORBIDDEN; - ctx.response.body = "run in dev mode to access builder"; - return; - } - ctx.body = await getApps(config); ctx.response.status = StatusCodes.OK; }) .get("/_builder/api/:appname/appPackage", async (ctx) => { - if(!config.dev) { - ctx.response.status = StatusCodes.FORBIDDEN; - ctx.body = "run in dev mode to access builder"; - return; - } - ctx.body = await getPackageForBuilder( config, ctx.params.appname); @@ -143,27 +137,16 @@ module.exports = (config, app) => { }) .post("/_builder/api/:appname/appPackage", async (ctx) => { - if(!config.dev) { - ctx.response.status = StatusCodes.FORBIDDEN; - ctx.body = "run in dev mode to access builder"; - return; - } - + ctx.body = await savePackage( config, ctx.params.appname, ctx.request.body); ctx.response.status = StatusCodes.OK; }) - .get("/_builder/api/:appname/components", async (ctx) => { - if(!config.dev) { - ctx.response.status = StatusCodes.FORBIDDEN; - ctx.body = "run in dev mode to access builder"; - return; - } - + .get("/_builder/api/:appname/rootcomponents", async (ctx) => { try { - ctx.body = getComponents( + ctx.body = getRootComponents( config, ctx.params.appname, ctx.query.lib); @@ -176,6 +159,28 @@ module.exports = (config, app) => { } } }) + .post("/_builder/api/:appname/derivedcomponent", async (ctx) => { + await saveDerivedComponent( + config, + ctx.params.appname, + ctx.request.body); + ctx.response.status = StatusCodes.OK; + }) + .patch("/_builder/api/:appname/derivedcomponent", async (ctx) => { + await renameDerivedComponent( + config, + ctx.params.appname, + ctx.request.body.oldname, + ctx.request.body.newname); + ctx.response.status = StatusCodes.OK; + }) + .delete("/_builder/api/:appname/derivedcomponent", async (ctx) => { + await deleteDerivedComponent( + config, + ctx.params.appname, + ctx.request.body.name); + ctx.response.status = StatusCodes.OK; + }) .get("/:appname", async (ctx) => { await send(ctx, "/index.html", { root: ctx.publicPath }); }) diff --git a/packages/server/package.json b/packages/server/package.json index 8213f3ff6a..1b5db19e06 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -15,14 +15,13 @@ "@koa/router": "^8.0.0", "argon2": "^0.23.0", "budibase-core": "file:../core/dist", + "fs-extra": "^8.1.0", "koa": "^2.7.0", "koa-body": "^4.1.0", "koa-send": "^5.0.0", "koa-session": "^5.12.0", "koa-static": "^5.0.0", "lodash": "^4.17.13", - "ncp": "^2.0.0", - "rimraf": "^2.6.3", "tar-fs": "^2.0.0", "uuid": "^3.3.2", "yargs": "^13.2.4" diff --git a/packages/server/tests/authenticate.js b/packages/server/tests/authenticate.js index ce8f8ec0fc..eba9510c3b 100644 --- a/packages/server/tests/authenticate.js +++ b/packages/server/tests/authenticate.js @@ -1,5 +1,5 @@ const statusCodes = require("../utilities/statusCodes"); -const { readFile } = require("../utilities/fsawait"); +const { readFile } = require("fs-extra"); const { timeout } = require("./helpers"); module.exports = (app, appName, userName) => { diff --git a/packages/server/tests/builder.spec.js b/packages/server/tests/builder.spec.js index 91c67f9a1b..24fe400c75 100644 --- a/packages/server/tests/builder.spec.js +++ b/packages/server/tests/builder.spec.js @@ -7,6 +7,7 @@ const testMoreComponents = require("../appPackages/testApp/moreCustomComponents/ const statusCodes = require("../utilities/statusCodes"); const derivedComponent1 = require("../appPackages/testApp/components/myTextBox.json"); const derivedComponent2 = require("../appPackages/testApp/components/subfolder/otherTextBox.json"); +const { readJSON, pathExists } = require("fs-extra"); const app = require("./testApp")(); @@ -64,3 +65,48 @@ it("/apppackage should get derivedComponents", async () => { expect(body.derivedComponents).toEqual(expectedComponents); }); + +it("should be able to create new derived component", async () => { + const newDerivedComponent = { + _name: "newTextBox", + _component: "./customComponents/textbox", + label: "something" + }; + + await app.post("/_builder/api/testApp/derivedcomponent", newDerivedComponent) + .expect(statusCodes.OK); + + const componentFile = "./appPackages/testApp/components/newTextBox.json"; + expect(await pathExists(componentFile)).toBe(true); + expect(await readJSON(componentFile)).toEqual(newDerivedComponent); + +}); + +it("should be able to update derived component", async () => { + const updatedDerivedComponent = { + _name: "newTextBox", + _component: "./customComponents/textbox", + label: "something else" + }; + + await app.post("/_builder/api/testApp/derivedcomponent", updatedDerivedComponent) + .expect(statusCodes.OK); + + const componentFile = "./appPackages/testApp/components/newTextBox.json"; + expect(await readJSON(componentFile)).toEqual(updatedDerivedComponent); +}); + +it("should be able to rename derived component", async () => { + await app.post("/_builder/api/testApp/derivedcomponent", { + oldname: "newTextBox", newName: "anotherSubFolder/newTextBox" + }).expect(statusCodes.OK); + const oldcomponentFile = "./appPackages/testApp/components/newTextBox.json"; + const newcomponentFile = "./appPackages/testApp/components/anotherSubFolder/newTextBox.json"; + expect(await pathExists(oldcomponentFile)).toBe(false); + expect(await pathExists(newcomponentFile)).toBe(true); + +}); + +it("should be able to delete derived component", async () => { + +}); diff --git a/packages/server/tests/createNewApp.js b/packages/server/tests/createNewApp.js index 82e659070c..497d361e6b 100644 --- a/packages/server/tests/createNewApp.js +++ b/packages/server/tests/createNewApp.js @@ -1,6 +1,6 @@ const statusCodes = require("../utilities/statusCodes"); const constructHierarchy = require("../utilities/constructHierarchy"); -const { readFile } = require("../utilities/fsawait"); +const { readFile } = require("fs-extra"); const { hierarchy } = require("budibase-core"); const { take } = require("lodash/fp"); const masterAppDefinition = constructHierarchy( diff --git a/packages/server/tests/multipleInstances.js b/packages/server/tests/multipleInstances.js index fcc8a0f34f..b39bdb9930 100644 --- a/packages/server/tests/multipleInstances.js +++ b/packages/server/tests/multipleInstances.js @@ -1,6 +1,6 @@ const statusCodes = require("../utilities/statusCodes"); const constructHierarchy = require("../utilities/constructHierarchy"); -const { readFile } = require("../utilities/fsawait"); +const { readFile } = require("fs-extra"); const {getRecordApi, getAuthApi} = require("budibase-core"); const masterAppDefinition = constructHierarchy( require("../appPackages/master/appDefinition.json")); diff --git a/packages/server/tests/serveui.js b/packages/server/tests/serveui.js index 6bb6855b91..51d43d34d1 100644 --- a/packages/server/tests/serveui.js +++ b/packages/server/tests/serveui.js @@ -1,5 +1,5 @@ const statusCodes = require("../utilities/statusCodes"); -const { readFile } = require("../utilities/fsawait"); +const { readFile } = require("fs-extra"); module.exports = (app) => { diff --git a/packages/server/tests/testApp.js b/packages/server/tests/testApp.js index e7cd9adac5..6cbea37009 100644 --- a/packages/server/tests/testApp.js +++ b/packages/server/tests/testApp.js @@ -1,5 +1,5 @@ const app = require("../app"); -const { rimraf, mkdir } = require("../utilities/fsawait"); +const { remove, mkdir } = require("fs-extra"); const createMasterDb = require("../initialise/createMasterDb"); const request = require("supertest"); const fs = require("fs"); @@ -123,7 +123,7 @@ const getRequest = (server, url) => const reInitialize = async () => { try { - await rimraf(config.datastoreConfig.rootPath); + await remove(config.datastoreConfig.rootPath); } catch(_){} await mkdir(config.datastoreConfig.rootPath); diff --git a/packages/server/utilities/builder.js b/packages/server/utilities/builder.js index 724d2b1009..97c9d1c26d 100644 --- a/packages/server/utilities/builder.js +++ b/packages/server/utilities/builder.js @@ -3,15 +3,19 @@ const { appsFolder } = require("./createAppPackage"); const { - writeFile, - readFile, + readJSON, + writeJSON, readdir, exists, - stat -} = require("./fsawait"); + stat, + ensureDir, + rename, + unlink +} = require("fs-extra"); const { resolve, - join + join, + dirname } = require("path"); const { $ } = require("budibase-core").common; const { @@ -25,18 +29,12 @@ const {merge} = require("lodash"); module.exports.getPackageForBuilder = async (config, appname) => { const appPath = appPackageFolder(config, appname); - const pages = JSON.parse(await readFile( - `${appPath}/pages.json`, - "utf8")); + const pages = await readJSON(`${appPath}/pages.json`); return ({ - appDefinition: JSON.parse(await readFile( - `${appPath}/appDefinition.json`, - "utf8")), + appDefinition: await readJSON(`${appPath}/appDefinition.json`), - accessLevels: JSON.parse(await readFile( - `${appPath}/access_levels.json`, - "utf8")), + accessLevels: await readJSON(`${appPath}/access_levels.json`), pages, @@ -50,26 +48,55 @@ module.exports.getPackageForBuilder = async (config, appname) => { module.exports.savePackage = async (config, appname, pkg) => { const appPath = appPackageFolder(config, appname); - await writeFile( + await writeJSON( `${appPath}/appDefinition.json`, - JSON.stringify(pkg.appDefinition), - "utf8"); + pkg.appDefinition); - await writeFile( + await writeJSON( `${appPath}/access_levels.json`, - JSON.stringify(pkg.accessLevels), - "utf8"); + pkg.accessLevels); - await writeFile( + await writeJSON( `${appPath}/pages.json`, - JSON.stringify(pkg.pages), - "utf8"); + pkg.pages); } module.exports.getApps = async (config) => await readdir(appsFolder(config)); +const componentPath = (appPath, name) => + join(appPath, "components", name + ".json"); + +module.exports.saveDerivedComponent = async (config, appname, component) => { + const appPath = appPackageFolder(config, appname); + + await writeJSON( + componentPath(appPath, component._name), + component, + {encoding:"utf8", flag:"w"}); +} + +module.exports.renameDerivedComponent = async (config, appname, oldName, newName) => { + const appPath = appPackageFolder(config, appname); + + const oldComponentPath = componentPath( + appPath, oldName); + + const newComponentPath = join( + appPath, newName); + + await ensureDir(dirname(newComponentPath)); + await rename( + oldComponentPath, + newComponentPath); +} + +module.exports.deleteDerivedComponent = async (config, appname, name) => { + const appPath = appPackageFolder(config, appname); + await unlink(componentPath(appPath, name)); +} + const getRootComponents = async (appPath, pages ,lib) => { const componentsInLibrary = async (libname) => { @@ -88,8 +115,7 @@ const getRootComponents = async (appPath, pages ,lib) => { let components; try { - components = JSON.parse( - await readFile(componentsPath, "utf8")); + components = await readJSON(componentsPath); } catch(e) { const err = `could not parse JSON - ${componentsPath} : ${e.message}`; throw new Error(err); @@ -106,9 +132,8 @@ const getRootComponents = async (appPath, pages ,lib) => { let libs; if(!lib) { - pages = pages || JSON.parse(await readFile( - `${appPath}/pages.json`, - "utf8")); + pages = pages || await readJSON( + `${appPath}/pages.json`); if(!pages.componentLibraries) return []; @@ -142,8 +167,8 @@ const fetchDerivedComponents = async (appPath, relativePath = "") => { if(!item.endsWith(".json")) continue; - const component = JSON.parse( - await readFile(itemFullPath, "utf8")); + const component = + await readJSON(itemFullPath); component._name = itemRelativePath .substring(0, itemRelativePath.length - 5) diff --git a/packages/server/utilities/fsawait.js b/packages/server/utilities/fsawait.js deleted file mode 100644 index ddc699f272..0000000000 --- a/packages/server/utilities/fsawait.js +++ /dev/null @@ -1,21 +0,0 @@ -const util = require("util"); -const fs = require("fs"); - -module.exports.readFile = util.promisify(fs.readFile); -module.exports.readdir = util.promisify(fs.readdir); -module.exports.writeFile = util.promisify(fs.writeFile); -module.exports.rimraf = util.promisify(require("rimraf")); -module.exports.mkdir = util.promisify(fs.mkdir); -module.exports.unlink = util.promisify(fs.unlink); -module.exports.stat = util.promisify(fs.stat); -module.exports.exists = async (path) => { - try { - await util.promisify(fs.access)( - path - ); - } catch (e) { - return false; - } - return true; -}; - diff --git a/packages/server/utilities/targzAppPackage.js b/packages/server/utilities/targzAppPackage.js index f88ba54717..d2f0bc6f0e 100644 --- a/packages/server/utilities/targzAppPackage.js +++ b/packages/server/utilities/targzAppPackage.js @@ -5,7 +5,7 @@ const fs = require("fs"); const tar = require('tar-fs'); const zlib = require("zlib"); const { join, dirname, sep } = require("path"); -const { exists, mkdir, unlink, stat } = require("../utilities/fsawait"); +const { exists, mkdir, unlink, stat } = require("fs-extra"); const { getRuntimePackageDirectory, getRuntimeAppsDirectory } = require("./runtimePackages"); module.exports.createTarGzPackage = async (config, appName) => { @@ -33,7 +33,7 @@ module.exports.unzipTarGzPackageToRuntime = async (src, appName, versionId) => { if(await exists(appDir)) { if(await exists(versionDir)) { - await rimraf(versionDir); + await remove(versionDir); } } else { await mkdir(appDir); diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 0189943584..5b1ae24147 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1373,6 +1373,15 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" @@ -1458,7 +1467,7 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== @@ -2339,6 +2348,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -2744,11 +2760,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -ncp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= - needle@^2.2.1: version "2.4.0" resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" @@ -3964,6 +3975,11 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"