From c6437a8e5c436b458a6bfa9a76dd464ef9318d79 Mon Sep 17 00:00:00 2001 From: Ole Date: Tue, 25 May 2021 15:36:14 +0200 Subject: [PATCH] feat: Artsy Open --- README.md | 2 + docs/open.md | 49 ++++++++++++ package.json | 8 +- src/commands/open.ts | 81 ++++++++++++++++++++ src/config.ts | 9 +++ src/lib/open/config.ts | 13 ++++ src/lib/open/data/config.json | 103 +++++++++++++++++++++++++ src/lib/open/index.ts | 62 ++++++++++++++++ test/commands/open/index.test.ts | 105 ++++++++++++++++++++++++++ tsconfig.json | 3 +- yarn.lock | 124 ++++++++++++++++++++++++++++++- 11 files changed, 555 insertions(+), 4 deletions(-) create mode 100644 docs/open.md create mode 100644 src/commands/open.ts create mode 100644 src/lib/open/config.ts create mode 100644 src/lib/open/data/config.json create mode 100644 src/lib/open/index.ts create mode 100644 test/commands/open/index.test.ts diff --git a/README.md b/README.md index 213c8f96..c4151105 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Artsy CLI is published on npm, so installing is really easy: $ npm install --global @artsy/cli ``` +## [Open](docs/open.md) + ## Releasing The release process happens automatically on every PR merge thanks to [auto](https://github.com/intuit/auto). To ensure diff --git a/docs/open.md b/docs/open.md new file mode 100644 index 00000000..24a52115 --- /dev/null +++ b/docs/open.md @@ -0,0 +1,49 @@ +# Artsy CLI Open + +Open Artsy links with iOS, Android or the browser. + +## Usage + +**With an alias:** + +``` +artsy open artist +``` + +opens https://artsy.net/artwork/banksy-love-rat-signed-16 on iOS + +**With a path:** + +``` +artsy open /artwork/andy-warhol-watercolor-paint-kit-with-brushes-11 +``` + +opens https://artsy.net/artwork/banksy-love-rat-signed-16 on iOS + +**With a full URL:** + +``` +artsy open https://staging.artsy.net/artwork/andy-warhol-watercolor-paint-kit-with-brushes-11 +``` + +opens https://staging.artsy.net/artwork/banksy-love-rat-signed-16 on iOS + +**With flags:** + +``` +artsy open artwork -a -l +``` + +opens https://localhost:3000/artwork/banksy-love-rat-signed-16 on Android + +**With custom variables:** + +``` +artsy open artist artistID:andy-warhol +``` + +opens https://artsy.net/artist/andy-warhol on Android + +## Config + +All aliases and defaults can be found [here](src/lib/open/data/config.json) and can be overridden by providing `~/.config/artsy-open.json`. diff --git a/package.json b/package.json index db484057..ed1c24ac 100644 --- a/package.json +++ b/package.json @@ -20,16 +20,20 @@ "apollo-client": "^2.6.10", "apollo-link-http": "^1.5.17", "cli-ux": "^5.3.1", + "colon-template": "^1.0.3", "cross-fetch": "^3.0.6", + "dashify": "^2.0.0", "dotenv": "^8.0.0", "graphql": "^15.5.0", "graphql-tag": "^2.11.0", "lodash.chunk": "^4.2.0", "lodash.shuffle": "^4.2.0", "node-fetch": "^2.6.0", + "open": "^8.0.9", "querystring": "^0.2.0", "rss-parser": "^3.11.0", - "tslib": "^2" + "tslib": "^2", + "uri-scheme": "^1.0.76" }, "devDependencies": { "@artsy/auto-config": "^1.0.1", @@ -42,6 +46,7 @@ "@oclif/test": "^1", "@oclif/tslint": "^3", "@types/chai": "^4", + "@types/dashify": "^1.0.0", "@types/mocha": "^8", "@types/node": "^14", "@types/node-fetch": "^2.5.0", @@ -52,6 +57,7 @@ "nock": "^13.0.10", "nyc": "^13", "prettier": "^1.18.2", + "sinon": "^10.0.0", "ts-node": "^9", "tslint": "^5", "tslint-config-prettier": "^1.18.0", diff --git a/src/commands/open.ts b/src/commands/open.ts new file mode 100644 index 00000000..5d39b5a4 --- /dev/null +++ b/src/commands/open.ts @@ -0,0 +1,81 @@ +import { flags } from "@oclif/command" +import Command from "../base" + +import openPage from "../lib/open" +import config from "../lib/open/config" + +export default class Open extends Command { + static description = + "Open Artsy links with the iOS/Android emulator or the browser" + + static examples = [ + `$ artsy open artist +opens "https://artsy.net/artwork/banksy-love-rat-signed-16" on iOS`, + `$ artsy open artwork/andy-warhol-watercolor-paint-kit-with-brushes-11 +opens "https://artsy.net/artwork/andy-warhol-watercolor-paint-kit-with-brushes-11" on iOS`, + `artsy open artist artistID:andy-warhol +Open "https://artsy.net/artist/andy-warhol" on iOS`, + `$ artsy open home -a +opens "https://artsy.net/" on Android`, + `$ artsy open about -l +opens "http://localhost/about" on iOS`, + `\nALL PAGES`, + Object.keys(config.pages).join(", "), + ] + + static flags = { + ...Command.flags, + ios: flags.boolean({ char: "i" }), + android: flags.boolean({ char: "a" }), + web: flags.boolean({ char: "w" }), + production: flags.boolean({ char: "p" }), + staging: flags.boolean({ char: "s" }), + local: flags.boolean({ char: "l" }), + } + + static args = [ + { name: "page", required: false, default: "/" }, + { name: "customVariables", required: false }, + ] + + parsePlatform(): string | undefined { + const { flags } = this.parse(Open) + + if (flags.ios) return "ios" + if (flags.android) return "android" + if (flags.web) return "web" + } + + parseEnvironment(): string | undefined { + const { flags } = this.parse(Open) + + if (flags.staging) return "staging" + if (flags.production) return "production" + if (flags.local) return "local" + } + + parseCustomVariables(): object { + const { + args: { customVariables }, + } = this.parse(Open) + + if (!customVariables) return {} + + return customVariables.split(",").reduce((acc: any, element: string) => { + const [key, value] = element.split(":") + acc[key] = value + return acc + }, {}) + } + + async run() { + const { args } = this.parse(Open) + + openPage({ + page: args.page as string, + platform: this.parsePlatform(), + environment: this.parseEnvironment(), + customVariables: this.parseCustomVariables(), + }) + } +} diff --git a/src/config.ts b/src/config.ts index 36ecf9c0..1b73e1b7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,6 +5,15 @@ export const Config = { path: (): string => { return `${os.homedir()}/.config/artsy` }, + readOpenConfig: (): any => { + try { + return JSON.parse( + fs.readFileSync(`${os.homedir()}/.config/artsy-open.json`) + ) + } catch { + return {} + } + }, readToken: (): string => { return fs.readFileSync(Config.path(), { encoding: "utf-8" }) }, diff --git a/src/lib/open/config.ts b/src/lib/open/config.ts new file mode 100644 index 00000000..38e8d090 --- /dev/null +++ b/src/lib/open/config.ts @@ -0,0 +1,13 @@ +import { Config } from "../../config" +import { defaults, environments, pages, variables } from "./data/config.json" + +const homeConfig = Config.readOpenConfig() + +const config = { + environments: { ...environments, ...homeConfig.environments }, + pages: { ...pages, ...homeConfig.pages }, + variables: { ...variables, ...homeConfig.variables }, + defaults: { ...defaults, ...homeConfig.defaults }, +} + +export default config diff --git a/src/lib/open/data/config.json b/src/lib/open/data/config.json new file mode 100644 index 00000000..cf9be4c6 --- /dev/null +++ b/src/lib/open/data/config.json @@ -0,0 +1,103 @@ +{ + "defaults": { + "environment": "production", + "platform": "ios" + }, + "environments": { + "local": "http://localhost:3000", + "production": "https://artsy.net", + "staging": "https://staging.artsy.net" + }, + "pages": { + "about": "/about", + "admin": "/admin", + "admin2": "/admin2", + "artist": "/artist/:artistID", + "artist-articles": "/artist/:artistID/articles", + "artist-series": "/artist-series/:artistSeriesID", + "artwork": "/artwork/:artworkID", + "artwork-attribution-class-faq": "/artwork-classifications", + "artwork-medium": "/artwork/:artworkID/medium", + "auction": "/auction/:auctionID", + "auction-bid-artwork": "/auction/:saleID/bid/:artworkID", + "auction-faq": "/auction-faq", + "auction-info": "/auction/:saleID/info", + "auction-registration": "/auction-registration/:saleID", + "auction-result": "/artist/:artistID/auction-result/:auctionResultInternalID", + "auction2": "/auction/:saleID", + "auctions": "/auctions", + "buy-now-feature-faq": "/buy-now-feature-faq", + "categories": "/categories", + "checkout": "/orders/:orderID", + "city-bmwlist": "/city-bmw-list/:citySlug", + "city-fair-list": "/city-fair/:citySlug", + "city-saved-list": "/city-save/:citySlug", + "city-section-list": "/city/:citySlug/:section", + "collection": "/collection/:collectionID", + "conditions-of-sale": "/conditions-of-sale", + "consignments-submission-form": "/consign/submission", + "conversation": "/user/conversations/:conversationID", + "fair": "/fair/:fairID/exhibitors", + "fair-all-followed-artists": "/fair/:fairID/followedArtists", + "fair-articles": "/fair/:fairID/articles", + "fair-bmwart-activation": "/fair/:fairID/bmw-sponsored-content", + "fair-more-info": "/fair/:fairID/info", + "favorites": "/favorites", + "feature": "/feature/:featureSlug", + "full-artist-series-list": "/artist/:artistID/artist-series", + "full-featured-artist-list": "/collection/:collectionID/artists", + "gene": "/gene/:geneID", + "home": "/", + "identity-verification-faq": "/identity-verification-faq", + "inbox": "/inbox", + "inquiry": "/inquiry/:artworkID", + "local-discovery": "/local-discovery", + "make-offer-modal": "/make-offer/:artworkID", + "my-account": "/my-account", + "my-account-edit-email": "/my-account/edit-email", + "my-account-edit-name": "/my-account/edit-name", + "my-account-edit-password": "/my-account/edit-password", + "my-account-edit-phone": "/my-account/edit-phone", + "my-collection": "/my-collection", + "my-collection-artwork": "/my-collection/artwork/:artworkSlug", + "my-collection-artwork-full-details": "/my-collection/artwork-details/:artworkSlug", + "my-collection-artwork-images": "/my-collection/artwork-images/:artworkSlug", + "my-profile": "/my-profile", + "my-profile-payment": "/my-profile/payment", + "my-profile-payment-new-credit-card": "/my-profile/payment/new-card", + "my-profile-push-notifications": "/my-profile/push-notifications", + "order": "/orders/:orderID", + "partner-locations": "/partner-locations/:partnerID", + "privacy": "/privacy", + "privacy-request": "/privacy-request", + "sales": "/sales", + "sales-not-root-tab-view": "/collections/my-collection/marketing-landing", + "search": "/search", + "show": "/show/:showID", + "show-more-info": "/show/:showID/info", + "terms": "/terms", + "viewing-room": "/viewing-room/:viewing_room_id", + "viewing-room-artwork": "/viewing-room/:viewing_room_id/:artworkID", + "viewing-room-artworks": "/viewing-room/:viewing_room_id/artworks", + "viewing-rooms": "/viewing-rooms", + "works-for-you": "/works-for-you" + }, + "variables": { + "artistID": "banksy", + "artistSeriesID": "andy-warhol-watercolor-paint-kit-with-brushes", + "artworkID": "banksy-love-rat-signed-16", + "auctionID": "american-friends-of-museums-in-israel-benefit-auction-2021", + "auctionResultInternalID": "", + "citySlug": "berlin", + "collectionID": "abstract-expressionism-works-on-paper", + "conversationID": "", + "fairID": "one-x-artsy", + "featureSlug": "museum-of-contemporary-art-san-diego-benefit-auction-2020", + "geneID": "design", + "orderID": "", + "partnerID": "menconi-plus-schoelkopf", + "saleID": "american-friends-of-museums-in-israel-benefit-auction-2021", + "showID": "first-floor-gallery-harare-amanda-mushate-nguve-inemuridzi", + "viewing_room_id": "artcn-panacea-of-liu-zhenchen" + } +} diff --git a/src/lib/open/index.ts b/src/lib/open/index.ts new file mode 100644 index 00000000..271279db --- /dev/null +++ b/src/lib/open/index.ts @@ -0,0 +1,62 @@ +const { Android, Ios } = require("uri-scheme") +const dashify = require("dashify") +const template = require("colon-template") +const open = require("open") + +import config from "./config" +interface OpenPageProps { + page: string + platform: string | undefined + environment: string | undefined + customVariables: object +} + +const openUri = (uri: string, platform: string) => { + switch (platform) { + case "android": + Android.openAsync({ uri }) + break + case "ios": + Ios.openAsync({ uri }) + break + case "web": + open(uri) + } +} + +const removeTrailingSlash = (path: string): string => { + return path.replace(/^\//, "") +} + +const getURI = ( + input: string, + variables: object, + environment: string +): string => { + if (input.includes("://")) return input + + const { pages, environments } = config + + const templatePath = removeTrailingSlash(pages[dashify(input)] || input) + + const path = template(templatePath, variables) + + return `${environments[environment]}/${path}` +} + +const openPage = ({ + page, + platform, + environment, + customVariables, +}: OpenPageProps) => { + const variables = { ...config.variables, ...customVariables } + const env = environment || config.defaults.environment + const uri = getURI(page, variables, env) + + console.log(`Open "${uri}" on ${platform || config.defaults.platform}`) + + openUri(uri, platform || config.defaults.platform) +} + +export default openPage diff --git a/test/commands/open/index.test.ts b/test/commands/open/index.test.ts new file mode 100644 index 00000000..48c52c15 --- /dev/null +++ b/test/commands/open/index.test.ts @@ -0,0 +1,105 @@ +import { expect, test } from "@oclif/test" +import { Config } from "../../../src/config" +const sinon = require("sinon") +const { Android, Ios } = require("uri-scheme") + +beforeEach(() => { + sinon.stub(Config, "readOpenConfig").callsFake(() => ({})) + sinon.stub(Android, "openAsync").callsFake() + sinon.stub(Ios, "openAsync").callsFake() +}) + +afterEach(() => { + sinon.restore() +}) + +describe("open default with alias", () => { + test + .stdout() + .command(["open", "artwork"]) + .it("opens artwork on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "https://artsy.net/artwork/banksy-love-rat-signed-16", + }) + ).to.be.ok + }) +}) + +describe("open default without alias", () => { + test + .stdout() + .command(["open", "/artworks"]) + .it("opens artworks on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "https://artsy.net/artworks", + }) + ).to.be.ok + }) +}) + +describe("open default on android", () => { + test + .stdout() + .command(["open", "/artworks", "-a"]) + .it("opens artwork on android", () => { + expect( + Android.openAsync.calledWith({ + uri: "https://artsy.net/artworks", + }) + ).to.be.ok + }) +}) + +describe("open default on ios", () => { + test + .stdout() + .command(["open", "/artworks", "-i"]) + .it("opens artwork on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "https://artsy.net/artworks", + }) + ).to.be.ok + }) +}) + +describe("open default on production", () => { + test + .stdout() + .command(["open", "/artworks", "-p"]) + .it("opens artworks on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "https://artsy.net/artworks", + }) + ).to.be.ok + }) +}) + +describe("open default on staging", () => { + test + .stdout() + .command(["open", "/artworks", "-s"]) + .it("opens artworks on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "https://staging.artsy.net/artworks", + }) + ).to.be.ok + }) +}) + +describe("open default on localhost", () => { + test + .stdout() + .command(["open", "/artworks", "-l"]) + .it("opens artworks on ios", () => { + expect( + Ios.openAsync.calledWith({ + uri: "http://localhost:3000/artworks", + }) + ).to.be.ok + }) +}) diff --git a/tsconfig.json b/tsconfig.json index 28f5e856..1c9124c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,9 +5,10 @@ "importHelpers": true, "module": "commonjs", "outDir": "lib", + "resolveJsonModule": true, "rootDir": "src", "strict": true, "target": "es2019" }, - "include": ["src/**/*"] + "include": ["src/**/*", "src/lib/open/data/config.json"] } diff --git a/yarn.lock b/yarn.lock index 35dec3d1..a1da2f88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1119,6 +1119,34 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@sinonjs/samsam@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.3.1.tgz#375a45fe6ed4e92fca2fb920e007c48232a6507f" + integrity sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg== + dependencies: + "@sinonjs/commons" "^1.6.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== + "@slack/client@^5.0.2": version "5.0.2" resolved "https://registry.yarnpkg.com/@slack/client/-/client-5.0.2.tgz#75a45bdd86a9eb8eaba2febb0bbdfeb281cf02e1" @@ -1207,6 +1235,11 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.17.tgz#85f9f0610f514b22a94125d441f73eef65bde5cc" integrity sha512-LaiwWNnYuL8xJlQcE91QB2JoswWZckq9A4b+nMPq8dt8AP96727Nb3X4e74u+E3tm4NLTILNI9MYFsyVc30wSA== +"@types/dashify@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/dashify/-/dashify-1.0.0.tgz#19ade107e1e330344a65ad65f0e7e1875483d2e9" + integrity sha512-uyYom3SM48jvowobcby+1z3r/sDX+5N8lAdPoNLKYMhF819pNjV6K5g8lAUGrwj80n+P7Qf10GcA9h7aIO2GJw== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -1996,6 +2029,14 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +colon-template@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colon-template/-/colon-template-1.0.3.tgz#a4dc563aedc0e51a08902fea47c1eb23e6fcf4fd" + integrity sha1-pNxWOu3A5RoIkC/qR8HrI+b89P0= + dependencies: + escape-regexp "0.0.1" + propget "1.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2152,6 +2193,11 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +dashify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dashify/-/dashify-2.0.0.tgz#fff270ca2868ca427fee571de35691d6e437a648" + integrity sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A== + dataloader@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" @@ -2224,6 +2270,11 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -2273,6 +2324,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== +diff@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2386,6 +2442,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-regexp@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/escape-regexp/-/escape-regexp-0.0.1.tgz#f44bda12d45bbdf9cb7f862ee7e4827b3dd32254" + integrity sha1-9EvaEtRbvfnLf4Yu5+SCez3TIlQ= + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -3184,6 +3245,11 @@ is-docker@^2.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== +is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -3500,6 +3566,11 @@ jsonwebtoken@^8.5.1: ms "^2.1.1" semver "^5.6.0" +just-extend@^4.0.2: + version "4.2.1" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" + integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== + jwa@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -3637,7 +3708,7 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.get@^4: +lodash.get@^4, lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= @@ -3959,6 +4030,17 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +nise@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-4.1.0.tgz#8fb75a26e90b99202fa1e63f448f58efbcdedaf6" + integrity sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@sinonjs/fake-timers" "^6.0.0" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" + path-to-regexp "^1.7.0" + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -4127,6 +4209,15 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +open@^8.0.9: + version "8.0.9" + resolved "https://registry.yarnpkg.com/open/-/open-8.0.9.tgz#a7a739fed91dfa3734094255badbeabd71116a12" + integrity sha512-vbCrqMav3K8mCCy8NdK4teUky0tpDrBbuiDLduCdVhc5oA9toJMip9rBkuwdwSI9E7NOkz4VkLWPi8DD2MP1gQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optimism@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.3.tgz#163268fdc741dea2fb50f300bedda80356445fd7" @@ -4369,6 +4460,13 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -4442,6 +4540,11 @@ propagate@^2.0.0: resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== +propget@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/propget/-/propget-1.0.0.tgz#d003512445efb813eabc29989cd5ecf715679f42" + integrity sha1-0ANRJEXvuBPqvCmYnNXs9xVnn0I= + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -4823,6 +4926,18 @@ signedsource@^1.0.0: resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" integrity sha1-HdrOSYF5j5O9gzlzgD2A1S6TrWo= +sinon@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-10.0.0.tgz#52279f97e35646ff73d23207d0307977c9b81430" + integrity sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw== + dependencies: + "@sinonjs/commons" "^1.8.1" + "@sinonjs/fake-timers" "^6.0.1" + "@sinonjs/samsam" "^5.3.1" + diff "^4.0.2" + nise "^4.1.0" + supports-color "^7.1.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -5314,7 +5429,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -5394,6 +5509,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +uri-scheme@^1.0.76: + version "1.0.76" + resolved "https://registry.yarnpkg.com/uri-scheme/-/uri-scheme-1.0.76.tgz#88de159c47a17f9d9b107ad357546351f07383f3" + integrity sha512-MvN5R8KX3NIdzt75N2E+o6SqEcSxB5zDX6UCZ5AQnPXLP8ZK68d5zAaxXOMk/79lzTNo18qmnHPBLe6vM+rqug== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"