diff --git a/design/publishing.md b/design/publishing.md index 685dc46dd..a248e811e 100644 --- a/design/publishing.md +++ b/design/publishing.md @@ -1,73 +1,77 @@ -##### This design document focuses on the following - +##### This design document focuses on the following - + 1. Separate entry points for node and browser. 2. Specifying the browser field in package.json. 3. Changes in the bundling process. ##### Terms - -* bundler - Module bundlers are tools frontend developers used to bundle JavaScript modules into a single JavaScript files that can be executed in the browser. +- bundler - Module bundlers are tools frontend developers used to bundle JavaScript modules into a single JavaScript files that can be executed in the browser. + +- rollup - rollup.js is the module bundler that the JS SDK uses. -* rollup - rollup.js is the module bundler that the JS SDK uses. +- package.json fields - -* package.json fields - - * main - The main field is a module ID that is the primary entry point to your program. Points to the CJS modules. + - main - The main field is a module ID that is the primary entry point to your program. Points to the CJS modules. - * module - The module field is not an official npm feature but a common convention among bundlers to designate how to import an ESM version of a library. Points to the ES modules. + - module - The module field is not an official npm feature but a common convention among bundlers to designate how to import an ESM version of a library. Points to the ES modules. - * browser - If the module is meant to be used client-side, the browser field should be used instead of the main field. + - browser - If the module is meant to be used client-side, the browser field should be used instead of the main field. ##### Current set up - -1. - TypeScript Source Code +1. TypeScript Source Code / \ - Transpiles into JavaScript + Transpiles into JavaScript 'lib' folder / \ CJS module ES modules -2. main - `lib/src/index.js` - module - `lib/es/src/index.js` +2. main - `lib/src/index.js` module - `lib/es/src/index.js` + +3. Rollup bundling output + +- `graph-js-sdk.js` - Bundled and minified file in IIFE format. This file can be directly used in the browser with a `; -// create an authProvider -var authProvider = new MicrosoftGraph.TokenCredentialAuthProvider.TokenCredentialAuthenticationProvider(tokenCred, { scopes: scopes }); - -client = MicrosoftGraph.Client.initWithMiddleware({ - authProvider: authProvider, -}); + +; // create an authProvider var authProvider = new MicrosoftGraph.TokenCredentialAuthProvider.TokenCredentialAuthenticationProvider(tokenCred, { scopes: scopes }); client = MicrosoftGraph.Client.initWithMiddleware({ authProvider: authProvider, }); ``` diff --git a/docs/tasks/LargeFileUploadTask.md b/docs/tasks/LargeFileUploadTask.md index f0e2d401f..21fd777c7 100644 --- a/docs/tasks/LargeFileUploadTask.md +++ b/docs/tasks/LargeFileUploadTask.md @@ -1,85 +1,159 @@ -# Large File Upload Task - Uploading large files to OneDrive +# Large File Upload Task - Uploading large files to OneDrive, Outlook, Print API. -This task simplifies the implementation of OneDrive's [resumable upload](https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/driveitem_createuploadsession). +References - + +- [Outlook's large file attachment](https://docs.microsoft.com/en-us/graph/outlook-large-attachments) +- [OneDrive's resumable upload](https://docs.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0&preserve-view=true) +- [Print API's large file upload](https://docs.microsoft.com/en-us/graph/upload-data-to-upload-session) ## Creating the client instance Refer [this documentation](../CreatingClientInstance.md) for initializing the client. -## Uploading from browser +## Using the LargeFileUpload Task + +#### Create an upload session + +First step for any upload task is the creation of the upload session. -HTML to select the file for uploading. +**Example of a payload for Outlook** -```HTML - +```typescript +const payload = { + AttachmentItem: { + attachmentType: "file", + name: "", + size: FILE_SIZE, + }, +}; ``` -Get files from the input element and start uploading. +**Example of a payload for OneDrive** ```typescript -async function fileUpload(elem) { - let file = elem.files[0]; - try { - let response = await largeFileUpload(client, file, file.name); - console.log(response); - console.log("File Uploaded Successfully.!!"); - } catch (error) { - console.error(error); - } -} +const payload = { + item: { + "@microsoft.graph.conflictBehavior": "rename", + name: "", + }, +}; +``` -async function largeFileUpload(client, file) { - try { - let options = { - path: "/Documents", - fileName: file.name, - rangeSize: 1024 * 1024, - }; - const uploadTask = await MicrosoftGraph.OneDriveLargeFileUploadTask.create(client, file, options); - const response = await uploadTask.upload(); - return response; - } catch (err) { - throw err; - } -} +**Create the upload session** + +```typescript +const uploadSession = LargeFileUploadTask.createUploadSession(client, "REQUEST_URL", payload); ``` -## Uploading from NodeJS +#### Creating the LargeFileUploadTask object + +- To create the LargeFileUploadTask object you need to create - +- An upload session as shown above. +- A `FileObject` instance. + +**FileObject Interface** ```typescript -function uploadFile() { - fs.readFile("", {}, function(err, file) { - if (err) { - throw err; - } - let fileName = ""; - oneDriveLargeFileUpload(client, file, fileName) - .then((response) => { - console.log(response); - console.log("File Uploaded Successfully.!!"); - }) - .catch((error) => { - throw err; - }); - }); +export interface FileObject { + content: T; + name: string; + size: number; + sliceFile(range: Range): Promise; } +``` + +The Microsoft Graph JavaScript Client SDK provides two implementions - + +1. StreamUpload - Supports Node.js stream upload + +```typescript +import StreamUpload from "@microsoft/microsoft-graph-client"; +import * as fs from "fs"; + +const fileName = ""; +const stats = fs.statSync(`./test/sample_files/${fileName}`); +const totalsize = stats.size; +const readStream = fs.createReadStream(`./test/sample_files/${fileName}`); +const fileObject = new StreamUpload(readStream, fileName, totalsize); +``` + +Note - In case of a browser application, you can use [stream-browserify](https://www.npmjs.com/package/stream-browserify) and [buffer](https://www.npmjs.com/package/buffer). + +2. FileUpload - Supports upload of file formats - ArrayBuffer, Blob, Buffer + +```typescript +import FileUpload from "@microsoft/microsoft-graph-client"; +import * as fs from "fs"; + +const fileName = ""; +const stats = fs.statSync(`./test/sample_files/${fileName}`); +const totalsize = stats.size; +const readStream = fs.readFileSync(`./test/sample_files/${fileName}`); +const fileObject = new FileUpload(readStream, fileName, totalsize); +``` -async function oneDriveLargeFileUpload(client, file, fileName) { - try { - let options = { - path: "/Documents", - fileName, - rangeSize: 1024 * 1024, - }; - const uploadTask = await OneDriveLargeFileUploadTask.create(client, file, options); - const response = await uploadTask.upload(); - return response; - } catch (err) { - console.log(err); - } +**_Note_** - You can also have a customized `FileObject` implementation which contains the `sliceFile(range: Range)` function which implements the logic to split the file into ranges. + +**Initiate the LargefileUploadTask options with Progress Handler and Range Size** + +```typescript +const progress = (range?: Range, extraCallBackParams?: unknown) => { + // Handle progress event +}; + +const progressCallBack: Progress = { + progress, + extraCallBackParam, // additional parameters to the callback +}; + +const options: LargeFileUploadTaskOptions = { + rangeSize: 327680, + progressCallBack: progressCallBack, +}; +``` + +**Create a LargefileUploadTask object** + +```typescript +const uploadTask = new LargeFileUploadTask(client, fileObj, uploadSession, optionsWithProgress); +const uploadResult: UploadResult = await uploadTask.upload(); +``` + +`UploadResult` contains the `location`(received in the Outlook API response headers) and the `responseBody` (responseBody received after successful upload.) properties. + +## OneDriveLargeFileUploadTask. + +_You can also use `OneDriveLargeFileUploadTask` which provides easier access to upload to OneDrive API_ + +Example - + +```typescript +const progressCallBack: Progress = { + progress, + completed, + failure, + extraCallBackParams: true, +}; + +const options: OneDriveLargeFileUploadOptions = { + path: "/Documents", + fileName, + rangeSize: 1024 * 1024, + progressCallBack, +}; +const readStream = fs.createReadStream(`./fileName`); +const fileObject = new StreamUpload(readStream, fileName, totalsize); +or +const readFile = fs.readFileSync(`./fileName`); +const fileObject = new FileUpload(readStream, fileName, totalsize); + +const uploadTask = await OneDriveLargeFileUploadTask.createTaskWithFileObject(client, fileObject, options); +const uploadResult:UploadResult = await uploadTask.upload(); } ``` +> Note: The `OneDriveLargeFileUploadTask.createTaskWithFileObject` also handles the upload session creation.** + ## We can just resume the broken upload _Lets consider some break down happens in the middle of uploading, with the uploadTask object in hand you can resume easily._ @@ -98,38 +172,6 @@ let slicedFile = uploadTask.sliceFile(range); uploadTask.uploadSlice(slicedFile, range, uploadTask.file.size); ``` -## Uploading with custom options - -_You can pass in the customized options using LargeFileUploadTask_ - -```typescript -async function largeFileUpload(client, file) { - const fileName = file.name; - const driveId = ""; - const path = ""; - try { - const requestUrl = `/drives/${driveId}/root:${path}/${fileName}:/createUploadSession`; - const payload = { - item: { - "@microsoft.graph.conflictBehavior": "fail", - name: fileName, - }, - }; - const fileObject = { - size: file.size, - content: file, - name: fileName, - }; - const uploadSession = await LargeFileUploadTask.createUploadSession(client, requestUrl, payload); - const uploadTask = await new LargeFileUploadTask(client, fileObject, uploadSession); - const response = await uploadTask.upload(); - return response; - } catch (err) { - throw err; - } -} -``` - ## Cancelling a largeFileUpload task _Cancelling an upload session sends a DELETE request to the upload session URL_ diff --git a/package-lock.json b/package-lock.json index 2ec492b3c..834ce5cf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -229,6 +229,62 @@ "lodash": "^4.17.19", "semver": "^5.4.1", "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "@babel/generator": { @@ -240,6 +296,25 @@ "@babel/types": "^7.12.11", "jsesc": "^2.5.1", "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-annotate-as-pure": { @@ -249,6 +324,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.10" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -259,6 +353,25 @@ "requires": { "@babel/helper-explode-assignable-expression": "^7.10.4", "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-compilation-targets": { @@ -305,6 +418,25 @@ "@babel/helper-function-name": "^7.10.4", "@babel/types": "^7.10.5", "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-explode-assignable-expression": { @@ -314,6 +446,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.1" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-function-name": { @@ -325,6 +476,25 @@ "@babel/helper-get-function-arity": "^7.12.10", "@babel/template": "^7.12.7", "@babel/types": "^7.12.11" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-get-function-arity": { @@ -334,6 +504,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.10" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-hoist-variables": { @@ -343,6 +532,25 @@ "dev": true, "requires": { "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-member-expression-to-functions": { @@ -352,6 +560,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.7" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-module-imports": { @@ -361,6 +588,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.5" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-module-transforms": { @@ -378,6 +624,36 @@ "@babel/traverse": "^7.12.1", "@babel/types": "^7.12.1", "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + } + } + } } }, "@babel/helper-optimise-call-expression": { @@ -387,6 +663,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.10" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-plugin-utils": { @@ -404,6 +699,25 @@ "@babel/helper-annotate-as-pure": "^7.10.4", "@babel/helper-wrap-function": "^7.10.4", "@babel/types": "^7.12.1" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-replace-supers": { @@ -416,6 +730,25 @@ "@babel/helper-optimise-call-expression": "^7.12.10", "@babel/traverse": "^7.12.10", "@babel/types": "^7.12.11" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-simple-access": { @@ -425,6 +758,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.1" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -434,6 +786,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.1" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-split-export-declaration": { @@ -443,6 +814,25 @@ "dev": true, "requires": { "@babel/types": "^7.12.11" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-validator-identifier": { @@ -467,6 +857,25 @@ "@babel/template": "^7.10.4", "@babel/traverse": "^7.10.4", "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helpers": { @@ -478,15 +887,34 @@ "@babel/template": "^7.10.4", "@babel/traverse": "^7.12.5", "@babel/types": "^7.12.5" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } @@ -498,9 +926,9 @@ "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", - "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", @@ -756,6 +1184,34 @@ "@babel/helper-module-imports": "^7.12.1", "@babel/helper-plugin-utils": "^7.10.4", "@babel/helper-remap-async-to-generator": "^7.12.1" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-block-scoped-functions": { @@ -768,9 +1224,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.11.tgz", - "integrity": "sha512-atR1Rxc3hM+VPg/NvNvfYw0npQEAcHuJ+MGZnFn6h3bo+1U3BWXMdFMlvVRApBTWKQMX7SOwRJZA5FBF/JQbvA==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" @@ -995,6 +1451,34 @@ "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", "semver": "^5.5.1" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-shorthand-properties": { @@ -1134,6 +1618,34 @@ "@babel/types": "^7.12.11", "core-js-compat": "^3.8.0", "semver": "^5.5.0" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/preset-modules": { @@ -1166,23 +1678,105 @@ "@babel/code-frame": "^7.10.4", "@babel/parser": "^7.12.7", "@babel/types": "^7.12.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + } + } + } } }, "@babel/traverse": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.10.tgz", - "integrity": "sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.10", - "@babel/types": "^7.12.10", + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + } + } + } } }, "@babel/types": { @@ -1431,6 +2025,20 @@ "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } } }, "@samverschueren/stream-to-observable": { @@ -1490,15 +2098,15 @@ "dev": true }, "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", "dev": true }, "@types/json-schema": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", "dev": true }, "@types/mocha": { @@ -1508,9 +2116,9 @@ "dev": true }, "@types/node": { - "version": "12.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", + "version": "12.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.1.tgz", + "integrity": "sha512-tCkE96/ZTO+cWbln2xfyvd6ngHLanvVlJ3e5BeirJ3BYI5GbAyubIrmV4JjjugDly5D9fHjOL5MNsqsCnqwW6g==", "dev": true }, "@types/node-fetch": { @@ -1700,9 +2308,9 @@ "dev": true }, "acorn-walk": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.1.tgz", - "integrity": "sha512-zn/7dYtoTVkG4EoMU55QlQU4F+m+T7Kren6Vj3C2DapWPnakG/DL9Ns5aPAPW5Ixd3uxXrV/BoMKKVFIazPcdg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.2.tgz", + "integrity": "sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==", "dev": true }, "after": { @@ -2024,9 +2632,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } @@ -2085,12 +2693,6 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, "async-settle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", @@ -2131,9 +2733,9 @@ }, "dependencies": { "follow-redirects": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", - "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==", "dev": true } } @@ -2249,15 +2851,6 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -2307,9 +2900,9 @@ "dev": true }, "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true }, "body-parser": { @@ -2405,18 +2998,6 @@ "dev": true, "requires": { "resolve": "^1.17.0" - }, - "dependencies": { - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - } } }, "browser-stdout": { @@ -2489,12 +3070,6 @@ "safe-buffer": "^5.2.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -2505,12 +3080,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true } } }, @@ -2524,16 +3093,16 @@ } }, "browserslist": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz", - "integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", + "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001165", + "caniuse-lite": "^1.0.30001173", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.621", + "electron-to-chromium": "^1.3.634", "escalade": "^3.1.1", - "node-releases": "^1.1.67" + "node-releases": "^1.1.69" } }, "buffer": { @@ -2643,13 +3212,7 @@ "dev": true, "requires": { "caller-callsite": "^2.0.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true + } }, "callsites": { "version": "2.0.0", @@ -2664,9 +3227,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001170", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz", - "integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==", + "version": "1.0.30001178", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz", + "integrity": "sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==", "dev": true }, "chai": { @@ -3040,9 +3603,9 @@ } }, "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", "dev": true }, "copy-descriptor": { @@ -3062,12 +3625,12 @@ } }, "core-js-compat": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.1.tgz", - "integrity": "sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", + "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", "dev": true, "requires": { - "browserslist": "^4.15.0", + "browserslist": "^4.16.0", "semver": "7.0.0" }, "dependencies": { @@ -3120,9 +3683,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } @@ -3480,9 +4043,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } @@ -3552,9 +4115,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.632", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.632.tgz", - "integrity": "sha512-LkaEH9HHr9fodmm3txF4nFMyHN3Yr50HcpD/DBHpLCxzM9doV8AV0er6aBWva4IDs2aA9kGguces0rp+WKL7rg==", + "version": "1.3.641", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.641.tgz", + "integrity": "sha512-b0DLhsHSHESC1I+Nx6n4w4Lr61chMd3m/av1rZQhS2IXTzaS5BMM5N+ldWdMIlni9CITMRM09m8He4+YV/92TA==", "dev": true }, "elegant-spinner": { @@ -3564,24 +4127,24 @@ "dev": true }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } @@ -3608,17 +4171,17 @@ } }, "engine.io": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", - "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", + "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "0.3.1", + "cookie": "~0.4.1", "debug": "~4.1.0", "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" + "ws": "~7.4.2" }, "dependencies": { "debug": { @@ -3633,9 +4196,9 @@ } }, "engine.io-client": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", - "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.1.tgz", + "integrity": "sha512-oVu9kBkGbcggulyVF0kz6BV3ganqUeqXvD79WOFKa+11oK692w1NyFkuEj4xrkFRpZhn92QOqTk4RQq5LiBXbQ==", "dev": true, "requires": { "component-emitter": "~1.3.0", @@ -3646,7 +4209,7 @@ "indexof": "0.0.1", "parseqs": "0.0.6", "parseuri": "0.0.6", - "ws": "~6.1.0", + "ws": "~7.4.2", "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" }, @@ -3665,27 +4228,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", - "dev": true - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", - "dev": true - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } } } }, @@ -3840,12 +4382,12 @@ "dev": true }, "eslint": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.19.0.tgz", - "integrity": "sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -3857,7 +4399,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -3941,6 +4483,21 @@ "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", "dev": true }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -4140,35 +4697,12 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -5101,6 +5635,12 @@ "ansi-regex": "^2.0.0" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", @@ -5186,12 +5726,6 @@ "safe-buffer": "^5.2.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -5202,12 +5736,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true } } }, @@ -5497,10 +6025,13 @@ } }, "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -5508,6 +6039,12 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -5517,6 +6054,15 @@ "binary-extensions": "^1.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -5626,9 +6172,9 @@ } }, "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", + "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", "dev": true }, "is-glob": { @@ -5647,11 +6193,12 @@ "dev": true }, "is-nan": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", - "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3" } }, @@ -5687,6 +6234,12 @@ } } }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -5780,6 +6333,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -5790,16 +6349,107 @@ } }, "is-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.4.tgz", - "integrity": "sha512-ILaRgn4zaSrVNXNGtON6iFNotXW3hAPF3+0fB1usg2jFlWqo5fEDdmJkz0zBfoi7Dgskr8Khi2xZ8cXqZEfXNA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", "dev": true, "requires": { "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", "foreach": "^2.0.5", "has-symbols": "^1.0.1" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "dependencies": { + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } + } + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + } } }, "is-typedarray": { @@ -6304,9 +6954,9 @@ "dev": true }, "chokidar": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.0.tgz", - "integrity": "sha512-JgQM9JS92ZbFR4P90EvmzNpSGhpPBGBSj10PILeDyYFwp4h2/D9OM03wsJ4zW1fEp4ka2DGrnUeD7FuvQ2aZ2Q==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -6371,9 +7021,9 @@ } }, "fsevents": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz", - "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -6384,9 +7034,9 @@ "dev": true }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -6468,9 +7118,9 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -6596,9 +7246,9 @@ } }, "karma-typescript": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.2.0.tgz", - "integrity": "sha512-idMJ0SKPLYudNiPaRw+GyOu0RQPJFpyUfrSN6/uFTzPLnJ7sLDd6xPMcxB+pNBHpL6s4fQfC5W9OlNblRvt2Dg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.5.0.tgz", + "integrity": "sha512-ZbRcDo6ERl8os+aVFintWOW9lngm6VEsQ3VumJBmHXcZOw24K6eEW4qDxLGAcy55bFMxCmdvR0p3Rhen7m8p9A==", "dev": true, "requires": { "acorn": "^8.0.1", @@ -6647,40 +7297,17 @@ }, "dependencies": { "acorn": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", - "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.0.tgz", + "integrity": "sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==", "dev": true }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -6692,12 +7319,6 @@ "util-deprecate": "^1.0.1" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -6711,14 +7332,6 @@ "dev": true, "requires": { "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } } } } @@ -7301,17 +7914,17 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } }, "mime": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", - "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true }, "mime-db": { @@ -7715,9 +8328,9 @@ "dev": true }, "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", @@ -7763,9 +8376,9 @@ } }, "node-releases": { - "version": "1.1.67", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz", - "integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==", + "version": "1.1.70", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", + "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==", "dev": true }, "noop-logger": { @@ -8094,12 +8707,6 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -8138,13 +8745,25 @@ "dev": true }, "object-is": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", - "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" + }, + "dependencies": { + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + } } }, "object-keys": { @@ -8435,22 +9054,16 @@ "dev": true }, "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true }, "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true }, "parseurl": { "version": "1.3.3", @@ -8763,9 +9376,9 @@ }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true } } @@ -8974,6 +9587,23 @@ "dev": true, "requires": { "@babel/runtime": "^7.8.4" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + } } }, "regex-not": { @@ -9013,9 +9643,9 @@ "dev": true }, "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", + "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -9176,9 +9806,9 @@ "dev": true }, "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.2.0.tgz", + "integrity": "sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA==", "dev": true }, "rimraf": { @@ -9201,9 +9831,9 @@ } }, "rollup": { - "version": "2.41.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.2.tgz", - "integrity": "sha512-6u8fJJXJx6fmvKrAC9DHYZgONvSkz8S9b/VFBjoQ6dkKdHyPpPbpqiNl2Bao9XBzDHpq672X6sGZ9G1ZBqAHMg==", + "version": "2.39.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.39.0.tgz", + "integrity": "sha512-+WR3bttcq7zE+BntH09UxaW3bQo3vItuYeLsyk4dL2tuwbeSKJuvwiawyhEnvRdRgrII0Uzk00FpctHO/zB1kw==", "dev": true, "requires": { "fsevents": "~2.3.1" @@ -9574,16 +10204,16 @@ } }, "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", - "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", + "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", "dev": true, "requires": { "debug": "~4.1.0", - "engine.io": "~3.4.0", + "engine.io": "~3.5.0", "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", + "socket.io-client": "2.4.0", "socket.io-parser": "~3.4.0" }, "dependencies": { @@ -9605,54 +10235,31 @@ "dev": true }, "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", + "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", "dev": true, "requires": { "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.5.0", "has-binary2": "~1.0.2", - "has-cors": "1.1.0", "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", + "parseqs": "0.0.6", + "parseuri": "0.0.6", "socket.io-parser": "~3.3.0", "to-array": "0.1.4" }, "dependencies": { - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "^2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } + "ms": "2.0.0" } }, "isarray": { @@ -9668,31 +10275,14 @@ "dev": true }, "socket.io-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", - "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", + "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", "dev": true, "requires": { "component-emitter": "~1.3.0", "debug": "~3.1.0", "isarray": "2.0.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } } } @@ -9916,12 +10506,6 @@ "readable-stream": "^3.5.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -9953,12 +10537,6 @@ "xtend": "^4.0.2" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -9969,12 +10547,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true } } }, @@ -10599,6 +11171,18 @@ } } }, + "unbox-primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", + "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.0", + "has-symbols": "^1.0.0", + "which-boxed-primitive": "^1.0.1" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -10940,6 +11524,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", @@ -11012,9 +11609,9 @@ } }, "ws": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", - "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", "dev": true }, "xml2js": { diff --git a/package.json b/package.json index 210259d6b..ac39bccdf 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,10 @@ "license": "MIT", "main": "lib/src/index.js", "module": "lib/es/src/index.js", + "browser": { + "./lib/es/src/index.js": "./lib/es/src/browser/index.js", + "stream": "stream-browserify" + }, "types": "./lib/src/index.d.ts", "typings": "lib/src/index", "files": [ @@ -24,17 +28,12 @@ "authProviders/" ], "scripts": { - "setVersion": "gulp setVersion", - "build:sub_cjs": "tsc -b tsconfig-sub-cjs.json", - "build:sub_es": "tsc -b tsconfig-sub-es.json", + "build": "npm run pre-build && npm run build:sub_cjs && npm run build:sub_es && rollup -c", "build:cjs": "tsc --p tsconfig-cjs.json", "build:es": "tsc --p tsconfig-es.json", - "pre-build": "npm run setVersion", - "build": "npm run pre-build && npm run build:sub_cjs && npm run build:sub_es && rollup -c", - "test": "npm run test:cjs && npm run test:esm", - "test:development": "tsc --p test/tsconfig-test-development.json && mocha 'lib/test/development/**/*.js' --require isomorphic-fetch", - "lint": "eslint . --ext .ts", - "lint:fix": "eslint . --ext .ts --fix", + "build:sub_cjs": "tsc -b tsconfig-sub-cjs.json", + "build:sub_es": "tsc -b tsconfig-sub-es.json", + "format": "npm run format:css && npm run format:html && npm run format:js && npm run format:json && npm run format:md && npm run format:rc && npm run format:ts", "format:css": "prettier --write \"**/*.css\"", "format:html": "prettier --write \"**/*.html\"", "format:js": "prettier --write \"**/*.js\"", @@ -42,12 +41,17 @@ "format:md": "prettier --write \"**/*.md\"", "format:rc": "prettier --write --parser json \"**/.*rc\"", "format:ts": "prettier --write \"**/*.ts\"", - "format": "npm run format:css && npm run format:html && npm run format:js && npm run format:json && npm run format:md && npm run format:rc && npm run format:ts", + "karma": "karma start --single-run --browsers ChromeHeadless karma.conf.js", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", "prepack": "npm install && npm run build && npm run test", - "test:coverage": "TS_NODE_PROJECT='./tsconfig-cjs.json' nyc mocha --require isomorphic-fetch -r ts-node/register test/common/**/*.ts && mocha --require isomorphic-fetch -r ts-node/register test/common/**/*.ts", + "pre-build": "npm run setVersion", + "setVersion": "gulp setVersion", + "test": "npm run test:cjs && npm run test:esm", "test:cjs": "npm run build:sub_cjs && mocha 'lib/test/common/**/*.js' --require isomorphic-fetch && mocha 'lib/test/node/**/*.js' --require isomorphic-fetch", - "test:esm": "npm run build:sub_es && mocha 'lib/es/test/common/**/*.js' --require esm --require isomorphic-fetch && mocha 'lib/es/test/node/**/*.js' --require esm --require isomorphic-fetch", - "karma": "karma start --single-run --browsers ChromeHeadless karma.conf.js" + "test:coverage": "TS_NODE_PROJECT='./tsconfig-cjs.json' nyc mocha --require isomorphic-fetch -r ts-node/register test/common/**/*.ts && mocha --require isomorphic-fetch -r ts-node/register test/common/**/*.ts", + "test:development": "tsc --p test/tsconfig-test-development.json && mocha 'lib/test/development/**/*.js' --require isomorphic-fetch", + "test:esm": "npm run build:sub_es && mocha 'lib/es/test/common/**/*.js' --require esm --require isomorphic-fetch && mocha 'lib/es/test/node/**/*.js' --require esm --require isomorphic-fetch" }, "nyc": { "all": true, @@ -72,9 +76,9 @@ "@babel/preset-env": "^7.12.11", "@istanbuljs/nyc-config-typescript": "^1.0.1", "@microsoft/microsoft-graph-types": "^1.28.0", - "@rollup/plugin-babel": "^5.2.3", - "@rollup/plugin-commonjs": "^17.1.0", - "@rollup/plugin-node-resolve": "^11.1.1", + "@rollup/plugin-babel": "^5.2.2", + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.1.0", "@types/chai": "^4.2.14", "@types/mocha": "^5.2.7", "@types/node": "^12.0.10", @@ -101,11 +105,12 @@ "mocha": "^6.2.3", "msal": "^1.0.0", "nyc": "^15.1.0", - "prettier": "^1.19.1", - "rollup": "^2.38.2", + "prettier": "^1.17.0", + "rollup": "^2.36.2", "rollup-plugin-terser": "^7.0.2", "sinon": "^9.2.4", "source-map-support": "^0.5.19", + "stream-browserify": "^3.0.0", "ts-node": "^9.0.0", "typescript": "^3.4.5", "uglify-es": "^3.3.9" @@ -114,8 +119,14 @@ "@azure/identity": { "optional": true }, + "buffer": { + "optional": true + }, "msal": { "optional": true + }, + "stream-browserify": { + "optional": true } } } diff --git a/rollup.config.js b/rollup.config.js index 58f966105..210e99a53 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -51,7 +51,10 @@ const config = [ name: "MicrosoftGraph.TokenCredentialAuthProvider", }, plugins: [ - resolve({ browser: true, preferBuiltins: false }), + resolve({ + browser: true, + preferBuiltins: false, + }), babel({ babelHelpers: "runtime", exclude: "node_modules/**", diff --git a/src/browser/index.ts b/src/browser/index.ts index ed0b4d0cd..228e3bc0b 100644 --- a/src/browser/index.ts +++ b/src/browser/index.ts @@ -26,11 +26,19 @@ export * from "../middleware/ChaosHandler"; export * from "../tasks/LargeFileUploadTask"; export * from "../tasks/OneDriveLargeFileUploadTask"; +export * from "../tasks/OneDriveLargeFileUploadTaskUtil"; +export * from "../tasks/FileUploadTask/FileObjectClasses/StreamUpload"; +export * from "../tasks/FileUploadTask/FileObjectClasses/FileUpload"; +export * from "../tasks/FileUploadTask/FileObjectClasses/StreamUpload"; +export * from "../tasks/FileUploadTask/UploadResult"; +export * from "../tasks/FileUploadTask/Interfaces/IUploadEventHandlers"; +export * from "../tasks/FileUploadTask/Range"; export * from "../tasks/PageIterator"; export * from "../Client"; export * from "../CustomAuthenticationProvider"; export * from "../GraphError"; +export * from "../GraphClientError"; export * from "../GraphRequest"; export * from "../IAuthProvider"; export * from "../IAuthenticationProvider"; @@ -41,5 +49,4 @@ export * from "../IContext"; export * from "../IFetchOptions"; export * from "../IGraphRequestCallback"; export * from "../IOptions"; -export * from "../authentication/msal/MSALAuthenticationProviderOptions"; export * from "../ResponseType"; diff --git a/src/index.ts b/src/index.ts index d0250f0e3..c6766c092 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,11 +26,19 @@ export * from "./middleware/ChaosHandler"; export * from "./tasks/LargeFileUploadTask"; export * from "./tasks/OneDriveLargeFileUploadTask"; +export * from "./tasks/OneDriveLargeFileUploadTaskUtil"; +export * from "./tasks/FileUploadTask/FileObjectClasses/StreamUpload"; +export * from "./tasks/FileUploadTask/FileObjectClasses/FileUpload"; +export * from "./tasks/FileUploadTask/FileObjectClasses/StreamUpload"; +export * from "./tasks/FileUploadTask/UploadResult"; +export * from "./tasks/FileUploadTask/Interfaces/IUploadEventHandlers"; +export * from "./tasks/FileUploadTask/Range"; export * from "./tasks/PageIterator"; export * from "./Client"; export * from "./CustomAuthenticationProvider"; export * from "./GraphError"; +export * from "./GraphClientError"; export * from "./GraphRequest"; export * from "./IAuthProvider"; export * from "./IAuthenticationProvider"; diff --git a/src/tasks/FileUploadTask/FileObjectClasses/FileUpload.ts b/src/tasks/FileUploadTask/FileObjectClasses/FileUpload.ts new file mode 100644 index 000000000..686d80f1c --- /dev/null +++ b/src/tasks/FileUploadTask/FileObjectClasses/FileUpload.ts @@ -0,0 +1,41 @@ +/** + * ------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. + * See License in the project root for license information. + * ------------------------------------------------------------------------------------------- + */ + +import { GraphClientError } from "../../../GraphClientError"; +import { FileObject, SliceType } from "../../LargeFileUploadTask"; +import { Range } from "../Range"; + +/** + * @class + * Class used for creating LargeFileUploadTask fileobject. + * This class accepts files of type ArrayBuffer, Blob, Buffer. + */ +export class FileUpload implements FileObject { + /** + * @public + * @constructor + * @param {ArrayBuffer | Blob | Buffer} content - The file to be uploaded + * @param {string} name - The name of the file to be uploaded + * @param {number} size - The total size of the file to be uploaded + * @returns An instance of the FileUpload class + */ + public constructor(public content: ArrayBuffer | Blob | Buffer, public name: string, public size: number) { + if (!content || !name || !size) { + throw new GraphClientError("Please provide the Readable Stream content, name of the file and size of the file"); + } + } + + /** + * @public + * Slices the file content to the given range + * @param {Range} range - The range value + * @returns The sliced file part + */ + public sliceFile(range: Range): ArrayBuffer | Blob | Buffer { + return this.content.slice(range.minValue, range.maxValue + 1); + } +} diff --git a/src/tasks/FileUploadTask/FileObjectClasses/StreamUpload.ts b/src/tasks/FileUploadTask/FileObjectClasses/StreamUpload.ts new file mode 100644 index 000000000..eddc257ba --- /dev/null +++ b/src/tasks/FileUploadTask/FileObjectClasses/StreamUpload.ts @@ -0,0 +1,76 @@ +import { Readable } from "stream"; + +import { GraphClientError } from "../../../GraphClientError"; +import { FileObject, SliceType } from "../../LargeFileUploadTask"; +import { Range } from "../Range"; +export class StreamUpload implements FileObject { + public constructor(public content: Readable, public name: string, public size: number) { + if (!content || !name || !size) { + throw new GraphClientError("Please provide the Readable Stream content, name of the file and size of the file"); + } + } + + /** + * @public + * Slices the file content to the given range + * @param {Range} range - The range value + * @returns The sliced file part + */ + public async sliceFile(range: Range): Promise { + const rangeSize = range.maxValue - range.minValue + 1; + /* readable.readable Is true if it is safe to call readable.read(), + * which means the stream has not been destroyed or emitted 'error' or 'end' + */ + if (this.content && this.content.readable) { + if (this.content.readableLength >= rangeSize) { + return this.content.read(rangeSize); + } else { + return await this.readNBytesFromStream(rangeSize); + } + } else { + throw new GraphClientError("Stream is not readable."); + } + } + + /** + * @private + * Reads the specified byte size from the stream + * @param {number} size - The size of bytes to be read + * @returns Buffer with the given length of data. + */ + + private readNBytesFromStream(size: number): Promise { + return new Promise((resolve, reject) => { + const chunks = []; + let remainder = size; + let length = 0; + this.content.on("end", () => { + if (remainder > 0) { + return reject(new GraphClientError("Stream ended before reading required range size")); + } + }); + this.content.on("readable", () => { + /** + * (chunk = this.content.read(size)) can return null if size of stream is less than 'size' parameter. + * Read the remainder number of bytes from the stream iteratively as they are available. + */ + let chunk; + while (length < size && (chunk = this.content.read(remainder)) !== null) { + length += chunk.length; + chunks.push(chunk); + if (remainder > 0) { + remainder = size - length; + } + } + + if (length === size) { + return resolve(Buffer.concat(chunks)); + } + + if (!this.content || !this.content.readable) { + return reject(new GraphClientError("Error encountered while reading the stream during the upload")); + } + }); + }); + } +} diff --git a/src/tasks/FileUploadTask/Interfaces/IUploadEventHandlers.ts b/src/tasks/FileUploadTask/Interfaces/IUploadEventHandlers.ts new file mode 100644 index 000000000..ffd8de8d4 --- /dev/null +++ b/src/tasks/FileUploadTask/Interfaces/IUploadEventHandlers.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/type-annotation-spacing */ +import { Range } from "../Range"; + +/** + * Interface enabling progress handling with callbacks. + */ +export interface UploadEventHandlers { + /** + * Parameters that are passed into the progress, completed, failure callback options. + */ + extraCallbackParam?: unknown; + /** + * Callback function called on each slice upload during the LargeFileUploadTask.upload() process + */ + progress?: (range?: Range, extraCallbackParam?: unknown) => void; +} diff --git a/src/Range.ts b/src/tasks/FileUploadTask/Range.ts similarity index 100% rename from src/Range.ts rename to src/tasks/FileUploadTask/Range.ts diff --git a/src/tasks/FileUploadUtil/UploadResult.ts b/src/tasks/FileUploadTask/UploadResult.ts similarity index 100% rename from src/tasks/FileUploadUtil/UploadResult.ts rename to src/tasks/FileUploadTask/UploadResult.ts diff --git a/src/tasks/LargeFileUploadTask.ts b/src/tasks/LargeFileUploadTask.ts index 8b37e8fa6..f0e09fbdf 100644 --- a/src/tasks/LargeFileUploadTask.ts +++ b/src/tasks/LargeFileUploadTask.ts @@ -12,9 +12,10 @@ import { GraphClientError } from "../GraphClientError"; import { GraphResponseHandler } from "../GraphResponseHandler"; import { Client } from "../index"; -import { Range } from "../Range"; import { ResponseType } from "../ResponseType"; -import { UploadResult } from "./FileUploadUtil/UploadResult"; +import { UploadEventHandlers } from "./FileUploadTask/Interfaces/IUploadEventHandlers"; +import { Range } from "./FileUploadTask/Range"; +import { UploadResult } from "./FileUploadTask/UploadResult"; /** * @interface @@ -43,6 +44,7 @@ interface UploadStatusResponse { */ export interface LargeFileUploadTaskOptions { rangeSize?: number; + uploadEventHandlers?: UploadEventHandlers; } /** @@ -57,6 +59,12 @@ export interface LargeFileUploadSession { isCancelled?: boolean; } +/** + * @type + * Representing the return type of the sliceFile function that is type of the slice of a given range. + */ +export type SliceType = ArrayBuffer | Blob | Buffer; + /** * @interface * Signature to define the properties and content of the file in upload task @@ -64,17 +72,18 @@ export interface LargeFileUploadSession { * @property {string} name - Specifies the file name with extension * @property {number} size - Specifies size of the file */ -export interface FileObject { - content: ArrayBuffer | File; +export interface FileObject { + content: T; name: string; size: number; + sliceFile(range: Range): SliceType | Promise; } /** * @class * Class representing LargeFileUploadTask */ -export class LargeFileUploadTask { +export class LargeFileUploadTask { /** * @private * Default value for the rangeSize @@ -91,7 +100,7 @@ export class LargeFileUploadTask { * @protected * The object holding file details */ - protected file: FileObject; + protected file: FileObject; /** * @protected @@ -121,7 +130,7 @@ export class LargeFileUploadTask { * @param {KeyValuePairObjectStringNumber} headers - The headers that needs to be sent * @returns The promise that resolves to LargeFileUploadSession */ - public static async createUploadSession(client: Client, requestUrl: string, payload: any, headers: KeyValuePairObjectStringNumber = {}): Promise { + public static async createUploadSession(client: Client, requestUrl: string, payload: any, headers: KeyValuePairObjectStringNumber = {}): Promise { const session = await client .api(requestUrl) .headers(headers) @@ -144,12 +153,19 @@ export class LargeFileUploadTask { * @param {LargeFileUploadTaskOptions} options - The upload task options * @returns An instance of LargeFileUploadTask */ - public constructor(client: Client, file: FileObject, uploadSession: LargeFileUploadSession, options: LargeFileUploadTaskOptions = {}) { + public constructor(client: Client, file: FileObject, uploadSession: LargeFileUploadSession, options: LargeFileUploadTaskOptions = {}) { this.client = client; + + if (!file.sliceFile) { + throw new GraphClientError("Please pass the FileUpload object, StreamUpload object or any custom implementation of the FileObject interface"); + } else { + this.file = file; + } this.file = file; - if (options.rangeSize === undefined) { + if (!options.rangeSize) { options.rangeSize = this.DEFAULT_FILE_SIZE; } + this.options = options; this.uploadSession = uploadSession; this.nextRange = new Range(0, this.options.rangeSize - 1); @@ -204,14 +220,18 @@ export class LargeFileUploadTask { } /** + * @deprecated This function has been moved into FileObject interface. * @public * Slices the file content to the given range * @param {Range} range - The range value * @returns The sliced ArrayBuffer or Blob */ public sliceFile(range: Range): ArrayBuffer | Blob { - const blob = this.file.content.slice(range.minValue, range.maxValue + 1); - return blob; + console.warn("The LargeFileUploadTask.sliceFile() function has been deprecated and moved into the FileObject interface."); + if (this.file.content instanceof ArrayBuffer || this.file.content instanceof Blob || this.file.content instanceof Buffer) { + return this.file.content.slice(range.minValue, range.maxValue + 1); + } + throw new GraphClientError("The LargeFileUploadTask.sliceFile() function expects only Blob, ArrayBuffer or Buffer file content. Please note that the sliceFile() function is deprecated."); } /** @@ -220,7 +240,8 @@ export class LargeFileUploadTask { * Uploads file to the server in a sequential order by slicing the file * @returns The promise resolves to uploaded response */ - public async upload(): Promise { + public async upload(): Promise { + const uploadEventHandlers = this.options && this.options.uploadEventHandlers; while (!this.uploadSession.isCancelled) { const nextRange = this.getNextRange(); if (nextRange.maxValue === -1) { @@ -228,7 +249,7 @@ export class LargeFileUploadTask { err.name = "Invalid Session"; throw err; } - const fileSlice = this.sliceFile(nextRange); + const fileSlice = await this.file.sliceFile(nextRange); const rawResponse = await this.uploadSliceGetRawResponse(fileSlice, nextRange, this.file.size); if (!rawResponse) { throw new GraphClientError("Something went wrong! Large file upload slice response is null."); @@ -240,18 +261,21 @@ export class LargeFileUploadTask { * (rawResponse.status === 200 && responseBody.id) -> This additional condition is applicable only for OneDrive API. */ if (rawResponse.status === 201 || (rawResponse.status === 200 && responseBody.id)) { - return UploadResult.CreateUploadResult(responseBody, rawResponse.headers); + const uploadResult = UploadResult.CreateUploadResult(responseBody, rawResponse.headers); + return uploadResult; } /* Handling the API issue where the case of Outlook upload response property -'nextExpectedRanges' is not uniform. * https://github.com/microsoftgraph/msgraph-sdk-serviceissues/issues/39 */ const res: UploadStatusResponse = { - expirationDateTime: responseBody.expirationDateTime, + expirationDateTime: responseBody.expirationDateTime || responseBody.ExpirationDateTime, nextExpectedRanges: responseBody.NextExpectedRanges || responseBody.nextExpectedRanges, }; - this.updateTaskStatus(res); + if (uploadEventHandlers && uploadEventHandlers.progress) { + uploadEventHandlers.progress(nextRange, uploadEventHandlers.extraCallbackParam); + } } } @@ -264,7 +288,7 @@ export class LargeFileUploadTask { * @param {number} totalSize - The total size of a complete file * @returns The response body of the upload slice result */ - public async uploadSlice(fileSlice: ArrayBuffer | Blob | File, range: Range, totalSize: number): Promise { + public async uploadSlice(fileSlice: ArrayBuffer | Blob | File, range: Range, totalSize: number): Promise { return await this.client .api(this.uploadSession.url) .headers({ @@ -273,6 +297,7 @@ export class LargeFileUploadTask { }) .put(fileSlice); } + /** * @public * @async @@ -299,7 +324,7 @@ export class LargeFileUploadTask { * Deletes upload session in the server * @returns The promise resolves to cancelled response */ - public async cancel(): Promise { + public async cancel(): Promise { const cancelResponse = await this.client .api(this.uploadSession.url) .responseType(ResponseType.RAW) @@ -316,7 +341,7 @@ export class LargeFileUploadTask { * Gets status for the upload session * @returns The promise resolves to the status enquiry response */ - public async getStatus(): Promise { + public async getStatus(): Promise { const response = await this.client.api(this.uploadSession.url).get(); this.updateTaskStatus(response); return response; @@ -328,7 +353,7 @@ export class LargeFileUploadTask { * Resumes upload session and continue uploading the file from the last sent range * @returns The promise resolves to the uploaded response */ - public async resume(): Promise { + public async resume(): Promise { await this.getStatus(); return await this.upload(); } diff --git a/src/tasks/OneDriveLargeFileUploadTask.ts b/src/tasks/OneDriveLargeFileUploadTask.ts index e671489e1..747b794ee 100644 --- a/src/tasks/OneDriveLargeFileUploadTask.ts +++ b/src/tasks/OneDriveLargeFileUploadTask.ts @@ -9,7 +9,10 @@ * @module OneDriveLargeFileUploadTask */ +import { GraphClientError } from "../GraphClientError"; import { Client } from "../index"; +import { FileUpload } from "./FileUploadTask/FileObjectClasses/FileUpload"; +import { UploadEventHandlers } from "./FileUploadTask/Interfaces/IUploadEventHandlers"; import { FileObject, LargeFileUploadSession, LargeFileUploadTask, LargeFileUploadTaskOptions } from "./LargeFileUploadTask"; import { getValidRangeSize } from "./OneDriveLargeFileUploadTaskUtil"; @@ -20,17 +23,31 @@ import { getValidRangeSize } from "./OneDriveLargeFileUploadTaskUtil"; * @property {string} [path] - The path to which the file needs to be uploaded * @property {number} [rangeSize] - Specifies the range chunk size */ -interface OneDriveLargeFileUploadOptions { +export interface OneDriveLargeFileUploadOptions { fileName: string; path?: string; rangeSize?: number; + conflictBehavior?: string; + uploadEventHandlers?: UploadEventHandlers; +} + +/** + * @interface + * Signature to define options when creating an upload task + * @property {string} fileName - Specifies the name of a file to be uploaded (with extension) + * @property {string} [path] - The path to which the file needs to be uploaded + * @property {number} [rangeSize] - Specifies the range chunk size + */ +interface OneDriveFileUploadSessionPayLoad { + fileName: string; + conflictBehavior?: string; } /** * @class * Class representing OneDriveLargeFileUploadTask */ -export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { +export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { /** * @private * @static @@ -76,7 +93,10 @@ export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { * @param {OneDriveLargeFileUploadOptions} options - The options for upload task * @returns The promise that will be resolves to OneDriveLargeFileUploadTask instance */ - public static async create(client: Client, file: Blob | Buffer | File, options: OneDriveLargeFileUploadOptions): Promise { + public static async create(client: Client, file: Blob | Buffer | File, options: OneDriveLargeFileUploadOptions): Promise { + if (!client || !file || !options) { + throw new GraphClientError("Please provide the Graph client instance, file object and OneDriveLargeFileUploadOptions value"); + } const name: string = options.fileName; let content; let size; @@ -91,17 +111,34 @@ export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { size = b.byteLength - b.byteOffset; content = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength); } + const fileObj = new FileUpload(content, name, size); + return this.createTaskWithFileObject(client, fileObj, options); + } + /** + * @public + * @static + * @async + * Creates a OneDriveLargeFileUploadTask + * @param {Client} client - The GraphClient instance + * @param {FileObject} file - FileObject instance + * @param {OneDriveLargeFileUploadOptions} options - The options for upload task + * @returns The promise that will be resolves to OneDriveLargeFileUploadTask instance + */ + public static async createTaskWithFileObject(client: Client, fileObject: FileObject, options: OneDriveLargeFileUploadOptions): Promise> { + if (!client || !fileObject || !options) { + throw new GraphClientError("Please provide the Graph client instance, FileObject interface implementation and OneDriveLargeFileUploadOptions value"); + } const requestUrl = OneDriveLargeFileUploadTask.constructCreateSessionUrl(options.fileName, options.path); - const session = await OneDriveLargeFileUploadTask.createUploadSession(client, requestUrl, options.fileName); - const rangeSize = getValidRangeSize(options.rangeSize); - const fileObj: FileObject = { - content, - name, - size, + const uploadSessionPayload: OneDriveFileUploadSessionPayLoad = { + fileName: options.fileName, + conflictBehavior: options.conflictBehavior, }; - return new OneDriveLargeFileUploadTask(client, fileObj, session, { + const session = await OneDriveLargeFileUploadTask.createUploadSession(client, requestUrl, uploadSessionPayload); + const rangeSize = getValidRangeSize(options.rangeSize); + return new OneDriveLargeFileUploadTask(client, fileObject, session, { rangeSize, + uploadEventHandlers: options.uploadEventHandlers, }); } @@ -113,13 +150,14 @@ export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { * @param {Client} client - The GraphClient instance * @param {string} requestUrl - The URL to create the upload session * @param {string} fileName - The name of a file to upload, (with extension) + * @param {string} conflictBehavior - Conflict behaviour option. Default is 'rename' * @returns The promise that resolves to LargeFileUploadSession */ - public static async createUploadSession(client: Client, requestUrl: string, fileName: string): Promise { + public static async createUploadSession(client: Client, requestUrl: string, payloadOptions: OneDriveFileUploadSessionPayLoad): Promise { const payload = { item: { - "@microsoft.graph.conflictBehavior": "rename", - name: fileName, + "@microsoft.graph.conflictBehavior": payloadOptions?.conflictBehavior || "rename", + name: payloadOptions?.fileName, }, }; return super.createUploadSession(client, requestUrl, payload); @@ -135,7 +173,7 @@ export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { * @param {LargeFileUploadTaskOptions} options - The upload task options * @returns An instance of OneDriveLargeFileUploadTask */ - public constructor(client: Client, file: FileObject, uploadSession: LargeFileUploadSession, options: LargeFileUploadTaskOptions) { + public constructor(client: Client, file: FileObject, uploadSession: LargeFileUploadSession, options: LargeFileUploadTaskOptions) { super(client, file, uploadSession, options); } @@ -143,12 +181,13 @@ export class OneDriveLargeFileUploadTask extends LargeFileUploadTask { * @public * Commits upload session to end uploading * @param {string} requestUrl - The URL to commit the upload session + * @param {string} conflictBehavior - Conflict behaviour option. Default is 'rename' * @returns The promise resolves to committed response */ - public async commit(requestUrl: string): Promise { + public async commit(requestUrl: string, conflictBehavior = "rename"): Promise { const payload = { name: this.file.name, - "@microsoft.graph.conflictBehavior": "rename", + "@microsoft.graph.conflictBehavior": conflictBehavior, "@microsoft.graph.sourceUrl": this.uploadSession.url, }; return await this.client.api(requestUrl).put(payload); diff --git a/test/common/core/Range.ts b/test/common/core/Range.ts index e5b5b1bbd..b14191a29 100644 --- a/test/common/core/Range.ts +++ b/test/common/core/Range.ts @@ -7,7 +7,7 @@ import { assert } from "chai"; -import { Range } from "../../../src/Range"; +import { Range } from "../../../src/tasks/FileUploadTask/Range"; describe("Range.ts", () => { describe("Constructor", () => { diff --git a/test/common/tasks/LargeFileUploadTask.ts b/test/common/tasks/LargeFileUploadTask.ts index edf45857a..a6d498201 100644 --- a/test/common/tasks/LargeFileUploadTask.ts +++ b/test/common/tasks/LargeFileUploadTask.ts @@ -5,28 +5,29 @@ * ------------------------------------------------------------------------------------------- */ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { assert } from "chai"; import * as sinon from "sinon"; -import { UploadResult } from "../../../src/tasks/FileUploadUtil/UploadResult"; +import { Range } from ".../../../src/tasks/FileUploadTask/Range"; +import { FileUpload, LargeFileUploadTaskOptions } from "../../../src"; +import { UploadEventHandlers } from "../../../src/tasks/FileUploadTask/Interfaces/IUploadEventHandlers"; +import { UploadResult } from "../../../src/tasks/FileUploadTask/UploadResult"; import { LargeFileUploadTask } from "../../../src/tasks/LargeFileUploadTask"; import { getClient } from "../../test-helper"; describe("LargeFileUploadTask.ts", () => { + const rangeSize = 327680; + const uploadSession = { + url: "test url", + expiry: new Date(), + }; describe("Parsing Range", () => { const name = "sample_image.jpg"; const arrayBuffer = new ArrayBuffer(80000); const size = 100000; - const fileObj = { - content: arrayBuffer, - name, - size, - }; - const uploadSession = { - url: "test url", - expiry: new Date(), - }; const options = {}; + const fileObj = new FileUpload(arrayBuffer, name, size); const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); it("Should return default range for given undefined range", (done) => { const range = uploadTask["parseRange"]([]); @@ -60,16 +61,8 @@ describe("LargeFileUploadTask.ts", () => { const name = "sample_image.jpg"; const arrayBuffer = new ArrayBuffer(80000); const size = 100000; - const fileObj = { - content: arrayBuffer, - name, - size, - }; - const uploadSession = { - url: "test url", - expiry: new Date(), - }; const options = {}; + const fileObj = new FileUpload(arrayBuffer, name, size); const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); it("Should update status with expiration date and next expected ranges as given", (done) => { const statusResponse = { @@ -97,18 +90,10 @@ describe("LargeFileUploadTask.ts", () => { const name = "sample_image.jpg"; const arrayBuffer = new ArrayBuffer(80000); const size = 328680; - const fileObj = { - content: arrayBuffer, - name, - size, - }; - const uploadSession = { - url: "test url", - expiry: new Date(), - }; const options = { - rangeSize: 327680, + rangeSize, }; + const fileObj = new FileUpload(arrayBuffer, name, size); const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); it("Should return proper next range well within the file size", (done) => { @@ -147,71 +132,139 @@ describe("LargeFileUploadTask.ts", () => { const name = "sample_image.jpg"; const arrayBuffer = new ArrayBuffer(80000); const size = 328680; - const fileObj = { - content: arrayBuffer, - name, - size, - }; - const uploadSession = { - url: "test url", - expiry: new Date(), - }; const options = { rangeSize: 327680, }; + const fileObj = new FileUpload(arrayBuffer, name, size); + const location = "TEST_URL"; + const body = { + id: "TEST_ID", + }; - it("Should return a Upload Result object after a completed task with 201 status", async () => { + it("Should return a Upload Result object after a completed task with 201 status", () => { const location = "TEST_URL"; - const body = { - id: "TEST_ID", - }; - const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); - const status201 = { - status: 200, - stautsText: "OK", - headers: { - "Content-Type": "application/json", - location, - }, - }; - const rawResponse = new Response(JSON.stringify(body), status201); - - const moq = sinon.mock(uploadTask); - moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); - const result = await uploadTask.upload(); - assert.isDefined(result); - assert.instanceOf(result, UploadResult); - assert.equal(result["location"], location); - const responseBody = result["responseBody"]; - assert.isDefined(responseBody); - assert.equal(responseBody["id"], "TEST_ID"); + it("Test with progressCallback", async () => { + let isProgressReportCalled = false; + + const progress = (range?: Range) => { + isProgressReportCalled = true; + }; + + const uploadEventHandlers: UploadEventHandlers = { + progress, + }; + + const optionsWithProgress: LargeFileUploadTaskOptions = { + rangeSize, + uploadEventHandlers, + }; + + const emptyBody = {}; + const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, optionsWithProgress); + const status201 = { + status: 201, + statusText: "OK", + headers: { + "Content-Type": "application/json", + location, + }, + }; + const rawResponse = new Response(JSON.stringify(emptyBody), status201); + + const moq = sinon.mock(uploadTask); + moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); + const result = await uploadTask.upload(); + assert.isDefined(result); + assert.instanceOf(result, UploadResult); + assert.equal(result["location"], location); + assert.isFalse(isProgressReportCalled); + }); + + it("Test without progress callback", async () => { + const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); + const status201 = { + status: 201, + statusText: "OK", + headers: { + "Content-Type": "application/json", + location, + }, + }; + + const rawResponse = new Response(JSON.stringify(body), status201); + const moq = sinon.mock(uploadTask); + moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); + const result = await uploadTask.upload(); + assert.isDefined(result); + assert.instanceOf(result, UploadResult); + assert.equal(result["location"], location); + const responseBody = result["responseBody"]; + assert.isDefined(responseBody); + assert.equal(responseBody["id"], "TEST_ID"); + }); }); - it("Should return a Upload Result object after a completed task with 200 status and id", async () => { - const location = "TEST_URL"; - const body = { - id: "TEST_ID", - }; - const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); - const status200 = { - status: 200, - stautsText: "OK", - headers: { - "Content-Type": "application/json", - location, - }, - }; - const rawResponse = new Response(JSON.stringify(body), status200); - - const moq = sinon.mock(uploadTask); - moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); - const result = await uploadTask.upload(); - assert.isDefined(result); - assert.instanceOf(result, UploadResult); - assert.equal(result["location"], location); - const responseBody = result["responseBody"]; - assert.isDefined(responseBody); - assert.equal(responseBody["id"], "TEST_ID"); + it("Should return a Upload Result object after a completed task with 200 status and body", () => { + it("Test with progress callback", async () => { + let isProgressReportCalled = false; + + const progress = (range?: Range) => { + isProgressReportCalled = true; + }; + const uploadEventHandlers: UploadEventHandlers = { + progress, + }; + + const optionsWithProgress: LargeFileUploadTaskOptions = { + rangeSize, + uploadEventHandlers, + }; + + const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, optionsWithProgress); + const status200 = { + status: 200, + statusText: "OK", + headers: { + "Content-Type": "application/json", + location, + }, + }; + const rawResponse = new Response(JSON.stringify(body), status200); + + const moq = sinon.mock(uploadTask); + moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); + const result = await uploadTask.upload(); + assert.isDefined(result); + assert.instanceOf(result, UploadResult); + assert.equal(result["location"], location); + const responseBody = result["responseBody"]; + assert.isDefined(responseBody); + assert.equal(responseBody["id"], "TEST_ID"); + assert.isFalse(isProgressReportCalled); + }); + it("Test without progress callback", async () => { + const uploadTask = new LargeFileUploadTask(getClient(), fileObj, uploadSession, options); + + const status200 = { + status: 200, + statusText: "OK", + headers: { + "Content-Type": "application/json", + location, + }, + }; + const rawResponse = new Response(JSON.stringify(body), status200); + + const moq = sinon.mock(uploadTask); + moq.expects("uploadSliceGetRawResponse").resolves(rawResponse); + const result = await uploadTask.upload(); + assert.isDefined(result); + assert.instanceOf(result, UploadResult); + assert.equal(result["location"], location); + const responseBody = result["responseBody"]; + assert.isDefined(responseBody); + assert.equal(responseBody["id"], "TEST_ID"); + }); }); it("Should return an exception while trying to upload the file upload completed task", (done) => { const statusResponse = { @@ -222,8 +275,7 @@ describe("LargeFileUploadTask.ts", () => { uploadTask["updateTaskStatus"](statusResponse); uploadTask .upload() - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .then((res) => { + .then(() => { throw new Error("Test Failed - Upload is working for upload completed task"); }) .catch((err) => { diff --git a/test/common/tasks/StreamUpload.ts b/test/common/tasks/StreamUpload.ts new file mode 100644 index 000000000..a87fdfda4 --- /dev/null +++ b/test/common/tasks/StreamUpload.ts @@ -0,0 +1,75 @@ +/** + * ------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. + * See License in the project root for license information. + * ------------------------------------------------------------------------------------------- + */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import "isomorphic-fetch"; + +import { assert } from "chai"; +import { Readable } from "stream"; + +import { GraphClientError } from "../../../src"; +import { StreamUpload } from "../../../src/tasks/FileUploadTask/FileObjectClasses/StreamUpload"; + +const fileName = "Test_File_Name"; +describe("StreamUpload.test", () => { + it("Should return slice with defined size less than complete range size", async () => { + const totalRangesize = 36; + const sliceSize = 20; + const buf = Buffer.alloc(totalRangesize, "a"); + const readStream = new Readable({ + read() { + this.push(buf); + this.push(null); + }, + }); + + const upload = new StreamUpload(readStream, fileName, totalRangesize); + + const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); + + assert.isDefined(slice); + assert.equal(sliceSize, (slice as Buffer).length); + assert.equal(readStream.readableLength, 16); + }); +}); + +it("Should return slice ", async () => { + const totalRangesize = 36; + const buf = Buffer.alloc(totalRangesize, "a"); + const readStream = new Readable({ + read() { + this.push(buf); + this.push(null); + }, + }); + const upload = new StreamUpload(readStream, fileName, totalRangesize); + const slice = await upload.sliceFile({ minValue: 0, maxValue: totalRangesize - 1 }); + assert.isDefined(slice); + assert.equal(totalRangesize, (slice as Buffer).length); + assert.equal(readStream.readableLength, 0); +}); + +it("Should throw error if stream ends before complete range size is read", async () => { + const totalsize = 6; + const sliceSize = 20; + const buf = Buffer.alloc(totalsize, "a"); + const readStream = new Readable({ + read() { + this.push(buf); + this.push(null); + }, + }); + try { + const upload = new StreamUpload(readStream, fileName, totalsize); + const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); + if (slice) { + throw Error("Test failed. Expected error now thrown"); + } + } catch (err) { + assert.instanceOf(err, GraphClientError); + assert.equal(err.message, "Stream ended before reading required range size"); + } +}); diff --git a/test/development/workload/largeFileUpload.ts b/test/development/workload/largeFileUpload.ts new file mode 100644 index 000000000..8487808bf --- /dev/null +++ b/test/development/workload/largeFileUpload.ts @@ -0,0 +1,61 @@ +/** + * ------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. + * See License in the project root for license information. + * ------------------------------------------------------------------------------------------- + */ + +import "isomorphic-fetch"; + +import { assert } from "chai"; +import * as fs from "fs"; + +import { getClient } from "../test-helper"; +const client = getClient(); + +import { OneDriveLargeFileUploadOptions, OneDriveLargeFileUploadTask, Range, StreamUpload, UploadEventHandlers } from "../../../src/index"; + +describe("LargeFileUpload", () => { + const fileName = "sample_image.jpg"; + const stats = fs.statSync(`./test/sample_files/${fileName}`); + const totalsize = stats.size; + it("Test OneDrive stream upload with progress callback options", async () => { + let isProgressReportCalled = false; + + const progress = (range?: Range, extraCallBackParams?: unknown) => { + assert.isTrue(extraCallBackParams); + assert.isDefined(range); + isProgressReportCalled = true; + }; + + const uploadEventHandlers: UploadEventHandlers = { + progress, + extraCallbackParam: true, + }; + + const options: OneDriveLargeFileUploadOptions = { + path: "/Documents", + fileName, + rangeSize: 1024 * 1024, + uploadEventHandlers, + }; + const readStream = fs.createReadStream(`./test/sample_files/${fileName}`); + const file = new StreamUpload(readStream, fileName, totalsize); + const uploadTask = await OneDriveLargeFileUploadTask.createTaskWithFileObject(client, file, options); + const response = await uploadTask.upload(); + assert.isDefined(response.responseBody["id"]); + assert.isTrue(isProgressReportCalled); + }).timeout(30 * 1000); + + it("Test OneDrive File Upload", async () => { + const options: OneDriveLargeFileUploadOptions = { + path: "/Documents", + fileName, + rangeSize: 1024 * 1024, + }; + const file = fs.readFileSync(`./test/sample_files/${fileName}`); + const uploadTask = await OneDriveLargeFileUploadTask.create(client, file, options); + const response = await uploadTask.upload(); + assert.isDefined(response.responseBody["id"]); + }).timeout(30 * 1000); +}); diff --git a/test/node/tasks/StreamUpload.ts b/test/node/tasks/StreamUpload.ts new file mode 100644 index 000000000..cf869d649 --- /dev/null +++ b/test/node/tasks/StreamUpload.ts @@ -0,0 +1,53 @@ +/** + * ------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. + * See License in the project root for license information. + * ------------------------------------------------------------------------------------------- + */ + +import "isomorphic-fetch"; + +import { assert } from "chai"; +import * as fs from "fs"; + +import { StreamUpload } from "../../../src/tasks/FileUploadTask/FileObjectClasses/StreamUpload"; + +describe("StreamUpload", () => { + const fileName = "sample_image.jpg"; + const filePath = `./test/sample_files/${fileName}`; + const stats = fs.statSync(`./test/sample_files/${fileName}`); + const totalsize = stats.size; + it("Stream size smaller than upload range size", async () => { + const readStream = fs.createReadStream(`./test/sample_files/${fileName}`, { highWaterMark: 8 }); + + const sliceSize = 200; + + const upload = new StreamUpload(readStream, fileName, totalsize); + + const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); + assert.isDefined(slice); + assert.equal(sliceSize, (slice as Buffer).length); + }); + + it("Stream size greater than upload range size", async () => { + const readStream = fs.createReadStream(filePath, { highWaterMark: 200 }); + const sliceSize = 100; + + const upload = new StreamUpload(readStream, fileName, totalsize); + + const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); + assert.isDefined(slice); + assert.equal(sliceSize, (slice as Buffer).length); + }); + + it("Stream size with complete file and greater than upload range size", async () => { + const readStream = fs.createReadStream(filePath, { highWaterMark: totalsize }); + const sliceSize = 100; + + const upload = new StreamUpload(readStream, fileName, totalsize); + + const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); + assert.isDefined(slice); + assert.equal(sliceSize, (slice as Buffer).length); + }); +});