├── .azure-pipelines ├── ci-build-production.yml └── common-templates │ ├── security-post-checks.yml │ └── security-pre-checks.yml ├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── 01-sdk-bug.yml │ ├── 02-sdk-feature-request.yml │ ├── 03-blank-issue.md │ └── config.yml ├── dependabot.yml ├── policies │ ├── msgraph-sdk-javascript-branch-protection.yml │ └── resourceManagement.yml ├── pull_request_template.md └── workflows │ ├── ci_validation.yml │ ├── codeql-analysis.yml │ └── project-auto-add.yml ├── .gitignore ├── .huskyrc ├── .jshintrc ├── .lintstagedrc ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── .vscode ├── launch.json └── tasks.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README-Localized ├── README-es-es.md ├── README-fr-fr.md ├── README-ja-jp.md ├── README-pt-br.md ├── README-ru-ru.md └── README-zh-cn.md ├── README.md ├── THIRD PARTY NOTICES ├── _config.yml ├── authProviderOptions ├── ReadMe.md ├── authCodeMsalBrowser │ └── index.ts ├── azureTokenCredentials │ └── index.ts └── es │ ├── authCodeMsalBrowser │ └── index.ts │ └── azureTokenCredentials │ └── index.ts ├── babel.config.js ├── changelogs └── v3-upgrade-guide.md ├── design ├── kiota-e2e.md ├── large-file-upload-task-design.md └── publishing.md ├── docs ├── Actions.md ├── AuthCodeMSALBrowserAuthenticationProvider.md ├── CallingPattern.md ├── CancellingAHTTPRequest.md ├── ChaosHandlerSamples.md ├── CreatingClientInstance.md ├── CustomAuthenticationProvider.md ├── CustomMiddlewareChain.md ├── GettingRawResponse.md ├── OtherAPIs.md ├── QueryParameters.md ├── TokenCredentialAuthenticationProvider.md ├── content │ └── Batching.md └── tasks │ ├── LargeFileUploadTask.md │ └── PageIterator.md ├── gulpfile.js ├── karma.conf.js ├── lib └── .npmignore ├── msgraph-sdk-javascript.yml ├── package-lock.json ├── package.json ├── rollup.config.js ├── sample.png ├── samples ├── javascript │ ├── SampleRequests.js │ ├── clientInitialization │ │ ├── ClientWithOptions.js │ │ └── tokenCredentialAuthenticationProvider │ │ │ ├── README.md │ │ │ ├── index.js │ │ │ └── secrets.js │ └── tasks │ │ ├── LargeFileUploadTask.js │ │ └── OneDriveLargeFileUploadTask.js ├── package-lock.json ├── package.json ├── tsconfig.json └── typescript │ ├── clientInitialization │ ├── ClientWithOptions.ts │ └── tokenCredentialAuthenticationProvider │ │ └── index.ts │ └── tasks │ ├── LargeFileUploadTask.ts │ └── OneDriveLargeFileUploadTask.ts ├── scripts └── src │ ├── AddGithubUser.ps1 │ ├── CalculateNewPreviewVersion.ps1 │ ├── CalculateNewProductionVersion.ps1 │ ├── CommitAndPushChangesToGithub.ps1 │ ├── GetLatestCommitSHA.ps1 │ ├── GetPackageVersion.ps1 │ ├── HasNewCommitsAfterLastProductionRelease.ps1 │ ├── HasNewCommitsAfterLastRelease.ps1 │ ├── MergeChangesTillLastestRelease.ps1 │ ├── MergeVersionChangesBackToPreviewBranch.ps1 │ └── RemoveGithubUser.ps1 ├── shims.d.ts ├── src ├── Client.ts ├── Constants.ts ├── CustomAuthenticationProvider.ts ├── GraphClientError.ts ├── GraphError.ts ├── GraphErrorHandler.ts ├── GraphRequest.ts ├── GraphRequestUtil.ts ├── GraphResponseHandler.ts ├── HTTPClient.ts ├── HTTPClientFactory.ts ├── IAuthProvider.ts ├── IAuthProviderCallback.ts ├── IAuthenticationProvider.ts ├── IAuthenticationProviderOptions.ts ├── IClientOptions.ts ├── IContext.ts ├── IFetchOptions.ts ├── IGraphRequestCallback.ts ├── IOptions.ts ├── RequestMethod.ts ├── ResponseType.ts ├── ValidatePolyFilling.ts ├── Version.ts ├── authentication │ ├── azureTokenCredentials │ │ ├── ITokenCredentialAuthenticationProviderOptions.ts │ │ ├── TokenCredentialAuthenticationProvider.ts │ │ └── index.ts │ ├── msal-browser │ │ ├── AuthCodeMSALBrowserAuthenticationProvider.ts │ │ └── index.ts │ └── msalOptions │ │ └── MSALAuthenticationProviderOptions.ts ├── browser │ └── index.ts ├── content │ ├── BatchRequestContent.ts │ └── BatchResponseContent.ts ├── index.ts ├── middleware │ ├── AuthenticationHandler.ts │ ├── ChaosHandler.ts │ ├── HTTPMessageHandler.ts │ ├── IMiddleware.ts │ ├── MiddlewareControl.ts │ ├── MiddlewareFactory.ts │ ├── MiddlewareUtil.ts │ ├── RedirectHandler.ts │ ├── RetryHandler.ts │ ├── TelemetryHandler.ts │ └── options │ │ ├── AuthenticationHandlerOptions.ts │ │ ├── ChaosHandlerData.ts │ │ ├── ChaosHandlerOptions.ts │ │ ├── ChaosStrategy.ts │ │ ├── IMiddlewareOptions.ts │ │ ├── RedirectHandlerOptions.ts │ │ ├── RetryHandlerOptions.ts │ │ └── TelemetryHandlerOptions.ts └── tasks │ ├── FileUploadTask │ ├── FileObjectClasses │ │ ├── FileUpload.ts │ │ └── StreamUpload.ts │ ├── Interfaces │ │ └── IUploadEventHandlers.ts │ ├── Range.ts │ └── UploadResult.ts │ ├── LargeFileUploadTask.ts │ ├── OneDriveLargeFileUploadTask.ts │ ├── OneDriveLargeFileUploadTaskUtil.ts │ └── PageIterator.ts ├── test-esm ├── README.md ├── package-lock.json ├── package.json ├── tests │ └── testESM.ts └── tsconfig.json ├── test ├── DummyAuthenticationProvider.ts ├── DummyHTTPMessageHandler.ts ├── DummyHandlerOptions.ts ├── Tests.md ├── browser │ ├── BrowserTests.md │ └── core │ │ └── GraphResponseHandler.ts ├── common │ ├── authentication │ │ └── AuthCodeMSALBrowserAuthenticationProvider.ts │ ├── content │ │ ├── BatchRequestContent.ts │ │ └── BatchResponseContent.ts │ ├── core │ │ ├── Client.ts │ │ ├── GraphClientError.ts │ │ ├── GraphErrorHandler.ts │ │ ├── GraphRequestUtil.ts │ │ ├── GraphResponseHandler.ts │ │ ├── HTTPClient.ts │ │ ├── HTTPClientFactory.ts │ │ ├── Range.ts │ │ ├── urlGeneration.ts │ │ └── urlParsing.ts │ ├── middleware │ │ ├── AuthenticationHandler.ts │ │ ├── AuthenticationHandlerOptions.ts │ │ ├── ChaosHandler.ts │ │ ├── MiddlewareControl.ts │ │ ├── MiddlewareFactory.ts │ │ ├── MiddlewareUtil.ts │ │ ├── RedirectHandler.ts │ │ ├── RedirectHandlerOptions.ts │ │ ├── RetryHandler.ts │ │ ├── RetryHandlerOptions.ts │ │ ├── TelemetryHandler.ts │ │ └── TelemetryHandlerOptions.ts │ └── tasks │ │ ├── LargeFileUploadTask.ts │ │ ├── OneDriveLargeFileUploadTask.ts │ │ ├── OneDriveLargeFileUploadTaskUtil.ts │ │ ├── PageIterator.ts │ │ └── StreamUpload.ts ├── development │ ├── DevelopmentTests.md │ ├── HardCodedAuthenticationProvider.ts │ ├── secrets.sample.ts │ ├── test-helper.ts │ └── workload │ │ ├── OneNote.ts │ │ ├── PageIterator.ts │ │ ├── delta-query.ts │ │ ├── excel.ts │ │ ├── groups.ts │ │ ├── insights.ts │ │ ├── largeFileUpload.ts │ │ ├── open-extensions.ts │ │ └── users.ts ├── node │ ├── NodeTests.md │ ├── authentication │ │ └── TokenCredentialAuthenticationProvider.ts │ ├── content │ │ └── BatchRequestContent.ts │ └── tasks │ │ └── StreamUpload.ts ├── sample_files │ ├── empty-spreadsheet.xlsx │ ├── onenotepage.html │ ├── onenotepage_fileattachment.html │ └── sample_image.jpg ├── test-helper.ts └── tsconfig-test-development.json ├── tsconfig-base.json ├── tsconfig-cjs.json ├── tsconfig-es.json ├── tsconfig-sub-cjs.json ├── tsconfig-sub-es.json └── types-demo.PNG /.azure-pipelines/ci-build-production.yml: -------------------------------------------------------------------------------- 1 | # Node.js 2 | # Build a general Node.js project with npm. 3 | # Add steps that analyze code, save build artifacts, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/javascript 5 | 6 | name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 7 | 8 | trigger: 9 | branches: 10 | include: 11 | - main 12 | 13 | pr: none 14 | 15 | stages: 16 | - stage: "Test" 17 | jobs: 18 | - job: 19 | pool: 20 | vmImage: windows-latest 21 | strategy: 22 | matrix: 23 | Node 14: 24 | NODE_VERSION: '14.x' 25 | Node 16: 26 | NODE_VERSION: '16.x' 27 | Node 18: 28 | NODE_VERSION: '18.x' 29 | Node 20: 30 | NODE_VERSION: '20.x' 31 | maxParallel: 2 32 | steps: 33 | - template: ./common-templates/security-pre-checks.yml 34 | - task: NodeTool@0 35 | inputs: 36 | versionSpec: $(NODE_VERSION) 37 | displayName: 'Install Node.js' 38 | 39 | - script: npm ci 40 | displayName: 'npm install for tests' 41 | - script: npm run build 42 | displayName: 'npm build for tests' 43 | - script: npm run test 44 | displayName: 'Run the node tests' 45 | - script: npm run karma 46 | displayName: 'Run karma tests' 47 | 48 | - task: PublishTestResults@2 49 | displayName: 'Publish Unit Test Results' 50 | inputs: 51 | testResultsFormat: 'JUnit' 52 | testResultsFiles: '**/testResult.xml' 53 | failTaskOnFailedTests: true 54 | 55 | - template: ./common-templates/security-post-checks.yml 56 | 57 | - stage: "Build" 58 | jobs: 59 | - job: 60 | 61 | pool: 62 | vmImage: ubuntu-latest 63 | steps: 64 | - task: NodeTool@0 65 | inputs: 66 | versionSpec: '16.x' 67 | displayName: 'Install Node.js' 68 | 69 | - script: | 70 | npm ci 71 | npm run build 72 | displayName: 'Build for production artifact' 73 | - task: CopyFiles@2 74 | inputs: 75 | sourceFolder: '$(Build.SourcesDirectory)' 76 | targetFolder: $(Build.ArtifactStagingDirectory) 77 | Contents: | 78 | **/* 79 | !.azure-pipelines/** 80 | !.github/** 81 | !.git/** 82 | !.vscode/** 83 | displayName: 'Copy npm package' 84 | 85 | - task: PublishBuildArtifacts@1 86 | inputs: 87 | pathtoPublish: $(Build.ArtifactStagingDirectory) 88 | artifactName: "release-drop" 89 | displayName: 'Publish artifacts' 90 | 91 | -------------------------------------------------------------------------------- /.azure-pipelines/common-templates/security-post-checks.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT License. 3 | steps: 4 | - task: CodesignValidation@0 5 | 6 | - task: SdtReport@1 7 | displayName: "Security Analysis Report" 8 | continueOnError: true 9 | condition: succeededOrFailed() 10 | inputs: 11 | AllTools: false 12 | APIScan: false 13 | BinSkim: false 14 | BinSkimBreakOn: "WarningAbove" 15 | CodesignValidation: true 16 | CodesignValidationBreakOn: "WarningAbove" 17 | CredScan: true 18 | FortifySCA: false 19 | FxCop: false 20 | ModernCop: false 21 | MSRD: false 22 | PoliCheck: true 23 | PoliCheckBreakOn: "Severity1" 24 | RoslynAnalyzers: true 25 | RoslynAnalyzersBreakOn: "WarningAbove" 26 | SDLNativeRules: false 27 | Semmle: false 28 | TSLint: false 29 | TSLintBreakOn: "WarningAbove" 30 | ToolLogsNotFoundAction: "Standard" 31 | 32 | - task: PublishSecurityAnalysisLogs@3 33 | displayName: "Publish Security Analysis Logs" 34 | inputs: 35 | ArtifactName: "CodeAnalysisLogs" 36 | ArtifactType: "Container" 37 | AllTools: false 38 | AntiMalware: false 39 | APIScan: false 40 | BinSkim: false 41 | CodesignValidation: true 42 | CredScan: true 43 | FortifySCA: false 44 | FxCop: false 45 | ModernCop: true 46 | MSRD: false 47 | PoliCheck: true 48 | RoslynAnalyzers: true 49 | SDLNativeRules: false 50 | Semmle: false 51 | TSLint: false 52 | WebScout: false 53 | ToolLogsNotFoundAction: "Standard" -------------------------------------------------------------------------------- /.azure-pipelines/common-templates/security-pre-checks.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT License. 3 | steps: 4 | - task: CredScan@2 5 | displayName: "Run CredScan" 6 | inputs: 7 | debugMode: false 8 | batchSize: 20 9 | toolMajorVersion: "V2" 10 | searchersFileType: "Skype" 11 | 12 | - task: PoliCheck@1 13 | displayName: "Run PoliCheck" 14 | condition: and(succeeded(), eq(eq(variables['Build.SourceBranch'], 'refs/heads/main'), false)) 15 | inputs: 16 | targetType: F 17 | SOMEnabled: true 18 | optionsFC: 0 19 | optionsXS: 0 20 | optionsHMENABLE: 0 21 | continueOnError: true -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | *.js 2 | *.js.map 3 | *.d.ts 4 | 5 | node_modules 6 | lib 7 | spec/development -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=TypeScript -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoftgraph/msgraph-devx-typescript-write 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/02-sdk-feature-request.yml: -------------------------------------------------------------------------------- 1 | name: SDK Feature request 2 | description: Request a new feature on the SDK 3 | labels: ["type:feature", "status:waiting-for-triage"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | **Thank you for taking the time to fill out this feature request form!** 9 | 💥Please search to see if an issue already exists for the feature you are requesting. 10 | - type: textarea 11 | attributes: 12 | label: Is your feature request related to a problem? Please describe the problem. 13 | description: A clear and concise description of what the problem is. 14 | placeholder: I am trying to do [...] but [...] 15 | validations: 16 | required: false 17 | - type: textarea 18 | attributes: 19 | label: Describe the solution you'd like. 20 | description: | 21 | A clear and concise description of what you want to happen. Include any alternative solutions you've considered. 22 | validations: 23 | required: true 24 | - type: textarea 25 | attributes: 26 | label: Additional context? 27 | description: | 28 | Add any other context or screenshots about the feature request here. 29 | validations: 30 | required: false 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03-blank-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Blank issue 3 | about: Something that doesn't fit the other categories 4 | title: '' 5 | labels: ["status:waiting-for-triage"] 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Question on use of graph sdk 4 | url: https://github.com/microsoftgraph/msgraph-sdk-javascript/discussions 5 | about: Please add your question in the discussions section of the repo 6 | - name: Question on use of kiota 7 | url: https://github.com/microsoft/kiota/discussions 8 | about: Please add your question in the discussions section of the repo 9 | - name: Question or Feature Request for the MS Graph API? 10 | url: https://aka.ms/msgraphsupport 11 | about: Report an issue or limitation with the MS Graph service APIs 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | groups: 9 | eslint: 10 | patterns: 11 | - "*eslint*" 12 | sinon: 13 | patterns: 14 | - "*sinon*" 15 | chai: 16 | patterns: 17 | - "*chai*" 18 | karma: 19 | patterns: 20 | - "*karma*" 21 | mocha: 22 | patterns: 23 | - "*mocha*" 24 | babel: 25 | patterns: 26 | - "*babel*" 27 | - package-ecosystem: github-actions 28 | directory: "/" 29 | schedule: 30 | interval: weekly 31 | open-pull-requests-limit: 10 32 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | A similar PR may already be submitted! Please search among the [Pull request](https://github.com/microsoftgraph/msgraph-sdk-javascript/pulls) before creating one. 2 | 3 | Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. 4 | 5 | **NOTE: PR's will be accepted only in case of appropriate information is provided below** 6 | 7 | ## Summary 8 | 9 | 10 | 11 | ## Motivation 12 | 13 | Explain the **motivation** for making this change. What existing problem does the pull request solve? 14 | 15 | 16 | 17 | ## Test plan 18 | 19 | Demonstrate the code is solid. Example: The exact commands you ran and their output. 20 | 21 | 22 | 23 | ## Closing issues 24 | 25 | 26 | 27 | Fixes # 28 | 29 | ## Types of changes 30 | 31 | 32 | 33 | - [ ] Bug fix (non-breaking change which fixes an issue) 34 | - [ ] New feature (non-breaking change which adds functionality) 35 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 36 | 37 | ## Checklist 38 | 39 | - [ ] I have read the **CONTRIBUTING** document. 40 | - [ ] My code follows the code style of this project. 41 | - [ ] My change requires a change to the documentation. 42 | - [ ] I have updated the documentation accordingly. 43 | - [ ] I have added tests to cover my changes. 44 | - [ ] All new and existing tests passed. 45 | -------------------------------------------------------------------------------- /.github/workflows/ci_validation.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Graph JS SDK CI 5 | 6 | on: [pull_request] 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x, 18.x, 20.x] 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - name: Install dependencies 23 | run: npm ci 24 | 25 | - name: Build for node 16, 18 & 20 26 | run: npm run build 27 | 28 | - name: Run unit tests 29 | run: npm test 30 | 31 | - name: Verify ESM compatibility 32 | working-directory: './test-esm' 33 | run: | 34 | npm ci 35 | npm test 36 | 37 | # The check-build-matrix returns success if all matrix jobs in build are successful; otherwise, it returns a failure. 38 | # Use this as a PR status check for GitHub Policy Service instead of individual matrix entry checks. 39 | check-build-matrix: 40 | runs-on: ubuntu-latest 41 | needs: build 42 | if: always() 43 | steps: 44 | - name: All build matrix options are successful 45 | if: ${{ !(contains(needs.*.result, 'failure')) }} 46 | run: exit 0 47 | - name: One or more build matrix options failed 48 | if: ${{ contains(needs.*.result, 'failure') }} 49 | run: exit 1 -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ dev, 3.0.0, main, support/v2, v2/dev ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ dev ] 20 | schedule: 21 | - cron: '23 15 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v3 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v3 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/* 2 | !/.vscode/launch.json 3 | !/.vscode/tasks.json 4 | 5 | .DS_Store 6 | .tmp 7 | tmp 8 | node_modules 9 | typings 10 | coverage 11 | **/*.tgz 12 | npm-debug.log 13 | 14 | /lib/* 15 | !/lib/.npmignore 16 | 17 | /authProviders/* 18 | 19 | src/**/*.js 20 | src/**/*.js.map 21 | src/**/*.d.ts 22 | 23 | samples/**/secrets.ts 24 | samples/node_modules/** 25 | samples/lib/ 26 | 27 | test/development/secrets.ts 28 | 29 | .nyc_output/* 30 | 31 | .idea/* 32 | 33 | testResult.xml 34 | test-results.xml 35 | 36 | test-esm/lib/* 37 | -------------------------------------------------------------------------------- /.huskyrc: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-commit": "npm run pre-build && git add src/Version.ts && lint-staged && npm run lint && npm run test" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": "true" 3 | } 4 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.css": ["npm run format:css", "git add"], 3 | "*.html": ["npm run format:html", "git add"], 4 | "*.js": ["npm run format:js", "git add"], 5 | "*.json": ["npm run format:json", "git add"], 6 | "*.md": ["npm run format:md", "git add"], 7 | ".*rc": ["npm run format:rc", "git add"], 8 | "*.ts": ["npm run format:ts", "git add"] 9 | } 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | scripts/ 3 | design/ 4 | changelogs/ 5 | testResult.xml 6 | test-esm/ -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | 3 | scripts/**/* 4 | 5 | src/**/*.js 6 | src/**/*.js.map 7 | src/**/*.d.ts 8 | 9 | test/**/*.js 10 | test/**/*.js.map 11 | test/**/*.d.ts 12 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "jsxBracketSameLine": true, 5 | "jsxSingleQuote": false, 6 | "printWidth": 5000, 7 | "proseWrap": "never", 8 | "semi": true, 9 | "singleQuote": false, 10 | "tabWidth": 4, 11 | "trailingComma": "all", 12 | "useTabs": true 13 | } 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | - "lts/*" 5 | - "10.15.1" 6 | - "10.0.0" 7 | - "9.11.2" 8 | - "9.0.0" 9 | - "8.15.0" 10 | - "8.0.0" 11 | - "7.10.1" 12 | - "7.0.0" 13 | - "6.16.0" 14 | - "6.0.0" -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Run Node samples", 11 | "program": "${workspaceRoot}/samples/node/main.js", 12 | "cwd": "${workspaceRoot}", 13 | "outFiles": [], 14 | "internalConsoleOptions": "openOnSessionStart" 15 | }, 16 | { 17 | "type": "node", 18 | "request": "launch", 19 | "name": "Run Content tests", 20 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 21 | "args": ["${workspaceRoot}/lib/test/common/**/*.js"], 22 | "cwd": "${workspaceRoot}", 23 | "preLaunchTask": "Run Compile", 24 | "outFiles": [], 25 | "internalConsoleOptions": "openOnSessionStart" 26 | }, 27 | { 28 | "type": "node", 29 | "request": "launch", 30 | "name": "Run Core tests", 31 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 32 | "args": ["${workspaceRoot}/lib/test/common/core/*.js"], 33 | "cwd": "${workspaceRoot}", 34 | "preLaunchTask": "Run Compile", 35 | "outFiles": [], 36 | "internalConsoleOptions": "openOnSessionStart" 37 | }, 38 | { 39 | "type": "node", 40 | "request": "launch", 41 | "name": "Run Middleware tests", 42 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 43 | "args": ["${workspaceRoot}/lib/test/common/middleware/*.js"], 44 | "cwd": "${workspaceRoot}", 45 | "preLaunchTask": "Run Compile", 46 | "outFiles": [], 47 | "internalConsoleOptions": "openOnSessionStart" 48 | }, 49 | { 50 | "type": "node", 51 | "request": "launch", 52 | "name": "Run Tasks tests", 53 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 54 | "args": ["${workspaceRoot}/lib/test/common/tasks/*.js"], 55 | "cwd": "${workspaceRoot}", 56 | "preLaunchTask": "Run Compile", 57 | "outFiles": [], 58 | "internalConsoleOptions": "openOnSessionStart" 59 | }, 60 | { 61 | "type": "node", 62 | "request": "launch", 63 | "name": "Run Workload tests", 64 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 65 | "args": ["${workspaceRoot}/test/common/development/workload/*.js"], 66 | "cwd": "${workspaceRoot}", 67 | "preLaunchTask": "Run Compile", 68 | "outFiles": [], 69 | "internalConsoleOptions": "openOnSessionStart" 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Run Compile", 8 | "type": "typescript", 9 | "tsconfig": "tsconfig-cjs.json", 10 | "group": "build" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.4.0 4 | 5 | New Features 6 | 7 | - Added Search query param functionality 8 | 9 | Bug Fixes 10 | 11 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/115 12 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/107 13 | 14 | ## 1.3.0 15 | 16 | New Features 17 | 18 | - Support for Large File upload [[#1](https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/driveitem_createuploadsession), [#2](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/tasks/LargeFileUploadTask.md)] 19 | - Batching made easy [[#1](https://developer.microsoft.com/en-us/graph/docs/concepts/json_batching), [#2](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/content/Batching.md)] 20 | 21 | Bug Fixes 22 | 23 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/97 24 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/110 25 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/39 26 | - https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/111 27 | 28 | ## 1.2.0 29 | 30 | Updates 31 | 32 | - Two output js files, one with polyfills for Fetch-API and ES6-Promises lib/graph-js-sdk-web.js and one without lib/graph-js-sdk-core.js [Refer [README.md](https://github.com/microsoftgraph/msgraph-sdk-javascript#browser) for usage] 33 | - Enum for ResponseType, which lists down the available ResponseType options in autocomplete 34 | 35 | Bug Fix 36 | 37 | - Cannot access the property "request-id" of undefined in GraphError handling 38 | 39 | ## 1.1.0 40 | 41 | New Features 42 | 43 | - Support for Multipart POST request 44 | 45 | Updates 46 | 47 | - Light weight FetchAPI dependency (in replacement for SuperAgent) 48 | 49 | Bug Fixes 50 | 51 | - Updated putStream and getStream to work for all sized files 52 | - Added obfuscation for output js file (graph-js-sdk-web.js) 53 | - Updated versions of mocha and chai to 5.2.0 and 4.1.2 to fix security vulnerability in growl (which is a dependency of mocha) 54 | - Running unit test files under types directory 55 | - Compiling ts files 56 | 57 | ## 1.0.0 58 | 59 | - Added tests for new Graph functionality - Delta query, Extensibility, OneNote, and more. 60 | 61 | ## 0.4.0 62 | 63 | - Add support for ES5. Make sure to use `graph-js-sdk-web.js` for web apps 64 | - Removed iterator helper method. 65 | 66 | ## 0.3.1 67 | 68 | - Support for Node.js versions 4 and 5 69 | 70 | ## 0.3.0 71 | 72 | - Migrated away from typings in client library core and TypeScript sample 73 | 74 | ## 0.2.2 75 | 76 | - Updated SuperAgent to version `3.3.0` 77 | 78 | ## 0.2.0 79 | 80 | - **Breaking change for existing apps** - Initialize the client library with `MicrosoftGraph.Client.init({...})`. See the updated usage section below for code samples. 81 | - Added response handling tests to simulate Graph calls 82 | - Added type declarations file for core client library, which adds intellisense for chained methods. 83 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /THIRD PARTY NOTICES: -------------------------------------------------------------------------------- 1 | This file is based on or incorporates material from the projects listed below (Third Party OSS). The original copyright notice and the license under which Microsoft received such Third Party OSS, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party OSS to you under the licensing terms for the Microsoft product or service. Microsoft 2 | reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. 3 | 4 | tslib 5 | 6 | isomorphic-fetch 7 | 8 | es6-promise 9 | 10 | Provided for Informational Purposes Only 11 | 12 | MIT License 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /authProviderOptions/ReadMe.md: -------------------------------------------------------------------------------- 1 | The authProviderOptions/ folders contains barrels for exporting Authentication Provider options such as MSAL and Azure Identity Token Credentials. 2 | 3 | [tsconfig-sub-cjs.json](../tsconfig-sub-es.json) and [tsconfig-sub-cjs.json](../tsconfig-sub-es.json) contains the config for transpiling the files to authProviders/ output folder. 4 | 5 | This approach is used because of the limitations of creating a submodule structure - References - https://github.com/microsoft/TypeScript/issues/8305 https://github.com/microsoft/TypeScript/issues/33079 6 | -------------------------------------------------------------------------------- /authProviderOptions/authCodeMsalBrowser/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "../../lib/src/authentication/msal-browser/AuthCodeMSALBrowserAuthenticationProvider"; 8 | export * from "../../lib/src/authentication/msalOptions/MSALAuthenticationProviderOptions"; 9 | -------------------------------------------------------------------------------- /authProviderOptions/azureTokenCredentials/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "../../lib/src/authentication/azureTokenCredentials/TokenCredentialAuthenticationProvider"; 8 | export * from "../../lib/src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions"; 9 | -------------------------------------------------------------------------------- /authProviderOptions/es/authCodeMsalBrowser/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "../../../lib/es/src/authentication/msal-browser/AuthCodeMSALBrowserAuthenticationProvider"; 8 | export * from "../../../lib/es/src/authentication/msalOptions/MSALAuthenticationProviderOptions"; 9 | -------------------------------------------------------------------------------- /authProviderOptions/es/azureTokenCredentials/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export * from "../../../lib/es/src/authentication/azureTokenCredentials/TokenCredentialAuthenticationProvider"; 8 | export * from "../../../lib/es/src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions"; 9 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | const presets = [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | ie: 11, 9 | }, 10 | }, 11 | ], 12 | ]; 13 | 14 | const plugins = [ 15 | [ 16 | "@babel/plugin-transform-runtime", 17 | { 18 | absoluteRuntime: false, 19 | corejs: false, 20 | helpers: true, 21 | regenerator: true, 22 | useESModules: false, 23 | }, 24 | ], 25 | ]; 26 | return { 27 | presets, 28 | plugins, 29 | }; 30 | }; 31 | -------------------------------------------------------------------------------- /docs/AuthCodeMSALBrowserAuthenticationProvider.md: -------------------------------------------------------------------------------- 1 | #### Creating an instance of AuthCodeMSALBrowserAuthenticationProvider for a browser application 2 | 3 | **Note**: The `AuthCodeMSALBrowserAuthenticationProvider` is introduced in version 3.0.0 of Microsoft Graph Client Library 4 | 5 | ###### Links for more information - 6 | 7 | - [npm - @azure/msal-browser](https://www.npmjs.com/package/@azure/msal-browser) 8 | - [github - @azure/msal-browser](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/README.md) 9 | 10 | Steps to use `AuthCodeMSALBrowserAuthenticationProvider`; 11 | 12 | 1. Installation 13 | 14 | - Using npm: `npm install @azure/msal-browser @microsoft/microsoft-graph-client` 15 | 16 | - Using CDN: 17 | 18 | ```html 19 | 20 | 21 | 22 | 23 | ``` 24 | Reference : [MSAL Browser CDN usage](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/cdn-usage.md) 25 | 26 | 2. Initialize the `msal-browser` `PublicClientApplication` instance: Learn more [how to initialize msal](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/initialization.md) 27 | 28 | 3. Following sample shows how to initialize a Microsoft Graph SDK `Client` instance, 29 | 30 | Using npm: 31 | 32 | ```typescript 33 | import { PublicClientApplication, InteractionType, AccountInfo } from "@azure/msal-browser"; 34 | 35 | import { AuthCodeMSALBrowserAuthenticationProvider, AuthCodeMSALBrowserAuthenticationProviderOptions } from "@microsoft/microsoft-graph-client/authProviders/authCodeMsalBrowser"; 36 | import { Client } from "@microsoft/microsoft-graph-client"; 37 | 38 | const options: AuthCodeMSALBrowserAuthenticationProviderOptions = { 39 | account: account, // the AccountInfo instance to acquire the token for. 40 | interactionType: InteractionType.Popup, // msal-browser InteractionType 41 | scopes: ["user.read", "mail.send"] // example of the scopes to be passed 42 | }; 43 | 44 | // Pass the PublicClientApplication instance from step 2 to create AuthCodeMSALBrowserAuthenticationProvider instance 45 | const authProvider = new AuthCodeMSALBrowserAuthenticationProvider(publicClientApplication, options); 46 | 47 | 48 | // Initialize the Graph client 49 | const graphClient = Client.initWithMiddleware({ 50 | authProvider 51 | }); 52 | 53 | ``` 54 | 55 | Using CDN or script: 56 | 57 | ```javascript 58 | const msalClient = new msal.PublicClientApplication(msalConfig); 59 | 60 | const authProvider = new MSGraphAuthCodeMSALBrowserAuthProvider.AuthCodeMSALBrowserAuthenticationProvider(msalClient, { 61 | account, // the AccountInfo instance to acquire the token for 62 | scopes: ["user.read", "mail.send"], 63 | interactionType: msal.InteractionType.Popup, 64 | }); 65 | 66 | // Initialize the Graph client 67 | const graphClient = MicrosoftGraph.Client.initWithMiddleware({ authProvider }); 68 | ``` 69 | -------------------------------------------------------------------------------- /docs/CallingPattern.md: -------------------------------------------------------------------------------- 1 | # Calling Pattern 2 | 3 | All calls to Microsoft Graph are chained together starting with **.api()**, then chain [query parameters](./QueryParameters.md) and end with an [action](./Actions.md). 4 | 5 | ## Path supports the following formats 6 | 7 | - `me` 8 | - `/me` 9 | - `https://graph.microsoft.com/v1.0/me` 10 | - `https://graph.microsoft.com/beta/me` 11 | - `me/events?$filter=startswith(subject, "Adventure")` 12 | 13 | ## Promise based calling 14 | 15 | Getting user details with `async`/`await`, 16 | 17 | ```typescript 18 | try { 19 | let res = await client.api("/me").get(); 20 | console.log(res); 21 | } catch (error) { 22 | throw error; 23 | } 24 | ``` 25 | 26 | Getting user details with `then`/`catch`, 27 | 28 | ```typescript 29 | client 30 | .api("/me") 31 | .get() 32 | .then((res) => { 33 | console.log(res); 34 | }) 35 | .catch((err) => { 36 | console.log(err); 37 | }); 38 | ``` 39 | 40 | ## Callback based calling 41 | 42 | Getting user details by passing `callback`, 43 | 44 | ```typescript 45 | client.api("/me").get((err, res) => { 46 | console.log(res); 47 | }); 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/CancellingAHTTPRequest.md: -------------------------------------------------------------------------------- 1 | # Cancel a HTTP request 2 | 3 | > The `abort()` method of the AbortController interface aborts a DOM request (e.g. a Fetch request) 4 | > 5 | > -- [AbortController interface](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) 6 | 7 | References - 8 | * [AbortController interface](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) 9 | * [abortcontroller npm](https://www.npmjs.com/package/abort-controller) 10 | * [abortcontroller-polyfill](https://www.npmjs.com/package/abortcontroller-polyfill) 11 | * [Example of the AbortController implementation](https://github.com/node-fetch/node-fetch#request-cancellation-with-abortsignal) 12 | 13 | #### Following is how canceling a fetch call works: 14 | 15 | * Create an AbortController instance. 16 | * That instance has a signal property. 17 | * Pass the signal as a fetch option for signal. 18 | * Call the AbortController's abort property to cancel all fetches that use that signal. 19 | 20 | #### Setting the AbortController.signal as a fetch option while creating the MSGraph SDK Client instance: 21 | 22 | ```typescript 23 | import { Client,FetchOptions } from "@microsoft/microsoft-graph-client"; 24 | import { AbortController } from "abort-controller"; // <- import when using the abort-controller npm package. 25 | 26 | const controller = new AbortController(); 27 | 28 | const timeout = setTimeout(() => { 29 | controller.abort(); 30 | }, 150); 31 | 32 | const fetchOptions: FetchOptions = { 33 | signal: controller.signal; 34 | } 35 | 36 | const client = Client.initWithMiddleware({ 37 | fetchOptions, // Pass the FetchOptions value where the AbortController.signal is set 38 | authProvider, 39 | ... 40 | }); 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/ChaosHandlerSamples.md: -------------------------------------------------------------------------------- 1 | # Testing Handler 2 | 3 | ### How to include 4 | 5 | > Uses [Custom Middleware Chain](https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CustomMiddlewareChain.md), it's not included in default middleware chain 6 | 7 | ### Modes in Chaos Handler 8 | 9 | - Manual mode - Setting the Response code manually. - Global/Client Level - Provide a map declared manually containing response code for the requests. - Request Level - Providing response code per request. This would be overriding the Global level response code (if any). 10 | - Random mode - We get a random Response code from a set of response code defined for each method. 11 | 12 | **A request Passes through to the Graph, if there is no entry for the request** 13 | 14 | **Note - Always add ChaosHandler before HttpMessageHandler in the middlewareChain** 15 | 16 | ### Samples 17 | 18 | ```js 19 | require("isomorphic-fetch"); 20 | const MicrosoftGraph = require("../../lib/src/index.js"); 21 | const secrets = require("./secrets"); 22 | const fs = require("fs"); 23 | // Initialising the client 24 | const client = MicrosoftGraph.Client.init({ 25 | defaultVersion: "v1.0", 26 | debugLogging: true, 27 | authProvider: (done) => { 28 | done(null, secrets.accessToken); 29 | }, 30 | }); 31 | 32 | /* 33 | Create a custom MiddlewareChain passing information in this way 34 | 35 | const manualMap = new Map([["/me/messages/.*", new Map([["GET", 429], ["PATCH", 429]])], ["/me", new Map([["POST", 502]])]]); 36 | const chaosHandler = new MicrosoftGraph.ChaosHandler(new MicrosoftGraph.ChaosHandlerOptions(MicrosoftGraph.ChaosStrategy.MANUAL), manualMap); 37 | */ 38 | 39 | // This request would use the Map (Manual mode) 40 | const mail = { 41 | subject: "Chaos Handler Samples", 42 | toRecipients: [ 43 | { 44 | emailAddress: { 45 | address: "admin@M365x003297.OnMicrosoft.com", 46 | }, 47 | }, 48 | ], 49 | body: { 50 | content: "

Testing Handler Samples Sample


https://github.com/microsoftgraph/msgraph-sdk-javascript", 51 | contentType: "html", 52 | }, 53 | }; 54 | client 55 | .api("/users/me/sendMail") 56 | .post({ 57 | message: mail, 58 | }) 59 | .then((res) => { 60 | console.log(res, "This is for sendMail"); 61 | }) 62 | .catch((err) => { 63 | console.log(err, "This is for sendMail in error case"); 64 | }); 65 | 66 | // OverRiding to Random mode, providing the chaos percentage as 60(percentage times the error would be generated from handler) 67 | client 68 | .api("/me") 69 | .middlewareOptions([new MicrosoftGraph.ChaosHandlerOptions(MicrosoftGraph.ChaosStrategy.RANDOM, "I generated the error", undefined, 60)]) 70 | .get() 71 | .then((res) => { 72 | console.log(res); 73 | }) 74 | .catch((err) => { 75 | console.log(err); 76 | }); 77 | 78 | // This request is passed to the graph and gets a response from the graph, as no entry for /me GET request in the Map 79 | client 80 | .api("/me") 81 | .get() 82 | .then((res) => { 83 | console.log("Found", res, "users"); 84 | }) 85 | .catch((err) => { 86 | console.log(err, "!!!!!!!!!"); 87 | }); 88 | 89 | // Using Manual Map with regex matching 90 | client 91 | .api("/me/messages/hjdlfslod-fdssdkjfs-6zdkmghs-sadhsu2") 92 | .header("content-type", "application/json") 93 | .update({ 94 | birthday: "1908-12-22T00:00:00Z", 95 | }) 96 | .then((res) => { 97 | console.log("This is regex matching... Updated Bday"); 98 | }) 99 | .catch((err) => { 100 | console.log(err, "matched"); 101 | }); 102 | ``` 103 | -------------------------------------------------------------------------------- /docs/CustomAuthenticationProvider.md: -------------------------------------------------------------------------------- 1 | # Using Custom Authentication Provider 2 | 3 | Using preferred choice of Authentication library for authenticating with Microsoft is possible. 4 | 5 | ## Step by step procedure 6 | 7 | ### Implement AuthenticationProvider 8 | 9 | Create own implementation of Authentication provider which implements [AuthenticationProvider](../src/IAuthenticationProvider.ts) interface. 10 | 11 | ```typescript 12 | // MyAuthenticationProvider.ts 13 | import { AuthenticationProvider } from "@microsoft/microsoft-graph-client"; 14 | 15 | class MyAuthenticationProvider implements AuthenticationProvider { 16 | /** 17 | * This method will get called before every request to the msgraph server 18 | * This should return a Promise that resolves to an accessToken (in case of success) or rejects with error (in case of failure) 19 | * Basically this method will contain the implementation for getting and refreshing accessTokens 20 | */ 21 | public async getAccessToken(): Promise {} 22 | } 23 | ``` 24 | 25 | ### Initialize Client 26 | 27 | Pass instance of MyAuthenticationProvider while initializing. 28 | 29 | ```typescript 30 | import { MyAuthenticationProvider } from "./MyAuthenticationProvider"; 31 | 32 | let clientOptions: ClientOptions = { 33 | authProvider: new MyAuthenticationProvider(), 34 | }; 35 | const client = Client.initWithMiddleware(clientOptions); 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/GettingRawResponse.md: -------------------------------------------------------------------------------- 1 | # Getting Raw Response 2 | 3 | Steps for getting the raw response [i.e [Response Object](https://developer.mozilla.org/en-US/docs/Web/API/Response)] 4 | 5 | ## Initialize the Client 6 | 7 | Refer [this documentation](./CreatingClientInstance.md) for initializing the client. 8 | 9 | ## Getting Raw Response by setting ResponseType 10 | 11 | To get the raw response set the responseType of a request to ResponseType.RAW. 12 | 13 | ```typescript 14 | const rawResponse = await client 15 | .api("/me") 16 | .select("displayName") 17 | .responseType(ResponseType.RAW) 18 | .get(); 19 | console.log(rawResponse); 20 | ``` 21 | 22 | Using callback method, 23 | 24 | ```typescript 25 | client 26 | .api("/me") 27 | .select("displayName") 28 | .responseType(ResponseType.RAW) 29 | .get((error, rawResponse) => { 30 | console.log(rawResponse); 31 | }); 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/tasks/PageIterator.md: -------------------------------------------------------------------------------- 1 | # PageIterator 2 | 3 | For a variety of reasons, collections of entities are often split into pages and each page is returned with a URL to the next page. Sometimes, page granularity provided by the API does not match the requirements of the consumer. PageIterator simplifies consuming of paged collections. 4 | 5 | ## Iterate over all the messages 6 | 7 | ```typescript 8 | async function callingPattern() { 9 | try { 10 | // Makes request to fetch mails list. Which is expected to have multiple pages of data. 11 | let response: PageCollection = await client.api("/me/messages").get(); 12 | // A callback function to be called for every item in the collection. This call back should return boolean indicating whether not to continue the iteration process. 13 | let callback: PageIteratorCallback = (data) => { 14 | console.log(data); 15 | return true; 16 | }; 17 | // Creating a new page iterator instance with client a graph client instance, page collection response from request and callback 18 | let pageIterator = new PageIterator(client, response, callback); 19 | // This iterates the collection until the nextLink is drained out. 20 | await pageIterator.iterate(); 21 | } catch (e) { 22 | throw e; 23 | } 24 | } 25 | ``` 26 | 27 | ## Stopping and Resuming the iteration 28 | 29 | ```typescript 30 | // Populating custom size pages if the api restricts to some maximum size. Lazy loading more data on user prompt or something, stop and resume will do the trick. 31 | async function customSize() { 32 | try { 33 | let response: PageCollection = await client.api("/me/messages").get(); 34 | let size = 1000; 35 | let count = 0; 36 | let callback: PageIteratorCallback = (data) => { 37 | console.log(data); 38 | count++; 39 | if (count === size) { 40 | count = 0; 41 | return false; 42 | } 43 | return true; 44 | }; 45 | let pageIterator = new PageIterator(client, response, callback); 46 | // This stops iterating over for 1000 entities. 47 | await pageIterator.iterate(); 48 | 49 | // Resuming will do start from where it left off and iterate for next 1000 entities. 50 | // Check and resume is likely to be called in any user interaction requiring to load more data. 51 | if (!pageIterator.isComplete()) { 52 | await pageIterator.resume(); 53 | } 54 | } catch (e) { 55 | throw e; 56 | } 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const { series } = require("gulp"); 2 | 3 | const licenseStr = `/** 4 | * ------------------------------------------------------------------------------------------- 5 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 6 | * See License in the project root for license information. 7 | * ------------------------------------------------------------------------------------------- 8 | */ 9 | `; 10 | 11 | const moduleHeader = `/** 12 | * @module Version 13 | */ 14 | `; 15 | 16 | const versionFile = `${licenseStr} 17 | // THIS FILE IS AUTO GENERATED 18 | // ANY CHANGES WILL BE LOST DURING BUILD 19 | 20 | ${moduleHeader} 21 | export const PACKAGE_VERSION = "[VERSION]"; 22 | `; 23 | 24 | function setVersion(cb) { 25 | var pkg = require("./package.json"); 26 | var fs = require("fs"); 27 | fs.writeFileSync("src/Version.ts", versionFile.replace("[VERSION]", pkg.version)); 28 | cb(); 29 | } 30 | 31 | exports.setVersion = setVersion; 32 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | config.set({ 3 | frameworks: ["mocha", "chai", "karma-typescript"], 4 | files: ["test/common/**/*.ts", "src/**/!(azureTokenCredentials)/*.ts", "src/*.ts", "test/browser/**/*.ts", "test/*.ts"], 5 | preprocessors: { 6 | "**/*.ts": ["karma-typescript"], 7 | }, 8 | karmaTypescriptConfig: { 9 | tsconfig: "./tsconfig-cjs.json", 10 | }, 11 | browsers: ["ChromeHeadless"], 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /lib/.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | test/ 3 | **/*.tsbuildinfo 4 | es/test/ -------------------------------------------------------------------------------- /msgraph-sdk-javascript.yml: -------------------------------------------------------------------------------- 1 | page_type: sample 2 | products: 3 | - office-365 4 | - ms-graph 5 | languages: 6 | - javascript 7 | - typescript 8 | extensions: 9 | contentType: sdks 10 | technologies: 11 | - Microsoft Graph 12 | - Microsoft identity platform 13 | createdDate: '9/22/2016 2:44:49 PM' 14 | title: Microsoft Graph JavaScript Client Library 15 | description: Microsoft Graph client library for JavaScript 16 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import terser from "@rollup/plugin-terser"; 9 | import resolve from "@rollup/plugin-node-resolve"; 10 | import babel from "@rollup/plugin-babel"; 11 | import commonjs from "@rollup/plugin-commonjs"; 12 | 13 | const copyRight = `/** 14 | * ------------------------------------------------------------------------------------------- 15 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 16 | * See License in the project root for license information. 17 | * ------------------------------------------------------------------------------------------- 18 | */`; 19 | 20 | const config = [ 21 | { 22 | input: ["lib/es/src/browser/index.js"], 23 | output: { 24 | file: "lib/graph-js-sdk.js", 25 | format: "iife", 26 | name: "MicrosoftGraph", 27 | }, 28 | plugins: [ 29 | resolve({ 30 | browser: true, 31 | preferBuiltins: false, 32 | }), 33 | babel({ 34 | babelHelpers: "runtime", 35 | exclude: "node_modules/**", 36 | }), 37 | commonjs({ include: "node_modules/**" }), 38 | terser({ 39 | format: { 40 | comments: false, 41 | preamble: copyRight, 42 | }, 43 | }), 44 | ], 45 | }, 46 | { 47 | input: ["authProviders/es/azureTokenCredentials/index.js"], 48 | output: { 49 | file: "lib/graph-client-tokenCredentialAuthProvider.js", 50 | format: "iife", 51 | name: "MicrosoftGraphTokenCredentialAuthProvider", 52 | }, 53 | plugins: [ 54 | resolve({ 55 | browser: true, 56 | preferBuiltins: false, 57 | }), 58 | babel({ 59 | babelHelpers: "runtime", 60 | exclude: "node_modules/**", 61 | }), 62 | commonjs({ include: "node_modules/**" }), 63 | terser({ 64 | format: { 65 | comments: false, 66 | preamble: copyRight, 67 | }, 68 | }), 69 | ], 70 | }, 71 | { 72 | input: ["lib/es/src/authentication/msal-browser/AuthCodeMSALBrowserAuthenticationProvider.js"], 73 | external: ["@azure/msal-browser"], 74 | output: { 75 | file: "lib/graph-client-msalBrowserAuthProvider.js", 76 | format: "iife", 77 | name: "MSGraphAuthCodeMSALBrowserAuthProvider", 78 | globals: { 79 | "@azure/msal-browser": "msal", 80 | }, 81 | }, 82 | plugins: [ 83 | resolve({ 84 | browser: true, 85 | preferBuiltins: false, 86 | }), 87 | babel({ 88 | babelHelpers: "runtime", 89 | exclude: "node_modules/**", 90 | }), 91 | commonjs({ include: "node_modules/**" }), 92 | terser({ 93 | format: { 94 | comments: false, 95 | preamble: copyRight, 96 | }, 97 | }), 98 | ], 99 | }, 100 | ]; 101 | 102 | export default config; 103 | -------------------------------------------------------------------------------- /sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-sdk-javascript/db1757abe7a4cad310f0cd4d7d2a83b961390cce/sample.png -------------------------------------------------------------------------------- /samples/javascript/clientInitialization/ClientWithOptions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | const { Client } = require("@microsoft/microsoft-graph-client"); 9 | require("isomorphic-fetch"); 10 | 11 | const error = "error throw by the authentication handler"; 12 | 13 | const client = Client.init({ 14 | defaultVersion: "v1.0", 15 | debugLogging: true, 16 | authProvider: (done) => { 17 | done(error, "ACCESS_TOKEN"); 18 | }, 19 | }); 20 | 21 | client 22 | .api("/me") 23 | .select("displayName") 24 | .get() 25 | .then((res) => { 26 | console.log(res); 27 | }) 28 | .catch((err) => { 29 | console.log(err); 30 | }); 31 | 32 | module.exports = { 33 | client: client, 34 | }; 35 | -------------------------------------------------------------------------------- /samples/javascript/clientInitialization/tokenCredentialAuthenticationProvider/README.md: -------------------------------------------------------------------------------- 1 | # Sample of passing a ClientSecretCredential to the Javascript Client Library 2 | 3 | 1. Register your application to enable authentication to Azure Active Directory using the client secret credential. For more details, please check the following links 4 | 5 | - [Register an application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) 6 | 7 | - [Documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application). 8 | 9 | 2. Update your `clientId`, `tenantId`, `scopes`, `clientSecret`, `port` in the index.js . 10 | 11 | ## Run Sample 12 | 13 | 1. Navigate to project home [../../] 14 | 15 | 2. Run `npm install` to install the application. 16 | 17 | 3. Run `npm run build` to build the library files. 18 | 19 | 4. Navigate to the samples folder [./samples]and run `npm install` 20 | 21 | 5. Navigate to secrets.js[./secrets] and populate all the values (tenantId, clientId, clientSecret, scopes) 22 | 23 | 6. Navigate to tokenCredentialAuthenticationProvider[./samples/javascript/clientInitialization/tokenCredentialAuthenticationProvider] in the samples directory. 24 | 25 | 7. For running this javascript sample, run `node index.js` 26 | -------------------------------------------------------------------------------- /samples/javascript/clientInitialization/tokenCredentialAuthenticationProvider/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | const { Client } = require("@microsoft/microsoft-graph-client"); 9 | const { TokenCredentialAuthenticationProvider } = require("@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials"); 10 | const { ClientSecretCredential } = require("@azure/identity"); 11 | const { clientId, clientSecret, scopes, tenantId } = require("./secrets"); 12 | 13 | require("isomorphic-fetch"); 14 | 15 | const port = ""; 16 | const redirectUri = `http://localhost:${port}/authresponse`; 17 | const authorityHost = "https://login.microsoftonline.com"; 18 | 19 | const credential = new ClientSecretCredential(tenantId, clientId, clientSecret); 20 | const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: [scopes] }); 21 | const client = Client.initWithMiddleware({ 22 | debugLogging: true, 23 | authProvider, 24 | }); 25 | 26 | client 27 | .api("/me") 28 | .select("displayName") 29 | .get() 30 | .then((res) => { 31 | console.log(res); 32 | }) 33 | .catch((err) => { 34 | console.log(err); 35 | }); 36 | 37 | module.exports = { 38 | client: client, 39 | }; 40 | -------------------------------------------------------------------------------- /samples/javascript/clientInitialization/tokenCredentialAuthenticationProvider/secrets.js: -------------------------------------------------------------------------------- 1 | const tenantId = ""; 2 | const clientId = ""; 3 | const clientSecret = ""; 4 | const scopes = ""; 5 | 6 | module.exports = { 7 | tenantId: tenantId, 8 | clientId: clientId, 9 | clientSecret: clientSecret, 10 | scopes: scopes 11 | } -------------------------------------------------------------------------------- /samples/javascript/tasks/LargeFileUploadTask.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | // First, create an instance of the Microsoft Graph JS SDK Client class 8 | const { client } = require("../clientInitialization/ClientWithOptions"); 9 | /** 10 | * OR 11 | * const { client } = require("../clientInitialization/TokenCredentialAuthenticationProvider"); 12 | * OR 13 | * require or import client created using an custom authentication provider 14 | */ 15 | const fs = require("fs"); 16 | const { LargeFileUploadTask } = require("@microsoft/microsoft-graph-types"); 17 | require("isomorphic-fetch"); 18 | 19 | async function upload() { 20 | const fileName = "FILE_NAME"; 21 | const file = fs.createReadStream(`./${fileName}`); 22 | 23 | const stats = fs.statSync(`./${fileName}`); 24 | const totalSize = stats.size; 25 | 26 | const progress = (range, extraCallbackParam) => { 27 | // Implement the progress callback here 28 | console.log("uploading range: ", range); 29 | console.log(extraCallbackParam); 30 | }; 31 | 32 | const uploadEventHandlers = { 33 | progress, 34 | extraCallbackParam: "Any parameter needed by the callback implementation", 35 | }; 36 | 37 | const options = { 38 | rangeSize: 1024 * 1024, 39 | uploadEventHandlers, 40 | }; 41 | 42 | // Create upload session for OneDrive or SharePoint Upload" 43 | const payload = { 44 | item: { 45 | "@microsoft.graph.conflictBehavior": "rename", 46 | }, 47 | }; 48 | 49 | const uploadSession = await new LargeFileUploadTask.createUploadSession(client, "https://graph.microsoft.com/v1.0/sites/root/drive/items/{item-id}/createuploadsession", payload); 50 | 51 | // OR 52 | // Create upload session for Outlook API 53 | // const uploadSessionURL = `me/messages/${messageId}/attachments/createUploadSession`; 54 | // const payload = { 55 | // AttachmentItem: { 56 | // attachmentType: 'file', 57 | // name: "FILE_NAME", 58 | // size: totalSize, 59 | // } 60 | // } 61 | 62 | const fileObject = new StreamUpload(file, fileName, totalSize); 63 | 64 | // OR 65 | // You can also use a FileUpload instance 66 | // const file = fs.readFileSync(); 67 | // const fileObject = new FileUpload(file, fileName, totalSize); 68 | 69 | // OR 70 | // You can also create an object from a custom implementation of the FileObject interface 71 | const task = new MicrosoftGraph.LargeFileUploadTask(client, fileObject, uploadSession, options); 72 | const uploadResult = await task.upload(); 73 | return uploadResult; 74 | } 75 | 76 | upload() 77 | .then((uploadResult) => console.log(uploadResult)) 78 | .catch((error) => console.log(error)); 79 | -------------------------------------------------------------------------------- /samples/javascript/tasks/OneDriveLargeFileUploadTask.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | // First, create an instance of the Microsoft Graph JS SDK Client class. 9 | 10 | const { client } = require("../clientInitialization/ClientWithOptions"); 11 | /** 12 | * OR 13 | * const { client } = require("../clientInitialization/TokenCredentialAuthenticationProvider"); 14 | * OR 15 | * require or import client created using an custom authentication provider 16 | */ 17 | 18 | const fs = require("fs"); 19 | const { OneDriveLargeFileUploadTask, StreamUpload } = require("@microsoft/microsoft-graph-client"); 20 | require("isomorphic-fetch"); 21 | 22 | async function upload() { 23 | const fileName = "FILE_NAME"; 24 | const file = fs.createReadStream(`./${fileName}`); 25 | const totalsize = stats.size; 26 | 27 | const progress = (range, extraCallbackParam) => { 28 | // implement the progress callback here 29 | console.log("uploading range: ", range); 30 | console.log(extraCallbackParam); 31 | return true; 32 | }; 33 | 34 | const uploadEventHandlers = { 35 | progress, 36 | extraCallbackParam: "any parameter needed by the callback implementation", 37 | }; 38 | 39 | const options = { 40 | fileName, 41 | conflictBehavior: "rename", 42 | rangeSize: 1024 * 1024, 43 | uploadEventHandlers, 44 | }; 45 | 46 | const fileObject = new StreamUpload(file, fileName, totalsize); 47 | //OR 48 | // You can also use a FileUpload instance 49 | //const file = fs.readFileSync(); 50 | //const fileObject = new FileUpload(file, fileName, totalsize); 51 | 52 | //OR 53 | // You can also create an object from a custom implementation of the FileObject interface 54 | const task = await OneDriveLargeFileUploadTask.createTaskWithFileObject(client, fileObject, options); 55 | const uploadResult = await task.upload(); 56 | return uploadResult; 57 | } 58 | 59 | upload() 60 | .then((uploadResult) => console.log(uploadResult)) 61 | .catch((error) => console.log(error)); 62 | -------------------------------------------------------------------------------- /samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "samples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build:typescript": "tsc" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@azure/identity": "^3.1.2", 14 | "@microsoft/microsoft-graph-client": "file:../", 15 | "isomorphic-fetch": "^3.0.0", 16 | "ts-node": "^9.1.1", 17 | "typescript": "^4.2.4" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "strict": true, 6 | "outDir": "lib" 7 | }, 8 | "include": ["typescript/"] 9 | } 10 | -------------------------------------------------------------------------------- /samples/typescript/clientInitialization/ClientWithOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Client } from "@microsoft/microsoft-graph-client"; 9 | 10 | const error = "error throw by the authentication handler"; 11 | 12 | export const client = Client.init({ 13 | defaultVersion: "v1.0", 14 | debugLogging: true, 15 | authProvider: (done) => { 16 | done(error, "ACCESS_TOKEN"); 17 | }, 18 | }); 19 | 20 | // Following is the example of how to make requests to the Microsoft Graph API using the client instance 21 | 22 | client 23 | .api("/me") 24 | .select("displayName") 25 | .get() 26 | .then((res) => { 27 | console.log(res); 28 | }) 29 | .catch((err) => { 30 | console.log(err); 31 | }); 32 | -------------------------------------------------------------------------------- /samples/typescript/clientInitialization/tokenCredentialAuthenticationProvider/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | /* eslint-disable @typescript-eslint/no-unused-vars*/ 8 | 9 | import "isomorphic-fetch"; 10 | 11 | import { ClientSecretCredential } from "@azure/identity"; 12 | import { Client } from "@microsoft/microsoft-graph-client"; 13 | import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials"; 14 | 15 | const port = ""; 16 | const tenantId = ""; 17 | const clientId = ""; 18 | const clientSecret = ""; 19 | const scopes = ""; 20 | const redirectUri = `http://localhost:${port}/authresponse`; 21 | const authorityHost = "https://login.microsoftonline.com"; 22 | 23 | async function runExample() { 24 | const credential = new ClientSecretCredential(tenantId, clientId, clientSecret); 25 | const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: [scopes] }); 26 | const client = Client.initWithMiddleware({ 27 | debugLogging: true, 28 | authProvider, 29 | }); 30 | const res = await client.api("/users/").get(); 31 | console.log(res); 32 | } 33 | 34 | runExample().catch((err) => { 35 | console.log("Encountered an error:\n\n", err); 36 | }); 37 | -------------------------------------------------------------------------------- /samples/typescript/tasks/LargeFileUploadTask.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | /* eslint-disable @typescript-eslint/no-unused-vars*/ 8 | /* eslint-disable simple-import-sort/imports*/ 9 | 10 | // First, create an instance of the Microsoft Graph JS SDK Client class 11 | 12 | import { LargeFileUploadSession, LargeFileUploadTask, LargeFileUploadTaskOptions, Range, StreamUpload, UploadEventHandlers, UploadResult } from "@microsoft/microsoft-graph-client"; 13 | import * as fs from "fs"; 14 | import { client } from "../clientInitialization/ClientWithOptions"; 15 | /** 16 | * OR 17 | * import { client } from ("../clientInitialization/TokenCredentialAuthenticationProvider"); 18 | * OR 19 | * require or import client created using an custom authentication provider 20 | */ 21 | 22 | async function upload(): Promise { 23 | const file = fs.createReadStream("./test.pdf"); 24 | 25 | const stats = fs.statSync(`./test.pdf`); 26 | const totalSize = stats.size; 27 | 28 | const progress = (range?: Range, extraCallbackParam?: unknown) => { 29 | // Implement the progress callback here 30 | 31 | console.log("uploading range: ", range); 32 | console.log(extraCallbackParam); 33 | }; 34 | 35 | const uploadEventHandlers: UploadEventHandlers = { 36 | progress, 37 | extraCallbackParam: "any parameter needed by the callback implementation", 38 | }; 39 | 40 | const options: LargeFileUploadTaskOptions = { 41 | rangeSize: 1024 * 1024, 42 | uploadEventHandlers, 43 | }; 44 | 45 | // Create upload session for OneDrive or SharePoint Upload" 46 | const payload = { 47 | item: { 48 | "@microsoft.graph.conflictBehavior": "rename", 49 | }, 50 | }; 51 | 52 | const uploadSession: LargeFileUploadSession = await LargeFileUploadTask.createUploadSession(client, "https://graph.microsoft.com/v1.0/sites/root/drive/items/{item-id}/createuploadsession", payload); 53 | 54 | // OR 55 | // Create upload session for Outlook API 56 | // const uploadSessionURL = `me/messages/${messageId}/attachments/createUploadSession`; 57 | // const payload = { 58 | // AttachmentItem: { 59 | // attachmentType: 'file', 60 | // name: "FILE_NAME", 61 | // size: totalSize, 62 | // } 63 | // } 64 | 65 | const fileObject = new StreamUpload(file, "test.pdf", totalSize); 66 | 67 | // OR 68 | // You can also use a FileUpload instance 69 | // const file = fs.readFileSync(); 70 | // const fileObject = new FileUpload(file, 'test.pdf', totalSize); 71 | 72 | // OR 73 | // You can also create an object from a custom implementation of FileObject 74 | const task = new LargeFileUploadTask(client, fileObject, uploadSession, options); 75 | const uploadResult = await task.upload(); 76 | return uploadResult; 77 | } 78 | 79 | upload() 80 | .then((uploadResult) => console.log(uploadResult)) 81 | .catch((error) => console.log(error)); 82 | -------------------------------------------------------------------------------- /samples/typescript/tasks/OneDriveLargeFileUploadTask.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | // First, create an instance of the Microsoft Graph JS SDK Client class 9 | /* eslint-disable simple-import-sort/imports*/ 10 | 11 | import { OneDriveLargeFileUploadOptions, OneDriveLargeFileUploadTask, Range, StreamUpload, UploadEventHandlers, UploadResult } from "@microsoft/microsoft-graph-client"; 12 | import * as fs from "fs"; 13 | import { Readable } from "stream"; 14 | import { client } from "../clientInitialization/ClientWithOptions"; 15 | /** 16 | * OR 17 | * import { client } from ("../clientInitialization/TokenCredentialAuthenticationProvider"); 18 | * OR 19 | * require or import client created using an custom authentication provider 20 | */ 21 | 22 | async function upload() { 23 | const file = fs.createReadStream("./test.pdf"); 24 | const fileName = "FILENAME"; 25 | const fileDescription = "FILEDESCRIPTION"; 26 | const stats = fs.statSync(`./test.pdf`); 27 | const totalSize = stats.size; 28 | 29 | const progress = (range?: Range, extraCallBackParam?: unknown) => { 30 | console.log("uploading range: ", range); 31 | console.log(extraCallBackParam); 32 | return true; 33 | }; 34 | 35 | const uploadEventHandlers: UploadEventHandlers = { 36 | progress, 37 | extraCallbackParam: "any parameter needed by the callback implementation", 38 | }; 39 | 40 | const options: OneDriveLargeFileUploadOptions = { 41 | fileName, 42 | fileDescription, 43 | conflictBehavior: "rename", 44 | rangeSize: 1024 * 1024, 45 | uploadEventHandlers, 46 | }; 47 | 48 | const stream = new StreamUpload(file, "test.pdf", totalSize); 49 | const task = await OneDriveLargeFileUploadTask.createTaskWithFileObject(client, stream, options); 50 | const uploadResult: UploadResult = await task.upload(); 51 | return uploadResult; 52 | } 53 | 54 | upload() 55 | .then((uploadResult) => console.log(uploadResult)) 56 | .catch((error) => console.log(error)); 57 | -------------------------------------------------------------------------------- /scripts/src/AddGithubUser.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$gitUserName, 3 | [string]$gitUserEmailId, 4 | [string]$gitRepoRoot 5 | ) 6 | 7 | Write-Host "Configuring Github User:" -ForegroundColor Magenta; 8 | 9 | Set-Location -Path $gitRepoRoot; 10 | Write-Host "Location changed to Git Repo Root '$(Get-Location)'" -ForegroundColor Green; 11 | 12 | git config user.name $gitUserName 13 | git config user.email $gitUserEmailId 14 | Write-Host "Git user.name=$($gitUserName) and user.email=$($gitUserEmailId) is set." -ForegroundColor Green; -------------------------------------------------------------------------------- /scripts/src/CalculateNewPreviewVersion.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$previewStr 5 | ) 6 | 7 | Write-Host "Calculating new Preview Version:" -ForegroundColor Magenta; 8 | 9 | $newVersionStr; 10 | 11 | $releasesUrl = "https://api.github.com/repos/$($owner)/$($repo)/releases"; 12 | 13 | Write-Host "Getting list of releases with '$($releasesUrl)'" -ForegroundColor Blue; 14 | $releasesJSON = Invoke-RestMethod -Uri $releasesUrl -Method Get; 15 | 16 | if ($releasesJSON.Count -eq 0) { 17 | Write-Host "Unable to get releases list with '$($releasesUrl)'" -ForegroundColor Red; 18 | Write-Host "NOTE: This Script cannot handle the first release" -ForegroundColor Cyan; 19 | EXIT 1; 20 | } 21 | 22 | $lastReleaseJSON = $releasesJSON[0]; 23 | $lastReleaseVersionStr = $lastReleaseJSON.tag_name; 24 | $isPreRelease = $lastReleaseJSON.prerelease; 25 | 26 | if ([string]::IsNullOrEmpty($lastReleaseVersionStr)) { 27 | Write-Host "Unable read the last release tag name" -ForegroundColor Red; 28 | Write-Host "Last Release Data:" -ForegroundColor Cyan; 29 | Write-Host -Object $lastReleaseJSON -ForegroundColor Cyan; 30 | EXIT 1; 31 | } 32 | 33 | if ([string]::IsNullOrEmpty($isPreRelease)) { 34 | Write-Host "Unable read the last release is pre-release or not" -ForegroundColor Red; 35 | Write-Host "Last Release Data:" -ForegroundColor Cyan; 36 | Write-Host -Object $lastReleaseJSON -ForegroundColor Cyan; 37 | EXIT 1; 38 | } 39 | 40 | $isPreRelease = $isPreRelease -as [bool]; 41 | $versionArr = $lastReleaseVersionStr.split("."); 42 | if ($isPreRelease) { 43 | if (!$versionArr[2].Contains("-$($previewStr)")) { 44 | Write-Host "Lastest release '$($lastReleaseVersionStr)' is mentioned as pre-release but '$($previewStr)' is missing in version string" -ForegroundColor Red; 45 | Write-Host "Last Release Data:" -ForegroundColor Cyan; 46 | Write-Host -Object $lastReleaseJSON -ForegroundColor Cyan; 47 | EXIT 1; 48 | } 49 | $previewVersionStr = $versionArr[$versionArr.Count - 1]; 50 | $previewVersion = $previewVersionStr -as [int]; 51 | $newPreviewVersion = $previewVersion + 1; 52 | $versionArr[$versionArr.Count - 1] = $newPreviewVersion; 53 | $newVersionStr = $versionArr -join "."; 54 | Write-Host "Current version is '$($lastReleaseVersionStr)'" -ForegroundColor Blue; 55 | Write-Host "New calculated version is '$($newVersionStr)'" -ForegroundColor Green; 56 | } 57 | else { 58 | if ($versionArr[2].Contains("-$($previewStr)")) { 59 | Write-Host "Lastest release '$($lastReleaseVersionStr)' is mentioned as production release but version string has '$($previewStr)'" -ForegroundColor Red; 60 | Write-Host "Last Release Data:" -ForegroundColor Cyan; 61 | Write-Host -Object $lastReleaseJSON -ForegroundColor Cyan; 62 | EXIT 1; 63 | } 64 | $minorVersionStr = $versionArr[1]; 65 | $minorVersion = $minorVersionStr -as [int]; 66 | $newMinorVersion = $minorVersion + 1; 67 | $newPatchVersion = 0; 68 | $newPreviewVersion = 1; 69 | $versionArr[1] = $newMinorVersion; 70 | $versionArr[2] = "$($newPatchVersion)-$($previewStr).$($newPreviewVersion)"; 71 | $newVersionStr = $versionArr -join "."; 72 | Write-Host "Current version is '$($lastReleaseVersionStr)'" -ForegroundColor Blue; 73 | Write-Host "New calculated version is '$($newVersionStr)'" -ForegroundColor Green; 74 | } 75 | 76 | Write-Host "##vso[task.setvariable variable=NEW_VERSION_STRING]$($newVersionStr)"; 77 | 78 | Write-Host "Updated new version in global variable" -ForegroundColor Green; -------------------------------------------------------------------------------- /scripts/src/CalculateNewProductionVersion.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$previewStr 5 | ) 6 | 7 | Write-Host "Calculating new Production Version:" -ForegroundColor Magenta; 8 | 9 | $newVersionStr; 10 | 11 | $releasesUrl = "https://api.github.com/repos/$($owner)/$($repo)/releases"; 12 | 13 | Write-Host "Getting list of releases with '$($releasesUrl)'" -ForegroundColor Blue; 14 | $releasesJSON = Invoke-RestMethod -Uri $releasesUrl -Method Get; 15 | 16 | if ($releasesJSON.Count -eq 0) { 17 | Write-Host "Unable to get releases list with '$($releasesUrl)'" -ForegroundColor Red; 18 | Write-Host "NOTE: This Script cannot handle the first release" -ForegroundColor Cyan; 19 | EXIT 1; 20 | } 21 | 22 | $latestReleaseJSON = $releasesJSON[0]; 23 | $latestReleaseVersionStr = $latestReleaseJSON.tag_name; 24 | $isPreRelease = $latestReleaseJSON.prerelease; 25 | 26 | if ([string]::IsNullOrEmpty($latestReleaseVersionStr)) { 27 | Write-Host "Unable read the latest release tag name" -ForegroundColor Red; 28 | Write-Host "Latest Release Data:" -ForegroundColor Cyan; 29 | Write-Host -Object $latestReleaseJSON -ForegroundColor Cyan; 30 | EXIT 1; 31 | } 32 | 33 | if ([string]::IsNullOrEmpty($isPreRelease)) { 34 | Write-Host "Unable read the latest release is pre-release or not" -ForegroundColor Red; 35 | Write-Host "Latest Release Data:" -ForegroundColor Cyan; 36 | Write-Host -Object $latestReleaseJSON -ForegroundColor Cyan; 37 | EXIT 1; 38 | } 39 | 40 | $isPreRelease = $isPreRelease -as [bool]; 41 | 42 | if (!$isPreRelease) { 43 | Write-Host "Preview is not released for the latest changes in '$($branchName)' branch" -ForegroundColor Red; 44 | Write-Host "Latest Release Data:" -ForegroundColor Cyan; 45 | Write-Host -Object $latestReleaseJSON -ForegroundColor Cyan; 46 | EXIT 1; 47 | } 48 | 49 | $versionArr = $latestReleaseVersionStr.split("-"); 50 | 51 | if ([string]::IsNullOrEmpty($versionArr[1])) { 52 | Write-Host "Latest release is a Preview release but the '$($previewStr)' is missing in version string $($latestReleaseVersionStr)" -ForegroundColor Red; 53 | Write-Host "Latest Release Data:" -ForegroundColor Cyan; 54 | Write-Host -Object $latestReleaseJSON -ForegroundColor Cyan; 55 | EXIT 1; 56 | } 57 | 58 | $newVersionStr = $versionArr[0]; 59 | 60 | Write-Host "Current version is '$($latestReleaseVersionStr)'" -ForegroundColor Blue; 61 | Write-Host "New calculated version is '$($newVersionStr)'" -ForegroundColor Green; 62 | 63 | Write-Host "##vso[task.setvariable variable=NEW_VERSION_STRING]$($newVersionStr)"; 64 | 65 | Write-Host "Updated new version in global variable" -ForegroundColor Green; -------------------------------------------------------------------------------- /scripts/src/CommitAndPushChangesToGithub.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$branchName, 5 | [string]$newVersion, 6 | [string]$gitPat 7 | ) 8 | 9 | Write-Host "Pushing Version bump change to Github:" -ForegroundColor Magenta; 10 | 11 | Write-Host "Adding Changes." -ForegroundColor Blue; 12 | git add . | Write-Host; 13 | Write-Host "Changes added to the '$($branchName)' branch." -ForegroundColor Green; 14 | 15 | Write-Host "Committing Changes." -ForegroundColor Blue; 16 | git commit -m "Bumped version to '$($newVersion)'" | Write-Host; 17 | Write-Host "Committed the changes to the '$($branchName)' branch." -ForegroundColor Green; 18 | 19 | Write-Host "Pushing changes." -ForegroundColor Blue; 20 | git push "https://$($gitPat)@github.com/$($owner)/$($repo).git" HEAD:$branchName | Write-Host; 21 | Write-Host "Pushed the changes to the '$($branchName)' branch." -ForegroundColor Green; -------------------------------------------------------------------------------- /scripts/src/GetLatestCommitSHA.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$branchName 5 | ) 6 | 7 | Write-Host "Getting the latest commit SHA for $($branchName):" -ForegroundColor Magenta; 8 | 9 | $latestCommitUrl = "https://api.github.com/repos/$($owner)/$($repo)/commits/$($branchName)"; 10 | 11 | Write-Host "Getting latest commit with '$($latestCommitUrl)'" -ForegroundColor Blue; 12 | $latestCommitData = Invoke-RestMethod -Uri $latestCommitUrl -Method Get; 13 | 14 | if ($latestCommitData.Count -eq 0) { 15 | Write-Host "Unable to get latest commit with '$($latestCommitUrl)'" -ForegroundColor Red; 16 | EXIT 1; 17 | } 18 | 19 | if ([string]::IsNullOrEmpty($latestCommitData.sha)) { 20 | Write-Host "SHA is not present in the latest commit that is fetched" -ForegroundColor Red; 21 | Write-Host "Latest Commit Data:" -ForegroundColor Cyan; 22 | Write-Host -Object $latestCommitData -ForegroundColor Cyan; 23 | EXIT 1; 24 | } 25 | 26 | Write-Host "Latest Commit SHA is '$($latestCommitData.sha)'" -ForegroundColor Green; 27 | 28 | Write-Host "##vso[task.setvariable variable=LASTEST_COMMIT_SHA]$($latestCommitData.sha)"; 29 | 30 | Write-Host "Updated latest commit sha in global variable" -ForegroundColor Green; -------------------------------------------------------------------------------- /scripts/src/GetPackageVersion.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$gitRepoRoot 3 | ) 4 | 5 | Write-Host "Get package version and update it in the global varaible:" -ForegroundColor Magenta; 6 | 7 | $pathToPackageJson = "$($gitRepoRoot)/package.json"; 8 | $packageJson = Get-Content -Path $pathToPackageJson -Raw | ConvertFrom-Json; 9 | Write-Host "Package version is '$($packageJson.version)'" -ForegroundColor Green; 10 | 11 | Write-Host "##vso[task.setvariable variable=VERSION_STRING]$($packageJson.version)"; 12 | 13 | Write-Host "Updated version in global variable" -ForegroundColor Green; 14 | -------------------------------------------------------------------------------- /scripts/src/HasNewCommitsAfterLastRelease.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$branchName 5 | ) 6 | 7 | Write-Host "Checking for availability of new commits after last release:" -ForegroundColor Magenta; 8 | $releasesUrl = "https://api.github.com/repos/$($owner)/$($repo)/releases"; 9 | 10 | Write-Host "Getting list of releases with '$($releasesUrl)'" -ForegroundColor Blue; 11 | $releasesJSON = Invoke-RestMethod -Uri $releasesUrl -Method Get; 12 | 13 | if ($releasesJSON.Count -eq 0) { 14 | Write-Host "Unable to get releases list with '$($releasesUrl)'" -ForegroundColor Red; 15 | Write-Host "NOTE: This Script cannot handle the first release!" -ForegroundColor Cyan; 16 | EXIT 1; 17 | } 18 | 19 | $lastReleaseJSON = $releasesJSON[0]; 20 | $publishedTime = $lastReleaseJSON.published_at; 21 | $lastReleaseTag = $lastReleaseJSON.tag_name; 22 | 23 | if ([string]::IsNullOrEmpty($publishedTime)) { 24 | Write-Host "Unable read the last release published time" -ForegroundColor Red; 25 | Write-Host "Last Release Data:" -ForegroundColor Red; 26 | Write-Host -Object $lastReleaseJSON -ForegroundColor Red; 27 | EXIT 1; 28 | } 29 | 30 | if ([string]::IsNullOrEmpty($lastReleaseTag)) { 31 | Write-Host "Unable read the last release tag name" -ForegroundColor Red; 32 | Write-Host "Last Release Data:" -ForegroundColor Red; 33 | Write-Host -Object $lastReleaseJSON -ForegroundColor Red; 34 | EXIT 1; 35 | } 36 | 37 | $newCommitsUrl = "https://api.github.com/repos/$($owner)/$($repo)/commits?sha=$($branchName)&since=$($publishedTime)"; 38 | 39 | Write-Host "Getting commits after last release with '$($newCommitsUrl)'" -ForegroundColor Blue; 40 | $newCommitsJSON = Invoke-RestMethod -Uri $newCommitsUrl -Method Get; 41 | 42 | if ($newCommitsJSON.Count -gt 0) { 43 | Write-Host "There are atleast '$($newCommitsJSON.Length)' Commits in '$($branchName)' branch after last release with tag $'($lastReleaseTag)'" -ForegroundColor Green; 44 | EXIT 0; 45 | } 46 | else { 47 | Write-Host "Unable to get commits after last release with '$($newCommitsUrl)'" -ForegroundColor Red; 48 | Write-Host "NOTE: Possibly, there are no commits in '$($branchName)' branch after last release with tag '$($lastReleaseTag)'" -ForegroundColor Cyan; 49 | Write-Host "To verify there are not commits, make a request by pasting '$($newCommitsUrl)' in your browser" -ForegroundColor Cyan; 50 | EXIT 1; 51 | } -------------------------------------------------------------------------------- /scripts/src/MergeChangesTillLastestRelease.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$branchName, 5 | [string]$gitPat 6 | ) 7 | Write-Host "Merge and Commit the changes into '$($branchName)' till last release:" -ForegroundColor Magenta; 8 | 9 | Write-Host "Checking out '$($branchName)'" -ForegroundColor Blue; 10 | git checkout main | Write-Host; 11 | Write-Host "Checked out" -ForegroundColor Green; 12 | 13 | Write-Host "Pulling '$($branchName)'" -ForegroundColor Blue; 14 | git pull origin main --allow-unrelated-histories | Write-Host; 15 | Write-Host "Pulled '$($branchName)'" -ForegroundColor Green; 16 | 17 | Write-Host "Getting SHA for last commit in the latest release" -ForegroundColor Blue; 18 | $latestReleaseCommitSHA = git rev-list --tags --max-count=1; 19 | 20 | if([string]::IsNullOrEmpty($latestReleaseCommitSHA)) { 21 | Write-Host "Unable to get the SHA for last commit in latest release" -ForegroundColor Red; 22 | EXIT 1; 23 | } 24 | 25 | Write-Host "SHA for last commit in the latest release is '$($latestReleaseCommitSHA)'" -ForegroundColor Green; 26 | 27 | Write-Host "Merging Changes till '$($latestReleaseCommitSHA)'" -ForegroundColor Blue; 28 | git merge $latestReleaseCommitSHA | Write-Host; 29 | 30 | Write-Host "Checking Conflicted Files"; 31 | $conflictedFiles = git diff --name-only --diff-filter=U; 32 | 33 | if (-Not [string]::IsNullOrEmpty($conflictedFiles)) { 34 | Write-Host "Unable to Merge" -ForegroundColor Red; 35 | Write-Host "There are conflicts in below files:" -ForegroundColor Cyan; 36 | Write-Host -Object $conflictedFiles -ForegroundColor Cyan; 37 | EXIT 1; 38 | } 39 | 40 | Write-Host "Merged changes to '$($branchName)'" -ForegroundColor Green; 41 | 42 | Write-Host "Pushing changes." -ForegroundColor Blue; 43 | git push "https://$($gitPat)@github.com/$($owner)/$($repo).git" HEAD:$branchName | Write-Host; 44 | Write-Host "Pushed changes to the $($branchName) branch." -ForegroundColor Green; 45 | -------------------------------------------------------------------------------- /scripts/src/MergeVersionChangesBackToPreviewBranch.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$owner, 3 | [string]$repo, 4 | [string]$branchName, 5 | [string]$previewBranchName, 6 | [string]$gitPat 7 | ) 8 | 9 | Write-Host "Merge and Commit the version changes from '$($branchName)' to '$($previewBranchName)':" -ForegroundColor Magenta; 10 | 11 | Write-Host "Starting checkout '$($previewBranchName)'" -ForegroundColor Blue; 12 | git checkout $previewBranchName | Write-Host; 13 | Write-Host "Checked out '$($previewBranchName)'" -ForegroundColor Green; 14 | 15 | Write-Host "Merging the changes from '$($branchName)' to '$($previewBranchName)'" -ForegroundColor Blue; 16 | git merge $branchName | Write-Host; 17 | 18 | $conflictedFiles = git diff --name-only --diff-filter=U; 19 | 20 | if (-Not ([string]::IsNullOrEmpty($conflictedFiles))) { 21 | Write-Host "Unable to Merge" -ForegroundColor Red; 22 | Write-Host "There are conflicts in below files:" -ForegroundColor Cyan; 23 | Write-Host -Object $conflictedFiles -ForegroundColor Cyan; 24 | EXIT 1; 25 | } 26 | 27 | Write-Host "Merged changes from '$($branchName)' to '$($previewBranchName)'" -ForegroundColor Green; 28 | 29 | Write-Host "Pushing changes." -ForegroundColor Blue; 30 | git push "https://$($gitPat)@github.com/$($owner)/$($repo).git" HEAD:$previewBranchName | Write-Host 31 | Write-Host "Pushed changes to the '$($previewBranchName)' branch." -ForegroundColor Green; 32 | -------------------------------------------------------------------------------- /scripts/src/RemoveGithubUser.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$gitRepoRoot 3 | ) 4 | 5 | Write-Host "Removing Github User:" -ForegroundColor Magenta; 6 | 7 | Set-Location -Path $gitRepoRoot; 8 | Write-Host "Location changed to Git Repo Root $(Get-Location)" -ForegroundColor Green; 9 | 10 | git config --unset user.name 11 | git config --unset user.email 12 | Write-Host "Git user.name and user.email is unset." -ForegroundColor Green; -------------------------------------------------------------------------------- /shims.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * Shim for Node stream interface. 10 | */ 11 | interface NodeStream { 12 | /** 13 | * Shim for Node stream interface when the environment does not use @types/node. 14 | * Using @types/node appends the ambient Node definition to the global scope which is not desirable. 15 | * https://github.com/microsoftgraph/msgraph-sdk-javascript/issues/600 16 | */ 17 | readable: boolean; 18 | readableLength: number; 19 | read(size?: number): any; 20 | on(event: string | symbol, listener: (...args: any[]) => void): this; 21 | } 22 | 23 | interface Headers{} -------------------------------------------------------------------------------- /src/Constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module Constants 10 | */ 11 | 12 | /** 13 | * @constant 14 | * A Default API endpoint version for a request 15 | */ 16 | export const GRAPH_API_VERSION = "v1.0"; 17 | 18 | /** 19 | * @constant 20 | * A Default base url for a request 21 | */ 22 | export const GRAPH_BASE_URL = "https://graph.microsoft.com/"; 23 | 24 | /** 25 | * To hold list of the service root endpoints for Microsoft Graph and Graph Explorer for each national cloud. 26 | * Set(iterable:Object) is not supported in Internet Explorer. The consumer is recommended to use a suitable polyfill. 27 | */ 28 | export const GRAPH_URLS = new Set(["graph.microsoft.com", "graph.microsoft.us", "dod-graph.microsoft.us", "graph.microsoft.de", "microsoftgraph.chinacloudapi.cn", "canary.graph.microsoft.com"]); 29 | -------------------------------------------------------------------------------- /src/CustomAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module CustomAuthenticationProvider 10 | */ 11 | 12 | import { GraphClientError } from "./GraphClientError"; 13 | import { AuthenticationProvider } from "./IAuthenticationProvider"; 14 | import { AuthProvider } from "./IAuthProvider"; 15 | 16 | /** 17 | * @class 18 | * Class representing CustomAuthenticationProvider 19 | * @extends AuthenticationProvider 20 | */ 21 | export class CustomAuthenticationProvider implements AuthenticationProvider { 22 | /** 23 | * @private 24 | * A member to hold authProvider callback 25 | */ 26 | private provider: AuthProvider; 27 | 28 | /** 29 | * @public 30 | * @constructor 31 | * Creates an instance of CustomAuthenticationProvider 32 | * @param {AuthProviderCallback} provider - An authProvider function 33 | * @returns An instance of CustomAuthenticationProvider 34 | */ 35 | public constructor(provider: AuthProvider) { 36 | this.provider = provider; 37 | } 38 | 39 | /** 40 | * @public 41 | * @async 42 | * To get the access token 43 | * @returns The promise that resolves to an access token 44 | */ 45 | public async getAccessToken(): Promise { 46 | return new Promise((resolve: (accessToken: string) => void, reject: (error: any) => void) => { 47 | this.provider(async (error: any, accessToken: string | null) => { 48 | if (accessToken) { 49 | resolve(accessToken); 50 | } else { 51 | if (!error) { 52 | const invalidTokenMessage = "Access token is undefined or empty.\ 53 | Please provide a valid token.\ 54 | For more help - https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CustomAuthenticationProvider.md"; 55 | error = new GraphClientError(invalidTokenMessage); 56 | } 57 | const err = await GraphClientError.setGraphClientError(error); 58 | reject(err); 59 | } 60 | }); 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/GraphClientError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module GraphClientError 10 | */ 11 | 12 | /** 13 | * @class 14 | * Create GraphClientError object to handle client-side errors 15 | * encountered within the JavaScript Client SDK. 16 | * Whereas GraphError Class should be used to handle errors in the response from the Graph API. 17 | */ 18 | 19 | export class GraphClientError extends Error { 20 | /** 21 | * @public 22 | * A custom error. This property should set be when the error is not of instanceOf Error/GraphClientError. 23 | * Example = 24 | * const client = MicrosoftGraph.Client.init({ 25 | * defaultVersion: "v1.0", 26 | * authProvider: (done) => { done({TokenError:"AccessToken cannot be null"}, ""); 27 | * }); 28 | */ 29 | public customError?: any; 30 | 31 | /** 32 | * @public 33 | * @static 34 | * @async 35 | * To set the GraphClientError object 36 | * @param {any} error - The error returned encountered by the Graph JavaScript Client SDK while processing request 37 | * @returns GraphClientError object set to the error passed 38 | */ 39 | public static setGraphClientError(error: any): GraphClientError { 40 | let graphClientError: GraphClientError; 41 | if (error instanceof Error) { 42 | graphClientError = error; 43 | } else { 44 | graphClientError = new GraphClientError(); 45 | graphClientError.customError = error; 46 | } 47 | return graphClientError; 48 | } 49 | 50 | /** 51 | * @public 52 | * @constructor 53 | * Creates an instance of GraphClientError 54 | * @param {string} message? - Error message 55 | * @returns An instance of GraphClientError 56 | */ 57 | public constructor(message?: string) { 58 | super(message); 59 | Object.setPrototypeOf(this, GraphClientError.prototype); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/GraphError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module GraphError 10 | */ 11 | 12 | /** 13 | * @class 14 | * Class for GraphError 15 | * @NOTE: This is NOT what is returned from the Graph 16 | * GraphError is created from parsing JSON errors returned from the graph 17 | * Some fields are renamed ie, "request-id" => requestId so you can use dot notation 18 | */ 19 | 20 | export class GraphError extends Error { 21 | /** 22 | * @public 23 | * A member holding status code of the error 24 | */ 25 | public statusCode: number; 26 | 27 | /** 28 | * @public 29 | * A member holding code i.e name of the error 30 | */ 31 | public code: string | null; 32 | 33 | /** 34 | * @public 35 | * A member holding request-id i.e identifier of the request 36 | */ 37 | public requestId: string | null; 38 | 39 | /** 40 | * @public 41 | * A member holding processed date and time of the request 42 | */ 43 | public date: Date; 44 | 45 | public headers?: Headers; 46 | 47 | /** 48 | * @public 49 | * A member holding original error response by the graph service 50 | */ 51 | public body: any; 52 | 53 | /** 54 | * @public 55 | * @constructor 56 | * Creates an instance of GraphError 57 | * @param {number} [statusCode = -1] - The status code of the error 58 | * @param {string} [message] - The message of the error 59 | * @param {Error} [baseError] - The base error 60 | * @returns An instance of GraphError 61 | */ 62 | public constructor(statusCode = -1, message?: string, baseError?: Error) { 63 | super(message || (baseError && baseError.message)); 64 | // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work 65 | Object.setPrototypeOf(this, GraphError.prototype); 66 | this.statusCode = statusCode; 67 | this.code = null; 68 | this.requestId = null; 69 | this.date = new Date(); 70 | this.body = null; 71 | this.stack = baseError ? baseError.stack : this.stack; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/HTTPClient.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module HTTPClient 10 | */ 11 | 12 | import { Context } from "./IContext"; 13 | import { Middleware } from "./middleware/IMiddleware"; 14 | 15 | /** 16 | * @class 17 | * Class representing HTTPClient 18 | */ 19 | export class HTTPClient { 20 | /** 21 | * @private 22 | * A member holding first middleware of the middleware chain 23 | */ 24 | private middleware: Middleware; 25 | 26 | /** 27 | * @public 28 | * @constructor 29 | * Creates an instance of a HTTPClient 30 | * @param {...Middleware} middleware - The first middleware of the middleware chain or a sequence of all the Middleware handlers 31 | */ 32 | public constructor(...middleware: Middleware[]) { 33 | if (!middleware || !middleware.length) { 34 | const error = new Error(); 35 | error.name = "InvalidMiddlewareChain"; 36 | error.message = "Please provide a default middleware chain or custom middleware chain"; 37 | throw error; 38 | } 39 | this.setMiddleware(...middleware); 40 | } 41 | 42 | /** 43 | * @private 44 | * Processes the middleware parameter passed to set this.middleware property 45 | * The calling function should validate if middleware is not undefined or not empty. 46 | * @param {...Middleware} middleware - The middleware passed 47 | * @returns Nothing 48 | */ 49 | private setMiddleware(...middleware: Middleware[]): void { 50 | if (middleware.length > 1) { 51 | this.parseMiddleWareArray(middleware); 52 | } else { 53 | this.middleware = middleware[0]; 54 | } 55 | } 56 | 57 | /** 58 | * @private 59 | * Processes the middleware array to construct the chain 60 | * and sets this.middleware property to the first middleware handler of the array 61 | * The calling function should validate if middleware is not undefined or not empty 62 | * @param {Middleware[]} middlewareArray - The array of middleware handlers 63 | * @returns Nothing 64 | */ 65 | private parseMiddleWareArray(middlewareArray: Middleware[]) { 66 | middlewareArray.forEach((element, index) => { 67 | if (index < middlewareArray.length - 1) { 68 | element.setNext(middlewareArray[index + 1]); 69 | } 70 | }); 71 | this.middleware = middlewareArray[0]; 72 | } 73 | 74 | /** 75 | * @public 76 | * @async 77 | * To send the request through the middleware chain 78 | * @param {Context} context - The context of a request 79 | * @returns A promise that resolves to the Context 80 | */ 81 | public async sendRequest(context: Context): Promise { 82 | if (typeof context.request === "string" && context.options === undefined) { 83 | const error = new Error(); 84 | error.name = "InvalidRequestOptions"; 85 | error.message = "Unable to execute the middleware, Please provide valid options for a request"; 86 | throw error; 87 | } 88 | await this.middleware.execute(context); 89 | return context; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/IAuthProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { AuthProviderCallback } from "./IAuthProviderCallback"; 9 | 10 | /** 11 | * @interface 12 | * Signature that holds authProvider 13 | * @callback - The anonymous callback function which takes a single param 14 | */ 15 | export type AuthProvider = (done: AuthProviderCallback) => void; 16 | -------------------------------------------------------------------------------- /src/IAuthProviderCallback.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @interface 10 | * Signature that defines callback for an authentication provider 11 | * @callback - The anonymous callback function which takes two params 12 | */ 13 | export type AuthProviderCallback = (error: any, accessToken: string | null) => void; 14 | -------------------------------------------------------------------------------- /src/IAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { AuthenticationProviderOptions } from "./IAuthenticationProviderOptions"; 9 | 10 | /** 11 | * @interface 12 | * A signature representing Authentication provider 13 | * @property {Function} getAccessToken - The function to get the access token from the authentication provider 14 | */ 15 | export interface AuthenticationProvider { 16 | /** 17 | * To get access token from the authentication provider 18 | * @param {AuthenticationProviderOptions} [authenticationProviderOptions] - The authentication provider options instance 19 | * @returns A promise that resolves to an access token 20 | */ 21 | getAccessToken: (authenticationProviderOptions?: AuthenticationProviderOptions) => Promise; 22 | } 23 | -------------------------------------------------------------------------------- /src/IAuthenticationProviderOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @interface 10 | * A signature represents the Authentication provider options 11 | * @property {string[]} [scopes] - The array of scopes 12 | */ 13 | export interface AuthenticationProviderOptions { 14 | scopes?: string[]; 15 | } 16 | -------------------------------------------------------------------------------- /src/IClientOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { AuthenticationProvider } from "./IAuthenticationProvider"; 9 | import { FetchOptions } from "./IFetchOptions"; 10 | import { Middleware } from "./middleware/IMiddleware"; 11 | 12 | /** 13 | * @interface 14 | * Options for initializing the Graph Client 15 | * @property {Function} [authProvider] - The authentication provider instance 16 | * @property {string} [baseUrl] - Base url that needs to be appended to every request 17 | * @property {boolean} [debugLogging] - The boolean to enable/disable debug logging 18 | * @property {string} [defaultVersion] - The default version that needs to be used while making graph api request 19 | * @property {FetchOptions} [fetchOptions] - The options for fetch request 20 | * @property {Middleware| Middleware[]} [middleware] - The first middleware of the middleware chain or an array of the Middleware handlers 21 | * @property {Set}[customHosts] - A set of custom host names. Should contain hostnames only. 22 | */ 23 | 24 | export interface ClientOptions { 25 | authProvider?: AuthenticationProvider; 26 | baseUrl?: string; 27 | debugLogging?: boolean; 28 | defaultVersion?: string; 29 | fetchOptions?: FetchOptions; 30 | middleware?: Middleware | Middleware[]; 31 | /** 32 | * Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set(["test_host"])" 33 | */ 34 | customHosts?: Set; 35 | } 36 | -------------------------------------------------------------------------------- /src/IContext.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { FetchOptions } from "./IFetchOptions"; 9 | import { MiddlewareControl } from "./middleware/MiddlewareControl"; 10 | 11 | /** 12 | * @interface 13 | * @property {RequestInfo} request - The request url string or the Request instance 14 | * @property {FetchOptions} [options] - The options for the request 15 | * @property {Response} [response] - The response content 16 | * @property {MiddlewareControl} [middlewareControl] - The options for the middleware chain 17 | * @property {Set}[customHosts] - A set of custom host names. Should contain hostnames only. 18 | * 19 | */ 20 | 21 | export interface Context { 22 | request: RequestInfo; 23 | options?: FetchOptions; 24 | response?: Response; 25 | middlewareControl?: MiddlewareControl; 26 | /** 27 | * Example - If URL is "https://test_host", then set property "customHosts" as "customHosts: Set(["test_host"])" 28 | */ 29 | customHosts?: Set; 30 | } 31 | -------------------------------------------------------------------------------- /src/IFetchOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @interface {@link https://github.com/bitinn/node-fetch/#options} 10 | * Signature to define the fetch request options for node environment 11 | * @property {number} [follow] - node-fetch option: maximum redirect count. 0 to not follow redirect 12 | * @property {number} [compress] - node-fetch option: support gzip/deflate content encoding. false to disable 13 | * @property {number} [size] - node-fetch option: maximum response body size in bytes. 0 to disable 14 | * @property {any} [agent] - node-fetch option: HTTP(S).Agent instance, allows custom proxy, certificate, lookup, family etc. 15 | * @property {number} [highWaterMark] - node-fetch option: maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. 16 | * @property {boolean} [insecureHTTPParser] - node-fetch option: use an insecure HTTP parser that accepts invalid HTTP headers when `true`. 17 | */ 18 | export interface NodeFetchInit { 19 | follow?: number; 20 | compress?: boolean; 21 | size?: number; 22 | agent?: any; 23 | highWaterMark?: number; 24 | insecureHTTPParser?: boolean; 25 | } 26 | 27 | /** 28 | * @interface 29 | * Signature to define the fetch api options which includes both fetch standard options and also the extended node fetch options 30 | * @extends RequestInit @see {@link https://fetch.spec.whatwg.org/#requestinit} 31 | * @extends NodeFetchInit 32 | */ 33 | export interface FetchOptions extends RequestInit, NodeFetchInit {} 34 | -------------------------------------------------------------------------------- /src/IGraphRequestCallback.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { GraphError } from "./GraphError"; 9 | /** 10 | * @interface 11 | * Signature to define the GraphRequest callback 12 | * @callback - The anonymous callback function 13 | */ 14 | export type GraphRequestCallback = (error: GraphError, response: any, rawResponse?: any) => void; 15 | -------------------------------------------------------------------------------- /src/IOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { AuthProvider } from "./IAuthProvider"; 9 | import { FetchOptions } from "./IFetchOptions"; 10 | 11 | /** 12 | * @interface 13 | * Options for initializing the Graph Client 14 | * @property {AuthProvider} authProvider - The function to get the authentication token 15 | * @property {string} [baseUrl] - Base url that needs to be appended to every request 16 | * @property {boolean} [debugLogging] - The boolean to enable/disable debug logging 17 | * @property {string} [defaultVersion] - The default version that needs to be used while making graph api request 18 | * @property {FetchOptions} [fetchOptions] - The options for fetch request 19 | * @property {Set}[customHosts] - A set of custom host names. Should contain hostnames only. 20 | */ 21 | export interface Options { 22 | authProvider: AuthProvider; 23 | baseUrl?: string; 24 | debugLogging?: boolean; 25 | defaultVersion?: string; 26 | fetchOptions?: FetchOptions; 27 | /** 28 | * Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set(["test_host"])" 29 | */ 30 | customHosts?: Set; 31 | } 32 | -------------------------------------------------------------------------------- /src/RequestMethod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @enum 10 | * Enum for RequestMethods 11 | * @property {string} GET - The get request type 12 | * @property {string} PATCH - The patch request type 13 | * @property {string} POST - The post request type 14 | * @property {string} PUT - The put request type 15 | * @property {string} DELETE - The delete request type 16 | */ 17 | export enum RequestMethod { 18 | GET = "GET", 19 | PATCH = "PATCH", 20 | POST = "POST", 21 | PUT = "PUT", 22 | DELETE = "DELETE", 23 | } 24 | -------------------------------------------------------------------------------- /src/ResponseType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @enum 10 | * Enum for ResponseType values 11 | * @property {string} ARRAYBUFFER - To download response content as an [ArrayBuffer]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer} 12 | * @property {string} BLOB - To download content as a [binary/blob] {@link https://developer.mozilla.org/en-US/docs/Web/API/Blob} 13 | * @property {string} DOCUMENT - This downloads content as a document or stream 14 | * @property {string} JSON - To download response content as a json 15 | * @property {string} STREAM - To download response as a [stream]{@link https://nodejs.org/api/stream.html} 16 | * @property {string} TEXT - For downloading response as a text 17 | */ 18 | 19 | export enum ResponseType { 20 | ARRAYBUFFER = "arraybuffer", 21 | BLOB = "blob", 22 | DOCUMENT = "document", 23 | JSON = "json", 24 | RAW = "raw", 25 | STREAM = "stream", 26 | TEXT = "text", 27 | } 28 | -------------------------------------------------------------------------------- /src/ValidatePolyFilling.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @constant 10 | * @function 11 | * Validates availability of Promise and fetch in global context 12 | * @returns The true in case the Promise and fetch available, otherwise throws error 13 | */ 14 | 15 | export const validatePolyFilling = (): boolean => { 16 | if (typeof Promise === "undefined" && typeof fetch === "undefined") { 17 | const error = new Error("Library cannot function without Promise and fetch. So, please provide polyfill for them."); 18 | error.name = "PolyFillNotAvailable"; 19 | throw error; 20 | } else if (typeof Promise === "undefined") { 21 | const error = new Error("Library cannot function without Promise. So, please provide polyfill for it."); 22 | error.name = "PolyFillNotAvailable"; 23 | throw error; 24 | } else if (typeof fetch === "undefined") { 25 | const error = new Error("Library cannot function without fetch. So, please provide polyfill for it."); 26 | error.name = "PolyFillNotAvailable"; 27 | throw error; 28 | } 29 | return true; 30 | }; 31 | -------------------------------------------------------------------------------- /src/Version.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | // THIS FILE IS AUTO GENERATED 9 | // ANY CHANGES WILL BE LOST DURING BUILD 10 | 11 | /** 12 | * @module Version 13 | */ 14 | 15 | export const PACKAGE_VERSION = "3.0.7"; 16 | -------------------------------------------------------------------------------- /src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | import { GetTokenOptions } from "@azure/identity"; 8 | 9 | import { AuthenticationProviderOptions } from "../../IAuthenticationProviderOptions"; 10 | 11 | /** 12 | * @interface 13 | * A signature represents the Authentication provider options for Token Credentials 14 | * @property {getTokenOptions} [GetTokenOptions] - Defines options for TokenCredential.getToken. 15 | */ 16 | export interface TokenCredentialAuthenticationProviderOptions extends AuthenticationProviderOptions { 17 | getTokenOptions?: GetTokenOptions; 18 | } 19 | -------------------------------------------------------------------------------- /src/authentication/azureTokenCredentials/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export type { TokenCredentialAuthenticationProviderOptions } from "./ITokenCredentialAuthenticationProviderOptions"; 8 | export { TokenCredentialAuthenticationProvider } from "./TokenCredentialAuthenticationProvider"; 9 | -------------------------------------------------------------------------------- /src/authentication/msal-browser/AuthCodeMSALBrowserAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module AuthCodeMSALBrowserAuthenticationProvider 10 | */ 11 | 12 | import { AuthenticationResult, InteractionRequiredAuthError, InteractionType, PublicClientApplication } from "@azure/msal-browser"; 13 | 14 | import { GraphClientError } from "../../GraphClientError"; 15 | import { AuthenticationProvider } from "../../IAuthenticationProvider"; 16 | import { AuthCodeMSALBrowserAuthenticationProviderOptions } from "../msalOptions/MSALAuthenticationProviderOptions"; 17 | 18 | /** 19 | * an AuthenticationProvider implementation supporting msal-browser library. 20 | * This feature is introduced in Version 3.0.0 21 | * @class 22 | * @extends AuthenticationProvider 23 | */ 24 | export class AuthCodeMSALBrowserAuthenticationProvider implements AuthenticationProvider { 25 | /** 26 | * @public 27 | * @constructor 28 | * Creates an instance of ImplicitMSALAuthenticationProvider 29 | * @param {PublicClientApplication} msalApplication - An instance of MSAL PublicClientApplication 30 | * @param {AuthCodeMSALBrowserAuthenticationProviderOptions} options - An instance of MSALAuthenticationProviderOptions 31 | * @returns An instance of ImplicitMSALAuthenticationProvider 32 | */ 33 | public constructor(private publicClientApplication: PublicClientApplication, private options: AuthCodeMSALBrowserAuthenticationProviderOptions) { 34 | if (!options || !publicClientApplication) { 35 | throw new GraphClientError("Please pass valid PublicClientApplication instance and AuthCodeMSALBrowserAuthenticationProviderOptions instance to instantiate MSALBrowserAuthenticationProvider"); 36 | } 37 | } 38 | 39 | /** 40 | * @public 41 | * @async 42 | * To get the access token for the request 43 | * @returns The promise that resolves to an access token 44 | */ 45 | public async getAccessToken(): Promise { 46 | const scopes = this.options && this.options.scopes; 47 | const account = this.options && this.options.account; 48 | const error = new GraphClientError(); 49 | if (!scopes || scopes.length === 0) { 50 | error.name = "Empty Scopes"; 51 | error.message = "Scopes cannot be empty, Please provide scopes"; 52 | throw error; 53 | } 54 | try { 55 | const response: AuthenticationResult = await this.publicClientApplication.acquireTokenSilent({ 56 | scopes, 57 | account, 58 | }); 59 | if (!response || !response.accessToken) { 60 | error.name = "Access token is undefined"; 61 | error.message = "Received empty access token from PublicClientApplication"; 62 | throw error; 63 | } 64 | return response.accessToken; 65 | } catch (error) { 66 | if (error instanceof InteractionRequiredAuthError) { 67 | if (this.options.interactionType === InteractionType.Redirect) { 68 | this.publicClientApplication.acquireTokenRedirect({ scopes }); 69 | } else if (this.options.interactionType === InteractionType.Popup) { 70 | const response: AuthenticationResult = await this.publicClientApplication.acquireTokenPopup({ scopes }); 71 | return response.accessToken; 72 | } 73 | } else { 74 | throw error; 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/authentication/msal-browser/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | export { AuthCodeMSALBrowserAuthenticationProvider } from "./AuthCodeMSALBrowserAuthenticationProvider"; 8 | -------------------------------------------------------------------------------- /src/authentication/msalOptions/MSALAuthenticationProviderOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module MSALAuthenticationProviderOptions 10 | */ 11 | 12 | import { AccountInfo, InteractionType } from "@azure/msal-browser"; 13 | 14 | import { AuthenticationProviderOptions } from "../../IAuthenticationProviderOptions"; 15 | 16 | export interface AuthCodeMSALBrowserAuthenticationProviderOptions extends AuthenticationProviderOptions { 17 | scopes: string[]; 18 | account: AccountInfo; 19 | interactionType: InteractionType; 20 | } 21 | -------------------------------------------------------------------------------- /src/middleware/HTTPMessageHandler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module HTTPMessageHandler 10 | */ 11 | 12 | import { Context } from "../IContext"; 13 | import { Middleware } from "./IMiddleware"; 14 | 15 | /** 16 | * @class 17 | * @implements Middleware 18 | * Class for HTTPMessageHandler 19 | */ 20 | export class HTTPMessageHandler implements Middleware { 21 | /** 22 | * @public 23 | * @async 24 | * To execute the current middleware 25 | * @param {Context} context - The request context object 26 | * @returns A promise that resolves to nothing 27 | */ 28 | public async execute(context: Context): Promise { 29 | context.response = await fetch(context.request, context.options); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/middleware/IMiddleware.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Context } from "../IContext"; 9 | 10 | /** 11 | * @interface 12 | * @property {Function} execute - The method to execute the middleware 13 | * @property {Function} [setNext] - A method to set the next middleware in the chain 14 | */ 15 | export interface Middleware { 16 | execute: (context: Context) => Promise; 17 | setNext?: (middleware: Middleware) => void; 18 | } 19 | -------------------------------------------------------------------------------- /src/middleware/MiddlewareControl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module MiddlewareControl 10 | */ 11 | 12 | import { MiddlewareOptions } from "./options/IMiddlewareOptions"; 13 | 14 | /** 15 | * @class 16 | * Class representing MiddlewareControl 17 | */ 18 | export class MiddlewareControl { 19 | /** 20 | * @private 21 | * A member holding map of MiddlewareOptions 22 | */ 23 | private middlewareOptions: Map; 24 | 25 | /** 26 | * @public 27 | * @constructor 28 | * Creates an instance of MiddlewareControl 29 | * @param {MiddlewareOptions[]} [middlewareOptions = []] - The array of middlewareOptions 30 | * @returns The instance of MiddlewareControl 31 | */ 32 | public constructor(middlewareOptions: MiddlewareOptions[] = []) { 33 | this.middlewareOptions = new Map(); 34 | for (const option of middlewareOptions) { 35 | const fn = option.constructor; 36 | this.middlewareOptions.set(fn, option); 37 | } 38 | } 39 | 40 | /** 41 | * @public 42 | * To get the middleware option using the class of the option 43 | * @param {Function} fn - The class of the strongly typed option class 44 | * @returns The middleware option 45 | * @example 46 | * // if you wanted to return the middleware option associated with this class (MiddlewareControl) 47 | * // call this function like this: 48 | * getMiddlewareOptions(MiddlewareControl) 49 | */ 50 | public getMiddlewareOptions(fn: Function): MiddlewareOptions { 51 | return this.middlewareOptions.get(fn); 52 | } 53 | 54 | /** 55 | * @public 56 | * To set the middleware options using the class of the option 57 | * @param {Function} fn - The class of the strongly typed option class 58 | * @param {MiddlewareOptions} option - The strongly typed middleware option 59 | * @returns nothing 60 | */ 61 | public setMiddlewareOptions(fn: Function, option: MiddlewareOptions): void { 62 | this.middlewareOptions.set(fn, option); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/middleware/MiddlewareFactory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module MiddlewareFactory 10 | */ 11 | 12 | import { AuthenticationProvider } from "../IAuthenticationProvider"; 13 | import { AuthenticationHandler } from "./AuthenticationHandler"; 14 | import { HTTPMessageHandler } from "./HTTPMessageHandler"; 15 | import { Middleware } from "./IMiddleware"; 16 | import { RedirectHandlerOptions } from "./options/RedirectHandlerOptions"; 17 | import { RetryHandlerOptions } from "./options/RetryHandlerOptions"; 18 | import { RedirectHandler } from "./RedirectHandler"; 19 | import { RetryHandler } from "./RetryHandler"; 20 | import { TelemetryHandler } from "./TelemetryHandler"; 21 | 22 | /** 23 | * @private 24 | * To check whether the environment is node or not 25 | * @returns A boolean representing the environment is node or not 26 | */ 27 | const isNodeEnvironment = (): boolean => { 28 | return typeof process === "object" && typeof require === "function"; 29 | }; 30 | 31 | /** 32 | * @class 33 | * Class containing function(s) related to the middleware pipelines. 34 | */ 35 | export class MiddlewareFactory { 36 | /** 37 | * @public 38 | * @static 39 | * Returns the default middleware chain an array with the middleware handlers 40 | * @param {AuthenticationProvider} authProvider - The authentication provider instance 41 | * @returns an array of the middleware handlers of the default middleware chain 42 | */ 43 | public static getDefaultMiddlewareChain(authProvider: AuthenticationProvider): Middleware[] { 44 | const middleware: Middleware[] = []; 45 | const authenticationHandler = new AuthenticationHandler(authProvider); 46 | const retryHandler = new RetryHandler(new RetryHandlerOptions()); 47 | const telemetryHandler = new TelemetryHandler(); 48 | const httpMessageHandler = new HTTPMessageHandler(); 49 | 50 | middleware.push(authenticationHandler); 51 | middleware.push(retryHandler); 52 | if (isNodeEnvironment()) { 53 | const redirectHandler = new RedirectHandler(new RedirectHandlerOptions()); 54 | middleware.push(redirectHandler); 55 | } 56 | middleware.push(telemetryHandler); 57 | middleware.push(httpMessageHandler); 58 | 59 | return middleware; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/middleware/options/AuthenticationHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module AuthenticationHandlerOptions 10 | */ 11 | 12 | import { AuthenticationProvider } from "../../IAuthenticationProvider"; 13 | import { AuthenticationProviderOptions } from "../../IAuthenticationProviderOptions"; 14 | import { MiddlewareOptions } from "./IMiddlewareOptions"; 15 | 16 | /** 17 | * @class 18 | * @implements MiddlewareOptions 19 | * Class representing AuthenticationHandlerOptions 20 | */ 21 | export class AuthenticationHandlerOptions implements MiddlewareOptions { 22 | /** 23 | * @public 24 | * A member holding an instance of an authentication provider 25 | */ 26 | public authenticationProvider: AuthenticationProvider; 27 | 28 | /** 29 | * @public 30 | * A member holding an instance of authentication provider options 31 | */ 32 | public authenticationProviderOptions: AuthenticationProviderOptions; 33 | 34 | /** 35 | * @public 36 | * @constructor 37 | * To create an instance of AuthenticationHandlerOptions 38 | * @param {AuthenticationProvider} [authenticationProvider] - The authentication provider instance 39 | * @param {AuthenticationProviderOptions} [authenticationProviderOptions] - The authentication provider options instance 40 | * @returns An instance of AuthenticationHandlerOptions 41 | */ 42 | public constructor(authenticationProvider?: AuthenticationProvider, authenticationProviderOptions?: AuthenticationProviderOptions) { 43 | this.authenticationProvider = authenticationProvider; 44 | this.authenticationProviderOptions = authenticationProviderOptions; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/middleware/options/ChaosHandlerData.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module ChaosHandlerData 10 | */ 11 | 12 | /** 13 | * Contains RequestMethod to corresponding array of possible status codes, used for Random mode 14 | */ 15 | export const methodStatusCode: { [key: string]: number[] } = { 16 | GET: [429, 500, 502, 503, 504], 17 | POST: [429, 500, 502, 503, 504, 507], 18 | PUT: [429, 500, 502, 503, 504, 507], 19 | PATCH: [429, 500, 502, 503, 504], 20 | DELETE: [429, 500, 502, 503, 504, 507], 21 | }; 22 | 23 | /** 24 | * Contains statusCode to statusMessage map 25 | */ 26 | export const httpStatusCode: { [key: number]: string } = { 27 | 100: "Continue", 28 | 101: "Switching Protocols", 29 | 102: "Processing", 30 | 103: "Early Hints", 31 | 200: "OK", 32 | 201: "Created", 33 | 202: "Accepted", 34 | 203: "Non-Authoritative Information", 35 | 204: "No Content", 36 | 205: "Reset Content", 37 | 206: "Partial Content", 38 | 207: "Multi-Status", 39 | 208: "Already Reported", 40 | 226: "IM Used", 41 | 300: "Multiple Choices", 42 | 301: "Moved Permanently", 43 | 302: "Found", 44 | 303: "See Other", 45 | 304: "Not Modified", 46 | 305: "Use Proxy", 47 | 307: "Temporary Redirect", 48 | 308: "Permanent Redirect", 49 | 400: "Bad Request", 50 | 401: "Unauthorized", 51 | 402: "Payment Required", 52 | 403: "Forbidden", 53 | 404: "Not Found", 54 | 405: "Method Not Allowed", 55 | 406: "Not Acceptable", 56 | 407: "Proxy Authentication Required", 57 | 408: "Request Timeout", 58 | 409: "Conflict", 59 | 410: "Gone", 60 | 411: "Length Required", 61 | 412: "Precondition Failed", 62 | 413: "Payload Too Large", 63 | 414: "URI Too Long", 64 | 415: "Unsupported Media Type", 65 | 416: "Range Not Satisfiable", 66 | 417: "Expectation Failed", 67 | 421: "Misdirected Request", 68 | 422: "Unprocessable Entity", 69 | 423: "Locked", 70 | 424: "Failed Dependency", 71 | 425: "Too Early", 72 | 426: "Upgrade Required", 73 | 428: "Precondition Required", 74 | 429: "Too Many Requests", 75 | 431: "Request Header Fields Too Large", 76 | 451: "Unavailable For Legal Reasons", 77 | 500: "Internal Server Error", 78 | 501: "Not Implemented", 79 | 502: "Bad Gateway", 80 | 503: "Service Unavailable", 81 | 504: "Gateway Timeout", 82 | 505: "HTTP Version Not Supported", 83 | 506: "Variant Also Negotiates", 84 | 507: "Insufficient Storage", 85 | 508: "Loop Detected", 86 | 510: "Not Extended", 87 | 511: "Network Authentication Required", 88 | }; 89 | -------------------------------------------------------------------------------- /src/middleware/options/ChaosHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module ChaosHandlerOptions 10 | */ 11 | 12 | import { ChaosStrategy } from "./ChaosStrategy"; 13 | import { MiddlewareOptions } from "./IMiddlewareOptions"; 14 | 15 | /** 16 | * Class representing ChaosHandlerOptions 17 | * @class 18 | * Class 19 | * @implements MiddlewareOptions 20 | */ 21 | export class ChaosHandlerOptions implements MiddlewareOptions { 22 | /** 23 | * Specifies the startegy used for the Testing Handler -> RANDOM/MANUAL 24 | * 25 | * @public 26 | */ 27 | public chaosStrategy: ChaosStrategy; 28 | 29 | /** 30 | * Status code to be returned in the response 31 | * 32 | * @public 33 | */ 34 | public statusCode: number; 35 | 36 | /** 37 | * The Message to be returned in the response 38 | * 39 | * @public 40 | */ 41 | public statusMessage: string; 42 | 43 | /** 44 | * The percentage of randomness/chaos in the handler 45 | * 46 | * Setting the default value as 10% 47 | * @public 48 | */ 49 | public chaosPercentage: number; 50 | 51 | /** 52 | * The response body to be returned in the response 53 | * 54 | * @public 55 | */ 56 | public responseBody: any; 57 | 58 | /** 59 | * The response headers to be returned in the response 60 | * 61 | * @public 62 | */ 63 | public headers: Headers; 64 | 65 | /** 66 | * @public 67 | * @constructor 68 | * To create an instance of Testing Handler Options 69 | * @param {ChaosStrategy} chaosStrategy - Specifies the startegy used for the Testing Handler -> RAMDOM/MANUAL 70 | * @param {string} statusMessage - The Message to be returned in the response 71 | * @param {number?} statusCode - The statusCode to be returned in the response 72 | * @param {number?} chaosPercentage - The percentage of randomness/chaos in the handler 73 | * @param {any?} responseBody - The response body to be returned in the response 74 | * @returns An instance of ChaosHandlerOptions 75 | */ 76 | public constructor(chaosStrategy: ChaosStrategy = ChaosStrategy.RANDOM, statusMessage = "Some error Happened", statusCode?: number, chaosPercentage?: number, responseBody?: any, headers?: Headers) { 77 | this.chaosStrategy = chaosStrategy; 78 | this.statusCode = statusCode; 79 | this.statusMessage = statusMessage; 80 | this.chaosPercentage = chaosPercentage !== undefined ? chaosPercentage : 10; 81 | this.responseBody = responseBody; 82 | this.headers = headers; 83 | if (this.chaosPercentage > 100) { 84 | throw new Error("Error Pecentage can not be more than 100"); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/middleware/options/ChaosStrategy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module ChaosStrategy 10 | */ 11 | 12 | /** 13 | * Strategy used for Testing Handler 14 | * @enum 15 | */ 16 | export enum ChaosStrategy { 17 | MANUAL, 18 | RANDOM, 19 | } 20 | -------------------------------------------------------------------------------- /src/middleware/options/IMiddlewareOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @interface 10 | * Signature representing the middleware options 11 | */ 12 | 13 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 14 | export interface MiddlewareOptions {} 15 | -------------------------------------------------------------------------------- /src/middleware/options/RedirectHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module RedirectHandlerOptions 10 | */ 11 | 12 | import { MiddlewareOptions } from "./IMiddlewareOptions"; 13 | 14 | /** 15 | * @type 16 | * A type declaration for shouldRetry callback 17 | */ 18 | export type ShouldRedirect = (response: Response) => boolean; 19 | 20 | /** 21 | * @class 22 | * @implements MiddlewareOptions 23 | * A class representing RedirectHandlerOptions 24 | */ 25 | export class RedirectHandlerOptions implements MiddlewareOptions { 26 | /** 27 | * @private 28 | * @static 29 | * A member holding default max redirects value 30 | */ 31 | private static DEFAULT_MAX_REDIRECTS = 5; 32 | 33 | /** 34 | * @private 35 | * @static 36 | * A member holding maximum max redirects value 37 | */ 38 | private static MAX_MAX_REDIRECTS = 20; 39 | 40 | /** 41 | * @public 42 | * A member holding max redirects value 43 | */ 44 | public maxRedirects: number; 45 | 46 | /** 47 | * @public 48 | * A member holding shouldRedirect callback 49 | */ 50 | public shouldRedirect: ShouldRedirect; 51 | 52 | /** 53 | * @private 54 | * A member holding default shouldRedirect callback 55 | */ 56 | private static defaultShouldRedirect: ShouldRedirect = () => true; 57 | 58 | /** 59 | * @public 60 | * @constructor 61 | * To create an instance of RedirectHandlerOptions 62 | * @param {number} [maxRedirects = RedirectHandlerOptions.DEFAULT_MAX_REDIRECTS] - The max redirects value 63 | * @param {ShouldRedirect} [shouldRedirect = RedirectHandlerOptions.DEFAULT_SHOULD_RETRY] - The should redirect callback 64 | * @returns An instance of RedirectHandlerOptions 65 | */ 66 | public constructor(maxRedirects: number = RedirectHandlerOptions.DEFAULT_MAX_REDIRECTS, shouldRedirect: ShouldRedirect = RedirectHandlerOptions.defaultShouldRedirect) { 67 | if (maxRedirects > RedirectHandlerOptions.MAX_MAX_REDIRECTS) { 68 | const error = new Error(`MaxRedirects should not be more than ${RedirectHandlerOptions.MAX_MAX_REDIRECTS}`); 69 | error.name = "MaxLimitExceeded"; 70 | throw error; 71 | } 72 | if (maxRedirects < 0) { 73 | const error = new Error(`MaxRedirects should not be negative`); 74 | error.name = "MinExpectationNotMet"; 75 | throw error; 76 | } 77 | this.maxRedirects = maxRedirects; 78 | this.shouldRedirect = shouldRedirect; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/middleware/options/TelemetryHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module TelemetryHandlerOptions 10 | */ 11 | 12 | import { Context } from "../../IContext"; 13 | import { MiddlewareControl } from "../MiddlewareControl"; 14 | import { MiddlewareOptions } from "./IMiddlewareOptions"; 15 | 16 | /** 17 | * @enum 18 | * @property {number} NONE - The hexadecimal flag value for nothing enabled 19 | * @property {number} REDIRECT_HANDLER_ENABLED - The hexadecimal flag value for redirect handler enabled 20 | * @property {number} RETRY_HANDLER_ENABLED - The hexadecimal flag value for retry handler enabled 21 | * @property {number} AUTHENTICATION_HANDLER_ENABLED - The hexadecimal flag value for the authentication handler enabled 22 | */ 23 | 24 | export enum FeatureUsageFlag { 25 | /* eslint-disable @typescript-eslint/naming-convention */ 26 | NONE = 0x0, 27 | REDIRECT_HANDLER_ENABLED = 0x1, 28 | RETRY_HANDLER_ENABLED = 0x2, 29 | AUTHENTICATION_HANDLER_ENABLED = 0x4, 30 | /* eslint-enable @typescript-eslint/naming-convention */ 31 | } 32 | 33 | /** 34 | * @class 35 | * @implements MiddlewareOptions 36 | * Class for TelemetryHandlerOptions 37 | */ 38 | 39 | export class TelemetryHandlerOptions implements MiddlewareOptions { 40 | /** 41 | * @private 42 | * A member to hold the OR of feature usage flags 43 | */ 44 | private featureUsage: FeatureUsageFlag = FeatureUsageFlag.NONE; 45 | 46 | /** 47 | * @public 48 | * @static 49 | * To update the feature usage in the context object 50 | * @param {Context} context - The request context object containing middleware options 51 | * @param {FeatureUsageFlag} flag - The flag value 52 | * @returns nothing 53 | */ 54 | public static updateFeatureUsageFlag(context: Context, flag: FeatureUsageFlag): void { 55 | let options: TelemetryHandlerOptions; 56 | if (context.middlewareControl instanceof MiddlewareControl) { 57 | options = context.middlewareControl.getMiddlewareOptions(TelemetryHandlerOptions) as TelemetryHandlerOptions; 58 | } else { 59 | context.middlewareControl = new MiddlewareControl(); 60 | } 61 | if (typeof options === "undefined") { 62 | options = new TelemetryHandlerOptions(); 63 | context.middlewareControl.setMiddlewareOptions(TelemetryHandlerOptions, options); 64 | } 65 | options.setFeatureUsage(flag); 66 | } 67 | 68 | /** 69 | * @private 70 | * To set the feature usage flag 71 | * @param {FeatureUsageFlag} flag - The flag value 72 | * @returns nothing 73 | */ 74 | private setFeatureUsage(flag: FeatureUsageFlag): void { 75 | this.featureUsage = this.featureUsage | flag; 76 | } 77 | 78 | /** 79 | * @public 80 | * To get the feature usage 81 | * @returns A feature usage flag as hexadecimal string 82 | */ 83 | public getFeatureUsage(): string { 84 | return this.featureUsage.toString(16); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/tasks/FileUploadTask/FileObjectClasses/FileUpload.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { GraphClientError } from "../../../GraphClientError"; 9 | import { FileObject, SliceType } from "../../LargeFileUploadTask"; 10 | import { Range } from "../Range"; 11 | 12 | /** 13 | * @class 14 | * Class used for creating LargeFileUploadTask fileobject. 15 | * This class accepts files of type ArrayBuffer, Blob, Uint8Array. 16 | */ 17 | export class FileUpload implements FileObject { 18 | /** 19 | * @public 20 | * @constructor 21 | * @param {ArrayBuffer | Blob | Uint8Array} content - The file to be uploaded 22 | * @param {string} name - The name of the file to be uploaded 23 | * @param {number} size - The total size of the file to be uploaded 24 | * @returns An instance of the FileUpload class 25 | */ 26 | public constructor(public content: ArrayBuffer | Blob | Uint8Array, public name: string, public size: number) { 27 | if (!content || !name || !size) { 28 | throw new GraphClientError("Please provide the upload content, name of the file and size of the file"); 29 | } 30 | } 31 | 32 | /** 33 | * @public 34 | * Slices the file content to the given range 35 | * @param {Range} range - The range value 36 | * @returns The sliced file part 37 | */ 38 | public sliceFile(range: Range): ArrayBuffer | Blob | Uint8Array { 39 | return this.content.slice(range.minValue, range.maxValue + 1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/tasks/FileUploadTask/Interfaces/IUploadEventHandlers.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/type-annotation-spacing */ 2 | import { Range } from "../Range"; 3 | 4 | /** 5 | * Interface enabling progress handling with callbacks. 6 | */ 7 | export interface UploadEventHandlers { 8 | /** 9 | * Parameters that are passed into the progress, completed, failure callback options. 10 | */ 11 | extraCallbackParam?: unknown; 12 | /** 13 | * Callback function called on each slice upload during the LargeFileUploadTask.upload() process 14 | */ 15 | progress?: (range?: Range, extraCallbackParam?: unknown) => void; 16 | } 17 | -------------------------------------------------------------------------------- /src/tasks/FileUploadTask/Range.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module Range 10 | */ 11 | 12 | /** 13 | * @class 14 | * Class representing Range 15 | */ 16 | export class Range { 17 | /** 18 | * @public 19 | * The minimum value of the range 20 | */ 21 | public minValue: number; 22 | 23 | /** 24 | * @public 25 | * The maximum value of the range 26 | */ 27 | public maxValue: number; 28 | 29 | /** 30 | * @public 31 | * @constructor 32 | * Creates a range for given min and max values 33 | * @param {number} [minVal = -1] - The minimum value. 34 | * @param {number} [maxVal = -1] - The maximum value. 35 | * @returns An instance of a Range 36 | */ 37 | public constructor(minVal = -1, maxVal = -1) { 38 | this.minValue = minVal; 39 | this.maxValue = maxVal; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/tasks/FileUploadTask/UploadResult.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * Class representing a successful file upload result 10 | */ 11 | export class UploadResult { 12 | /** 13 | * @private 14 | * Location value looked up in the response header 15 | */ 16 | private _location: string; 17 | 18 | /** 19 | * @private 20 | * Response body of the final raw response 21 | */ 22 | private _responseBody: unknown; 23 | 24 | /** 25 | * @public 26 | * Get of the location value. 27 | * Location value is looked up in the response header 28 | */ 29 | public get location(): string { 30 | return this._location; 31 | } 32 | 33 | /** 34 | * @public 35 | * Set the location value 36 | * Location value is looked up in the response header 37 | */ 38 | public set location(location: string) { 39 | this._location = location; 40 | } 41 | 42 | /** 43 | * @public 44 | * Get The response body from the completed upload response 45 | */ 46 | public get responseBody() { 47 | return this._responseBody; 48 | } 49 | 50 | /** 51 | * @public 52 | * Set the response body from the completed upload response 53 | */ 54 | public set responseBody(responseBody: unknown) { 55 | this._responseBody = responseBody; 56 | } 57 | 58 | /** 59 | * @public 60 | * @param {responseBody} responsebody - The response body from the completed upload response 61 | * @param {location} location - The location value from the headers from the completed upload response 62 | */ 63 | public constructor(responseBody: unknown, location: string) { 64 | // Response body or the location parameter can be undefined. 65 | this._location = location; 66 | this._responseBody = responseBody; 67 | } 68 | 69 | /** 70 | * @public 71 | * @param {responseBody} responseBody - The response body from the completed upload response 72 | * @param {responseHeaders} responseHeaders - The headers from the completed upload response 73 | */ 74 | public static CreateUploadResult(responseBody?: unknown, responseHeaders?: Headers) { 75 | return new UploadResult(responseBody, responseHeaders.get("location")); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/tasks/OneDriveLargeFileUploadTaskUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module OneDriveLargeFileUploadTaskUtil 10 | */ 11 | 12 | /** 13 | * @constant 14 | * Default value for the rangeSize 15 | * Recommended size is between 5 - 10 MB {@link https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/driveitem_createuploadsession#best-practices} 16 | */ 17 | const DEFAULT_FILE_SIZE: number = 5 * 1024 * 1024; 18 | 19 | /** 20 | * @constant 21 | * Rounds off the given value to a multiple of 320 KB 22 | * @param {number} value - The value 23 | * @returns The rounded off value 24 | */ 25 | const roundTo320KB = (value: number): number => { 26 | if (value > 320 * 1024) { 27 | value = Math.floor(value / (320 * 1024)) * 320 * 1024; 28 | } 29 | return value; 30 | }; 31 | 32 | /** 33 | * @constant 34 | * Get the valid rangeSize for a file slicing (validity is based on the constrains mentioned in here 35 | * {@link https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/driveitem_createuploadsession#upload-bytes-to-the-upload-session}) 36 | * 37 | * @param {number} [rangeSize = DEFAULT_FILE_SIZE] - The rangeSize value. 38 | * @returns The valid rangeSize 39 | */ 40 | export const getValidRangeSize = (rangeSize: number = DEFAULT_FILE_SIZE): number => { 41 | const sixtyMB = 60 * 1024 * 1024; 42 | if (rangeSize > sixtyMB) { 43 | rangeSize = sixtyMB; 44 | } 45 | return roundTo320KB(rangeSize); 46 | }; 47 | -------------------------------------------------------------------------------- /test-esm/README.md: -------------------------------------------------------------------------------- 1 | The test-esm project verifies if the Graph JS Client compiles with ESM projects successfully. -------------------------------------------------------------------------------- /test-esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-esm", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "tsc && npx mocha ./lib/testESM.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@microsoft/microsoft-graph-client": "file:../", 15 | "@types/chai": "^4.3.4", 16 | "@types/mocha": "^10.0.1", 17 | "chai": "^4.3.7", 18 | "isomorphic-fetch": "^3.0.0", 19 | "mocha": "^10.2.0", 20 | "ts-node": "^9.1.1", 21 | "typescript": "^4.2.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test-esm/tests/testESM.ts: -------------------------------------------------------------------------------- 1 | import "isomorphic-fetch"; 2 | 3 | import { ChaosHandler, ChaosHandlerOptions, ChaosStrategy, Client, ClientOptions } from "@microsoft/microsoft-graph-client"; 4 | import { assert } from "chai"; 5 | 6 | const middleware = new ChaosHandler(); 7 | const clientOptions: ClientOptions = { 8 | middleware, 9 | }; 10 | 11 | export const TestClient = Client.initWithMiddleware(clientOptions); 12 | 13 | describe("", () => { 14 | it("should work", async () => { 15 | const responseBody = { 16 | "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", 17 | businessPhones: ["+1 412 555 0109"], 18 | displayName: "Megan Bowen", 19 | givenName: "Megan", 20 | userPrincipalName: "MeganB@M365x214355.onmicrosoft.com", 21 | id: "48d31887-5fad-4d73-a9f5-3c356e68a038", 22 | }; 23 | 24 | const middlewareOptions = [new ChaosHandlerOptions(ChaosStrategy.MANUAL, "middleware options", 200, 0, JSON.stringify(responseBody)), new Headers({ "Content-Type": "application/json", "content-length": "100" })]; 25 | 26 | const response = JSON.parse(await TestClient.api("/me").middlewareOptions(middlewareOptions).get()); 27 | assert.isDefined(response); 28 | assert.isDefined(response["id"]); 29 | assert.equal(response["displayName"], responseBody.displayName); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test-esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ES6", 4 | "target": "es6", 5 | "outDir": "lib", 6 | "moduleResolution": "node" 7 | }, 8 | "exclude": [ 9 | "node_modules" 10 | ] 11 | } -------------------------------------------------------------------------------- /test/DummyAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module DummyAuthenticationProvider 10 | */ 11 | 12 | import { AuthenticationProvider } from "../src/IAuthenticationProvider"; 13 | 14 | /** 15 | * @class 16 | * @implements AuthenticationProvider 17 | * Class representing DummyAuthenticationProvider 18 | */ 19 | export class DummyAuthenticationProvider implements AuthenticationProvider { 20 | /** 21 | * @public 22 | * @async 23 | * To get the access token 24 | * @returns The promise that resolves to an access token 25 | */ 26 | public async getAccessToken(): Promise { 27 | const token = "DUMMY_TOKEN"; 28 | return Promise.resolve(token); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/DummyHTTPMessageHandler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module DummyHTTPMessageHandler 10 | */ 11 | 12 | import { Context } from "../src/IContext"; 13 | import { Middleware } from "../src/middleware/IMiddleware"; 14 | 15 | /** 16 | * @class 17 | * @implements Middleware 18 | * Class representing DummyHTTPMessageHandler 19 | */ 20 | export class DummyHTTPMessageHandler implements Middleware { 21 | /** 22 | * @private 23 | * A member holding the array of response objects 24 | */ 25 | private responses: Response[]; 26 | 27 | /** 28 | * @public 29 | * @constructor 30 | * To create an instance of DummyHTTPMessageHandler 31 | * @param {Response[]} [responses = []] - The array of response objects 32 | * @returns An instance of DummyHTTPMessageHandler 33 | */ 34 | public constructor(responses: Response[] = []) { 35 | this.responses = responses; 36 | } 37 | 38 | /** 39 | * @public 40 | * To set the array of responses 41 | * @param {Response[]} response - The array of responses 42 | * @returns Nothing 43 | */ 44 | public setResponses(responses: Response[]): void { 45 | this.responses = responses; 46 | } 47 | 48 | /** 49 | * @public 50 | * @async 51 | * To execute the current middleware 52 | * @param {Context} context - The request context object 53 | * @returns A promise that resolves to nothing 54 | */ 55 | public async execute(context: Context) { 56 | context.response = this.responses.shift(); 57 | return; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/DummyHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module DummyHandlerOptions 10 | */ 11 | 12 | import { MiddlewareOptions } from "../src/middleware/options/IMiddlewareOptions"; 13 | 14 | /** 15 | * @class 16 | * @implements MiddlewareOptions 17 | * Class for DummyHandlerOptions 18 | */ 19 | 20 | export class DummyHandlerOptions implements MiddlewareOptions { 21 | /** 22 | * @public 23 | * A member holding a dummy string 24 | */ 25 | public dummyString: string; 26 | 27 | /** 28 | * @public 29 | * @async 30 | * To create an instance of DummyHandlerOptions 31 | * @param {string} dummyString - The dummy string 32 | * @returns An instance of DummyHandlerOptions 33 | */ 34 | public constructor(dummyString = "dummy") { 35 | this.dummyString = dummyString; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/Tests.md: -------------------------------------------------------------------------------- 1 | The /test folder consists of unit tests written using the following testing tools 2 | 3 | - mocha 4 | - chai 5 | - karma 6 | - @istanbuljs/nyc-config-typescript 7 | 8 | Scripts used 9 | 10 | - `npm run test` - To run unit tests in test/common and test/node. 11 | - `npm run test:cjs` - To run unit tests in test/common and test/node compiled as CommonJS modules. 12 | - `npm run test:esm` - To run unit tests in test/common and test/node compiled as ESM modules. 13 | - `npm run test:development` - To run tests in test/development folder. 14 | - `npm run test:coverage` - To get the test code coverage after running the tests. 15 | - `npm run karma` - To run the units tests in test/common and test/browser folders on a headless browser. 16 | -------------------------------------------------------------------------------- /test/browser/BrowserTests.md: -------------------------------------------------------------------------------- 1 | This folder contains unit tests which are browser-specific. Example - The tests in [GraphResponseHandler](./core/GraphResponseHandler.ts) requires the DOMParser which is a browser functionality. 2 | 3 | Karma is used for testing the code in browsers. To run the unit tests using karma run the following steps - 4 | 5 | - Run the script `npm install`. 6 | - Run the script `npm run karma`. 7 | -------------------------------------------------------------------------------- /test/browser/core/GraphResponseHandler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { DocumentType, GraphResponseHandler } from "../../../src/GraphResponseHandler"; 11 | import { ResponseType } from "../../../src/ResponseType"; 12 | 13 | /** 14 | * References - https://fetch.spec.whatwg.org/#responses 15 | */ 16 | describe("GraphResponseHandler.ts", () => { 17 | const htmlString = ` 18 | 19 | 20 | 21 | Testing Document 22 | 23 | 24 |

Testing

25 | 26 | `; 27 | const status200 = { 28 | status: 200, 29 | statusText: "OK", 30 | }; 31 | 32 | /* tslint:disable: no-string-literal */ 33 | describe("parseDocumentResponse", () => { 34 | it("Should return the html string", async () => { 35 | const response = new Response(htmlString, status200); 36 | const dom = await GraphResponseHandler["parseDocumentResponse"](response, DocumentType.TEXT_HTML); 37 | assert.isDefined(dom); 38 | assert.instanceOf(dom, Document); 39 | }); 40 | 41 | it("Should return response value as text for text/html return type", async () => { 42 | const response = new Response(htmlString, status200); 43 | const responseValue = await GraphResponseHandler["convertResponse"](response, ResponseType.DOCUMENT); 44 | assert.isDefined(responseValue); 45 | assert.instanceOf(responseValue, Document); 46 | }); 47 | }); 48 | /* tslint:enable: no-string-literal */ 49 | }); 50 | -------------------------------------------------------------------------------- /test/common/core/GraphClientError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { GraphClientError } from "../../../src/GraphClientError"; 11 | 12 | describe("GraphClientError", () => { 13 | const message = "test"; 14 | const name = "test_name"; 15 | it("Should return GraphClientError error with message set", () => { 16 | const gError = new GraphClientError(message); 17 | assert.equal(gError.message, message); 18 | }); 19 | 20 | it("Should return GraphClientError when Error object is passed", () => { 21 | const errorParameter = new Error(message); 22 | errorParameter.name = name; 23 | const gError = GraphClientError.setGraphClientError(errorParameter); 24 | assert.equal(gError.message, message); 25 | assert.equal(gError.name, name); 26 | }); 27 | 28 | it("Should return GraphClientError when custom error object is passed", () => { 29 | const customErrorParameter = { errorName: name, errorMessage: message }; 30 | const gError = GraphClientError.setGraphClientError(customErrorParameter); 31 | assert.isDefined(gError.customError); 32 | assert.equal(gError.customError, customErrorParameter); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/common/core/GraphRequestUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { serializeContent, urlJoin } from "../../../src/GraphRequestUtil"; 11 | 12 | describe("GraphRequestUtil.ts", () => { 13 | describe("urlJoin", () => { 14 | const output = "host/version/path"; 15 | 16 | it("Should append parts with /", () => { 17 | const joined = urlJoin(["host", "version", "path"]); 18 | assert.equal(joined, output); 19 | }); 20 | 21 | it("Should append parts with / by removing / from start", () => { 22 | const joined = urlJoin(["host", "/version", "/path"]); 23 | assert.equal(joined, output); 24 | }); 25 | 26 | it("Should append parts with / by removing / from end", () => { 27 | const joined = urlJoin(["host/", "version/", "path"]); 28 | assert.equal(joined, output); 29 | }); 30 | 31 | it("Should append parts with / by removing / from start and end", () => { 32 | const joined = urlJoin(["host/", "/version/", "/path"]); 33 | assert.equal(joined, output); 34 | }); 35 | }); 36 | 37 | describe("serializeContent", () => { 38 | it("Should return Buffer/Blob/File/FormData/String as it is", () => { 39 | const str = "Content"; 40 | assert.equal(serializeContent(str), str); 41 | const buffer = Buffer.alloc(2, "Buffer"); 42 | assert.equal(serializeContent(buffer), buffer); 43 | }); 44 | 45 | it("Should convert it to string", () => { 46 | const data = 123; 47 | const str = "123"; 48 | assert.equal(serializeContent(data), str); 49 | }); 50 | 51 | it("Should throw error for objects that cannot be converted to string", () => { 52 | const node1 = { 53 | data: 1, 54 | link: undefined, 55 | }; 56 | const node2 = { 57 | data: 2, 58 | link: undefined, 59 | }; 60 | node1.link = node2; 61 | node2.link = node1; 62 | try { 63 | serializeContent(node1); 64 | throw new Error("Test Failed - Something wrong with the serialize content, it should not stringify cyclic referenced objects"); 65 | } catch (error) { 66 | assert.equal(error.message, "Unable to stringify the content"); 67 | } 68 | }); 69 | 70 | it("Should return undefined for the case of undefined content value", () => { 71 | const val = undefined; 72 | assert.equal(serializeContent(val), undefined); 73 | }); 74 | 75 | it("Should return 'null' for the case of null content value", () => { 76 | const val = null; 77 | assert.equal(serializeContent(val), "null"); 78 | }); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /test/common/core/HTTPClient.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { HTTPClient } from "../../../src/HTTPClient"; 11 | import { Context } from "../../../src/IContext"; 12 | import { FetchOptions } from "../../../src/IFetchOptions"; 13 | import { DummyHTTPMessageHandler } from "../../DummyHTTPMessageHandler"; 14 | import { DUMMY_BASE_URL } from "../../test-helper"; 15 | 16 | describe("HTTPClient.ts", () => { 17 | const httpMessageHandler: DummyHTTPMessageHandler = new DummyHTTPMessageHandler(); 18 | const httpClient: HTTPClient = new HTTPClient(httpMessageHandler); 19 | describe("constructor", () => { 20 | it("Should create an instance and populate middleware member", () => { 21 | assert.isDefined(httpClient["middleware"]); 22 | assert.equal(httpClient["middleware"], httpMessageHandler); 23 | }); 24 | 25 | it("Should create an instance and populate middleware member when passing a middleware array", () => { 26 | const client = new HTTPClient(...[httpMessageHandler]); 27 | assert.isDefined(client["middleware"]); 28 | assert.equal(client["middleware"], httpMessageHandler); 29 | }); 30 | 31 | it("Should throw an error if middleware is undefined", () => { 32 | try { 33 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 34 | const client = new HTTPClient(); 35 | throw new Error("Test failed - Expected error was not thrown"); 36 | } catch (error) { 37 | assert.equal(error.name, "InvalidMiddlewareChain"); 38 | } 39 | }); 40 | 41 | it("Should throw an error if middleware is passed as an empty array", () => { 42 | try { 43 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 44 | const client = new HTTPClient(...[]); 45 | throw new Error("Test failed - Expected error was not thrown"); 46 | } catch (error) { 47 | assert.equal(error.name, "InvalidMiddlewareChain"); 48 | } 49 | }); 50 | }); 51 | 52 | describe("sendRequest", async () => { 53 | it("Should throw error for invalid request options incase if the url and options are passed", async () => { 54 | try { 55 | const url = "dummy_url"; 56 | const context: Context = { 57 | request: url, 58 | }; 59 | await httpClient.sendRequest(context); 60 | throw new Error("Test Failed - Something wrong with the context validation"); 61 | } catch (error) { 62 | assert.equal(error.name, "InvalidRequestOptions"); 63 | } 64 | }); 65 | 66 | it("Should execute for context object with Request instance", async () => { 67 | const request: Request = new Request(DUMMY_BASE_URL + "/dummy_url", { 68 | method: "GET", 69 | }); 70 | const context: Context = { 71 | request, 72 | }; 73 | await httpClient.sendRequest(context); 74 | }); 75 | 76 | it("Should execute for context object with request uri and options", async () => { 77 | const url = "dummy_url"; 78 | const options: FetchOptions = { 79 | method: "GET", 80 | }; 81 | const context: Context = { 82 | request: url, 83 | options, 84 | }; 85 | await httpClient.sendRequest(context); 86 | }); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /test/common/core/HTTPClientFactory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { HTTPClient } from "../../../src/HTTPClient"; 11 | import { HTTPClientFactory } from "../../../src/HTTPClientFactory"; 12 | import { DummyAuthenticationProvider } from "../../DummyAuthenticationProvider"; 13 | import { DummyHTTPMessageHandler } from "../../DummyHTTPMessageHandler"; 14 | 15 | describe("HTTPClientFactory.ts", () => { 16 | describe("createWithAuthenticationProvider", () => { 17 | const dummyAuthProvider = new DummyAuthenticationProvider(); 18 | const dummyHTTPHandler = new DummyHTTPMessageHandler(); 19 | it("Should create an HTTPClient instance with default middleware chain", () => { 20 | const client: HTTPClient = HTTPClientFactory.createWithAuthenticationProvider(dummyAuthProvider); 21 | assert.isTrue(client instanceof HTTPClient); 22 | assert.isDefined(client["middleware"]); 23 | }); 24 | 25 | it("Should create an HTTPClient with given middleware chain", () => { 26 | const client: HTTPClient = HTTPClientFactory.createWithMiddleware(dummyHTTPHandler); 27 | assert.isTrue(client instanceof HTTPClient); 28 | assert.isDefined(client["middleware"]); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/common/core/Range.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { Range } from "../../../src/tasks/FileUploadTask/Range"; 11 | 12 | describe("Range.ts", () => { 13 | describe("Constructor", () => { 14 | const defaultValue = -1; 15 | 16 | it("Should create a Range instance with given min and max values", () => { 17 | const min = 1; 18 | const max = 10; 19 | const range = new Range(min, max); 20 | assert.equal(range.minValue, min); 21 | assert.equal(range.maxValue, max); 22 | }); 23 | 24 | it("Should create a range instance with default values", () => { 25 | const range = new Range(); 26 | assert.equal(range.minValue, defaultValue); 27 | assert.equal(range.maxValue, defaultValue); 28 | }); 29 | 30 | it("Should create a range instance with default max value", () => { 31 | const min = 1; 32 | const range = new Range(min); 33 | assert.equal(range.minValue, min); 34 | assert.equal(range.maxValue, defaultValue); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/common/middleware/AuthenticationHandler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { ChaosHandler, ChaosHandlerOptions, ChaosStrategy } from "../../../src"; 11 | import { GRAPH_BASE_URL } from "../../../src/Constants"; 12 | import { Context } from "../../../src/IContext"; 13 | import { AuthenticationHandler } from "../../../src/middleware/AuthenticationHandler"; 14 | import { DummyAuthenticationProvider } from "../../DummyAuthenticationProvider"; 15 | import { DUMMY_BASE_URL } from "../../test-helper"; 16 | 17 | const dummyAuthProvider = new DummyAuthenticationProvider(); 18 | const authHandler = new AuthenticationHandler(dummyAuthProvider); 19 | const chaosHandler = new ChaosHandler(new ChaosHandlerOptions(ChaosStrategy.MANUAL, "TEST_MESSAGE", 200)); 20 | 21 | describe("AuthenticationHandler.ts", async () => { 22 | describe("Constructor", () => { 23 | it("Should return an AuthenticationHandler for given AuthenticationProvider", () => { 24 | assert.isTrue(authHandler instanceof AuthenticationHandler); 25 | assert.equal(authHandler["authenticationProvider"], dummyAuthProvider); 26 | }); 27 | }); 28 | describe("Auth Headers", () => { 29 | it("Should delete Auth header when Request object is passed with non Graph URL", async () => { 30 | const request = new Request(DUMMY_BASE_URL + "/test_url"); 31 | const context: Context = { 32 | request, 33 | options: { 34 | headers: { 35 | Authorization: "TEST_VALUE", 36 | }, 37 | }, 38 | }; 39 | authHandler.setNext(chaosHandler); 40 | await authHandler.execute(context); 41 | assert.equal(context.options.headers["Authorization"], undefined); 42 | }); 43 | 44 | it("Should contain Auth header when Request object is passed with custom URL", async () => { 45 | const request = new Request("https://custom/"); 46 | const context: Context = { 47 | request, 48 | customHosts: new Set(["custom"]), 49 | options: { 50 | headers: {}, 51 | }, 52 | }; 53 | const accessToken = "Bearer DUMMY_TOKEN"; 54 | 55 | await authHandler.execute(context); 56 | assert.equal((request as Request).headers.get("Authorization"), accessToken); 57 | }); 58 | 59 | it("Should contain Auth header when Request object is passed with a valid Graph URL", async () => { 60 | const request = new Request(GRAPH_BASE_URL); 61 | const context: Context = { 62 | request, 63 | customHosts: new Set(["custom"]), 64 | options: { 65 | headers: {}, 66 | }, 67 | }; 68 | const accessToken = "Bearer DUMMY_TOKEN"; 69 | await authHandler.execute(context); 70 | assert.equal((request as Request).headers.get("Authorization"), accessToken); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/common/middleware/AuthenticationHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { AuthenticationHandlerOptions } from "../../../src/middleware/options/AuthenticationHandlerOptions"; 11 | import { DummyAuthenticationProvider } from "../../DummyAuthenticationProvider"; 12 | 13 | describe("AuthenticationHandlerOptions.ts", () => { 14 | const dummyAuthProvider = new DummyAuthenticationProvider(); 15 | const authOptions = { scopes: ["test"] }; 16 | it("Should create an instance with all the given options", () => { 17 | const options = new AuthenticationHandlerOptions(dummyAuthProvider, authOptions); 18 | assert.equal(options.authenticationProvider, dummyAuthProvider); 19 | assert.equal(options.authenticationProviderOptions, authOptions); 20 | }); 21 | 22 | it("Should be undefined value if no value is passed", () => { 23 | const options = new AuthenticationHandlerOptions(undefined, authOptions); 24 | assert.isUndefined(options.authenticationProvider); 25 | assert.equal(options.authenticationProviderOptions, authOptions); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/common/middleware/MiddlewareControl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module MiddlewareControl 10 | */ 11 | 12 | import "isomorphic-fetch"; 13 | 14 | import { assert } from "chai"; 15 | 16 | import { MiddlewareControl } from "../../../src/middleware/MiddlewareControl"; 17 | import { DummyHandlerOptions } from "../../DummyHandlerOptions"; 18 | 19 | describe("MiddlewareControl.ts", () => { 20 | const dummyHandlerOption = new DummyHandlerOptions(); 21 | 22 | describe("constructor", () => { 23 | it("Should populate its middleware options map", () => { 24 | const middlewareControl = new MiddlewareControl([dummyHandlerOption]); 25 | assert.isDefined(middlewareControl["middlewareOptions"]); 26 | assert.equal(middlewareControl["middlewareOptions"].size, 1); 27 | }); 28 | 29 | it("Should create empty middleware options map by default", () => { 30 | const middlewareControl = new MiddlewareControl(); 31 | assert.isDefined(middlewareControl["middlewareOptions"]); 32 | assert.equal(middlewareControl["middlewareOptions"].size, 0); 33 | }); 34 | }); 35 | 36 | describe("getMiddlewareOption", () => { 37 | it("Should return the middleware option for a given class name", () => { 38 | const middlewareControl = new MiddlewareControl([dummyHandlerOption]); 39 | const retryOptions: DummyHandlerOptions = middlewareControl.getMiddlewareOptions(dummyHandlerOption.constructor as () => any) as DummyHandlerOptions; 40 | assert.isDefined(retryOptions); 41 | assert.equal(dummyHandlerOption, retryOptions); 42 | }); 43 | 44 | it("Should return undefined for unknown class name", () => { 45 | const middlewareControl = new MiddlewareControl([dummyHandlerOption]); 46 | const retryOptions = middlewareControl.getMiddlewareOptions(() => "NotAvailableHandlerOption"); 47 | assert.isUndefined(retryOptions); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/common/middleware/MiddlewareFactory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { AuthenticationHandler, CustomAuthenticationProvider, HTTPMessageHandler, RedirectHandler, RetryHandler, TelemetryHandler } from "../../../src"; 11 | import { AuthProvider } from "../../../src/IAuthProvider"; 12 | import { MiddlewareFactory } from "../../../src/middleware/MiddlewareFactory"; 13 | 14 | describe("MiddlewareFactory", () => { 15 | it("Should return the default pipeline", () => { 16 | const provider: AuthProvider = (done) => { 17 | done(null, "dummy_token"); 18 | }; 19 | const defaultMiddleWareArray = MiddlewareFactory.getDefaultMiddlewareChain(new CustomAuthenticationProvider(provider)); 20 | 21 | assert.isTrue(defaultMiddleWareArray[0] instanceof AuthenticationHandler); 22 | assert.isTrue(defaultMiddleWareArray[1] instanceof RetryHandler); 23 | assert.isTrue(defaultMiddleWareArray[2] instanceof RedirectHandler); 24 | assert.isTrue(defaultMiddleWareArray[3] instanceof TelemetryHandler); 25 | assert.isTrue(defaultMiddleWareArray[4] instanceof HTTPMessageHandler); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/common/middleware/RedirectHandlerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { RedirectHandlerOptions } from "../../../src/middleware/options/RedirectHandlerOptions"; 11 | 12 | describe("RedirectHandlerOptions.ts", () => { 13 | describe("constructor", () => { 14 | it("Should initialize the instance with given options", () => { 15 | const shouldRedirect = (response: Response) => { 16 | if (response.status === 301) { 17 | return true; 18 | } 19 | return false; 20 | }; 21 | const maxRedirects = 5; 22 | const options = new RedirectHandlerOptions(maxRedirects, shouldRedirect); 23 | assert.equal(options.maxRedirects, maxRedirects); 24 | assert.equal(options.shouldRedirect, shouldRedirect); 25 | }); 26 | 27 | it("Should throw error for setting max redirects more than allowed", () => { 28 | try { 29 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 30 | const options = new RedirectHandlerOptions(100); 31 | throw new Error("Test Failed - Something wrong with the max redirects value redirection"); 32 | } catch (error) { 33 | assert.equal(error.name, "MaxLimitExceeded"); 34 | } 35 | }); 36 | it("Should throw error for setting max redirects to negative", () => { 37 | try { 38 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 39 | const options = new RedirectHandlerOptions(-10); 40 | throw new Error(" Test Failed - Something wrong with the max redirects value redirection"); 41 | } catch (error) { 42 | assert.equal(error.name, "MinExpectationNotMet"); 43 | } 44 | }); 45 | 46 | it("Should initialize instance with default options", () => { 47 | const options = new RedirectHandlerOptions(); 48 | assert.equal(options.maxRedirects, RedirectHandlerOptions["DEFAULT_MAX_REDIRECTS"]); 49 | assert.equal(options.shouldRedirect, RedirectHandlerOptions["defaultShouldRedirect"]); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/common/tasks/OneDriveLargeFileUploadTask.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import { OneDriveLargeFileUploadTask } from "../../../src/tasks/OneDriveLargeFileUploadTask"; 11 | 12 | describe("OneDriveLargeFileUploadTask.ts", () => { 13 | describe("constructCreateSessionUrl", () => { 14 | const spaceFileName = " test.png "; 15 | const fileName = "test.png"; 16 | const specialFileName = "test file.png"; 17 | const encodedFileName = "test%20file.png"; 18 | 19 | it("Should trim the extra spaces in the filename", () => { 20 | assert.equal(`/me/drive/root:/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](spaceFileName)); 21 | }); 22 | 23 | it("Should encode space in the filename", () => { 24 | assert.equal(`/me/drive/root:/${encodedFileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](specialFileName)); 25 | }); 26 | 27 | it("Should return url with default root value", () => { 28 | assert.equal(`/me/drive/root:/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](fileName)); 29 | }); 30 | 31 | it("Should return url with default root value for an empty path string", () => { 32 | assert.equal(`/me/drive/root:/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](fileName, "")); 33 | }); 34 | 35 | it("Should add / in front of the path", () => { 36 | assert.equal(`/me/drive/root:/Documents/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](fileName, "Documents/")); 37 | }); 38 | 39 | it("Should add / in back of the path", () => { 40 | assert.equal(`/me/drive/root:/Documents/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](fileName, "/Documents")); 41 | }); 42 | 43 | it("Should trim the extra spaces in the path", () => { 44 | assert.equal(`/me/drive/root:/Documents/${fileName}:/createUploadSession`, OneDriveLargeFileUploadTask["constructCreateSessionUrl"](fileName, " /Documents/ ")); 45 | }); 46 | }); 47 | 48 | describe("getFileInfo", () => { 49 | /* tslint:disable: no-string-literal */ 50 | it("Should return file content info for Buffer", () => { 51 | const bytes = [1, 2, 3, 4, 5]; 52 | const buffer = Buffer.from(bytes); 53 | const fileContent = OneDriveLargeFileUploadTask["getFileInfo"](buffer, "test.png"); 54 | const arrayBuffer = new ArrayBuffer(bytes.length); 55 | const typedArray = new Uint8Array(arrayBuffer); 56 | for (let i = 0; i < bytes.length; i++) { 57 | typedArray[i] = bytes[i]; 58 | } 59 | assert.deepEqual(fileContent, { content: arrayBuffer as Buffer, size: bytes.length }); 60 | }); 61 | /* tslint:enable: no-string-literal */ 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /test/common/tasks/OneDriveLargeFileUploadTaskUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { assert } from "chai"; 9 | 10 | import * as OneDriveLargeFileUploadTaskUtil from "../../../src/tasks/OneDriveLargeFileUploadTaskUtil"; 11 | 12 | describe("OneDriveLargeFileUploadTaskUtil", () => { 13 | describe("getValidRangeSize", () => { 14 | it("Should return size in multiple of 320KB for the size not a multiple of 320KB", (done) => { 15 | assert.equal(327680, OneDriveLargeFileUploadTaskUtil.getValidRangeSize(327685)); 16 | done(); 17 | }); 18 | it("Should return same size for the size less than 320 KB", (done) => { 19 | assert.equal(100, OneDriveLargeFileUploadTaskUtil.getValidRangeSize(100)); 20 | done(); 21 | }); 22 | it("Should return size in multiple of 320KB with max range of 60 MB for file size more than 60 MB", (done) => { 23 | assert.equal(62914560, OneDriveLargeFileUploadTaskUtil.getValidRangeSize(104857600)); 24 | done(); 25 | }); 26 | it("Should return size in multiple of 320KB for the size multiple of 320 KB", (done) => { 27 | assert.equal(1638400, OneDriveLargeFileUploadTaskUtil.getValidRangeSize(1638400)); 28 | done(); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/common/tasks/StreamUpload.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | /* eslint-disable @typescript-eslint/no-unused-vars */ 8 | import "isomorphic-fetch"; 9 | 10 | import { assert } from "chai"; 11 | import { Readable } from "stream"; 12 | 13 | import { GraphClientError } from "../../../src"; 14 | import { StreamUpload } from "../../../src/tasks/FileUploadTask/FileObjectClasses/StreamUpload"; 15 | 16 | const fileName = "Test_File_Name"; 17 | describe("StreamUpload.test", () => { 18 | it("Should return slice with defined size less than complete range size", async () => { 19 | const totalRangesize = 36; 20 | const sliceSize = 20; 21 | const buf = Buffer.alloc(totalRangesize, "a"); 22 | const readStream = new Readable({ 23 | read() { 24 | this.push(buf); 25 | this.push(null); 26 | }, 27 | }); 28 | 29 | const upload = new StreamUpload(readStream, fileName, totalRangesize); 30 | 31 | const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); 32 | 33 | assert.isDefined(slice); 34 | assert.equal(sliceSize, (slice as Buffer).length); 35 | assert.equal(readStream.readableLength, 16); 36 | }); 37 | }); 38 | 39 | it("Should return slice ", async () => { 40 | const totalRangesize = 36; 41 | const buf = Buffer.alloc(totalRangesize, "a"); 42 | const readStream = new Readable({ 43 | read() { 44 | this.push(buf); 45 | this.push(null); 46 | }, 47 | }); 48 | const upload = new StreamUpload(readStream, fileName, totalRangesize); 49 | const slice = await upload.sliceFile({ minValue: 0, maxValue: totalRangesize - 1 }); 50 | assert.isDefined(slice); 51 | assert.equal(totalRangesize, (slice as Buffer).length); 52 | assert.equal(readStream.readableLength, 0); 53 | }); 54 | 55 | it("Should throw error if stream ends before complete range size is read", async () => { 56 | const totalsize = 6; 57 | const sliceSize = 20; 58 | const buf = Buffer.alloc(totalsize, "a"); 59 | const readStream = new Readable({ 60 | read() { 61 | this.push(buf); 62 | this.push(null); 63 | }, 64 | }); 65 | try { 66 | const upload = new StreamUpload(readStream, fileName, totalsize); 67 | const slice = await upload.sliceFile({ minValue: 0, maxValue: sliceSize - 1 }); 68 | if (slice) { 69 | throw Error("Test failed. Expected error now thrown"); 70 | } 71 | } catch (err) { 72 | assert.instanceOf(err, GraphClientError); 73 | assert.equal(err.message, "Stream ended before reading required range size"); 74 | } 75 | }); 76 | -------------------------------------------------------------------------------- /test/development/DevelopmentTests.md: -------------------------------------------------------------------------------- 1 | This folder contains test which are real-time. 2 | 3 | Following are the steps to run the tests in the test/development folder. 4 | 5 | 1. Rename the [secrets.sample.ts](../secrets.sample.ts) to secrets.ts 6 | 2. Go to Graph Explorer. 7 | 3. Login with the account you want to use to run the unit tests. 8 | 4. Click on the Access token tab option to get an access token. 9 | 5. Copy the access token and put it into the secrets.ts file and save. 10 | 6. Run the script `npm run test:development`. 11 | -------------------------------------------------------------------------------- /test/development/HardCodedAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | /** 9 | * @module HardCodedAuthenticationProvider 10 | */ 11 | 12 | import { AuthenticationProvider } from "../../src/IAuthenticationProvider"; 13 | import { AccessToken } from "./secrets"; 14 | 15 | /** 16 | * @class 17 | * @implements AuthenticationProvider 18 | * Class representing HardCodedAuthenticationProvider 19 | */ 20 | export class HardCodedAuthenticationProvider implements AuthenticationProvider { 21 | /** 22 | * @public 23 | * @async 24 | * To get the access token 25 | * @returns The promise that resolves to an access token 26 | */ 27 | public async getAccessToken(): Promise { 28 | return Promise.resolve(AccessToken); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/development/secrets.sample.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Defines access token exporting structure 4 | * 5 | * To use authentication based(making real requests to the graph service) testing populate this access token's value and rename this file as secrets.ts 6 | */ 7 | export const AccessToken = ""; 8 | -------------------------------------------------------------------------------- /test/development/test-helper.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "isomorphic-fetch"; 9 | 10 | import { Client } from "../../src/index"; 11 | import { HardCodedAuthenticationProvider } from "./HardCodedAuthenticationProvider"; 12 | 13 | export function getClient(): Client { 14 | return Client.initWithMiddleware({ 15 | authProvider: new HardCodedAuthenticationProvider(), 16 | }); 17 | } 18 | 19 | export function randomString() { 20 | return Math.random() 21 | .toString(36) 22 | .substring(7); 23 | } 24 | -------------------------------------------------------------------------------- /test/development/workload/PageIterator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Event } from "@microsoft/microsoft-graph-types"; 9 | import { assert } from "chai"; 10 | 11 | import { GraphRequestOptions, PageIterator, PageIteratorCallback } from "../../../src/tasks/PageIterator"; 12 | import { getClient } from "../test-helper"; 13 | const client = getClient(); 14 | describe("PageIterator", () => { 15 | const pstHeader = { Prefer: 'outlook.timezone= "pacific standard time"' }; 16 | const utc = "UTC"; 17 | const pst = "Pacific Standard Time"; 18 | const testURL = "/me/events"; 19 | 20 | before(async function() { 21 | this.timeout(20000); 22 | 23 | const response = await client.api(testURL + "?count=true").get(); 24 | const numberOfEvents = 4; 25 | const existingEventsCount = response.value["@odata.count"]; 26 | 27 | if (existingEventsCount >= numberOfEvents) { 28 | return; 29 | } 30 | const eventSubject = '"subject": "Test event '; 31 | const eventTimeZone = '"timeZone": "UTC"'; 32 | const eventStartDateTime = '"start": { "dateTime":"' + new Date().toISOString() + '",' + eventTimeZone + "}"; 33 | const eventEndDateTime = '"end": { "dateTime":"' + new Date().toISOString() + '",' + eventTimeZone + "}"; 34 | 35 | for (let i = 1; i <= numberOfEvents - existingEventsCount; i++) { 36 | const eventBody = "{" + eventSubject + "" + 1 + '",' + eventStartDateTime + "," + eventEndDateTime + "}"; 37 | const response = await client.api(testURL).post(eventBody); 38 | if (response.error) { 39 | throw response.error; 40 | } 41 | } 42 | }); 43 | 44 | it("same headers passed with pageIterator", async () => { 45 | const response = await client 46 | .api(`${testURL}?$top=2`) 47 | .headers(pstHeader) 48 | .select("id,start,end") 49 | .get(); 50 | 51 | const callback: PageIteratorCallback = (eventResponse) => { 52 | const event = eventResponse as Event; 53 | assert.equal(event.start.timeZone, pst); 54 | return true; 55 | }; 56 | const requestOptions: GraphRequestOptions = { options: { headers: pstHeader } }; 57 | if (response["@odata.nextLink"]) { 58 | const pageIterator = new PageIterator(client, response, callback, requestOptions); 59 | await pageIterator.iterate(); 60 | assert.isTrue(pageIterator.isComplete()); 61 | } 62 | }).timeout(30 * 1000); 63 | 64 | it("different headers passed with pageIterator", async () => { 65 | const response = await client 66 | .api(`${testURL}?$top=2`) 67 | .headers({ Prefer: `outlook.timezone= "${utc}"` }) 68 | .select("id,start,end") 69 | .get(); 70 | 71 | let counter = 0; 72 | const callback: PageIteratorCallback = (eventResponse) => { 73 | const event = eventResponse as Event; 74 | if (counter < 2) { 75 | assert.equal(event.start.timeZone, utc); 76 | counter++; 77 | } else { 78 | assert.equal(event.start.timeZone, pst); 79 | } 80 | return true; 81 | }; 82 | 83 | const requestOptions = { headers: pstHeader }; 84 | if (response["@odata.nextLink"]) { 85 | const pageIterator = new PageIterator(client, response, callback, requestOptions); 86 | await pageIterator.iterate(); 87 | assert.isTrue(pageIterator.isComplete()); 88 | } 89 | }).timeout(30 * 1000); 90 | }); 91 | -------------------------------------------------------------------------------- /test/development/workload/delta-query.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "isomorphic-fetch"; 9 | 10 | import { Event } from "@microsoft/microsoft-graph-types"; 11 | import { assert } from "chai"; 12 | 13 | import { getClient, randomString } from "../test-helper"; 14 | 15 | const client = getClient(); 16 | 17 | describe("Delta Query", function() { 18 | this.timeout(10 * 1000); 19 | const today = new Date(); 20 | const tomorrow = new Date(today.getTime() + 1 * 24 * 60 * 60 * 1000); 21 | const nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000); 22 | 23 | let deltaLink: string; 24 | 25 | const subject: string = randomString(); 26 | 27 | const mockEvent: Event = { 28 | originalStartTimeZone: tomorrow.toISOString(), 29 | originalEndTimeZone: tomorrow.toISOString(), 30 | reminderMinutesBeforeStart: 99, 31 | isReminderOn: true, 32 | subject, 33 | }; 34 | 35 | it("Gets the delta link for the initial calendar view list", async () => { 36 | let res = await client 37 | .api("/me/calendarview/delta") 38 | .query({ 39 | startdatetime: today.toISOString(), 40 | enddatetime: nextWeek.toISOString(), 41 | }) 42 | .get(); 43 | while (res["@odata.nextLink"] !== undefined) { 44 | res = await client.api(res["@odata.nextLink"]).get(); 45 | } 46 | assert.isDefined(res["@odata.deltaLink"]); 47 | deltaLink = res["@odata.deltaLink"]; 48 | }); 49 | 50 | it("Creates a calendar event to see changes in the delta response", async () => { 51 | const response = await client.api("/me/events").post(mockEvent); 52 | assert.isDefined(response.id); 53 | assert.equal(response.subject, subject); 54 | }); 55 | 56 | it("Uses delta token to see changed calendar view", async () => { 57 | let found = false; 58 | if (typeof deltaLink !== "undefined") { 59 | const res = await client.api(deltaLink).get(); 60 | const events: Event[] = res.value; 61 | for (const event of events) { 62 | if (event.subject === mockEvent.subject) { 63 | found = true; 64 | } 65 | } 66 | } 67 | assert.isTrue(found); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/development/workload/excel.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { WorkbookRange, WorkbookWorksheet } from "@microsoft/microsoft-graph-types"; 9 | import { assert } from "chai"; 10 | import * as fs from "fs"; 11 | 12 | import { getClient, randomString } from "../test-helper"; 13 | 14 | const client = getClient(); 15 | 16 | const ExcelFilename = `empty-spreadsheet-${randomString()}.xlsx`; 17 | 18 | describe("Excel", function() { 19 | this.timeout(10 * 1000); 20 | beforeEach((done) => { 21 | setTimeout(() => { 22 | done(); 23 | }, 1000); 24 | }); 25 | it("Uploads an Excel file to OneDrive", async () => { 26 | const file = fs.readFileSync("./test/sample_files/empty-spreadsheet.xlsx"); 27 | const res = await client.api(`/me/drive/root/children/${ExcelFilename}/content`).put(file); 28 | assert.isDefined(res.id); 29 | }); 30 | 31 | it("Lists the worksheets in an excel file", async () => { 32 | const res = await client.api(`/me/drive/root:/${ExcelFilename}:/workbook/worksheets`).get(); 33 | const worksheets = res.value as WorkbookWorksheet[]; 34 | const sheet1 = worksheets[0]; 35 | assert.isNumber(sheet1.position); 36 | assert.isString(sheet1.visibility); 37 | assert.isString(sheet1.id); 38 | assert.isUndefined(sheet1["random fake property that should be null"]); 39 | }); 40 | 41 | it("Updates workbook worksheet range", async () => { 42 | const sampleData: WorkbookRange = { 43 | values: [ 44 | ["cell a1", "cell a2"], 45 | ["cell b1", "cell b2"], 46 | ], 47 | }; 48 | const response = await client.api(`/me/drive/root:/${ExcelFilename}:/workbook/worksheets/Sheet1/range(address='A1:B2')`).patch(sampleData); 49 | assert.isDefined(response["@odata.id"]); 50 | assert.isDefined(response.values); 51 | }); 52 | 53 | it("GETs the used range of the worksheet", async () => { 54 | const res: WorkbookRange = await client.api(`/me/drive/root:/${ExcelFilename}:/workbook/worksheets/Sheet1/range/usedrange`).get(); 55 | assert.isNumber(res.cellCount); 56 | assert.isString(res.address); 57 | assert.isUndefined(res["random fake property that should be null"]); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/development/workload/groups.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Group } from "@microsoft/microsoft-graph-types"; 9 | import { assert } from "chai"; 10 | 11 | import { getClient, randomString } from "../test-helper"; 12 | 13 | const client = getClient(); 14 | 15 | describe("Groups", function() { 16 | this.timeout(10 * 1000); 17 | it("Fetch a list of groups and access properties on a collection item", async () => { 18 | const res = await client.api("/groups").get(); 19 | const group = res.value[0] as Group; 20 | assert.isDefined(group.displayName); 21 | assert.isDefined(group.mail); 22 | assert.isDefined(group.id); 23 | assert.isUndefined(group["random fake property that should be null"]); 24 | }); 25 | 26 | it("Create a group and validate properties were set", async () => { 27 | const group: Group = { 28 | displayName: randomString(), 29 | description: randomString(), 30 | groupTypes: ["Unified"], 31 | mailEnabled: true, 32 | mailNickname: randomString(), 33 | securityEnabled: true, 34 | }; 35 | const res = await client.api("/groups").post(group); 36 | const createdGroup = res as Group; 37 | assert.equal(createdGroup.displayName, group.displayName); 38 | assert.equal(createdGroup.description, group.description); 39 | assert.equal(createdGroup.mailEnabled, group.mailEnabled); 40 | assert.isString(createdGroup.id); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/development/workload/insights.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Person } from "@microsoft/microsoft-graph-types"; 9 | import { assert } from "chai"; 10 | 11 | import { getClient } from "../test-helper"; 12 | 13 | const client = getClient(); 14 | 15 | describe("Social and Insights", function() { 16 | this.timeout(10 * 1000); 17 | it("Fetch a list of people", async () => { 18 | const res = await client.api("/me/people").get(); 19 | const person = res.value[0] as Person; 20 | assert.isDefined(person.displayName); 21 | assert.isDefined(person.surname); 22 | assert.isDefined(person.id); 23 | assert.isUndefined(person["random fake property that should be null"]); 24 | }); 25 | 26 | it("Searches the people list", async () => { 27 | await client 28 | .api("/me/people") 29 | .query("$search=j") 30 | .get(); 31 | }); 32 | 33 | it("Searches the people list with a topic", async () => { 34 | await client 35 | .api("/me/people") 36 | .query(`$search="topic: planning"`) 37 | .get(); 38 | }); 39 | 40 | it("Finds items trending around me", async () => { 41 | await client 42 | .api("/me/insights/trending") 43 | .version("beta") 44 | .get(); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test/development/workload/largeFileUpload.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "isomorphic-fetch"; 9 | 10 | import { assert } from "chai"; 11 | import * as fs from "fs"; 12 | 13 | import { getClient } from "../test-helper"; 14 | const client = getClient(); 15 | 16 | import { OneDriveLargeFileUploadOptions, OneDriveLargeFileUploadTask, Range, StreamUpload, UploadEventHandlers } from "../../../src/index"; 17 | 18 | describe("LargeFileUpload", () => { 19 | const fileName = "sample_image.jpg"; 20 | const stats = fs.statSync(`./test/sample_files/${fileName}`); 21 | const totalsize = stats.size; 22 | it("Test OneDrive stream upload with progress callback options", async () => { 23 | let isProgressReportCalled = false; 24 | 25 | const progress = (range?: Range, extraCallBackParams?: unknown) => { 26 | assert.isTrue(extraCallBackParams); 27 | assert.isDefined(range); 28 | isProgressReportCalled = true; 29 | }; 30 | 31 | const uploadEventHandlers: UploadEventHandlers = { 32 | progress, 33 | extraCallbackParam: true, 34 | }; 35 | 36 | const options: OneDriveLargeFileUploadOptions = { 37 | path: "/Documents", 38 | fileName, 39 | rangeSize: 1024 * 1024, 40 | uploadEventHandlers, 41 | }; 42 | const readStream = fs.createReadStream(`./test/sample_files/${fileName}`); 43 | const file = new StreamUpload(readStream, fileName, totalsize); 44 | const uploadTask = await OneDriveLargeFileUploadTask.createTaskWithFileObject(client, file, options); 45 | const response = await uploadTask.upload(); 46 | assert.isDefined(response.responseBody["id"]); 47 | assert.isTrue(isProgressReportCalled); 48 | }).timeout(30 * 1000); 49 | 50 | it("Test OneDrive File Upload", async () => { 51 | const options: OneDriveLargeFileUploadOptions = { 52 | path: "/Documents", 53 | fileName, 54 | rangeSize: 1024 * 1024, 55 | }; 56 | const file = fs.readFileSync(`./test/sample_files/${fileName}`); 57 | const uploadTask = await OneDriveLargeFileUploadTask.create(client, file, options); 58 | const response = await uploadTask.upload(); 59 | assert.isDefined(response.responseBody["id"]); 60 | }).timeout(30 * 1000); 61 | 62 | it("Test OneDrive File Upload to custom url", async () => { 63 | const options: OneDriveLargeFileUploadOptions = { 64 | path: "/Documents", 65 | fileName, 66 | rangeSize: 1024 * 1024, 67 | uploadSessionURL: `https://graph.microsoft.com/v1.0/me/drive/special/approot:/sampleTest/${fileName}:/createUploadSession`, 68 | }; 69 | const file = fs.readFileSync(`./test/sample_files/${fileName}`); 70 | const uploadTask = await OneDriveLargeFileUploadTask.create(client, file, options); 71 | const response = await uploadTask.upload(); 72 | assert.isDefined(response.responseBody["id"]); 73 | }).timeout(30 * 1000); 74 | }); 75 | -------------------------------------------------------------------------------- /test/development/workload/open-extensions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { OpenTypeExtension } from "@microsoft/microsoft-graph-types"; 9 | import { assert } from "chai"; 10 | 11 | import { getClient, randomString } from "../test-helper"; 12 | 13 | const client = getClient(); 14 | 15 | interface ColorOpenExtension extends OpenTypeExtension { 16 | color: string; 17 | } 18 | 19 | let extension: ColorOpenExtension = { 20 | extensionName: `com.javascript.extension-${randomString()}`, 21 | color: randomString(), 22 | }; 23 | 24 | describe("Open Extensions", function() { 25 | this.timeout(10 * 1000); 26 | 27 | it("Use open extensions to add a field to users", async () => { 28 | const response = await client.api("/me/extensions").post(extension); 29 | const createdExtension = response as ColorOpenExtension; 30 | assert.isDefined(createdExtension.id); 31 | assert.equal(createdExtension.color, extension.color); 32 | assert.equal(createdExtension.extensionName, extension.extensionName); 33 | assert.isUndefined(createdExtension["random fake property that should be null"]); 34 | // save this createdExtension for later tests (id) 35 | extension = createdExtension; 36 | }); 37 | 38 | it("Deletes the created open extension", async () => { 39 | await client.api(`/me/extensions/${extension.id}`).delete(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/development/workload/users.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "isomorphic-fetch"; 9 | 10 | import { User } from "@microsoft/microsoft-graph-types"; 11 | import { assert } from "chai"; 12 | 13 | import { getClient, randomString } from "../test-helper"; 14 | 15 | const client = getClient(); 16 | 17 | describe("Users", function() { 18 | this.timeout(10 * 1000); 19 | 20 | it("Fetch the authenticated user and access entity properties", async () => { 21 | const res = await client.api("/me").get(); 22 | const user = res as User; 23 | assert.isDefined(user.displayName); 24 | assert.isDefined(user.mail); 25 | assert.isDefined(user.id); 26 | 27 | assert.isDefined(user.surname); 28 | assert.isDefined(user.userPrincipalName); 29 | 30 | assert.isArray(user.businessPhones); 31 | assert.isUndefined(user["random fake property that should be null"]); 32 | }); 33 | 34 | it("Fetch the authenticated user and access entity properties", async () => { 35 | const res = await client.api("/me").get(); 36 | const user = res as User; 37 | assert.isDefined(user.displayName); 38 | assert.isDefined(user.mail); 39 | assert.isDefined(user.id); 40 | 41 | assert.isDefined(user.surname); 42 | assert.isDefined(user.userPrincipalName); 43 | 44 | assert.isArray(user.businessPhones); 45 | assert.isUndefined(user["random fake property that should be null"]); 46 | }); 47 | 48 | it("Modify and verify officeLocation property", async () => { 49 | const officeLocation = randomString(); 50 | await client.api("/me").patch({ officeLocation }); 51 | const res = await client.api("/me").get(); 52 | const user = res as User; 53 | assert.equal(user.officeLocation, officeLocation); 54 | }); 55 | 56 | it("Modify and verify givenName property", async () => { 57 | const givenName = randomString(); 58 | await client.api("/me").patch({ givenName }); 59 | const res = await client.api("/me").get(); 60 | const user = res as User; 61 | assert.equal(user.givenName, givenName); 62 | }); 63 | 64 | it("Fetch a list of users and access properties on a collection item", async () => { 65 | const collection = await client.api("/users").get(); 66 | const users: User[] = collection.value; 67 | assert.isDefined(users[0].displayName); 68 | assert.isDefined(users[0].id); 69 | assert.isDefined(users[0].mail); 70 | }); 71 | 72 | it("Filters on users list", async () => { 73 | await client 74 | .api("/users") 75 | .filter("Department eq 'Finance'") 76 | .get(); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/node/NodeTests.md: -------------------------------------------------------------------------------- 1 | This folder contains unit tests which are node-specific. 2 | 3 | Karma is used for testing the code in browsers. To run the unit tests using karma run the following steps - 4 | 5 | - Run the script `npm install` 6 | - Run the script `npm run test` 7 | -------------------------------------------------------------------------------- /test/node/authentication/TokenCredentialAuthenticationProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | /*tslint:disable*/ 8 | import { AccessToken, ClientSecretCredential } from "@azure/identity"; 9 | import { assert } from "chai"; 10 | import * as sinon from "sinon"; 11 | 12 | import { TokenCredentialAuthenticationProviderOptions } from "../../../src/authentication/azureTokenCredentials/ITokenCredentialAuthenticationProviderOptions"; 13 | import { TokenCredentialAuthenticationProvider } from "../../../src/authentication/azureTokenCredentials/TokenCredentialAuthenticationProvider"; 14 | describe("TokenCredentialAuthenticationProvider.ts", () => { 15 | const tenantId = "0000-1111-0000-1111"; 16 | const clientId = "CLIENT_ID"; 17 | const clientSecret = "CLIENT_SECRET"; 18 | const scopes = ["test_scopes"]; 19 | it("AccessToken is returned correctly from getToken function", async () => { 20 | const client = new ClientSecretCredential(tenantId, clientId, clientSecret); 21 | if (typeof client.getToken !== "function") { 22 | throw new Error("Method definition for getToken is not found"); 23 | } 24 | 25 | const authProviderOptions: TokenCredentialAuthenticationProviderOptions = { 26 | getTokenOptions: null, 27 | scopes, 28 | }; 29 | const accessToken: AccessToken = { token: "dummy_valid_token", expiresOnTimestamp: 1 }; 30 | 31 | const moq = sinon.mock(client); 32 | moq.expects("getToken").resolves(accessToken); 33 | const tokenCredentialAuthenticationProvider = new TokenCredentialAuthenticationProvider(client, authProviderOptions); 34 | const access = await tokenCredentialAuthenticationProvider.getAccessToken(); 35 | assert.equal(access, accessToken.token); 36 | }); 37 | 38 | it("Error is thrown when accessToken cannot be retrieved from getToken function", async () => { 39 | let expectedError; 40 | try { 41 | const client = new ClientSecretCredential(tenantId, clientId, clientSecret); 42 | if (typeof client.getToken !== "function") { 43 | throw new Error("Method definition for getToken is not found"); 44 | } 45 | const authProviderOptions: TokenCredentialAuthenticationProviderOptions = { 46 | getTokenOptions: null, 47 | scopes, 48 | }; 49 | const accessToken: AccessToken = undefined; 50 | 51 | const moq = sinon.mock(client); 52 | moq.expects("getToken").resolves(accessToken); 53 | const tokenCredentialAuthenticationProvider = new TokenCredentialAuthenticationProvider(client, authProviderOptions); 54 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 55 | const access = await tokenCredentialAuthenticationProvider.getAccessToken(); 56 | } catch (err) { 57 | expectedError = err; 58 | } 59 | assert.equal(expectedError.name, "Access token is undefined"); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/node/content/BatchRequestContent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import "isomorphic-fetch"; 9 | 10 | import { assert } from "chai"; 11 | import * as fs from "fs"; 12 | 13 | import { BatchRequestContent } from "../../../src/content/BatchRequestContent"; 14 | import { GRAPH_BASE_URL } from "../../../src/Constants"; 15 | 16 | describe("BatchRequestContent.ts", () => { 17 | describe("getContent", () => { 18 | it("Should return image's base64 string", async () => { 19 | const fileName = "sample_image.jpg"; 20 | fs.readFile(`./test/sample_files/${fileName}`, {}, async (err, file) => { 21 | if (err) { 22 | throw err; 23 | } 24 | const uploadOneDriveFile = { 25 | id: "1", 26 | request: new Request(`${GRAPH_BASE_URL}me/drive/root:/Documents/${fileName}:/content`, { 27 | method: "PUT", 28 | headers: { 29 | "Content-type": "image/jpg", 30 | }, 31 | body: file, 32 | }), 33 | }; 34 | const batchReq = new BatchRequestContent([uploadOneDriveFile]); 35 | const content = await batchReq.getContent(); 36 | assert.isDefined(content.requests[0].body); 37 | }); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/sample_files/empty-spreadsheet.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-sdk-javascript/db1757abe7a4cad310f0cd4d7d2a83b961390cce/test/sample_files/empty-spreadsheet.xlsx -------------------------------------------------------------------------------- /test/sample_files/onenotepage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | New Page 5 | 6 | 7 | 8 |

Created a OneNote page from HTML

9 | 10 | 11 | -------------------------------------------------------------------------------- /test/sample_files/onenotepage_fileattachment.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A page with rendered file attachment 5 | 6 | 7 | 8 |

Here is an attached file:

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/sample_files/sample_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-sdk-javascript/db1757abe7a4cad310f0cd4d7d2a83b961390cce/test/sample_files/sample_image.jpg -------------------------------------------------------------------------------- /test/test-helper.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ------------------------------------------------------------------------------------------- 3 | * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. 4 | * See License in the project root for license information. 5 | * ------------------------------------------------------------------------------------------- 6 | */ 7 | 8 | import { Client } from "../src/index"; 9 | import { DummyAuthenticationProvider } from "./DummyAuthenticationProvider"; 10 | 11 | export function getClient(): Client { 12 | return Client.initWithMiddleware({ 13 | authProvider: new DummyAuthenticationProvider(), 14 | }); 15 | } 16 | 17 | export function randomString() { 18 | return Math.random() 19 | .toString(36) 20 | .substring(7); 21 | } 22 | 23 | export const DUMMY_BASE_URL = "https://localhost"; 24 | -------------------------------------------------------------------------------- /test/tsconfig-test-development.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./../tsconfig-base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es5", 6 | "esModuleInterop": true, 7 | "noEmitOnError": true, 8 | "lib": ["dom", "esnext"], 9 | "outDir": "../lib/" 10 | }, 11 | "include": ["./development/", "../src/"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "importHelpers": true, 4 | "noEmitOnError": true, 5 | "noImplicitAny": false, 6 | "moduleResolution": "node", 7 | "removeComments": false, 8 | "sourceMap": true, 9 | "declaration": true, 10 | } 11 | } -------------------------------------------------------------------------------- /tsconfig-cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es5", 6 | "lib": ["dom", "esnext"], 7 | "outDir": "lib", 8 | "composite": true 9 | }, 10 | "exclude": ["node_modules", "lib", "samples", "test/development"], 11 | "include": ["./src/**/*.ts", "./test"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig-es.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-base.json", 3 | "compilerOptions": { 4 | "module": "es6", 5 | "target": "es6", 6 | "lib": ["dom", "esnext"], 7 | "outDir": "lib/es", 8 | "composite": true 9 | }, 10 | "exclude": ["node_modules", "lib", "samples", "test/development"], 11 | "include": ["./src/**/*.ts", "./test/**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig-sub-cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es5", 6 | "lib": ["dom", "esnext"], 7 | "outDir": "authProviders" 8 | }, 9 | "exclude": ["node_modules", "lib", "samples", "test/", "src"], 10 | "include": ["authProviderOptions/azureTokenCredentials/", "authProviderOptions/authCodeMsalBrowser"], 11 | "references": [ 12 | { 13 | "path": "./tsconfig-cjs.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig-sub-es.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-base.json", 3 | "compilerOptions": { 4 | "module": "es6", 5 | "target": "es6", 6 | "lib": ["dom", "esnext"], 7 | "outDir": "authProviders/es" 8 | }, 9 | "exclude": ["node_modules", "lib", "samples", "test/**", "src"], 10 | "include": ["authProviderOptions/es/**/*.ts"], 11 | "references": [ 12 | { 13 | "path": "./tsconfig-es.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /types-demo.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-sdk-javascript/db1757abe7a4cad310f0cd4d7d2a83b961390cce/types-demo.PNG --------------------------------------------------------------------------------