diff --git a/doc/SDK.md b/doc/SDK.md index 4cd6c68c..87e7c897 100644 --- a/doc/SDK.md +++ b/doc/SDK.md @@ -1,80 +1,94 @@ -# How to use Hydrogen as an SDK +# Hydrogen View SDK -If you want to use end-to-end encryption, it is recommended to use a [supported build system](../src/sdk/paths/) (currently only vite) to be able to locate the olm library files. -**NOTE**: For now, these instructions will only work at development time, support when building (e.g. `vite build`) is being worked on and tracked in [#529](https://github.com/vector-im/hydrogen-web/issues/529). +The Hydrogen view SDK allows developers to integrate parts of the Hydrogen application into the UI of their own application. Hydrogen is written with the MVVM pattern, so to construct a view, you'd first construct a view model, which you then pass into the view. For most view models, you will first need a running client. -You can create a project using the following commands +## Example + +The Hydrogen SDK requires some assets to be shipped along with your app for things like downloading attachments, and end-to-end encryption. A convenient way to make this happen is provided by the SDK (importing `hydrogen-view-sdk/paths/vite`) but depends on your build system. Currently, only [vite](https://vitejs.dev/) is supported, so that's what we'll be using in the example below. + +You can create a vite project using the following commands: ```sh # you can pick "vanilla-ts" here for project type if you're not using react or vue yarn create vite cd yarn -yarn add https://github.com/vector-im/hydrogen-web.git +yarn add hydrogen-view-sdk ``` -If you go into the `src` directory, you should see a `main.ts` file. If you put this code in there, you should see a basic timeline after login and initial sync have finished. +You should see a `index.html` in the project root directory, containing an element with `id="app"`. Add the attribute `class="hydrogen"` to this element, as the CSS we'll include from the SDK assumes for now that the app is rendered in an element with this classname. + +If you go into the `src` directory, you should see a `main.ts` file. If you put this code in there, you should see a basic timeline after login and initial sync have finished (might take a while before you see anything on the screen actually). + +You'll need to provide the username and password of a user that is already in the [#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) room (or change the room id). ```ts import { Platform, - SessionContainer, + Client, LoadStatus, createNavigation, createRouter, RoomViewModel, TimelineView -} from "hydrogen-web"; -import {olmPaths, downloadSandboxPath} from "hydrogen-web/src/sdk/paths/vite"; +} from "hydrogen-view-sdk"; +import assetPaths from "hydrogen-view-sdk/paths/vite"; +import "hydrogen-view-sdk/style.css"; -const app = document.querySelector('#app')! - -// bootstrap a session container -const platform = new Platform(app, { - downloadSandbox: downloadSandboxPath, - olm: olmPaths, -}, null, { development: true }); -const navigation = createNavigation(); -platform.setNavigation(navigation); -const urlRouter = createRouter({ - navigation: navigation, - history: platform.history -}); -urlRouter.attach(); -const sessionContainer = new SessionContainer({ - platform, - olmPromise: platform.loadOlm(), - workerPromise: platform.loadOlmWorker() -}); - -// wait for login and first sync to finish -const loginOptions = await sessionContainer.queryLogin("matrix.org").result; -sessionContainer.startWithLogin(loginOptions.password("user", "password")); -await sessionContainer.loadStatus.waitFor((status: string) => { - return status === LoadStatus.Ready || - status === LoadStatus.Error || - status === LoadStatus.LoginFailed; -}).promise; -// check the result -if (sessionContainer.loginFailure) { - alert("login failed: " + sessionContainer.loginFailure); -} else if (sessionContainer.loadError) { - alert("load failed: " + sessionContainer.loadError.message); -} else { - // we're logged in, we can access the room now - const {session} = sessionContainer; - // room id for #element-dev:matrix.org - const room = session.rooms.get("!bEWtlqtDwCLFIAKAcv:matrix.org"); - const vm = new RoomViewModel({ - room, - ownUserId: session.userId, - platform, - urlCreator: urlRouter, - navigation, +async function main() { + const app = document.querySelector('#app')! + const platform = new Platform(app, assetPaths, { development: import.meta.env.DEV }); + const navigation = createNavigation(); + platform.setNavigation(navigation); + const urlRouter = createRouter({ + navigation: navigation, + history: platform.history }); - await vm.load(); - const view = new TimelineView(vm.timelineViewModel); - app.appendChild(view.mount()); + urlRouter.attach(); + const client = new Client(platform); + + const loginOptions = await client.queryLogin("matrix.org").result; + client.startWithLogin(loginOptions.password("username", "password")); + + await client.loadStatus.waitFor((status: string) => { + return status === LoadStatus.Ready || + status === LoadStatus.Error || + status === LoadStatus.LoginFailed; + }).promise; + + if (client.loginFailure) { + alert("login failed: " + client.loginFailure); + } else if (client.loadError) { + alert("load failed: " + client.loadError.message); + } else { + const {session} = client; + // looks for room corresponding to #element-dev:matrix.org, assuming it is already joined + const room = session.rooms.get("!bEWtlqtDwCLFIAKAcv:matrix.org"); + const vm = new RoomViewModel({ + room, + ownUserId: session.userId, + platform, + urlCreator: urlRouter, + navigation, + }); + await vm.load(); + const view = new TimelineView(vm.timelineViewModel); + app.appendChild(view.mount()); + } } + +main(); ``` + +## Typescript support + +There is partial typescript support while we are still in the process of converting the Hydrogen codebase to typesccript. + +## API Stability + +This library follows semantic versioning; there is no API stability promised as long as the major version is still 0. Once 1.0.0 is released, breaking changes will be released with a change in major versioning. + +## Third-party licenses + +This package bundles the bs58 package ([license](https://github.com/cryptocoinjs/bs58/blob/master/LICENSE)), and the Inter font ([license](https://github.com/rsms/inter/blob/master/LICENSE.txt)). diff --git a/package.json b/package.json index d90747ab..1efafb16 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "hydrogen-web", "version": "0.2.22", "description": "A javascript matrix client prototype, trying to minize RAM usage by offloading as much as possible to IndexedDB", - "main": "src/lib.ts", "directories": { "doc": "doc" }, @@ -12,7 +11,8 @@ "lint-ci": "eslint src/", "test": "impunity --entry-point src/platform/web/main.js src/platform/web/Platform.js --force-esm-dirs lib/ src/ --root-dir src/", "start": "vite --port 3000", - "build": "vite build" + "build": "vite build", + "build:sdk": "./scripts/sdk/build.sh" }, "repository": { "type": "git", @@ -27,27 +27,31 @@ "devDependencies": { "@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/parser": "^4.29.2", + "acorn": "^8.6.0", + "acorn-walk": "^8.2.0", + "aes-js": "^3.1.2", "core-js": "^3.6.5", + "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", + "escodegen": "^2.0.0", "eslint": "^7.32.0", "fake-indexeddb": "^3.1.2", "impunity": "^1.0.9", "mdn-polyfills": "^5.20.0", + "merge-options": "^3.0.4", "node-html-parser": "^4.0.0", "postcss-css-variables": "^0.18.0", "postcss-flexbugs-fixes": "^5.0.2", "regenerator-runtime": "^0.13.7", + "text-encoding": "^0.7.0", "typescript": "^4.3.5", "vite": "^2.6.14", "xxhashjs": "^0.2.2" }, "dependencies": { "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz", - "aes-js": "^3.1.2", "another-json": "^0.2.0", "base64-arraybuffer": "^0.2.0", "bs58": "^4.0.1", - "dompurify": "^2.3.0", - "es6-promise": "https://github.com/bwindels/es6-promise.git#bwindels/expose-flush", - "text-encoding": "^0.7.0" + "dompurify": "^2.3.0" } } diff --git a/scripts/build-plugins/service-worker.js b/scripts/build-plugins/service-worker.js index 19ae793f..805f6000 100644 --- a/scripts/build-plugins/service-worker.js +++ b/scripts/build-plugins/service-worker.js @@ -12,6 +12,7 @@ function injectServiceWorker(swFile, otherUnhashedFiles, placeholdersPerChunk) { const swName = path.basename(swFile); let root; let version; + let logger; return { name: "hydrogen:injectServiceWorker", @@ -27,6 +28,7 @@ function injectServiceWorker(swFile, otherUnhashedFiles, placeholdersPerChunk) { configResolved: config => { root = config.root; version = JSON.parse(config.define.DEFINE_VERSION); // unquote + logger = config.logger; }, generateBundle: async function(options, bundle) { const unhashedFilenames = [swName].concat(otherUnhashedFiles); @@ -46,7 +48,7 @@ function injectServiceWorker(swFile, otherUnhashedFiles, placeholdersPerChunk) { ...getCacheFileNamePlaceholderValues(swName, unhashedFilenames, assets, placeholdersPerChunk) }; replacePlaceholdersInChunks(assets, placeholdersPerChunk, placeholderValues); - console.log(`\nBuilt ${version} (${globalHash})`); + logger.info(`\nBuilt ${version} (${globalHash})`); } }; } diff --git a/scripts/sdk/base-manifest.json b/scripts/sdk/base-manifest.json new file mode 100644 index 00000000..612d69a4 --- /dev/null +++ b/scripts/sdk/base-manifest.json @@ -0,0 +1,14 @@ +{ + "name": "hydrogen-view-sdk", + "description": "Embeddable matrix client library, including view components", + "version": "0.0.1", + "main": "./hydrogen.cjs.js", + "exports": { + ".": { + "import": "./hydrogen.es.js", + "require": "./hydrogen.cjs.js" + }, + "./paths/vite": "./paths/vite.js" + }, + "types": "types/lib.d.ts" +} diff --git a/scripts/sdk/build.sh b/scripts/sdk/build.sh new file mode 100755 index 00000000..3145df80 --- /dev/null +++ b/scripts/sdk/build.sh @@ -0,0 +1,20 @@ +rm -rf target +yarn run vite build -c vite.sdk-assets-config.js +yarn run vite build -c vite.sdk-lib-config.js +yarn tsc -p tsconfig-declaration.json +./scripts/sdk/create-manifest.js ./target/package.json +mkdir target/paths +./scripts/sdk/transform-paths.js ./src/platform/web/sdk/paths/vite.js ./target/paths/vite.js +cp doc/SDK.md target/README.md +pushd target +pushd asset-build/assets +mv main.*.js ../../main.js +mv index.*.css ../../style.css +mv download-sandbox.*.html ../../download-sandbox.html +rm *.js *.wasm +mv ./* ../../ +popd +rm -rf asset-build +mv lib-build/* . +rm -rf lib-build +popd diff --git a/scripts/sdk/create-manifest.js b/scripts/sdk/create-manifest.js new file mode 100755 index 00000000..7a01de0a --- /dev/null +++ b/scripts/sdk/create-manifest.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +const fs = require("fs"); +const appManifest = require("../../package.json") +const baseSDKManifest = require("./base-manifest.json") +const mergeOptions = require('merge-options'); + +const manifestExtension = { + devDependencies: undefined, + scripts: undefined, +}; + +const manifest = mergeOptions(appManifest, baseSDKManifest, manifestExtension); +const json = JSON.stringify(manifest, undefined, 2); +const outFile = process.argv[2]; +fs.writeFileSync(outFile, json, {encoding: "utf8"}); diff --git a/scripts/sdk/transform-paths.js b/scripts/sdk/transform-paths.js new file mode 100755 index 00000000..60724c21 --- /dev/null +++ b/scripts/sdk/transform-paths.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node + +/** +This script transforms the string literals in the sdk path files to adjust paths +from what they are at development time to what they will be in the sdk package. + +It does this by looking in all string literals in the paths file and looking for file names +that we expect and need replacing (as they are bundled with the sdk). + +Usage: ./transform-paths.js +*/ + +const acorn = require("acorn"); +const walk = require("acorn-walk") +const escodegen = require("escodegen"); +const fs = require("fs"); + +const code = fs.readFileSync(process.argv[2], {encoding: "utf8"}); +const ast = acorn.parse(code, {ecmaVersion: "13", sourceType: "module"}); + +function changePrefix(value, file, newPrefix = "") { + const idx = value.indexOf(file); + if (idx !== -1) { + return newPrefix + value.substr(idx); + } + return value; +} + +walk.simple(ast, { + Literal(node) { + node.value = changePrefix(node.value, "download-sandbox.html", "../"); + node.value = changePrefix(node.value, "main.js", "../"); + } +}); +const transformedCode = escodegen.generate(ast); +fs.writeFileSync(process.argv[3], transformedCode, {encoding: "utf8"}) diff --git a/src/index.html b/src/index.html new file mode 100644 index 00000000..456f095a --- /dev/null +++ b/src/index.html @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/platform/web/sdk/paths/vite.ts b/src/platform/web/sdk/paths/vite.js similarity index 100% rename from src/platform/web/sdk/paths/vite.ts rename to src/platform/web/sdk/paths/vite.js diff --git a/tsconfig-declaration.json b/tsconfig-declaration.json new file mode 100644 index 00000000..472e1698 --- /dev/null +++ b/tsconfig-declaration.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "outDir": "target/types", + "rootDir": "src" + }, + "exclude": [ + "src/sdk/paths/*" + ], + "include": ["src/**/*"], +} diff --git a/tsconfig.json b/tsconfig.json index e3fae938..f46cc7eb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,12 @@ { "compilerOptions": { "strictNullChecks": true, + "noImplicitAny": false, "noEmit": true, "target": "ES2020", - "moduleResolution": "node" + "module": "ES2020", + "moduleResolution": "node", + "esModuleInterop": true }, "exclude": [ "src/sdk/paths/*" diff --git a/vite.common-config.js b/vite.common-config.js new file mode 100644 index 00000000..44c884bd --- /dev/null +++ b/vite.common-config.js @@ -0,0 +1,49 @@ +const cssvariables = require("postcss-css-variables"); +const flexbugsFixes = require("postcss-flexbugs-fixes"); +const fs = require("fs"); +const path = require("path"); +const manifest = require("./package.json"); +const version = manifest.version; + +const commonOptions = { + logLevel: "warn", + publicDir: false, + server: { + hmr: false + }, + resolve: { + alias: { + // these should only be imported by the base-x package in any runtime code + // and works in the browser with a Uint8Array shim, + // rather than including a ton of polyfill code + "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", + "buffer": "./scripts/package-overrides/buffer/index.js", + } + }, + build: { + emptyOutDir: true, + assetsInlineLimit: 0, + polyfillModulePreload: false, + }, + define: { + DEFINE_VERSION: JSON.stringify(version), + DEFINE_GLOBAL_HASH: JSON.stringify(null), + }, + css: { + postcss: { + plugins: [ + cssvariables({ + preserve: (declaration) => { + return declaration.value.indexOf("var(--ios-") == 0; + } + }), + // the grid option creates some source fragment that causes the vite warning reporter to crash because + // it wants to log a warning on a line that does not exist in the source fragment. + // autoprefixer({overrideBrowserslist: ["IE 11"], grid: "no-autoplace"}), + flexbugsFixes() + ] + } + } +}; + +module.exports = commonOptions; diff --git a/vite.config.js b/vite.config.js index 1562269e..b6ec597d 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,39 +1,18 @@ -const cssvariables = require("postcss-css-variables"); -const flexbugsFixes = require("postcss-flexbugs-fixes"); - -const fs = require("fs"); -const path = require("path"); - const injectWebManifest = require("./scripts/build-plugins/manifest"); const {injectServiceWorker, createPlaceholderValues} = require("./scripts/build-plugins/service-worker"); const {defineConfig} = require('vite'); -const version = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; +const mergeOptions = require('merge-options').bind({concatArrays: true}); +const commonOptions = require("./vite.common-config.js"); export default defineConfig(({mode}) => { const definePlaceholders = createPlaceholderValues(mode); - return { - public: false, + return mergeOptions(commonOptions, { root: "src/platform/web", base: "./", - server: { - hmr: false - }, - resolve: { - alias: { - // these should only be imported by the base-x package in any runtime code - // and works in the browser with a Uint8Array shim, - // rather than including a ton of polyfill code - "safe-buffer": "./scripts/package-overrides/safe-buffer/index.js", - "buffer": "./scripts/package-overrides/buffer/index.js", - } - }, build: { outDir: "../../../target", - emptyOutDir: true, minify: true, sourcemap: true, - assetsInlineLimit: 0, - polyfillModulePreload: false, }, plugins: [ // important this comes before service worker @@ -45,28 +24,6 @@ export default defineConfig(({mode}) => { "sw": definePlaceholders }), ], - define: { - DEFINE_VERSION: JSON.stringify(version), - ...definePlaceholders - }, - css: { - postcss: { - plugins: [ - cssvariables({ - preserve: (declaration) => { - return declaration.value.indexOf("var(--ios-") == 0; - } - }), - // the grid option creates some source fragment that causes the vite warning reporter to crash because - // it wants to log a warning on a line that does not exist in the source fragment. - // autoprefixer({overrideBrowserslist: ["IE 11"], grid: "no-autoplace"}), - flexbugsFixes() - ] - } - } - }; + define: definePlaceholders, + }); }); - -function scriptTagPath(htmlFile, index) { - return `${htmlFile}?html-proxy&index=${index}.js`; -} diff --git a/vite.sdk-assets-config.js b/vite.sdk-assets-config.js new file mode 100644 index 00000000..90720966 --- /dev/null +++ b/vite.sdk-assets-config.js @@ -0,0 +1,11 @@ +const path = require("path"); +const mergeOptions = require('merge-options'); +const commonOptions = require("./vite.common-config.js"); + +export default mergeOptions(commonOptions, { + root: "src/", + base: "./", + build: { + outDir: "../target/asset-build/", + }, +}); diff --git a/vite.sdk-lib-config.js b/vite.sdk-lib-config.js new file mode 100644 index 00000000..c1678d8b --- /dev/null +++ b/vite.sdk-lib-config.js @@ -0,0 +1,47 @@ +const path = require("path"); +const mergeOptions = require('merge-options'); +const commonOptions = require("./vite.common-config.js"); +const manifest = require("./package.json"); + +const externalDependencies = Object.keys(manifest.dependencies) + // just in case for safety in case fake-indexeddb wouldn't be + // treeshake'd out of the bundle + .concat(Object.keys(manifest.devDependencies)) + // bundle bs58 because it uses buffer indirectly, which is a pain to bundle, + // so we don't annoy our library users with it. + .filter(d => d !== "bs58"); +const moduleDir = path.join(__dirname, "node_modules"); + +export default mergeOptions(commonOptions, { + root: "src/", + build: { + lib: { + entry: path.resolve(__dirname, 'src/lib.ts'), + formats: ["cjs", "es"], + fileName: format => `hydrogen.${format}.js`, + }, + minify: false, + sourcemap: false, + outDir: "../target/lib-build", + // don't bundle any dependencies, they should be imported/required + rollupOptions: { + external(id) { + return externalDependencies.some(d => id === d || id.startsWith(d + "/")); + }, + /* don't bundle, so we can override imports per file at build time to replace components */ + // output: { + // manualChunks: (id) => { + // if (id.startsWith(srcDir)) { + // const idPath = id.substring(srcDir.length); + // const pathWithoutExt = idPath.substring(0, idPath.lastIndexOf(".")); + // return pathWithoutExt; + // } else { + // return "index"; + // } + // }, + // minifyInternalExports: false, + // chunkFileNames: "[format]/[name].js" + // } + } + }, +}); diff --git a/yarn.lock b/yarn.lock index 87d39fac..87b8ef96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -156,11 +156,21 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== +acorn-walk@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.6.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" + integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== + aes-js@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" @@ -401,6 +411,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -608,6 +623,18 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -695,7 +722,7 @@ espree@^7.3.0, espree@^7.3.1: acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -763,7 +790,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -963,6 +990,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1004,6 +1036,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -1036,6 +1076,13 @@ mdn-polyfills@^5.20.0: resolved "https://registry.yarnpkg.com/mdn-polyfills/-/mdn-polyfills-5.20.0.tgz#ca8247edf20a4f60dec6804372229812b348260b" integrity sha512-AbTv1ytcoOUAkxw6u5oo2QPf27kEZgxBAQr49jFb4i2VnTnFGfJbcIQ9UDBOdfNECeXsgkYFwB2BkdeTfOzztw== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1093,6 +1140,18 @@ once@^1.3.0: dependencies: wrappy "1" +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -1170,6 +1229,11 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -1297,6 +1361,11 @@ source-map-js@^0.6.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -1392,6 +1461,13 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -1471,7 +1547,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -word-wrap@^1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==