├── .aiAutoMinify.json ├── .eslintrc ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── codeql │ └── codeql-config.yml └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ ├── lock.yml │ └── stale.yml ├── .gitignore ├── .npmignore ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README-manual.md ├── README.md ├── RELEASES.md ├── SECURITY.md ├── SUPPORT.md ├── ThirdPartyNotices.txt ├── applicationinsights-react-native ├── .npmignore ├── LICENSE ├── NOTICE ├── PRIVACY ├── README.md ├── Tests │ ├── External │ │ └── DummyReactNative.js │ ├── Unit │ │ └── src │ │ │ └── reactnativeplugin.tests.ts │ ├── UnitTests.html │ └── tsconfig.json ├── api-extractor.json ├── package.json ├── rollup.config.js ├── src │ ├── DeviceInfo │ │ ├── DeviceModule.ts │ │ └── ReactNativeDeviceInfo.ts │ ├── Interfaces │ │ ├── IDeviceInfoModule.ts │ │ ├── INativeDevice.ts │ │ ├── IReactNativePluginConfig.ts │ │ └── index.ts │ ├── ReactNativeManualDevicePlugin.ts │ ├── ReactNativePlugin.ts │ ├── index.ts │ └── manualIndex.ts ├── tsconfig.json └── tslint.json ├── common ├── Tests │ ├── External │ │ ├── blanket-1.2.2.js │ │ ├── blanket-reporter.js │ │ ├── es6-promise.auto.min.js │ │ ├── jquery-1.11.1.js │ │ ├── jquery.d.ts │ │ ├── magic-string.umd.js │ │ ├── qunit-2.9.1.css │ │ ├── qunit-2.9.1.js │ │ ├── qunit-2.9.3.css │ │ ├── qunit-2.9.3.js │ │ ├── qunit.d.ts │ │ ├── require-2.2.0.js │ │ ├── require-2.3.6.js │ │ ├── sinon-2.3.8.js │ │ ├── sinon-7.3.1.js │ │ ├── sinon.d.ts │ │ └── whatwg-fetch.3.0.0.js │ ├── Framework │ │ ├── package.json │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── AITestClass.ts │ │ │ ├── Assert.ts │ │ │ ├── DebugHelpers.ts │ │ │ ├── PollingAssert.ts │ │ │ ├── TelemetryValidation │ │ │ │ ├── CommonValidator.ts │ │ │ │ ├── EventValidator.ts │ │ │ │ ├── ExceptionValidator.ts │ │ │ │ ├── ITypeValidator.ts │ │ │ │ ├── MetricValidator.ts │ │ │ │ ├── PageViewPerformanceValidator.ts │ │ │ │ ├── PageViewValidator.ts │ │ │ │ ├── RemoteDepdencyValidator.ts │ │ │ │ └── TraceValidator.ts │ │ │ ├── TestCase.ts │ │ │ └── ai-test-framework.ts │ │ └── tsconfig.json │ └── Selenium │ │ ├── ExceptionHelper.js │ │ ├── ModuleLoader.js │ │ └── SimpleSyncPromise.js ├── changes │ └── @microsoft │ │ └── applicationinsights-web │ │ └── markwolff-refactor_readme_2019-10-04-20-34.json ├── config │ └── rush │ │ ├── .npmrc │ │ ├── command-line.json │ │ ├── common-versions.json │ │ ├── npm-shrinkwrap.json │ │ └── version-policies.json ├── publish │ ├── AzureStorageHelper │ │ └── AzureStorageHelper.psm1 │ └── Logging │ │ └── Logging.psm1 └── scripts │ ├── install-run-rush-silent.js │ ├── install-run-rush.js │ ├── install-run-rushx.js │ ├── install-run-silent.js │ └── install-run.js ├── gruntfile.js ├── package.json ├── policheck-exclusions.xml ├── rush.json ├── sample ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png ├── babel.config.js └── package.json ├── scripts ├── dtsgen.js └── dtsgen.ps1 ├── tools ├── grunt-tasks │ ├── chrome │ │ └── bridge.js │ ├── minifyNames.js │ └── qunit.js ├── release-tools │ ├── README.md │ ├── npm-package.js │ ├── package.json │ ├── package_groups.json │ ├── setAiVersion.js │ ├── setVersion.js │ ├── updatemanifest.js │ └── zipbrowser.js ├── rollup-plugin-uglify3-js │ ├── .eslintrc │ ├── dist │ │ └── esm │ │ │ └── rollup-plugin-uglify3-js.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── uglify3-js.ts │ └── tsconfig.json ├── status-tools │ ├── github-status.js │ └── package.json ├── subResourceIntegrity │ └── generateIntegrityFile.js └── updateDistEsm │ └── updateDistEsm.js ├── tsconfig.json └── version.json /.aiAutoMinify.json: -------------------------------------------------------------------------------- 1 | { 2 | "pkgs": { 3 | "@microsoft/applicationinsights-core-js": { 4 | "constEnums": [ 5 | "CallbackType", 6 | "eEventsDiscardedReason", 7 | "eLoggingSeverity", 8 | "_eInternalMessageId", 9 | "SendRequestReason", 10 | "TelemetryUnloadReason", 11 | "TelemetryUpdateReason", 12 | "GetExtCfgMergeType" 13 | ] 14 | }, 15 | "@microsoft/applicationinsights-perfmarkmeasure-js": { 16 | "constEnums": [] 17 | }, 18 | "@microsoft/applicationinsights-common": { 19 | "constEnums": [ 20 | "eStorageType", 21 | "FieldType", 22 | "eDistributedTracingModes", 23 | "eRequestHeaders", 24 | "DataPointType", 25 | "DependencyKind", 26 | "DependencySourceType", 27 | "eSeverityLevel", 28 | "DataSanitizerValues" 29 | ] 30 | }, 31 | "@microsoft/applicationinsights-properties-js": { 32 | "constEnums": [] 33 | }, 34 | "@microsoft/applicationinsights-dependencies-js": { 35 | "constEnums": [] 36 | }, 37 | "@microsoft/applicationinsights-debugplugin-js": { 38 | "constEnums": [] 39 | }, 40 | "@microsoft/applicationinsights-channel-js": { 41 | "constEnums": [] 42 | }, 43 | "@microsoft/applicationinsights-react-native": { 44 | "constEnums": [] 45 | }, 46 | "@microsoft/applicationinsights-clickanalytics-js": { 47 | "constEnums": [ 48 | "_eExtendedInternalMessageId" 49 | ] 50 | }, 51 | "@microsoft/applicationinsights-web-basic": { 52 | "constEnums": [] 53 | }, 54 | "@microsoft/applicationinsights-analytics-js": { 55 | "constEnums": [] 56 | }, 57 | "@microsoft/applicationinsights-web": { 58 | "constEnums": [] 59 | }, 60 | "@microsoft/applicationinsights-react-js": { 61 | "constEnums": [] 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "plugins": [ 7 | "security" 8 | ], 9 | "extends": [ 10 | "eslint:recommended", 11 | "plugin:@typescript-eslint/recommended", 12 | "plugin:security/recommended" 13 | ], 14 | "rules": { 15 | "indent": ["error"], // Enabling for auto fixing 16 | "quotes": ["warn", "double"], // Enabled for auto fixing 17 | "curly": [ "error" ], // Enabling for auto fixing 18 | "brace-style": [ "error" ], // Enabling for auto fixing 19 | "prefer-const": "off", 20 | "prefer-spread": "off", 21 | "no-var": "off", 22 | "no-extra-boolean-cast": "off", 23 | "prefer-rest-params": "off", 24 | "no-case-declarations": "off", 25 | "no-prototype-builtins": "off", 26 | "no-useless-escape": "off", // Suppressing Error -- need to Review Later 27 | "no-trailing-spaces": [ "warn", { "skipBlankLines": true }],// Enabled for auto fixing 28 | "no-const-assign": "error", 29 | "comma-dangle": [ "error", "never" ], // Enabled for auto fixing 30 | "security/detect-object-injection": "off", // Suppress Warning -- need to Review Later 31 | "@typescript-eslint/ban-types": "off", 32 | "@typescript-eslint/no-unused-vars": [ "warn", { "vars": "all", "args": "none", "argsIgnorePattern": "^_", "ignoreRestSiblings": true } ], 33 | "@typescript-eslint/triple-slash-reference": "off", 34 | "@typescript-eslint/no-inferrable-types": "off", 35 | "@typescript-eslint/no-this-alias": "off", 36 | "@typescript-eslint/no-explicit-any": "off", 37 | "@typescript-eslint/no-empty-function": "off", 38 | "@typescript-eslint/no-empty-interface": "off", 39 | "@typescript-eslint/explicit-module-boundary-types": "off", 40 | "@typescript-eslint/no-extra-semi": "error", // Enabled for auto fixing 41 | "@typescript-eslint/no-non-null-assertion": "error" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | # Don't allow people to merge changes to these generated files, because the result 6 | # may be invalid. You need to run "rush update" again. 7 | shrinkwrap.yaml merge=binary 8 | npm-shrinkwrap.json merge=binary 9 | yarn.lock merge=binary 10 | 11 | ############################################################################### 12 | # Set default behavior for command prompt diff. 13 | # 14 | # This is need for earlier builds of msysgit that does not have it on by 15 | # default for csharp files. 16 | # Note: This is only used by command line 17 | ############################################################################### 18 | #*.cs diff=csharp 19 | 20 | ############################################################################### 21 | # Set the merge driver for project and solution files 22 | # 23 | # Merging from the command prompt will add diff markers to the files if there 24 | # are conflicts (Merging from VS is not affected by the settings below, in VS 25 | # the diff markers are never inserted). Diff markers may cause the following 26 | # file extensions to fail to load in VS. An alternative would be to treat 27 | # these files as binary and thus will always conflict and require user 28 | # intervention with every merge. To do so, just uncomment the entries below 29 | ############################################################################### 30 | #*.sln merge=binary 31 | #*.csproj merge=binary 32 | #*.vbproj merge=binary 33 | #*.vcxproj merge=binary 34 | #*.vcproj merge=binary 35 | #*.dbproj merge=binary 36 | #*.fsproj merge=binary 37 | #*.lsproj merge=binary 38 | #*.wixproj merge=binary 39 | #*.modelproj merge=binary 40 | #*.sqlproj merge=binary 41 | #*.wwaproj merge=binary 42 | 43 | ############################################################################### 44 | # behavior for image files 45 | # 46 | # image files are treated as binary by default. 47 | ############################################################################### 48 | #*.jpg binary 49 | #*.png binary 50 | #*.gif binary 51 | 52 | ############################################################################### 53 | # diff behavior for common document formats 54 | # 55 | # Convert binary document formats to text before diffing them. This feature 56 | # is only available from the command line. Turn it on by uncommenting the 57 | # entries below. 58 | ############################################################################### 59 | #*.doc diff=astextplain 60 | #*.DOC diff=astextplain 61 | #*.docx diff=astextplain 62 | #*.DOCX diff=astextplain 63 | #*.dot diff=astextplain 64 | #*.DOT diff=astextplain 65 | #*.pdf diff=astextplain 66 | #*.PDF diff=astextplain 67 | #*.rtf diff=astextplain 68 | #*.RTF diff=astextplain 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a new bug report 4 | title: "[BUG]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description/Screenshot** 11 | 12 | **Steps to Reproduce** 13 | 14 | - OS/Browser: 15 | - React-Native Version: 16 | - SDK Version [e.g. 22]: 17 | - How you initialized the SDK: 18 | 19 | **Expected behavior** 20 | 21 | **Additional context** 22 | Add any other context about the problem here. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL config" 2 | 3 | queries: 4 | - uses: security-and-quality 5 | 6 | paths-ignore: 7 | - '**/test/' 8 | - '**/Tests/' 9 | - '**/dist-history/' 10 | - '**/rollup.config.js' 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.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: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ main, release3.x ] 9 | pull_request: 10 | branches: [ main, release3.x ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [16.x, 18.x, 20.x] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - name: Update rush shrinkwrap dependencies (for different node versions) 28 | run: node common/scripts/install-run-rush.js update --full --recheck 29 | - run: npm install rollup -g 30 | - run: npm install grunt-cli findup-sync nopt pify@2.3.0 31 | - run: npm install 32 | - run: node common/scripts/install-run-rush.js check 33 | - run: node common/scripts/install-run-rush.js update --full --recheck 34 | - run: npm run build --verbose 35 | timeout-minutes: 10 36 | - run: npm run test --verbose 37 | timeout-minutes: 15 38 | -------------------------------------------------------------------------------- /.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: [ main, release3.x ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main, release3.x ] 20 | schedule: 21 | - cron: '17 15 * * 2' 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' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | config-file: ./.github/codeql/codeql-config.yml 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 54 | 55 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 56 | # If this step fails, then you should remove it and run the build manually (see below) 57 | - name: Autobuild 58 | uses: github/codeql-action/autobuild@v1 59 | 60 | # ℹ️ Command-line programs to run using the OS shell. 61 | # 📚 https://git.io/JvXDl 62 | 63 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 64 | # and modify them (or add more) to build your code if your project 65 | # uses a compiled language 66 | 67 | #- run: | 68 | # make bootstrap 69 | # make release 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v1 73 | -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: 'Lock Threads' 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | permissions: 8 | actions: write 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | action: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: dessant/lock-threads@v2 17 | with: 18 | github-token: ${{ github.token }} 19 | issue-lock-comment: > 20 | This issue has been automatically locked since there 21 | has not been any recent activity after it was closed. 22 | Please open a new issue for related bugs. 23 | process-only: 'issues' 24 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Stale issue handler' 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '0 7 * * *' 6 | 7 | permissions: 8 | actions: write 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/stale@v9 17 | id: stale 18 | with: 19 | stale-issue-message: 'This Issue will be closed in 30 days. Please remove the "Stale" label or comment to avoid closure with no action.' 20 | stale-pr-message: 'This PR will be closed in 30 days. Please remove the "Stale" label or comment to avoid closure with no action.' 21 | operations-per-run: 200 22 | days-before-stale: 300 23 | days-before-close: 30 24 | stale-issue-label: 'stale' 25 | stale-pr-label: 'stale' 26 | close-issue-label: 'closed' 27 | close-pr-label: 'closed' 28 | exempt-issue-labels: 'bug,enhancement,documentation,waiting,keep' 29 | exempt-pr-labels: 'waiting,keep' 30 | exempt-all-milestones: true 31 | exempt-all-assignees: true 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Rr]elease/ 12 | [Bb]in/ 13 | [Oo]bj/ 14 | [Oo]bj//Core/Javascript/ai*.[tj]s* 15 | 16 | # Telemetry output 17 | *.onesipkg 18 | 19 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 20 | !packages/*/build/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | report.*.json 26 | 27 | *_i.c 28 | *_p.c 29 | *.ilk 30 | *.meta 31 | *.obj 32 | *.pch 33 | *.pdb 34 | *.pgc 35 | *.pgd 36 | *.rsp 37 | *.sbr 38 | *.tlb 39 | *.tli 40 | *.tlh 41 | *.tmp 42 | *.tmp_proj 43 | *.log 44 | *.vspscc 45 | *.vssscc 46 | .builds 47 | *.pidb 48 | *.log 49 | *.scc 50 | 51 | # Visual C++ cache files 52 | ipch/ 53 | *.aps 54 | *.ncb 55 | *.opensdf 56 | *.sdf 57 | *.cachefile 58 | 59 | # Local tgz files 60 | *.tgz 61 | 62 | # Visual Studio profiler 63 | *.psess 64 | *.vsp 65 | *.vspx 66 | 67 | # Visual Studio Code 68 | .vscode/** 69 | 70 | # Guidance Automation Toolkit 71 | *.gpState 72 | 73 | # ReSharper is a .NET coding add-in 74 | _ReSharper*/ 75 | *.[Rr]e[Ss]harper 76 | 77 | # TeamCity is a build add-in 78 | _TeamCity* 79 | 80 | # DotCover is a Code Coverage Tool 81 | *.dotCover 82 | 83 | # NCrunch 84 | *.ncrunch* 85 | .*crunch*.local.xml 86 | 87 | # Installshield output folder 88 | [Ee]xpress/ 89 | 90 | # DocProject is a documentation generator add-in 91 | DocProject/buildhelp/ 92 | DocProject/Help/*.HxT 93 | DocProject/Help/*.HxC 94 | DocProject/Help/*.hhc 95 | DocProject/Help/*.hhk 96 | DocProject/Help/*.hhp 97 | DocProject/Help/Html2 98 | DocProject/Help/html 99 | 100 | # Click-Once directory 101 | publish/ 102 | 103 | # Publish Web Output 104 | *.Publish.xml 105 | 106 | # NuGet binaries downloaded automatically 107 | packages/ 108 | 109 | # Windows Azure Build Output 110 | csx 111 | *.build.csdef 112 | 113 | # Windows Store app package directory 114 | AppPackages/ 115 | 116 | # Others 117 | sql/ 118 | *.Cache 119 | ClientBin/ 120 | [Ss]tyle[Cc]op.* 121 | ~$* 122 | *~ 123 | *.dbmdl 124 | *.[Pp]ublish.xml 125 | *.publishsettings 126 | 127 | # RIA/Silverlight projects 128 | Generated_Code/ 129 | 130 | # Backup & report files from converting an old project file to a newer 131 | # Visual Studio version. Backup files are not needed, because we have git ;-) 132 | _UpgradeReport_Files/ 133 | Backup*/ 134 | UpgradeLog*.XML 135 | UpgradeLog*.htm 136 | 137 | # SQL Server files 138 | App_Data/*.mdf 139 | App_Data/*.ldf 140 | 141 | 142 | #LightSwitch generated files 143 | GeneratedArtifacts/ 144 | _Pvt_Extensions/ 145 | ModelManifest.xml 146 | 147 | # ========================= 148 | # Windows detritus 149 | # ========================= 150 | 151 | # Windows image file caches 152 | Thumbs.db 153 | ehthumbs.db 154 | 155 | # Folder config file 156 | Desktop.ini 157 | 158 | # Recycle Bin used on file shares 159 | $RECYCLE.BIN/ 160 | 161 | # Mac desktop service store files 162 | .DS_Store 163 | 164 | # Build log files 165 | *.err 166 | *.prf 167 | *.wrn 168 | 169 | # Visual studio 2015 user specific files 170 | legacy/JavaScript/.vs 171 | 172 | # Temp directories 173 | bundle/ 174 | node_modules/ 175 | out/ 176 | coreSDK/node_modules 177 | dist-esm/ 178 | browser/ 179 | types/ 180 | dist/ 181 | dest/ 182 | # Don't commit the sub resource integrity generated files 183 | **/*.integrity.json 184 | 185 | # Grunt 186 | .tscache 187 | **/Tests/Selenium/*tests.js 188 | **/Tests/Selenium/*tests.d.ts 189 | **/Tests/Selenium/*tests.js.map 190 | 191 | # Misc 192 | statistics.html 193 | npm 194 | tests_output 195 | 196 | # Logs 197 | *.log 198 | npm-debug.log* 199 | yarn-debug.log* 200 | yarn-error.log* 201 | 202 | # Runtime data 203 | *.pid 204 | *.seed 205 | *.pid.lock 206 | 207 | # Directory for instrumented libs generated by jscoverage/JSCover 208 | lib-cov 209 | 210 | # Coverage directory used by tools like istanbul 211 | coverage 212 | 213 | # nyc test coverage 214 | .nyc_output 215 | 216 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 217 | .grunt 218 | 219 | # Bower dependency directory (https://bower.io/) 220 | bower_components 221 | 222 | # node-waf configuration 223 | .lock-wscript 224 | 225 | # Compiled binary addons (https://nodejs.org/api/addons.html) 226 | build/Release 227 | 228 | # Dependency directories 229 | jspm_packages/ 230 | 231 | # Optional npm cache directory 232 | .npm 233 | 234 | # Optional eslint cache 235 | .eslintcache 236 | 237 | # Optional REPL history 238 | .node_repl_history 239 | 240 | # Output of 'npm pack' 241 | *.tgz 242 | 243 | # Yarn Integrity file 244 | .yarn-integrity 245 | 246 | # dotenv environment variables file 247 | .env 248 | 249 | # next.js build output 250 | .next 251 | 252 | # Common toolchain intermediate files 253 | temp 254 | 255 | # Rush files 256 | common/temp/** 257 | package-deps.json 258 | package-lock.json 259 | 260 | # test output 261 | aicore.tests.js* 262 | aicore.tests.d.ts 263 | ai.tests.d.ts 264 | /.vs 265 | /index.html 266 | 267 | # Generated Constant File 268 | **/__DynamicConstants.ts -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # NPM Ignore 2 | 3 | # ignore everything 4 | * 5 | 6 | # ... but these files 7 | !/package.json 8 | !/CODE_OF_CONDUCT.md 9 | !/CONTRIBUTING.md 10 | !/README.md 11 | !/SECURITY.md 12 | !/SUPPORT.md 13 | !/NOTICE 14 | !/PRIVACY 15 | !/LICENSE 16 | !/LICENSE.TXT 17 | !/API-reference.md 18 | !/bundle/ai.module.* 19 | !/dist/ai.js 20 | !/dist/ai.js.map 21 | !/dist/ai.0.js 22 | !/dist/ai.0.js.map -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @Microsoft/ApplicationInsights-JS-owners 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to 4 | agree to a Contributor License Agreement (CLA) declaring that you have the right to, 5 | and actually do, grant us the rights to use your contribution. For details, visit 6 | https://cla.microsoft.com. 7 | 8 | When you submit a pull request, a CLA-bot will automatically determine whether you need 9 | to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the 10 | instructions provided by the bot. You will only need to do this once across all repositories using our CLA. 11 | 12 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 13 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 14 | or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 15 | 16 | ## Welcome 17 | 18 | Welcome and thank you for your interest in contributing to ApplicationInsights-JS. 19 | 20 | We strongly welcome and encourage contributions to this project. Please read the [contributor's guide][ContribGuide] located in the ApplicationInsights-Home repository. If making a large change we request that you open an [issue][GitHubIssue] first. We follow the [Git Flow][GitFlow] approach to branching. 21 | 22 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 23 | 24 | [ContribGuide]: https://github.com/microsoft/ApplicationInsights-Home/blob/master/CONTRIBUTING.md 25 | [GitFlow]: http://nvie.com/posts/a-successful-git-branching-model/ 26 | [GitHubIssue]: https://github.com/microsoft/ApplicationInsights-JS/issues 27 | 28 | ## Clone and setup 29 | 1. Clone the repository and create a new branch 30 | 2. Install all dependencies 31 | ``` 32 | npm install 33 | npm install -g @microsoft/rush 34 | ``` 35 | 3. Navigate to the root folder and update rush dependencies 36 | ``` 37 | rush update 38 | ``` 39 | 4. Build and test 40 | ``` 41 | rush build 42 | npm run test 43 | ``` 44 | 45 | ## Build and test 46 | 47 | The root folder contains 8 packages that are components of this next version of the SDK. When making changes in multiple packages, you can build using the following commands in root folder: 48 | 49 | 1. rush rebuild --verbose 50 | 51 | This will build all packages in order of dependencies. If there are build errors, verbose options is required to view error details. 52 | 53 | 2. rush test --verbose 54 | 55 | This will run tests in all packages in parallel. 56 | 57 | If you are changing package versions or adding/removing any package dependencies, run> **rush update --purge --recheck --full** before building. Please check-in any files that change under common\ folder. 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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 | -------------------------------------------------------------------------------- /README-manual.md: -------------------------------------------------------------------------------- 1 | # Microsoft Application Insights JavaScript SDK - React Native Manual Device Plugin 2 | 3 | # Purpose 4 | This optional plugin is designed because expo could not run with device-info packages 5 | 6 | ## Getting Started 7 | ```zsh 8 | npm install --save @microsoft/applicationinsights-react-native @microsoft/applicationinsights-web 9 | ``` 10 | ## Initializing the Plugin 11 | 12 | To use this plugin, you only need to construct the plugin and add it as an `extension` to your existing Application Insights instance. 13 | 14 | However, different from the default react native plugin, this plugin needs to have device info provided, or set to be disabled manually. 15 | 16 | 17 | ### Disabling automatic device info collection 18 | 19 | ```ts 20 | import { ApplicationInsights } from '@microsoft/applicationinsights-web'; 21 | import {ReactNativeManualDevicePlugin} from '@microsoft/applicationinsights-react-native/manual'; 22 | var RNMPlugin = new ReactNativeManualDevicePlugin(); 23 | var appInsights = new ApplicationInsights({ 24 | config: { 25 | instrumentationKey: 'YOUR_INSTRUMENTATION_KEY_GOES_HERE', 26 | disableDeviceCollection: true, 27 | extensions: [RNMPlugin] 28 | } 29 | }); 30 | appInsights.loadAppInsights(); 31 | ``` 32 | #### Note for Android/iOS Expo Users 33 | Due to the specific internal logic in Expo, importing the ReactNativeManualDevicePlugin for the app might fail. If you encounter this issue, manually import the plugin using the following approach: 34 | ```ts 35 | import {ReactNativeManualDevicePlugin} from '@microsoft/applicationinsights-react-native/dist-esm/manualIndex'; 36 | ``` 37 | 38 | ### Using your own device info collection class 39 | 40 | ```ts 41 | import { ApplicationInsights } from '@microsoft/applicationinsights-web'; 42 | 43 | // Simple inline constant implementation 44 | const myDeviceInfoModule = { 45 | getModel: () => "deviceModel", 46 | getDeviceType: () => "deviceType", 47 | // v5 returns a string while latest returns a promise 48 | getUniqueId: () => "deviceId", // This "may" also return a Promise 49 | }; 50 | 51 | var RNMPlugin = new ReactNativeManualDevicePlugin(); 52 | RNMPlugin.setDeviceInfoModule(myDeviceInfoModule); 53 | 54 | var appInsights = new ApplicationInsights({ 55 | config: { 56 | instrumentationKey: 'YOUR_INSTRUMENTATION_KEY_GOES_HERE', 57 | extensions: [RNMPlugin] 58 | } 59 | }); 60 | 61 | appInsights.loadAppInsights(); 62 | ``` 63 | ## Requirements 64 | You must be using a version `>=2.0.0` of `@microsoft/applicationinsights-web`. This plugin will only work in react-native apps, e.g. it will not work with `expo`. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 7 | feature request as a new Issue. 8 | 9 | For help and questions about using this project, please create a Support request issue on 10 | https://github.com/microsoft/applicationinsights-react-js/issues. 11 | 12 | ## Microsoft Support Policy 13 | 14 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 15 | -------------------------------------------------------------------------------- /applicationinsights-react-native/.npmignore: -------------------------------------------------------------------------------- 1 | # NPM Ignore 2 | 3 | # ignore everything 4 | * 5 | 6 | # ... but these files 7 | !package.json 8 | !tsconfig.json 9 | !/CODE_OF_CONDUCT.md 10 | !/CONTRIBUTING.md 11 | !/README.md 12 | !/SECURITY.md 13 | !/SUPPORT.md 14 | !/NOTICE 15 | !/PRIVACY 16 | !/LICENSE 17 | !/LICENSE.TXT 18 | !dist-esm/** 19 | !dist/** 20 | !browser/** 21 | !types/** 22 | 23 | -------------------------------------------------------------------------------- /applicationinsights-react-native/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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 | -------------------------------------------------------------------------------- /applicationinsights-react-native/PRIVACY: -------------------------------------------------------------------------------- 1 | # Data Collection 2 | 3 | The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. -------------------------------------------------------------------------------- /applicationinsights-react-native/README.md: -------------------------------------------------------------------------------- 1 | # Microsoft Application Insights JavaScript SDK - React Native Plugin 2 | 3 | React Native Plugin for the Application Insights Javascript SDK 4 | 5 | ## Getting Started 6 | 7 | >**This plugin relies on [`react-native-device-info`](https://github.com/rebeccahughes/react-native-device-info). You must install and link this package. Keep `react-native-device-info` up-to-date to collect the latest device names using your app.** 8 | 9 | ```zsh 10 | npm install --save @microsoft/applicationinsights-react-native @microsoft/applicationinsights-web 11 | npm install --save react-native-device-info 12 | react-native link react-native-device-info 13 | ``` 14 | 15 | ## Initializing the Plugin 16 | To use this plugin, you only need to construct the plugin and add it as an `extension` to your existing Application Insights instance. 17 | ```ts 18 | import { ApplicationInsights } from '@microsoft/applicationinsights-web'; 19 | import { ReactNativePlugin } from '@microsoft/applicationinsights-react-native'; 20 | 21 | var RNPlugin = new ReactNativePlugin(); 22 | var appInsights = new ApplicationInsights({ 23 | config: { 24 | instrumentationKey: 'YOUR_INSTRUMENTATION_KEY_GOES_HERE', 25 | extensions: [RNPlugin] 26 | } 27 | }); 28 | appInsights.loadAppInsights(); 29 | ``` 30 | 31 | ## Requirements 32 | You must be using a version `>=2.0.0` of `@microsoft/applicationinsights-web`. This plugin will only work in react-native apps, e.g. it will not work with `expo`. 33 | 34 | ## Device Information Collected 35 | 36 | By default, this plugin automatically collects 37 | - **Unique Device ID** (also known as Installation ID) 38 | - **Device Model Name** (iPhone XS, etc.) 39 | - **Device Type** (Handset, Tablet, etc.) 40 | 41 | ## IDeviceInfoModule 42 | 43 | ```typescript 44 | /** 45 | * Interface to abstract how the plugin can access the Device Info, this is a stripped 46 | * down version of the "react-native-device-info" interface and is mostly supplied for 47 | * testing. 48 | */ 49 | export interface IDeviceInfoModule { 50 | /** 51 | * Returns the Device Model 52 | */ 53 | getModel: () => string; 54 | 55 | /** 56 | * Returns the device type 57 | */ 58 | getDeviceType: () => string; 59 | 60 | /** 61 | * Returns the unique Id for the device, to support both the current version and previous 62 | * versions react-native-device-info, this may return either a `string` or `Promise`, 63 | * when a promise is returned the plugin will "wait" for the promise to `resolve` or `reject` 64 | * before processing any events. This WILL cause telemetry to be BLOCKED until either of these 65 | * states, so when returning a Promise it MUST `resolve` or `reject` it can't just never resolve. 66 | * There is a default timeout configured via `uniqueIdPromiseTimeout` to automatically unblock 67 | * event processing when this issue occurs. 68 | */ 69 | getUniqueId: () => Promise | string; 70 | } 71 | ``` 72 | 73 | If events are getting "blocked" because the `Promise` returned via `getUniqueId` is never resolved / rejected 74 | you can call `setDeviceId()` on the plugin to "unblock" this waiting state. There is also an automatic timeout 75 | configured via `uniqueIdPromiseTimeout` (defaults to 5 seconds), which will internally call `setDeviceId()` with 76 | any previously configured value. 77 | 78 | ## Compatibility Matrix 79 | 80 | The [Compatibility Matrix](https://github.com/microsoft/applicationinsights-react-native#compatibility-matrix) 81 | is tracked and updated on the main project README.md page. 82 | 83 | ## Nightly Builds 84 | 85 | See the [Main Readme](https://github.com/microsoft/applicationinsights-react-native#nightly-builds) 86 | 87 | ## Contributing 88 | 89 | This project welcomes contributions and suggestions. Most contributions require you to 90 | agree to a Contributor License Agreement (CLA) declaring that you have the right to, 91 | and actually do, grant us the rights to use your contribution. For details, visit 92 | https://cla.microsoft.com. 93 | 94 | When you submit a pull request, a CLA-bot will automatically determine whether you need 95 | to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the 96 | instructions provided by the bot. You will only need to do this once across all repositories using our CLA. 97 | 98 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 99 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 100 | or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 101 | 102 | ## Data Collection 103 | 104 | As this SDK is designed to enable applications to perform data collection which is sent to the Microsoft collection endpoints the following is required to identify our privacy statement. 105 | 106 | The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. 107 | 108 | ## Trademarks 109 | 110 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. 111 | 112 | ## License 113 | 114 | [MIT](LICENSE) 115 | -------------------------------------------------------------------------------- /applicationinsights-react-native/Tests/External/DummyReactNative.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 | typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ReactNative = global.ReactNative || {}))); 5 | }(this, (function (exports) { 'use strict'; 6 | 7 | // This provides a bare bones support for the react-native-device-info module to support browser based testing 8 | exports.NativeModules = { 9 | RNDeviceInfo: 1 10 | }; 11 | 12 | function dummyEmitter() { 13 | 14 | } 15 | 16 | exports.NativeEventEmitter = function () { 17 | emit: dummyEmitter 18 | }; 19 | 20 | Object.defineProperty(exports, '__esModule', { value: true }); 21 | 22 | // Need to define so the device-info loads 23 | window.exports = window.exports || exports || {}; 24 | 25 | }))); 26 | -------------------------------------------------------------------------------- /applicationinsights-react-native/Tests/UnitTests.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Tests for Application Insights JavaScript API 8 | 9 | 10 | 11 | 12 | 13 | 14 | 58 | 59 | 60 | 61 |
62 |
63 |
64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /applicationinsights-react-native/Tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "inlineSources": true, 5 | "noImplicitAny": false, 6 | "module": "amd", 7 | "moduleResolution": "Node", 8 | "target": "es5", 9 | "alwaysStrict": true, 10 | "declaration": true, 11 | "outFile": "./Selenium/reactnativeplugin.tests.js" 12 | }, 13 | "include": [ 14 | ] 15 | } -------------------------------------------------------------------------------- /applicationinsights-react-native/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microsoft/applicationinsights-react-native", 3 | "version": "4.3.6", 4 | "description": "Microsoft Application Insights React Native Plugin", 5 | "main": "dist-esm/index.js", 6 | "exports": { 7 | ".": { 8 | "types": "./types/index.d.ts", 9 | "import": "./dist-esm/index.js" 10 | }, 11 | "./manual": { 12 | "types": "./types/manualIndex.d.ts", 13 | "import": "./dist-esm/manualIndex.js" 14 | } 15 | }, 16 | "types": "types/index.d.ts", 17 | "sideEffects": false, 18 | "author": "Microsoft Application Insights Team", 19 | "license": "MIT", 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/microsoft/applicationinsights-react-native" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/microsoft/applicationinsights-react-native/issues" 26 | }, 27 | "homepage": "https://github.com/microsoft/applicationinsights-react-native#readme", 28 | "keywords": [ 29 | "performance monitoring", 30 | "application insights", 31 | "microsoft", 32 | "azure", 33 | "react native" 34 | ], 35 | "scripts": { 36 | "build": "npm run build:esm && npm run build:package && npm run dtsgen", 37 | "build:esm": "grunt reactnative", 38 | "build:package": "rollup -c", 39 | "rebuild": "npm run build", 40 | "test": "grunt reactnativetests", 41 | "mintest": "grunt reactnative-mintests", 42 | "testx": "npm run build:test && grunt reactnativetests", 43 | "lint": "tslint -p tsconfig.json", 44 | "dtsgen": "api-extractor run --local && node ../scripts/dtsgen.js \"Microsoft Application Insights react native plugin\"", 45 | "ai-min": "grunt reactnative-min", 46 | "ai-restore": "grunt reactnative-restore" 47 | }, 48 | "devDependencies": { 49 | "@microsoft/ai-test-framework": "0.0.1", 50 | "@microsoft/applicationinsights-rollup-es3": "1.1.3", 51 | "@microsoft/api-extractor": "^7.18.1", 52 | "grunt": "^1.5.3", 53 | "grunt-cli": "^1.4.3", 54 | "grunt-contrib-uglify": "^5.0.1", 55 | "@nevware21/grunt-ts-plugin": "^0.4.3", 56 | "@nevware21/grunt-eslint-ts": "^0.2.2", 57 | "@typescript-eslint/eslint-plugin": "^4.28.0", 58 | "@typescript-eslint/parser": "^4.28.0", 59 | "eslint": "^7.29.0", 60 | "eslint-config-standard": "^16.0.3", 61 | "eslint-plugin-import": "^2.23.4", 62 | "eslint-plugin-node": "^11.1.0", 63 | "eslint-plugin-promise": "^5.1.0", 64 | "qunit": "^2.11.2", 65 | "react": "^18.0.0", 66 | "react-native": "^0.69.9", 67 | "globby": "^11.0.0", 68 | "magic-string": "^0.25.7", 69 | "@rollup/plugin-commonjs": "^18.0.0", 70 | "@rollup/plugin-node-resolve": "^11.2.1", 71 | "@rollup/plugin-replace": "^2.3.3", 72 | "rollup-plugin-cleanup": "^3.2.1", 73 | "rollup-plugin-peer-deps-external": "^2.2.4", 74 | "rollup": "^2.77.2", 75 | "typescript": "^4.3.4", 76 | "tslib": "^2.0.0", 77 | "uglify-js": "3.16.0" 78 | }, 79 | "dependencies": { 80 | "@microsoft/applicationinsights-common": "^3.3.6", 81 | "@microsoft/applicationinsights-core-js": "^3.3.6", 82 | "@microsoft/applicationinsights-shims": "^3.0.1", 83 | "@microsoft/dynamicproto-js": "^2.0.3", 84 | "@nevware21/ts-utils": ">= 0.11.3 < 2.x" 85 | }, 86 | "peerDependencies": { 87 | "tslib": "*", 88 | "react-native": "*", 89 | "react-native-device-info": ">=5.2.1" 90 | }, 91 | "peerDependenciesMeta": { 92 | "react-native-device-info": { 93 | "optional": true 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /applicationinsights-react-native/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from "@rollup/plugin-node-resolve"; 2 | import commonjs from "@rollup/plugin-commonjs"; 3 | import replace from "@rollup/plugin-replace"; 4 | import cleanup from "rollup-plugin-cleanup"; 5 | import peerDepsExternal from 'rollup-plugin-peer-deps-external'; 6 | import { uglify } from "../tools/rollup-plugin-uglify3-js/dist/esm/rollup-plugin-uglify3-js"; 7 | import { importCheck } from "@microsoft/applicationinsights-rollup-es3"; 8 | import dynamicRemove from "@microsoft/dynamicproto-js/tools/rollup"; 9 | import { updateDistEsmFiles } from "../tools/updateDistEsm/updateDistEsm"; 10 | 11 | const version = require("./package.json").version; 12 | const inputName = "index" 13 | const outputName = "applicationinsights-react-native"; 14 | const banner = [ 15 | "/*!", 16 | ` * Application Insights JavaScript SDK - React Native Plugin, ${version}`, 17 | " * Copyright (c) Microsoft and contributors. All rights reserved.", 18 | " */" 19 | ].join("\n"); 20 | 21 | const replaceValues = { 22 | "// Copyright (c) Microsoft Corporation. All rights reserved.": "", 23 | "// Licensed under the MIT License.": "" 24 | }; 25 | 26 | function doCleanup() { 27 | return cleanup({ 28 | comments: [ 29 | 'some', 30 | /^.\s*@DynamicProtoStub/i, 31 | /^\*\*\s*@class\s*$/ 32 | ] 33 | }) 34 | } 35 | 36 | const browserRollupConfigFactory = isProduction => { 37 | const browserRollupConfig = { 38 | input: `dist-esm/${inputName}.js`, 39 | output: { 40 | file: `browser/${outputName}.js`, 41 | banner: banner, 42 | format: "umd", 43 | name: "Microsoft.ApplicationInsights", 44 | extend: true, 45 | freeze: false, 46 | sourcemap: true 47 | }, 48 | plugins: [ 49 | dynamicRemove(), 50 | replace({ 51 | preventAssignment: true, 52 | delimiters: ["", ""], 53 | values: replaceValues 54 | }), 55 | importCheck({ exclude: [ "applicationinsights-react-native" ] }), 56 | peerDepsExternal(), 57 | nodeResolve({ 58 | browser: true, 59 | preferBuiltins: true, 60 | dedupe: [ "react", "react-dom" ] 61 | }), 62 | commonjs(), 63 | doCleanup(), 64 | ] 65 | }; 66 | 67 | if (isProduction) { 68 | browserRollupConfig.output.file = `browser/${outputName}.min.js`; 69 | browserRollupConfig.plugins.push( 70 | uglify({ 71 | ie8: true, 72 | ie: true, 73 | toplevel: true, 74 | compress: { 75 | ie: true, 76 | passes:3, 77 | unsafe: true 78 | }, 79 | output: { 80 | ie: true, 81 | preamble: banner, 82 | webkit:true 83 | } 84 | }) 85 | ); 86 | } 87 | 88 | return browserRollupConfig; 89 | }; 90 | 91 | const nodeUmdRollupConfigFactory = (isProduction) => { 92 | const nodeRollupConfig = { 93 | input: `dist-esm/${inputName}.js`, 94 | output: { 95 | file: `dist/${outputName}.js`, 96 | banner: banner, 97 | format: "umd", 98 | name: "Microsoft.ApplicationInsights", 99 | extend: true, 100 | freeze: false, 101 | sourcemap: true 102 | }, 103 | plugins: [ 104 | dynamicRemove(), 105 | replace({ 106 | preventAssignment: true, 107 | delimiters: ["", ""], 108 | values: replaceValues 109 | }), 110 | importCheck({ exclude: [ "applicationinsights-react-native" ] }), 111 | peerDepsExternal(), 112 | nodeResolve({ 113 | browser: true, 114 | preferBuiltins: true, 115 | dedupe: [ "react", "react-dom" ] 116 | }), 117 | commonjs(), 118 | doCleanup() 119 | ] 120 | }; 121 | 122 | if (isProduction) { 123 | nodeRollupConfig.output.file = `dist/${outputName}.min.js`; 124 | nodeRollupConfig.plugins.push( 125 | uglify({ 126 | ie8: true, 127 | ie: true, 128 | toplevel: true, 129 | compress: { 130 | ie: true, 131 | passes:3, 132 | unsafe: true 133 | }, 134 | output: { 135 | ie: true, 136 | preamble: banner, 137 | webkit:true 138 | } 139 | }) 140 | ); 141 | } 142 | 143 | return nodeRollupConfig; 144 | }; 145 | 146 | updateDistEsmFiles(replaceValues, banner); 147 | 148 | export default [ 149 | browserRollupConfigFactory(true), 150 | browserRollupConfigFactory(false), 151 | nodeUmdRollupConfigFactory(true), 152 | nodeUmdRollupConfigFactory(false) 153 | ]; 154 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/DeviceInfo/DeviceModule.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | import { objDefineAccessors } from "@microsoft/applicationinsights-core-js"; 5 | import { IDeviceInfoModule } from "../Interfaces/IDeviceInfoModule"; 6 | 7 | export const DEVICE_MODEL = "model"; 8 | export const DEVICE_TYPE = "type"; 9 | export const UNIQUE_ID = "id"; 10 | 11 | export class DeviceModule implements IDeviceInfoModule { 12 | public getModel: () => string; 13 | public getDeviceType: () => string; 14 | public getUniqueId: () => string | Promise; 15 | 16 | constructor() { 17 | let _self = this; 18 | let _model: string = null; 19 | let _deviceType: string = null; 20 | let _uniqueId: string | Promise = null; 21 | 22 | function _getModel() { 23 | return _model; 24 | } 25 | 26 | function _getDeviceType() { 27 | return _deviceType; 28 | } 29 | 30 | function _getUniqueId() { 31 | return _uniqueId; 32 | } 33 | 34 | // Provide the public interface methods for accessing the values 35 | _self.getModel = _getModel; 36 | _self.getDeviceType = _getDeviceType; 37 | _self.getUniqueId = _getUniqueId 38 | 39 | // Provide setters (for testing) and re-use the functions for minification 40 | objDefineAccessors(_self, DEVICE_MODEL, _getModel, (value) => _model = value); 41 | objDefineAccessors(_self, DEVICE_TYPE, _getDeviceType, (value) => _deviceType = value); 42 | objDefineAccessors(_self, UNIQUE_ID, _getUniqueId, (value) => _uniqueId = value); 43 | } 44 | } -------------------------------------------------------------------------------- /applicationinsights-react-native/src/DeviceInfo/ReactNativeDeviceInfo.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | import DeviceInfo from "react-native-device-info"; 5 | import { IDeviceInfoModule } from "../Interfaces/IDeviceInfoModule"; 6 | 7 | /** 8 | * Returns the "react-native-device-info" as the Device Info Module 9 | * @returns 10 | */ 11 | export function getReactNativeDeviceInfo(): IDeviceInfoModule { 12 | return DeviceInfo; 13 | } -------------------------------------------------------------------------------- /applicationinsights-react-native/src/Interfaces/IDeviceInfoModule.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | /** 5 | * Interface to abstract how the plugin can access the Device Info, this is a stripped 6 | * down version of the "react-native-device-info" interface and is mostly supplied for 7 | * testing. 8 | */ 9 | export interface IDeviceInfoModule { 10 | /** 11 | * Returns the Device Model 12 | */ 13 | getModel: () => string; 14 | 15 | /** 16 | * Returns the device type 17 | */ 18 | getDeviceType: () => string; 19 | 20 | /** 21 | * Returns the unique Id for the device, to support both the current version and previous 22 | * versions react-native-device-info, this may return either a `string` or `Promise`, 23 | * when a promise is returned the plugin will "wait" for the promise to `resolve` or `reject` 24 | * before processing any events. This WILL cause telemetry to be BLOCKED until either of these 25 | * states, so when returning a Promise it MUST `resolve` or `reject` it can't just never resolve. 26 | * There is a default timeout configured via `uniqueIdPromiseTimeout` to automatically unblock 27 | * event processing when this issue occurs. 28 | */ 29 | getUniqueId: () => Promise | string; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/Interfaces/INativeDevice.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | export interface INativeDevice { 5 | /** 6 | * Device type, e.g. Handset, Tablet, Tv 7 | */ 8 | deviceClass?: string; 9 | 10 | /** 11 | * Unique installation ID 12 | */ 13 | id?: string; 14 | 15 | /** 16 | * The device model: iPhone XS Max, Galaxy S10, etc 17 | */ 18 | model?: string; 19 | } 20 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/Interfaces/IReactNativePluginConfig.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | export interface IReactNativePluginConfig { 4 | /** 5 | * Disable automatic device collection 6 | */ 7 | disableDeviceCollection?: boolean; 8 | 9 | /** 10 | * Disable automatic exception collection 11 | */ 12 | disableExceptionCollection?: boolean; 13 | 14 | /** 15 | * Timeout value to unblock the processing of events if the DeviceInfoModule 16 | * returns a Promise. 17 | */ 18 | uniqueIdPromiseTimeout?: number; 19 | } 20 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/Interfaces/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | import { INativeDevice } from "./INativeDevice"; 5 | import { IReactNativePluginConfig } from "./IReactNativePluginConfig"; 6 | 7 | export { INativeDevice, IReactNativePluginConfig }; 8 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/ReactNativePlugin.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | 5 | import { getReactNativeDeviceInfo } from "./DeviceInfo/ReactNativeDeviceInfo"; 6 | import { IDeviceInfoModule } from "./Interfaces/IDeviceInfoModule"; 7 | import { ReactNativeManualDevicePlugin } from "./ReactNativeManualDevicePlugin"; 8 | 9 | 10 | export class ReactNativePlugin extends ReactNativeManualDevicePlugin { 11 | protected getDeviceInfoModule(_deviceInfoModule): IDeviceInfoModule { 12 | return _deviceInfoModule || getReactNativeDeviceInfo(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | import { ReactNativePlugin } from "./ReactNativePlugin"; 5 | import { INativeDevice, IReactNativePluginConfig } from "./Interfaces"; 6 | import { IDeviceInfoModule } from "./Interfaces/IDeviceInfoModule"; 7 | import { getReactNativeDeviceInfo } from "./DeviceInfo/ReactNativeDeviceInfo"; 8 | import { ReactNativeManualDevicePlugin } from "./ReactNativeManualDevicePlugin"; 9 | 10 | export { ReactNativePlugin, ReactNativeManualDevicePlugin, INativeDevice, IReactNativePluginConfig, IDeviceInfoModule }; 11 | export { getReactNativeDeviceInfo }; 12 | -------------------------------------------------------------------------------- /applicationinsights-react-native/src/manualIndex.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | 5 | import { INativeDevice, IReactNativePluginConfig } from "./Interfaces"; 6 | import { IDeviceInfoModule } from "./Interfaces/IDeviceInfoModule"; 7 | import { ReactNativeManualDevicePlugin } from "./ReactNativeManualDevicePlugin"; 8 | 9 | export { ReactNativeManualDevicePlugin, INativeDevice, IReactNativePluginConfig, IDeviceInfoModule }; 10 | 11 | -------------------------------------------------------------------------------- /applicationinsights-react-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "inlineSources": true, 5 | "noImplicitAny": false, 6 | "module": "es6", 7 | "moduleResolution": "Node", 8 | "target": "es5", 9 | "alwaysStrict": true, 10 | "suppressImplicitAnyIndexErrors": true, 11 | "allowSyntheticDefaultImports": true, 12 | "importHelpers": true, 13 | "noEmitHelpers": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "declaration": true, 16 | "declarationDir": "applicationinsights-react-native/types", 17 | "outDir": "dist-esm", 18 | "rootDir": "applicationinsights-react-native/src" 19 | }, 20 | "include": [ 21 | "./src/**/*.ts" 22 | ], 23 | "exclude": [ 24 | "./node_modules/**" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /applicationinsights-react-native/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "../../tslint-base.json" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /common/Tests/External/blanket-reporter.js: -------------------------------------------------------------------------------- 1 | (function myReporter() { 2 | 3 | var reported = false; 4 | var a = document.createElement("a"); 5 | 6 | document.body.appendChild(a); 7 | //your reporter code 8 | blanket.customReporter = function (coverage) { 9 | blanket.defaultReporter(coverage); 10 | 11 | var styleTags = document.getElementsByTagName("style"); 12 | 13 | var styles = ""; 14 | for (var i = 0; i < styleTags.length; i++) { 15 | styles += styleTags[i].outerHTML; 16 | } 17 | 18 | var scriptTags = document.getElementsByTagName("body")[0].getElementsByTagName("script"); 19 | 20 | var scripts = ""; 21 | for (var i = 0; i < scriptTags.length; i++) { 22 | scripts += scriptTags[i].outerHTML; 23 | } 24 | 25 | var title = document.getElementsByTagName("title")[0].text; 26 | var documentName = title.replace(/[^\w]/ig, '') + 'Coverage.html'; 27 | 28 | var coverageReport = ''; 29 | coverageReport += '' + '' + styles + "

" + title.replace(/[^\w\s]/ig, '') + "

" + scripts + document.getElementById("blanket-main").outerHTML + ""; 30 | 31 | var file = new Blob([coverageReport], { type: 'text/plain' }); 32 | 33 | a.href = URL.createObjectURL(file); 34 | 35 | a.download = documentName; 36 | 37 | if (!reported) { 38 | a.click(); 39 | reported = true; 40 | } 41 | 42 | }; 43 | 44 | })(); -------------------------------------------------------------------------------- /common/Tests/External/es6-promise.auto.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ES6Promise=e()}(this,function(){"use strict";function t(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function e(t){return"function"==typeof t}function n(t){I=t}function r(t){J=t}function o(){return function(){return process.nextTick(a)}}function i(){return"undefined"!=typeof H?function(){H(a)}:c()}function s(){var t=0,e=new V(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t * { 173 | box-sizing: border-box; 174 | max-height: 2.8em; 175 | display: block; 176 | padding: 0.4em; 177 | } 178 | 179 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > button { 180 | float: right; 181 | font: inherit; 182 | } 183 | 184 | #qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child { 185 | /* insert padding to align with checkbox margins */ 186 | padding-left: 3px; 187 | } 188 | 189 | #qunit-modulefilter-dropdown-list { 190 | max-height: 200px; 191 | overflow-y: auto; 192 | margin: 0; 193 | border-top: 2px groove threedhighlight; 194 | padding: 0.4em 0 0; 195 | font: smaller/1.5em sans-serif; 196 | } 197 | 198 | #qunit-modulefilter-dropdown-list li { 199 | white-space: nowrap; 200 | overflow: hidden; 201 | text-overflow: ellipsis; 202 | } 203 | 204 | #qunit-modulefilter-dropdown-list .clickable { 205 | display: block; 206 | padding-left: 0.15em; 207 | } 208 | 209 | 210 | /** Tests: Pass/Fail */ 211 | 212 | #qunit-tests { 213 | list-style-position: inside; 214 | } 215 | 216 | #qunit-tests li { 217 | padding: 0.4em 1em 0.4em 1em; 218 | border-bottom: 1px solid #FFF; 219 | list-style-position: inside; 220 | } 221 | 222 | #qunit-tests > li { 223 | display: none; 224 | } 225 | 226 | #qunit-tests li.running, 227 | #qunit-tests li.pass, 228 | #qunit-tests li.fail, 229 | #qunit-tests li.skipped, 230 | #qunit-tests li.aborted { 231 | display: list-item; 232 | } 233 | 234 | #qunit-tests.hidepass { 235 | position: relative; 236 | } 237 | 238 | #qunit-tests.hidepass li.running, 239 | #qunit-tests.hidepass li.pass:not(.todo) { 240 | visibility: hidden; 241 | position: absolute; 242 | width: 0; 243 | height: 0; 244 | padding: 0; 245 | border: 0; 246 | margin: 0; 247 | } 248 | 249 | #qunit-tests li strong { 250 | cursor: pointer; 251 | } 252 | 253 | #qunit-tests li.skipped strong { 254 | cursor: default; 255 | } 256 | 257 | #qunit-tests li a { 258 | padding: 0.5em; 259 | color: #C2CCD1; 260 | text-decoration: none; 261 | } 262 | 263 | #qunit-tests li p a { 264 | padding: 0.25em; 265 | color: #6B6464; 266 | } 267 | #qunit-tests li a:hover, 268 | #qunit-tests li a:focus { 269 | color: #000; 270 | } 271 | 272 | #qunit-tests li .runtime { 273 | float: right; 274 | font-size: smaller; 275 | } 276 | 277 | .qunit-assert-list { 278 | margin-top: 0.5em; 279 | padding: 0.5em; 280 | 281 | background-color: #FFF; 282 | 283 | border-radius: 5px; 284 | } 285 | 286 | .qunit-source { 287 | margin: 0.6em 0 0.3em; 288 | } 289 | 290 | .qunit-collapsed { 291 | display: none; 292 | } 293 | 294 | #qunit-tests table { 295 | border-collapse: collapse; 296 | margin-top: 0.2em; 297 | } 298 | 299 | #qunit-tests th { 300 | text-align: right; 301 | vertical-align: top; 302 | padding: 0 0.5em 0 0; 303 | } 304 | 305 | #qunit-tests td { 306 | vertical-align: top; 307 | } 308 | 309 | #qunit-tests pre { 310 | margin: 0; 311 | white-space: pre-wrap; 312 | word-wrap: break-word; 313 | } 314 | 315 | #qunit-tests del { 316 | color: #374E0C; 317 | background-color: #E0F2BE; 318 | text-decoration: none; 319 | } 320 | 321 | #qunit-tests ins { 322 | color: #500; 323 | background-color: #FFCACA; 324 | text-decoration: none; 325 | } 326 | 327 | /*** Test Counts */ 328 | 329 | #qunit-tests b.counts { color: #000; } 330 | #qunit-tests b.passed { color: #5E740B; } 331 | #qunit-tests b.failed { color: #710909; } 332 | 333 | #qunit-tests li li { 334 | padding: 5px; 335 | background-color: #FFF; 336 | border-bottom: none; 337 | list-style-position: inside; 338 | } 339 | 340 | /*** Passing Styles */ 341 | 342 | #qunit-tests li li.pass { 343 | color: #3C510C; 344 | background-color: #FFF; 345 | border-left: 10px solid #C6E746; 346 | } 347 | 348 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 349 | #qunit-tests .pass .test-name { color: #366097; } 350 | 351 | #qunit-tests .pass .test-actual, 352 | #qunit-tests .pass .test-expected { color: #999; } 353 | 354 | #qunit-banner.qunit-pass { background-color: #C6E746; } 355 | 356 | /*** Failing Styles */ 357 | 358 | #qunit-tests li li.fail { 359 | color: #710909; 360 | background-color: #FFF; 361 | border-left: 10px solid #EE5757; 362 | white-space: pre; 363 | } 364 | 365 | #qunit-tests > li:last-child { 366 | border-radius: 0 0 5px 5px; 367 | } 368 | 369 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 370 | #qunit-tests .fail .test-name, 371 | #qunit-tests .fail .module-name { color: #000; } 372 | 373 | #qunit-tests .fail .test-actual { color: #EE5757; } 374 | #qunit-tests .fail .test-expected { color: #008000; } 375 | 376 | #qunit-banner.qunit-fail { background-color: #EE5757; } 377 | 378 | 379 | /*** Aborted tests */ 380 | #qunit-tests .aborted { color: #000; background-color: orange; } 381 | /*** Skipped tests */ 382 | 383 | #qunit-tests .skipped { 384 | background-color: #EBECE9; 385 | } 386 | 387 | #qunit-tests .qunit-todo-label, 388 | #qunit-tests .qunit-skipped-label { 389 | background-color: #F4FF77; 390 | display: inline-block; 391 | font-style: normal; 392 | color: #366097; 393 | line-height: 1.8em; 394 | padding: 0 0.5em; 395 | margin: -0.4em 0.4em -0.4em 0; 396 | } 397 | 398 | #qunit-tests .qunit-todo-label { 399 | background-color: #EEE; 400 | } 401 | 402 | /** Result */ 403 | 404 | #qunit-testresult { 405 | color: #2B81AF; 406 | background-color: #D2E0E6; 407 | 408 | border-bottom: 1px solid #FFF; 409 | } 410 | #qunit-testresult .clearfix { 411 | height: 0; 412 | clear: both; 413 | } 414 | #qunit-testresult .module-name { 415 | font-weight: 700; 416 | } 417 | #qunit-testresult-display { 418 | padding: 0.5em 1em 0.5em 1em; 419 | width: 85%; 420 | float:left; 421 | } 422 | #qunit-testresult-controls { 423 | padding: 0.5em 1em 0.5em 1em; 424 | width: 10%; 425 | float:left; 426 | } 427 | 428 | /** Fixture */ 429 | 430 | #qunit-fixture { 431 | position: absolute; 432 | top: -10000px; 433 | left: -10000px; 434 | width: 1000px; 435 | height: 1000px; 436 | } 437 | -------------------------------------------------------------------------------- /common/Tests/Framework/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microsoft/ai-test-framework", 3 | "author": "Microsoft Corporation", 4 | "version": "0.0.1", 5 | "description": "Microsoft Application Insights Javascript SDK Internal Test Framework", 6 | "keywords": [ 7 | "azure", 8 | "cloud", 9 | "script errors", 10 | "microsoft", 11 | "application insights", 12 | "browser performance monitoring", 13 | "web analytics" 14 | ], 15 | "module": "dist-esm/src/ai-test-framework.js", 16 | "types": "dist-esm/src/ai-test-framework.d.ts", 17 | "scripts": { 18 | "clean": "grunt clean", 19 | "build": "npm run build:esm && npm run build:browser", 20 | "build:esm": "grunt tst-framework", 21 | "build:browser": "rollup -c rollup.config.js", 22 | "rebuild": "npm run build", 23 | "test": "" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/microsoft/ApplicationInsights-JS/tree/master/common/Tests/Framework" 28 | }, 29 | "license": "MIT", 30 | "sideEffects": false, 31 | "devDependencies": { 32 | "@types/qunit": "^2.5.3", 33 | "@types/sinon": "4.3.3", 34 | "grunt": "^1.5.3", 35 | "@nevware21/grunt-ts-plugin": "^0.4.3", 36 | "@rollup/plugin-commonjs": "^18.0.0", 37 | "@rollup/plugin-node-resolve": "^11.2.1", 38 | "@rollup/plugin-replace": "^2.3.3", 39 | "rollup": "^2.77.2", 40 | "typescript": "^4.3.4", 41 | "tslib": "^2.0.0", 42 | "qunit": "^2.11.2", 43 | "sinon": "^7.3.1", 44 | "globby": "^11.0.0", 45 | "magic-string": "^0.25.7" 46 | }, 47 | "peerDependencies": { 48 | "tslib": "*" 49 | }, 50 | "dependencies": { 51 | "@microsoft/dynamicproto-js": "^2.0.3" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/Tests/Framework/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from "@rollup/plugin-node-resolve"; 2 | import { updateDistEsmFiles } from "../../../tools/updateDistEsm/updateDistEsm"; 3 | 4 | const version = require("./package.json").version; 5 | const outputName = "ai-test-framework"; 6 | const banner = [ 7 | "/*!", 8 | ` * Application Insights JavaScript SDK - Internal Test Framework, ${version}`, 9 | " * Copyright (c) Microsoft and contributors. All rights reserved.", 10 | " */" 11 | ].join("\n"); 12 | 13 | const nodeUmdRollupConfigFactory = () => { 14 | const nodeRollupConfig = { 15 | input: `dist-esm/src/ai-test-framework.js`, 16 | output: { 17 | file: `dist/${outputName}.js`, 18 | banner: banner, 19 | format: "umd", 20 | name: "Microsoft.ApplicationInsights", 21 | extend: true, 22 | freeze: false, 23 | sourcemap: true 24 | }, 25 | globals: { 26 | 'qunit': 'QUnit' 27 | }, 28 | plugins: [ 29 | nodeResolve() 30 | ] 31 | }; 32 | 33 | return nodeRollupConfig; 34 | } 35 | 36 | updateDistEsmFiles({}, banner); 37 | 38 | export default [ 39 | nodeUmdRollupConfigFactory(), 40 | ]; 41 | -------------------------------------------------------------------------------- /common/Tests/Framework/src/Assert.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { expectedToString, stateToString } from "./DebugHelpers"; 4 | 5 | /** 6 | * Wrapper around QUnit asserts. This class has two purposes: 7 | * - Make Assertion methods easy to discover. 8 | * - Make them consistent with XUnit assertions in the order of the actual and expected parameter values. 9 | */ 10 | export class Assert { 11 | /** 12 | * A deep recursive comparison assertion, working on primitive types, arrays, objects, 13 | * regular expressions, dates and functions. 14 | * 15 | * The deepEqual() assertion can be used just like equal() when comparing the value of 16 | * objects, such that { key: value } is equal to { key: value }. For non-scalar values, 17 | * identity will be disregarded by deepEqual. 18 | * 19 | * @param expected Known comparison value 20 | * @param actual Object or Expression being tested 21 | * @param message A short description of the assertion 22 | */ 23 | public static deepEqual(expected: any, actual: any, message?: string): any { 24 | return QUnit.assert.deepEqual(actual, expected, message || expectedToString(expected)); 25 | } 26 | 27 | /** 28 | * A non-strict comparison assertion, roughly equivalent to JUnit assertEquals. 29 | * 30 | * The equal assertion uses the simple comparison operator (==) to compare the actual 31 | * and expected arguments. When they are equal, the assertion passes: any; otherwise, it fails. 32 | * When it fails, both actual and expected values are displayed in the test result, 33 | * in addition to a given message. 34 | * 35 | * @param expected Known comparison value 36 | * @param actual Expression being tested 37 | * @param message A short description of the assertion 38 | */ 39 | public static equal(expected: any, actual: any, message?: string): any { 40 | return QUnit.assert.equal(actual, expected, message || expectedToString(expected)); 41 | } 42 | 43 | /** 44 | * An inverted deep recursive comparison assertion, working on primitive types, 45 | * arrays, objects, regular expressions, dates and functions. 46 | * 47 | * The notDeepEqual() assertion can be used just like equal() when comparing the 48 | * value of objects, such that { key: value } is equal to { key: value }. For non-scalar 49 | * values, identity will be disregarded by notDeepEqual. 50 | * 51 | * @param expected Known comparison value 52 | * @param actual Object or Expression being tested 53 | * @param message A short description of the assertion 54 | */ 55 | public static notDeepEqual(expected: any, actual: any, message?: string): any { 56 | return QUnit.assert.notDeepEqual(actual, expected, message || expectedToString(expected)); 57 | } 58 | 59 | /** 60 | * A non-strict comparison assertion, checking for inequality. 61 | * 62 | * The notEqual assertion uses the simple inverted comparison operator (!=) to compare 63 | * the actual and expected arguments. When they aren't equal, the assertion passes: any; 64 | * otherwise, it fails. When it fails, both actual and expected values are displayed 65 | * in the test result, in addition to a given message. 66 | * 67 | * @param expected Known comparison value 68 | * @param actual Expression being tested 69 | * @param message A short description of the assertion 70 | */ 71 | public static notEqual(expected: any, actual: any, message?: string): any { 72 | return QUnit.assert.notEqual(actual, expected, message || expectedToString(expected)); 73 | } 74 | 75 | public static notPropEqual(expected: any, actual: any, message?: string): any { 76 | return QUnit.assert.notPropEqual(actual, expected, message || expectedToString(expected)); 77 | } 78 | 79 | public static propEqual(expected: any, actual: any, message?: string): any { 80 | return QUnit.assert.propEqual(actual, expected, message || expectedToString(expected)); 81 | } 82 | 83 | /** 84 | * A non-strict comparison assertion, checking for inequality. 85 | * 86 | * The notStrictEqual assertion uses the strict inverted comparison operator (!==) 87 | * to compare the actual and expected arguments. When they aren't equal, the assertion 88 | * passes: any; otherwise, it fails. When it fails, both actual and expected values are 89 | * displayed in the test result, in addition to a given message. 90 | * 91 | * @param expected Known comparison value 92 | * @param actual Expression being tested 93 | * @param message A short description of the assertion 94 | */ 95 | public static notStrictEqual(expected: any, actual: any, message?: string): any { 96 | return QUnit.assert.notStrictEqual(actual, expected, message || expectedToString(expected)); 97 | } 98 | 99 | /** 100 | * A boolean assertion, equivalent to CommonJS's assert.ok() and JUnit's assertTrue(). 101 | * Passes if the first argument is truthy. 102 | * 103 | * The most basic assertion in QUnit, ok() requires just one argument. If the argument 104 | * evaluates to true, the assertion passes; otherwise, it fails. If a second message 105 | * argument is provided, it will be displayed in place of the result. 106 | * 107 | * @param state Expression being tested 108 | * @param message A short description of the assertion 109 | */ 110 | public static ok(state: any, message?: string): any { 111 | return QUnit.assert.ok(state, message || stateToString(state)); 112 | } 113 | 114 | /** 115 | * A strict type and value comparison assertion. 116 | * 117 | * The strictEqual() assertion provides the most rigid comparison of type and value with 118 | * the strict equality operator (===) 119 | * 120 | * @param expected Known comparison value 121 | * @param actual Expression being tested 122 | * @param message A short description of the assertion 123 | */ 124 | public static strictEqual(expected: any, actual: any, message?: string): any { 125 | return QUnit.assert.strictEqual(actual, expected, message || expectedToString(expected)); 126 | } 127 | 128 | /** 129 | * Assertion to test if a callback throws an exception when run. 130 | * 131 | * When testing code that is expected to throw an exception based on a specific set of 132 | * circumstances, use throws() to catch the error object for testing and comparison. 133 | * 134 | * @param block Function to execute 135 | * @param expected Error Object to compare 136 | * @param message A short description of the assertion 137 | */ 138 | public static throws(block: () => any, expected: any, message?: string): any; 139 | 140 | /** 141 | * @param block Function to execute 142 | * @param message A short description of the assertion 143 | */ 144 | public static throws(block: () => any, message?: string): any; 145 | 146 | public static throws(block: () => any, expected?: any, message?: string): any { 147 | return QUnit.assert.throws(block, expected, message || expectedToString(expected)); 148 | } 149 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/DebugHelpers.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export function _toString(value: any, isRecursive: boolean = false): string { 4 | if (value === undefined) { 5 | return ""; 6 | } 7 | 8 | if (value === null) { 9 | return ""; 10 | } 11 | 12 | try { 13 | if (typeof value !== "string") { 14 | const objectTypeDump: string = Object.prototype.toString.call(value); 15 | let propertyValueDump: string = ""; 16 | if (objectTypeDump === "[object Error]") { 17 | propertyValueDump = "{ stack: '" + value.stack + "', message: '" + value.message + "', name: '" + value.name + "'"; 18 | } else { 19 | propertyValueDump = JSON.stringify(value); 20 | } 21 | 22 | return objectTypeDump + propertyValueDump; 23 | } 24 | } catch (e) { 25 | return "!!!Unable to convert to a string!!! - " + (!isRecursive ? _toString(e, true) : "%$#%&*@"); 26 | } 27 | 28 | return value || ""; 29 | } 30 | 31 | export function expectedToString(value: any) { 32 | return "Expected: [" + _toString(value) + "]"; 33 | } 34 | 35 | export function stateToString(value: any) { 36 | return "State: [" + _toString(value) + "]"; 37 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/PollingAssert.ts: -------------------------------------------------------------------------------- 1 | import { Assert } from "./Assert"; 2 | import { AITestClass } from "./AITestClass"; 3 | import { ITestContext } from "./TestCase"; 4 | 5 | export class PollingAssert { 6 | /** 7 | * Starts polling assertion function for a period of time after which it's considered failed. 8 | * @param {() => boolean} assertionFunctionReturnsBoolean - funciton returning true if condition passes and false if condition fails. Assertion will be done on this function's result. 9 | * @param {string} assertDescription - message shown with the assertion 10 | * @param {number} timeoutSeconds - timeout in seconds after which assertion fails 11 | * @param {number} pollIntervalMs - polling interval in milliseconds 12 | * @returns {(nextTestStep) => void} callback which will be invoked by the AITestClass 13 | */ 14 | public static createPollingAssert(assertionFunctionReturnsBoolean: (testContext?: ITestContext) => boolean, assertDescription: string, timeoutSeconds: number = 30, pollIntervalMs: number = 500): (testContext: ITestContext, nextTestStep: () => void) => void { 15 | const pollingAssert = (testContext: ITestContext, nextTestStep: () => void) => { 16 | const timeout = new Date(new Date().getTime() + timeoutSeconds * 1000); 17 | const polling = () => { 18 | try { 19 | if (assertionFunctionReturnsBoolean.apply(this)) { 20 | Assert.ok(true, assertDescription + "[" + (AITestClass.currentTestInfo ? AITestClass.currentTestInfo.name : "") + "]"); 21 | nextTestStep(); 22 | } else if (timeout < new Date()) { 23 | Assert.ok(false, "assert didn't succeed for " + timeout + " seconds: " + assertDescription + "[" + (AITestClass.currentTestInfo ? AITestClass.currentTestInfo.name : "") + "]"); 24 | nextTestStep(); 25 | } else { 26 | setTimeout(polling, pollIntervalMs); 27 | } 28 | } catch (e) { 29 | Assert.ok(true, "Polling exception - " + e); 30 | setTimeout(polling, pollIntervalMs); 31 | } 32 | 33 | if (testContext.clock) { 34 | // Using fake timers, so push the fake time forward in the next execution cycle 35 | AITestClass.orgSetTimeout(() => { 36 | testContext.clock.tick(pollIntervalMs); 37 | }, 0); 38 | } 39 | } 40 | 41 | setTimeout(polling, pollIntervalMs); 42 | if (testContext.clock) { 43 | AITestClass.orgSetTimeout(() => { 44 | testContext.clock.tick(pollIntervalMs); 45 | }, 0); 46 | } 47 | } 48 | 49 | pollingAssert[AITestClass.isPollingStepFlag] = true; 50 | 51 | return pollingAssert; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/CommonValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | 3 | export class CommonValidator implements ITypeValidator { 4 | 5 | static CommonValidator = new CommonValidator(); 6 | 7 | public Validate(item: any, _baseType: string): boolean { 8 | // verify item has data, iKey, name, tags, and time fields 9 | if (!item.data || !item.iKey || !item.name || !item.tags || !item.time) { 10 | return false; 11 | } 12 | 13 | if (item.data.baseData.ver !== 2) { 14 | return false; 15 | } 16 | 17 | // verify item.data has baseType field 18 | if (!item.data.baseType) { 19 | return false; 20 | } 21 | 22 | return true; 23 | } 24 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/EventValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class EventValidator implements ITypeValidator { 5 | 6 | static EventValidator = new EventValidator(); 7 | 8 | public Validate(item: any, baseType: string): boolean { 9 | // verify item passes CommonValidator 10 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 11 | return false; 12 | } 13 | 14 | // verify item has ver, name, properties, and measurement fields 15 | if (!item.data.baseData || 16 | !item.data.baseData.ver || 17 | !item.data.baseData.name || 18 | !item.data.baseData.properties || 19 | !item.data.baseData.measurements) { 20 | return false; 21 | } 22 | 23 | return true; 24 | } 25 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/ExceptionValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class ExceptionValidator implements ITypeValidator { 5 | static ExceptionValidator = new ExceptionValidator(); 6 | 7 | private static _validateExceptions(exceptions: any[]): boolean { 8 | // verify exceptions has typeName, message, hasFullStack, stack, parsedStack fields 9 | if (!("typeName" in exceptions[0]) || 10 | !("message" in exceptions[0]) || 11 | !("hasFullStack" in exceptions[0]) || 12 | !("stack" in exceptions[0]) || 13 | !("parsedStack" in exceptions[0])) { 14 | return false; 15 | } 16 | 17 | return true; 18 | } 19 | 20 | Validate(item: any, baseType: string): boolean { 21 | // verify item passes CommonValidator 22 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 23 | console.log("ExceptionValidator::Validate failed - " + JSON.stringify(item)); 24 | return false; 25 | } 26 | 27 | // verify item has ver and exceptions fields 28 | if (!item.data.baseData || 29 | !item.data.baseData.ver || 30 | !item.data.baseData.exceptions) { 31 | console.log("ExceptionValidator::Validate missing basedata values - " + JSON.stringify(item.data)); 32 | return false; 33 | } 34 | 35 | // Exception.ver should be a number for breeze channel, but a string in CS4.0 36 | if (item.data.baseData.ver !== 2) { 37 | console.log("ExceptionValidator::Validate not breeze - " + JSON.stringify(item.data.baseData)); 38 | return false; // not a valid breeze exception 39 | } 40 | 41 | if (!ExceptionValidator._validateExceptions(item.data.baseData.exceptions)) { 42 | console.log("ExceptionValidator::_validateExceptions failed - " + JSON.stringify(item.data.baseData.exceptions)); 43 | return false; 44 | } 45 | 46 | return true; 47 | } 48 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/ITypeValidator.ts: -------------------------------------------------------------------------------- 1 | export interface ITypeValidator { 2 | Validate(item: any, baseType?: string): boolean; 3 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/MetricValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class MetricValidator implements ITypeValidator { 5 | static MetricValidator = new MetricValidator(); 6 | 7 | Validate(item: any, baseType: string): boolean { 8 | // verify item passes CommonValidator 9 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 10 | return false; 11 | } 12 | 13 | // verify item has ver, metrics, and properties fields 14 | if (!item.data.baseData || 15 | !item.data.baseData.ver || 16 | !item.data.baseData.metrics || 17 | !item.data.baseData.properties) { 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/PageViewPerformanceValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class PageViewPerformanceValidator implements ITypeValidator { 5 | static PageViewPerformanceValidator = new PageViewPerformanceValidator(); 6 | 7 | public Validate(item: any, baseType: string): boolean { 8 | // verify item passes CommonValidator 9 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 10 | return false; 11 | } 12 | 13 | // verify item has ver, url, perfTotal, name, duration, networkConnect, sentRequest, receivedResponse, and domProcessing fields 14 | if (!item.data.baseData || 15 | !item.data.baseData.ver || 16 | !item.data.baseData.url || 17 | !item.data.baseData.perfTotal || 18 | !item.data.baseData.name || 19 | !item.data.baseData.duration || 20 | !item.data.baseData.networkConnect || 21 | !item.data.baseData.sentRequest || 22 | !item.data.baseData.receivedResponse || 23 | !item.data.baseData.domProcessing) { 24 | return false; 25 | } 26 | 27 | return true; 28 | } 29 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/PageViewValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class PageViewValidator implements ITypeValidator { 5 | static PageViewValidator = new PageViewValidator(); 6 | 7 | public Validate(item: any, baseType: string): boolean { 8 | // verify item passes CommonValidator 9 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 10 | return false; 11 | } 12 | 13 | // verify item has ver, url, name, duration, id, properties, and measurements fields 14 | if (!item.data.baseData || 15 | !item.data.baseData.ver || 16 | !item.data.baseData.url || 17 | !item.data.baseData.name || 18 | !item.data.baseData.duration || 19 | !item.data.baseData.id || 20 | !item.data.baseData.properties || 21 | !item.data.baseData.measurements) { 22 | return false; 23 | } 24 | return true; 25 | } 26 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/RemoteDepdencyValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class RemoteDepdencyValidator implements ITypeValidator { 5 | static RemoteDepdencyValidator = new RemoteDepdencyValidator(); 6 | 7 | public Validate(item: any, baseType: string): boolean { 8 | // verify item passes CommonValidator 9 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 10 | return false; 11 | } 12 | 13 | // verify item has ver, name, id, resultCode, duration, data, target, type, properties, and measurement fields 14 | if (!item.data.baseData || 15 | !item.data.baseData.ver || 16 | !item.data.baseData.name || 17 | !item.data.baseData.id || 18 | !item.data.baseData.resultCode || 19 | !item.data.baseData.duration || 20 | !item.data.baseData.data || 21 | !item.data.baseData.target || 22 | !item.data.baseData.type || 23 | !item.data.baseData.properties || 24 | !item.data.baseData.measurements) { 25 | return false; 26 | } 27 | 28 | return true; 29 | } 30 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TelemetryValidation/TraceValidator.ts: -------------------------------------------------------------------------------- 1 | import { ITypeValidator } from "./ITypeValidator"; 2 | import { CommonValidator } from "./CommonValidator"; 3 | 4 | export class TraceValidator implements ITypeValidator { 5 | static TraceValidator = new TraceValidator(); 6 | 7 | public Validate(item: any, baseType: string): boolean { 8 | // verify item passes CommonValidator 9 | if (!CommonValidator.CommonValidator.Validate(item, baseType)) { 10 | return false; 11 | } 12 | 13 | // verify item has ver, message, and properties fields 14 | if (!item.data.baseData || 15 | !item.data.baseData.ver || 16 | !item.data.baseData.message || 17 | !item.data.baseData.properties) { 18 | return false; 19 | } 20 | return true; 21 | } 22 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/TestCase.ts: -------------------------------------------------------------------------------- 1 | 2 | /** Defines a test case */ 3 | export class TestCase { 4 | /** Name to use for the test case */ 5 | public name: string; 6 | 7 | useFakeServer?: boolean; 8 | fakeServerAutoRespond?: boolean; 9 | 10 | useFakeTimers?: boolean; 11 | 12 | /** Test case method */ 13 | public test: () => void|Promise; 14 | 15 | /** We expect the test to complete within this interval (defaults to 5 seconds) */ 16 | public timeout?: number; 17 | 18 | /** Used for debugging, set this value to ignore the automatic timeout for tests that return a promise */ 19 | public skipTimeout? : boolean; 20 | 21 | /** 22 | * Automatically assert that all registered events have been removed 23 | */ 24 | assertNoEvents?: boolean; 25 | 26 | /** 27 | * Automatically assert that all hooks have been removed 28 | */ 29 | assertNoHooks?: boolean; 30 | 31 | 32 | orgSetTimeout?: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timeout; 33 | orgClearTimeout?: (timeoutId: NodeJS.Timeout) => void; 34 | } 35 | 36 | export const enum StepResult { 37 | Abort = -1, 38 | Complete = 0, 39 | Repeat = 90, 40 | Retry = 99 41 | } 42 | 43 | export interface ITestContext { 44 | context: { [key: string]: any }; 45 | retryCnt: number; 46 | testDone: VoidFunction; // Consider that the test is complete 47 | clock: sinon.SinonFakeTimers 48 | } 49 | 50 | /** Defines a test case */ 51 | export interface TestCaseAsync { 52 | /** Name to use for the test case */ 53 | name: string; 54 | 55 | useFakeServer?: boolean; 56 | fakeServerAutoRespond?: boolean; 57 | 58 | useFakeTimers?: boolean; 59 | 60 | /** time to wait after pre before invoking post and calling start() */ 61 | stepDelay: number; 62 | 63 | /** async steps */ 64 | steps: Array<(testContext?: ITestContext) => StepResult|boolean|void>; 65 | 66 | /** 67 | * Terminate and fail the test if it runs longer than this 68 | */ 69 | timeOut?: number; 70 | 71 | /** 72 | * Flag which specifies that once all of the steps are completed the test case is completed. 73 | * True by default 74 | */ 75 | autoComplete?: boolean; 76 | 77 | /** 78 | * Automatically assert that all registered events have been removed 79 | */ 80 | assertNoEvents?: boolean; 81 | 82 | /** 83 | * Automatically assert that all hooks have been removed 84 | */ 85 | assertNoHooks?: boolean; 86 | 87 | orgSetTimeout?: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timeout; 88 | orgClearTimeout?: (timeoutId: NodeJS.Timeout) => void; 89 | } -------------------------------------------------------------------------------- /common/Tests/Framework/src/ai-test-framework.ts: -------------------------------------------------------------------------------- 1 | export { Assert } from "./Assert"; 2 | export { PollingAssert } from "./PollingAssert"; 3 | export { TestCase, TestCaseAsync } from "./TestCase"; 4 | export { AITestClass } from "./AITestClass"; 5 | 6 | export { ITypeValidator } from "./TelemetryValidation/ITypeValidator"; 7 | export { CommonValidator } from "./TelemetryValidation/CommonValidator"; 8 | export { EventValidator } from "./TelemetryValidation/EventValidator"; 9 | export { ExceptionValidator } from "./TelemetryValidation/ExceptionValidator"; 10 | export { MetricValidator } from "./TelemetryValidation/MetricValidator"; 11 | export { PageViewPerformanceValidator } from "./TelemetryValidation/PageViewPerformanceValidator"; 12 | export { PageViewValidator } from "./TelemetryValidation/PageViewValidator"; 13 | export { RemoteDepdencyValidator } from "./TelemetryValidation/RemoteDepdencyValidator"; 14 | export { TraceValidator } from "./TelemetryValidation/TraceValidator"; 15 | -------------------------------------------------------------------------------- /common/Tests/Framework/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "inlineSources": true, 5 | "noImplicitAny": true, 6 | "module": "es6", 7 | "moduleResolution": "node", 8 | "target": "es5", 9 | "forceConsistentCasingInFileNames": true, 10 | "importHelpers": true, 11 | "noEmitHelpers": false, 12 | "skipLibCheck": true, 13 | "alwaysStrict": true, 14 | "declaration": true, 15 | "outDir": "dist-esm/", 16 | "rootDir": "common/Tests/Framework", 17 | "suppressImplicitAnyIndexErrors": true, 18 | "allowSyntheticDefaultImports": true 19 | }, 20 | "include": [ 21 | "./src/**/*.ts" 22 | ], 23 | "exclude": [ 24 | "node_modules/" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /common/Tests/Selenium/ExceptionHelper.js: -------------------------------------------------------------------------------- 1 | 2 | function ExceptionHelper(config) { 3 | 4 | let orgError = null; 5 | 6 | function throwCorsException() { 7 | throw "Simulated Cors Exception"; 8 | } 9 | 10 | function throwPageException(value) { 11 | function doThrow() { 12 | throw value; 13 | } 14 | 15 | doThrow(); 16 | } 17 | 18 | function throwStrictException(value) { 19 | "use strict"; 20 | function doThrow() { 21 | throw value; 22 | } 23 | 24 | doThrow(); 25 | } 26 | 27 | function throwRuntimeException(timeoutFunc) { 28 | function doThrow() { 29 | var ug = "Hello"; 30 | // This should throw 31 | ug(); 32 | } 33 | 34 | if (!timeoutFunc) { 35 | timeoutFunc = setTimeout; 36 | } 37 | 38 | timeoutFunc(function() { 39 | doThrow(); 40 | }, 0); 41 | } 42 | 43 | function throwStrictRuntimeException(timeoutFunc) { 44 | "use strict"; 45 | function doThrow() { 46 | var ug = "Hello"; 47 | // This should throw 48 | ug(); 49 | } 50 | 51 | if (!timeoutFunc) { 52 | timeoutFunc = setTimeout; 53 | } 54 | 55 | timeoutFunc(function() { 56 | doThrow(); 57 | }, 0); 58 | } 59 | function saveOnError() { 60 | if (!orgError) { 61 | orgError = { 62 | onerror: window.onerror 63 | }; 64 | } 65 | } 66 | 67 | function restoreOnError() { 68 | if (orgError && orgError.onerror) { 69 | window.onerror = orgError.onerror; 70 | } 71 | } 72 | 73 | function captureStrictPageOnError(appInsights) { 74 | saveOnError(); 75 | 76 | "use strict"; 77 | function doCapture() { 78 | 79 | // Ignoring any previous handler 80 | window.onerror = function (message, url, lineNumber, columnNumber, error) { 81 | appInsights._onerror({ 82 | message, 83 | url, 84 | lineNumber, 85 | columnNumber, 86 | error: error, 87 | evt: window.event 88 | }); 89 | 90 | return true; 91 | } 92 | } 93 | 94 | doCapture(); 95 | } 96 | 97 | function capturePageOnError(appInsights) { 98 | saveOnError(); 99 | 100 | function doCapture() { 101 | // Ignoring any previous handler 102 | window.onerror = function (message, url, lineNumber, columnNumber, error) { 103 | appInsights._onerror({ 104 | message, 105 | url, 106 | lineNumber, 107 | columnNumber, 108 | error: error, 109 | evt: window.event 110 | }); 111 | 112 | return true; 113 | } 114 | } 115 | 116 | doCapture(); 117 | } 118 | 119 | return { 120 | capture: capturePageOnError, 121 | captureStrict: captureStrictPageOnError, 122 | restore: restoreOnError, 123 | throw: throwPageException, 124 | throwCors: throwCorsException, 125 | throwStrict: throwStrictException, 126 | throwRuntimeException: throwRuntimeException, 127 | throwStrictRuntimeException: throwStrictRuntimeException 128 | } 129 | } -------------------------------------------------------------------------------- /common/Tests/Selenium/ModuleLoader.js: -------------------------------------------------------------------------------- 1 | function getParameterByName(name, url) { 2 | if (!url) url = window.location.href; 3 | name = name.replace(/[\[\]]/g, '\\$&'); 4 | var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), 5 | results = regex.exec(url); 6 | if (!results) return null; 7 | if (!results[2]) return ''; 8 | return decodeURIComponent(results[2].replace(/\+/g, ' ')); 9 | } 10 | 11 | function loadFetchModule(moduleLoader, name) { 12 | // Load whatwg-fetch 13 | moduleLoader.add(name || "whatwg-fetch").afterLoad = function (polyFetch) { 14 | window.fetch = window.fetch || polyFetch.fetch; 15 | window.Headers = window.Headers || polyFetch.Headers; 16 | window.Response = window.Response || polyFetch.Response; 17 | window.Request = window.Request || polyFetch.Request; 18 | window.Promise = window.Promise || SimpleSyncPromise; 19 | 20 | var usePolyFetch = getParameterByName("polyFetch"); 21 | if (usePolyFetch) { 22 | window.fetch = polyFetch.fetch; 23 | window.Headers = polyFetch.Headers; 24 | window.Response = polyFetch.Response; 25 | window.Request = polyFetch.Request; 26 | } 27 | }; 28 | } 29 | 30 | function loadCommonModules(moduleLoader) { 31 | // Load and define the app insights test framework module 32 | moduleLoader.add("@microsoft/ai-test-framework", "./node_modules/@microsoft/ai-test-framework/dist/ai-test-framework"); 33 | 34 | // Load and define the app insights Shims module 35 | moduleLoader.add("@microsoft/applicationinsights-shims", "./node_modules/@microsoft/applicationinsights-shims/browser/applicationinsights-shims"); 36 | 37 | // Load DynamicProto 38 | moduleLoader.add("@microsoft/dynamicproto-js", "./node_modules/@microsoft/dynamicproto-js/lib/dist/umd/dynamicproto-js", true); 39 | } 40 | 41 | function ModuleLoader(config) { 42 | 43 | if (config) { 44 | require.config(config); 45 | } 46 | 47 | var requiredModules = []; 48 | 49 | function doModuleCb(moduleDef, theModule, cb) { 50 | if (theModule) { 51 | cb(module); 52 | } else { 53 | // Module was loaded, but has not yet created and instance -- so create one 54 | console && console.log("Module [" + moduleDef.name + "] loaded - creating instance - " + moduleDef.name); 55 | require([moduleDef.name], function (theModule) { 56 | cb(theModule); 57 | }); 58 | } 59 | } 60 | 61 | function processModules() { 62 | if (requiredModules.length > 0) { 63 | var moduleDef = requiredModules.shift(); 64 | if (moduleDef.prepare) { 65 | moduleDef.prepare(); 66 | } 67 | 68 | if (moduleDef.config) { 69 | require.config(config); 70 | } 71 | 72 | require([moduleDef.path], function (theModule) { 73 | try { 74 | if (moduleDef.run) { 75 | doModuleCb(moduleDef, theModule, function(theModule) { 76 | console && console.log("Running module - " + moduleDef.name); 77 | moduleDef.run(theModule); 78 | }); 79 | } else { 80 | define(moduleDef.name, function() { 81 | if (moduleDef.asDefault) { 82 | console && console.log("Returning default module - " + moduleDef.name); 83 | return { 84 | "default": theModule 85 | } 86 | } 87 | console && console.log("Returning module - " + moduleDef.name); 88 | return theModule 89 | }); 90 | 91 | if (moduleDef.afterLoad) { 92 | doModuleCb(moduleDef, theModule, function(theModule) { 93 | console && console.log("Module After Load called - " + moduleDef.name + " from " + moduleDef.path); 94 | moduleDef.afterLoad(theModule); 95 | }); 96 | } 97 | console && console.log("Loaded module - " + moduleDef.name + " from " + moduleDef.path); 98 | } 99 | } catch(err) { 100 | console && console.error("Failed to load and initialize [" + moduleDef.name + "] from [" + moduleDef.path + "]\n - Require ERROR: " + err.toString()); 101 | } 102 | 103 | processModules(); 104 | }, 105 | function (err) { 106 | console && console.error("Failed to load [" + moduleDef.name + "] from [" + moduleDef.path + "]\n - Require ERROR: " + err.toString()); 107 | if (moduleDef.path.toLowerCase() !== moduleDef.path) { 108 | console && console.log(" ** Validate the path it may need to be all lowercase -- " + moduleDef.path); 109 | } 110 | }); 111 | } 112 | } 113 | 114 | function addModule(name, path, asDefault) { 115 | var moduleDef = { 116 | name: name, 117 | path: !path ? name : path, 118 | asDefault: asDefault 119 | } 120 | 121 | requiredModules.push(moduleDef); 122 | 123 | return moduleDef; 124 | } 125 | 126 | return { 127 | add: addModule, 128 | run: processModules 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /common/Tests/Selenium/SimpleSyncPromise.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementing a simple synchronous promise interface as PhantomJS doesn't support / implement the es6 Promise as used by fetch 3 | */ 4 | function SimpleSyncPromise(executor) { 5 | var _self = this; 6 | var _state = "pending"; 7 | var _settledValue = null; 8 | var _queue = []; 9 | _self.then = function (onResolved, onRejected) { 10 | return new SimpleSyncPromise(function (resolve, reject) { 11 | // Queue the new promise returned to be resolved or rejected 12 | // when this promise settles. 13 | _enqueue(onResolved, onRejected, resolve, reject); 14 | }); 15 | }; 16 | _self["catch"] = function (onRejected) { 17 | // Just return an empty promise as this doesn't support rejection 18 | return _self.then(null, onRejected); 19 | } 20 | function _enqueue(onResolved, onRejected, resolve, reject) { 21 | _queue.push(function () { 22 | var value; 23 | try { 24 | if (_state === "resolved") { 25 | value = typeof onResolved === "function" ? onResolved(_settledValue) : _settledValue; 26 | } else { 27 | value = typeof onRejected === "function" ? onRejected(_settledValue) : _settledValue; 28 | } 29 | 30 | if (value instanceof SimpleSyncPromise) { 31 | // The called handlers returned a new promise, so the chained promise 32 | // will follow the state of this promise. 33 | value.then(resolve, reject); 34 | } else if (_state === "rejected" && typeof onRejected !== "function") { 35 | // If there wasn't an onRejected handler and this promise is rejected, then 36 | // the chained promise also rejects with the same reason. 37 | reject(value); 38 | } else { 39 | // If this promise is fulfilled, then the chained promise is also fulfilled 40 | // with either the settled value of this promise (if no onFulfilled handler 41 | // was available) or the return value of the handler. If this promise is 42 | // rejected and there was an onRejected handler, then the chained promise is 43 | // fulfilled with the return value of the handler. 44 | resolve(value); 45 | } 46 | } catch (e) { 47 | reject(e); 48 | } 49 | }); 50 | if (_state !== "pending") { 51 | _processQueue(); 52 | } 53 | } 54 | 55 | function _processQueue() { 56 | if (_queue.length > 0) { 57 | var pending = _queue.slice(); 58 | _queue = []; 59 | for (var i = 0, len = pending.length; i < len; ++i) { 60 | pending[i](); 61 | } 62 | } 63 | } 64 | 65 | function _resolve(value) { 66 | if (_state === "pending") { 67 | _settledValue = value; 68 | _state = "resolved"; 69 | _processQueue(); 70 | } 71 | } 72 | 73 | function _reject(reason) { 74 | if (_state === "pending") { 75 | _settledValue = reason; 76 | _state = "rejected"; 77 | _processQueue(); 78 | } 79 | } 80 | 81 | (function _initialize() { 82 | try { 83 | executor(_resolve, _reject); 84 | } catch (e) { 85 | _reject(e); 86 | } 87 | })(); 88 | } 89 | -------------------------------------------------------------------------------- /common/changes/@microsoft/applicationinsights-web/markwolff-refactor_readme_2019-10-04-20-34.json: -------------------------------------------------------------------------------- 1 | { 2 | "changes": [ 3 | { 4 | "packageName": "@microsoft/applicationinsights-web", 5 | "comment": "", 6 | "type": "none" 7 | } 8 | ], 9 | "packageName": "@microsoft/applicationinsights-web", 10 | "email": "marwolff@microsoft.com" 11 | } -------------------------------------------------------------------------------- /common/config/rush/.npmrc: -------------------------------------------------------------------------------- 1 | # Rush uses this file to configure the package registry, regardless of whether the 2 | # package manager is PNPM, NPM, or Yarn. Prior to invoking the package manager, 3 | # Rush will always copy this file to the folder where installation is performed. 4 | # When NPM is the package manager, Rush works around NPM's processing of 5 | # undefined environment variables by deleting any lines that reference undefined 6 | # environment variables. 7 | # 8 | # DO NOT SPECIFY AUTHENTICATION CREDENTIALS IN THIS FILE. It should only be used 9 | # to configure registry sources. 10 | 11 | registry=https://registry.npmjs.org/ 12 | always-auth=false 13 | -------------------------------------------------------------------------------- /common/config/rush/command-line.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", 3 | "commands": [ 4 | { 5 | "commandKind": "bulk", 6 | "name": "test", 7 | "summary": "Run all tests for all packages", 8 | "description": "Runs tests for all projects", 9 | "safeForSimultaneousRushProcesses": false, 10 | "enableParallelism": false, 11 | "ignoreMissingScript": false, 12 | "allowWarningsInSuccessfulBuild": true 13 | }, 14 | { 15 | "commandKind": "bulk", 16 | "name": "mintest", 17 | "summary": "Run all tests for all packages using the ai-minify for the source", 18 | "description": "Runs tests for all projects using the ai-minify for the source", 19 | "safeForSimultaneousRushProcesses": false, 20 | "enableParallelism": false, 21 | "ignoreMissingScript": true, 22 | "allowWarningsInSuccessfulBuild": true 23 | }, 24 | { 25 | "commandKind": "bulk", 26 | "name": "perftest", 27 | "summary": "Run all performance based tests for all packages", 28 | "description": "Runs performance tests for all projects", 29 | "safeForSimultaneousRushProcesses": false, 30 | "enableParallelism": false, 31 | "ignoreMissingScript": true, 32 | "allowWarningsInSuccessfulBuild": true 33 | }, 34 | { 35 | "commandKind": "bulk", 36 | "name": "lint", 37 | "summary": "Run all tslint for all packages", 38 | "description": "Runs tslint for all projects", 39 | "safeForSimultaneousRushProcesses": false, 40 | "enableParallelism": true, 41 | "ignoreMissingScript": false 42 | }, 43 | { 44 | "commandKind": "bulk", 45 | "summary": "Run all build for all packages", 46 | "name": "build", 47 | "allowWarningsInSuccessfulBuild": true 48 | }, 49 | { 50 | "commandKind": "bulk", 51 | "summary": "Run all build for all packages", 52 | "name": "rebuild", 53 | "allowWarningsInSuccessfulBuild": true 54 | }, 55 | { 56 | "commandKind": "bulk", 57 | "name": "ai-min", 58 | "summary": "Run all ai-minify tasks for all packages", 59 | "description": "Runs ai-minify tasks for all projects", 60 | "safeForSimultaneousRushProcesses": false, 61 | "enableParallelism": false, 62 | "ignoreMissingScript": true, 63 | "allowWarningsInSuccessfulBuild": true 64 | }, 65 | { 66 | "commandKind": "bulk", 67 | "name": "ai-restore", 68 | "summary": "Run all restore tasks for all packages to unminify the files", 69 | "description": "Runs all restore tasks for all projects to unminify the files", 70 | "safeForSimultaneousRushProcesses": false, 71 | "enableParallelism": false, 72 | "ignoreMissingScript": true, 73 | "allowWarningsInSuccessfulBuild": true 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /common/config/rush/common-versions.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This configuration file specifies NPM dependency version selections that affect all projects 3 | * in a Rush repo. For full documentation, please see https://rushjs.io 4 | */ 5 | { 6 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json", 7 | 8 | /** 9 | * A table that specifies a "preferred version" for a dependency package. The "preferred version" 10 | * is typically used to hold an indirect dependency back to a specific version, however generally 11 | * it can be any SemVer range specifier (e.g. "~1.2.3"), and it will narrow any (compatible) 12 | * SemVer range specifier. See the Rush documentation for details about this feature. 13 | */ 14 | "preferredVersions": { 15 | 16 | /** 17 | * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo, 18 | * instead of the latest version. 19 | */ 20 | // "some-library": "1.2.3" 21 | }, 22 | 23 | /** 24 | * The "rush check" command can be used to enforce that every project in the repo must specify 25 | * the same SemVer range for a given dependency. However, sometimes exceptions are needed. 26 | * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be 27 | * accepted by "rush check" for a given dependency. 28 | * 29 | * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE 30 | * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO). 31 | * This design avoids unnecessary churn in this file. 32 | */ 33 | "allowedAlternativeVersions": { 34 | 35 | /** 36 | * For example, allow some projects to use an older TypeScript compiler 37 | * (in addition to whatever "usual" version is being used by other projects in the repo): 38 | */ 39 | "typescript": [ 40 | "^3.9.2" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/config/rush/version-policies.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This is configuration file is used for advanced publishing configurations with Rush. 3 | * For full documentation, please see https://rushjs.io 4 | */ 5 | 6 | /** 7 | * A list of version policy definitions. A "version policy" is a custom package versioning 8 | * strategy that affets "rush change", "rush version", and "rush publish". The strategy applies 9 | * to a set of projects that are specified using the "versionPolicyName" field in rush.json. 10 | */ 11 | [ 12 | // { 13 | // /** 14 | // * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion"). 15 | // * 16 | // * The "lockStepVersion" mode specifies that the projects will use "lock-step versioning". This 17 | // * strategy is appropriate for a set of packages that act as selectable components of a 18 | // * unified product. The entire set of packages are always published together, and always share 19 | // * the same NPM version number. When the packages depend on other packages in the set, the 20 | // * SemVer range is usually restricted to a single version. 21 | // */ 22 | // "definitionName": "lockStepVersion", 23 | // 24 | // /** 25 | // * (Required) The name that will be used for the "versionPolicyName" field in rush.json. 26 | // * This name is also used command-line parameters such as "--version-policy" 27 | // * and "--to-version-policy". 28 | // */ 29 | // "policyName": "MyBigFramework", 30 | // 31 | // /** 32 | // * (Required) The current version. All packages belonging to the set should have this version 33 | // * in the current branch. When bumping versions, Rush uses this to determine the next version. 34 | // * (The "version" field in package.json is NOT considered.) 35 | // */ 36 | // "version": "1.0.0", 37 | // 38 | // /** 39 | // * (Required) The type of bump that will be performed when publishing the next release. 40 | // * When creating a release branch in Git, this field should be updated according to the 41 | // * type of release. 42 | // * 43 | // * Valid values are: "prerelease", "release", "minor", "patch", "major" 44 | // */ 45 | // "nextBump": "prerelease", 46 | // 47 | // /** 48 | // * (Optional) If specified, all packages in the set share a common CHANGELOG.md file. 49 | // * This file is stored with the specified "main" project, which must be a member of the set. 50 | // * 51 | // * If this field is omitted, then a separate CHANGELOG.md file will be maintained for each 52 | // * package in the set. 53 | // */ 54 | // "mainProject": "my-app" 55 | // }, 56 | // 57 | // { 58 | // /** 59 | // * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion"). 60 | // * 61 | // * The "individualVersion" mode specifies that the projects will use "individual versioning". 62 | // * This is the typical NPM model where each package has an independent version number 63 | // * and CHANGELOG.md file. Although a single CI definition is responsible for publishing the 64 | // * packages, they otherwise don't have any special relationship. The version bumping will 65 | // * depend on how developers answer the "rush change" questions for each package that 66 | // * is changed. 67 | // */ 68 | // "definitionName": "individualVersion", 69 | // 70 | // "policyName": "MyRandomLibraries", 71 | // 72 | // /** 73 | // * (Optional) This can be used to enforce that all packages in the set must share a common 74 | // * major version number, e.g. because they are from the same major release branch. 75 | // * It can also be used to discourage people from accidentally making "MAJOR" SemVer changes 76 | // * inappropriately. The minor/patch version parts will be bumped independently according 77 | // * to the types of changes made to each project, according to the "rush change" command. 78 | // */ 79 | // "lockedMajor": 3 80 | // } 81 | ] 82 | -------------------------------------------------------------------------------- /common/publish/Logging/Logging.psm1: -------------------------------------------------------------------------------- 1 | $global:hasErrors = $false 2 | $global:logPath = $null 3 | $global:logDir = $null 4 | $global:logFile = $null 5 | 6 | $fileTimeStamp = ((get-date).ToUniversalTime()).ToString("yyyyMMddThhmmss") 7 | 8 | ## Function: Get-TimeStamp 9 | ## Purpose: Used to get the timestamp for logging 10 | Function Get-TimeStamp 11 | { 12 | return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date) 13 | } 14 | 15 | Function Write-LogDetail( 16 | [string] $value 17 | ) { 18 | $logFile = Get-LogFile 19 | Add-Content $logFile "$(Get-TimeStamp) $value" 20 | } 21 | 22 | Function Clear-HasErrors { 23 | $global:hasErrors = $false 24 | } 25 | 26 | Function Get-HasErrors { 27 | return $global:hasErrors 28 | } 29 | 30 | Function Get-LogPath { 31 | if ([string]::IsNullOrWhiteSpace($global:logDir)) { 32 | $global:logDir = $global:logPath 33 | if ([string]::IsNullOrWhiteSpace($global:logPath) -eq $true) { 34 | $global:logDir = join-path ${env:SystemDrive} "\Logs" 35 | } 36 | 37 | if (!(Test-Path -Path $global:logDir)) { 38 | New-Item -ItemType directory -Path $global:logDir 39 | } 40 | } 41 | 42 | return $global:logDir 43 | } 44 | 45 | Function Set-LogPath { 46 | param ( 47 | [string] $logPath, 48 | [string] $filename = $null, 49 | [boolean] $clearHasErrors = $true 50 | ) 51 | 52 | $global:logDir = $null 53 | $global:logPath = $logPath 54 | 55 | if ([string]::IsNullOrWhiteSpace($filename) -ne $true) { 56 | $logDir = Get-LogPath 57 | $global:logFile = "$logDir\$($filename)_$fileTimeStamp.txt" 58 | } 59 | 60 | if ($clearHasErrors -eq $true) { 61 | Clear-HasErrors 62 | } 63 | } 64 | 65 | Function Get-LogFile { 66 | if ([string]::IsNullOrWhiteSpace($global:logFile) -eq $true) { 67 | $logDir = Get-LogPath 68 | $global:logFile = "$logDir\publishLog_$fileTimeStamp.txt" 69 | } 70 | 71 | return $global:logFile 72 | } 73 | 74 | ## Function: Write-Log 75 | ## Purpose: Used to log the output to both the Console and a log file 76 | Function Write-Log( 77 | [string] $value 78 | ) { 79 | Write-Host "$(Get-TimeStamp) $value" 80 | Write-LogDetail $value 81 | } 82 | 83 | ## Function: Write-LogWarning 84 | ## Purpose: Used to log warning messages to both the Console and a log file 85 | Function Write-LogWarning ( 86 | [string] $value 87 | ) { 88 | Write-Host "$(Get-TimeStamp) [WRN] $value" -ForegroundColor Yellow -BackgroundColor DarkBlue 89 | Write-LogDetail "[WRN] $value" 90 | } 91 | 92 | ## Function: Write-LogFailure 93 | ## Purpose: Used to log failure messages to both the Console and a log file 94 | Function Write-LogFailure ( 95 | [string] $value, 96 | [boolean] $isTerminal = $true 97 | ) { 98 | if ($isTerminal -eq $true) { 99 | Write-Host "$(Get-TimeStamp) [ERR] $value" -ForegroundColor Yellow -BackgroundColor DarkRed 100 | Write-LogDetail "[ERR] $value" 101 | $global:hasErrors = $true 102 | } else { 103 | Write-Host "$(Get-TimeStamp) [INF] $value" -ForegroundColor Red 104 | Write-LogDetail "[INF] $value" 105 | } 106 | } 107 | 108 | ## Function: Write-LogException 109 | ## Purpose: Used to log exception details to both the Console and a log file 110 | Function Write-LogException ( 111 | [System.Management.Automation.ErrorRecord] $err, 112 | [boolean] $asError = $true, 113 | [string] $prefix = "" 114 | ) { 115 | Write-LogFailure "$($prefix)Exception: $($err.Exception.Message)" $asError 116 | Write-LogFailure "$($prefix)Source : $($err.Exception.Source)" $asError 117 | Write-LogDetail "$($prefix)Full Exception: $($err.Exception)" 118 | Write-LogFailure "$($prefix)$($err.ScriptStackTrace)" $asError 119 | } 120 | 121 | ## Function: Write-LogErrors 122 | ## Purpose: Used to log error messages to both the Console and a log file 123 | Function Write-LogErrors ( 124 | [boolean] $asError = $true, 125 | [string] $prefix = "" 126 | ) { 127 | foreach ($err in $global:Error) { 128 | Write-LogException $err $asError 129 | foreach ($innerEx in $err.InnerExceptions) { 130 | Write-LogException $innerEx $asError "$prefix " 131 | } 132 | } 133 | } 134 | 135 | # Define the exported functions 136 | Export-ModuleMember -Function Clear-HasErrors 137 | Export-ModuleMember -Function Get-HasErrors 138 | Export-ModuleMember -Function Get-LogPath 139 | Export-ModuleMember -Function Set-LogPath 140 | Export-ModuleMember -Function Get-LogFile 141 | Export-ModuleMember -Function Write-Log 142 | Export-ModuleMember -Function Write-LogWarning 143 | Export-ModuleMember -Function Write-LogFailure 144 | Export-ModuleMember -Function Write-LogException 145 | Export-ModuleMember -Function Write-LogErrors 146 | -------------------------------------------------------------------------------- /common/scripts/install-run-rush.js: -------------------------------------------------------------------------------- 1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 2 | // 3 | // This script is intended for usage in an automated build environment where the Rush command may not have 4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to it. 6 | // An example usage would be: 7 | // 8 | // node common/scripts/install-run-rush.js install 9 | // 10 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 11 | // 12 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 13 | // See the @microsoft/rush package's LICENSE file for details. 14 | 15 | /******/ (() => { // webpackBootstrap 16 | /******/ "use strict"; 17 | /******/ var __webpack_modules__ = ({ 18 | 19 | /***/ 16928: 20 | /*!***********************!*\ 21 | !*** external "path" ***! 22 | \***********************/ 23 | /***/ ((module) => { 24 | 25 | module.exports = require("path"); 26 | 27 | /***/ }), 28 | 29 | /***/ 179896: 30 | /*!*********************!*\ 31 | !*** external "fs" ***! 32 | \*********************/ 33 | /***/ ((module) => { 34 | 35 | module.exports = require("fs"); 36 | 37 | /***/ }) 38 | 39 | /******/ }); 40 | /************************************************************************/ 41 | /******/ // The module cache 42 | /******/ var __webpack_module_cache__ = {}; 43 | /******/ 44 | /******/ // The require function 45 | /******/ function __webpack_require__(moduleId) { 46 | /******/ // Check if module is in cache 47 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 48 | /******/ if (cachedModule !== undefined) { 49 | /******/ return cachedModule.exports; 50 | /******/ } 51 | /******/ // Create a new module (and put it into the cache) 52 | /******/ var module = __webpack_module_cache__[moduleId] = { 53 | /******/ // no module.id needed 54 | /******/ // no module.loaded needed 55 | /******/ exports: {} 56 | /******/ }; 57 | /******/ 58 | /******/ // Execute the module function 59 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 60 | /******/ 61 | /******/ // Return the exports of the module 62 | /******/ return module.exports; 63 | /******/ } 64 | /******/ 65 | /************************************************************************/ 66 | /******/ /* webpack/runtime/compat get default export */ 67 | /******/ (() => { 68 | /******/ // getDefaultExport function for compatibility with non-harmony modules 69 | /******/ __webpack_require__.n = (module) => { 70 | /******/ var getter = module && module.__esModule ? 71 | /******/ () => (module['default']) : 72 | /******/ () => (module); 73 | /******/ __webpack_require__.d(getter, { a: getter }); 74 | /******/ return getter; 75 | /******/ }; 76 | /******/ })(); 77 | /******/ 78 | /******/ /* webpack/runtime/define property getters */ 79 | /******/ (() => { 80 | /******/ // define getter functions for harmony exports 81 | /******/ __webpack_require__.d = (exports, definition) => { 82 | /******/ for(var key in definition) { 83 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 84 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 85 | /******/ } 86 | /******/ } 87 | /******/ }; 88 | /******/ })(); 89 | /******/ 90 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 91 | /******/ (() => { 92 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 93 | /******/ })(); 94 | /******/ 95 | /******/ /* webpack/runtime/make namespace object */ 96 | /******/ (() => { 97 | /******/ // define __esModule on exports 98 | /******/ __webpack_require__.r = (exports) => { 99 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 100 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 101 | /******/ } 102 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 103 | /******/ }; 104 | /******/ })(); 105 | /******/ 106 | /************************************************************************/ 107 | var __webpack_exports__ = {}; 108 | // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. 109 | (() => { 110 | /*!************************************************!*\ 111 | !*** ./lib-esnext/scripts/install-run-rush.js ***! 112 | \************************************************/ 113 | __webpack_require__.r(__webpack_exports__); 114 | /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! path */ 16928); 115 | /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); 116 | /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 179896); 117 | /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); 118 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 119 | // See LICENSE in the project root for license information. 120 | /* eslint-disable no-console */ 121 | 122 | 123 | const { installAndRun, findRushJsonFolder, RUSH_JSON_FILENAME, runWithErrorAndStatusCode } = require('./install-run'); 124 | const PACKAGE_NAME = '@microsoft/rush'; 125 | const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; 126 | const INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_RUSH_LOCKFILE_PATH'; 127 | function _getRushVersion(logger) { 128 | const rushPreviewVersion = process.env[RUSH_PREVIEW_VERSION]; 129 | if (rushPreviewVersion !== undefined) { 130 | logger.info(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`); 131 | return rushPreviewVersion; 132 | } 133 | const rushJsonFolder = findRushJsonFolder(); 134 | const rushJsonPath = path__WEBPACK_IMPORTED_MODULE_0__.join(rushJsonFolder, RUSH_JSON_FILENAME); 135 | try { 136 | const rushJsonContents = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(rushJsonPath, 'utf-8'); 137 | // Use a regular expression to parse out the rushVersion value because rush.json supports comments, 138 | // but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script. 139 | const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/); 140 | return rushJsonMatches[1]; 141 | } 142 | catch (e) { 143 | throw new Error(`Unable to determine the required version of Rush from ${RUSH_JSON_FILENAME} (${rushJsonFolder}). ` + 144 | `The 'rushVersion' field is either not assigned in ${RUSH_JSON_FILENAME} or was specified ` + 145 | 'using an unexpected syntax.'); 146 | } 147 | } 148 | function _getBin(scriptName) { 149 | switch (scriptName.toLowerCase()) { 150 | case 'install-run-rush-pnpm.js': 151 | return 'rush-pnpm'; 152 | case 'install-run-rushx.js': 153 | return 'rushx'; 154 | default: 155 | return 'rush'; 156 | } 157 | } 158 | function _run() { 159 | const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv; 160 | // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the 161 | // appropriate binary inside the rush package to run 162 | const scriptName = path__WEBPACK_IMPORTED_MODULE_0__.basename(scriptPath); 163 | const bin = _getBin(scriptName); 164 | if (!nodePath || !scriptPath) { 165 | throw new Error('Unexpected exception: could not detect node path or script path'); 166 | } 167 | let commandFound = false; 168 | let logger = { info: console.log, error: console.error }; 169 | for (const arg of packageBinArgs) { 170 | if (arg === '-q' || arg === '--quiet') { 171 | // The -q/--quiet flag is supported by both `rush` and `rushx`, and will suppress 172 | // any normal informational/diagnostic information printed during startup. 173 | // 174 | // To maintain the same user experience, the install-run* scripts pass along this 175 | // flag but also use it to suppress any diagnostic information normally printed 176 | // to stdout. 177 | logger = { 178 | info: () => { }, 179 | error: console.error 180 | }; 181 | } 182 | else if (!arg.startsWith('-') || arg === '-h' || arg === '--help') { 183 | // We either found something that looks like a command (i.e. - doesn't start with a "-"), 184 | // or we found the -h/--help flag, which can be run without a command 185 | commandFound = true; 186 | } 187 | } 188 | if (!commandFound) { 189 | console.log(`Usage: ${scriptName} [args...]`); 190 | if (scriptName === 'install-run-rush-pnpm.js') { 191 | console.log(`Example: ${scriptName} pnpm-command`); 192 | } 193 | else if (scriptName === 'install-run-rush.js') { 194 | console.log(`Example: ${scriptName} build --to myproject`); 195 | } 196 | else { 197 | console.log(`Example: ${scriptName} custom-command`); 198 | } 199 | process.exit(1); 200 | } 201 | runWithErrorAndStatusCode(logger, () => { 202 | const version = _getRushVersion(logger); 203 | logger.info(`The ${RUSH_JSON_FILENAME} configuration requests Rush version ${version}`); 204 | const lockFilePath = process.env[INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE]; 205 | if (lockFilePath) { 206 | logger.info(`Found ${INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE}="${lockFilePath}", installing with lockfile.`); 207 | } 208 | return installAndRun(logger, PACKAGE_NAME, version, bin, packageBinArgs, lockFilePath); 209 | }); 210 | } 211 | _run(); 212 | //# sourceMappingURL=install-run-rush.js.map 213 | })(); 214 | 215 | module.exports = __webpack_exports__; 216 | /******/ })() 217 | ; 218 | //# sourceMappingURL=install-run-rush.js.map -------------------------------------------------------------------------------- /common/scripts/install-run-rushx.js: -------------------------------------------------------------------------------- 1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 2 | // 3 | // This script is intended for usage in an automated build environment where the Rush command may not have 4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the 6 | // rushx command. 7 | // 8 | // An example usage would be: 9 | // 10 | // node common/scripts/install-run-rushx.js custom-command 11 | // 12 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 13 | // 14 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 15 | // See the @microsoft/rush package's LICENSE file for details. 16 | 17 | /******/ (() => { // webpackBootstrap 18 | /******/ "use strict"; 19 | var __webpack_exports__ = {}; 20 | /*!*************************************************!*\ 21 | !*** ./lib-esnext/scripts/install-run-rushx.js ***! 22 | \*************************************************/ 23 | 24 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 25 | // See LICENSE in the project root for license information. 26 | require('./install-run-rush'); 27 | //# sourceMappingURL=install-run-rushx.js.map 28 | module.exports = __webpack_exports__; 29 | /******/ })() 30 | ; 31 | //# sourceMappingURL=install-run-rushx.js.map -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microsoft/applicationinsights-react-native", 3 | "version": "4.3.6", 4 | "description": "Microsoft Application Insights React Native Plugin", 5 | "main": "dist-esm/index.js", 6 | "types": "types/index.d.ts", 7 | "sideEffects": false, 8 | "author": "Microsoft Application Insights Team", 9 | "license": "MIT", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/microsoft/applicationinsights-react-native" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/microsoft/applicationinsights-react-native/issues" 16 | }, 17 | "homepage": "https://github.com/microsoft/applicationinsights-react-native#readme", 18 | "keywords": [ 19 | "performance monitoring", 20 | "application insights", 21 | "microsoft", 22 | "azure", 23 | "react native" 24 | ], 25 | "scripts": { 26 | "postinstall": "node common/scripts/install-run-rush-silent.js update", 27 | "build": "node common/scripts/install-run-rush.js rebuild --verbose", 28 | "rebuild": "npm run build", 29 | "testx": "rush test --verbose", 30 | "test": "node common/scripts/install-run-rush.js test --verbose", 31 | "mintest": "node common/scripts/install-run-rush.js mintest --verbose", 32 | "lint": "node common/scripts/install-run-rush.js lint --verbose", 33 | "perftest": "node common/scripts/install-run-rush.js perftest --verbose", 34 | "rupdate": "node common/scripts/install-run-rush.js update --recheck --purge --full", 35 | "serve": "grunt serve", 36 | "setVersion": "node ./tools/release-tools/setVersion.js", 37 | "setAiVersion": "node ./tools/release-tools/setAiVersion.js", 38 | "purge": "node common/scripts/install-run-rush.js purge", 39 | "fullClean": "git clean -xdf && npm install && rush update --recheck --full", 40 | "fullCleanBuild": "npm run fullClean && npm run rebuild", 41 | "ai-min": "node common/scripts/install-run-rush.js ai-min", 42 | "ai-restore": "node common/scripts/install-run-rush.js ai-restore", 43 | "gh-status": "node ./tools/status-tools/github-status.js", 44 | "npm-package": "node ./tools/release-tools/npm-package.js" 45 | }, 46 | "devDependencies": { 47 | "@microsoft/rush": "5.153.1", 48 | "@nevware21/grunt-eslint-ts": "^0.2.2", 49 | "@nevware21/grunt-ts-plugin": "^0.4.3", 50 | "@typescript-eslint/eslint-plugin": "^4.28.0", 51 | "@typescript-eslint/parser": "^4.28.0", 52 | "archiver": "^5.3.0", 53 | "chromium": "^3.0.2", 54 | "connect": "^3.7.0", 55 | "eslint": "^7.29.0", 56 | "eslint-config-standard": "^16.0.3", 57 | "eslint-plugin-import": "^2.23.4", 58 | "eslint-plugin-node": "^11.1.0", 59 | "eslint-plugin-promise": "^5.1.0", 60 | "eslint-plugin-security": "^1.4.0", 61 | "grunt": "^1.5.3", 62 | "grunt-cli": "^1.4.3", 63 | "grunt-contrib-connect": "^3.0.0", 64 | "grunt-contrib-uglify": "^5.0.1", 65 | "grunt-string-replace": "^1.3.1", 66 | "eventemitter2": "6.4.9", 67 | "puppeteer": "24.8.2", 68 | "typedoc": "^0.22.8", 69 | "typescript": "^4.3.4", 70 | "whatwg-fetch": "^3.0.0" 71 | }, 72 | "dependencies": { 73 | "@microsoft/applicationinsights-common": "^3.3.6", 74 | "@microsoft/applicationinsights-core-js": "^3.3.6", 75 | "@microsoft/applicationinsights-shims": "^3.0.1", 76 | "@microsoft/dynamicproto-js": "^2.0.3", 77 | "@nevware21/ts-utils": ">= 0.11.3 < 2.x" 78 | }, 79 | "peerDependencies": { 80 | "react-native": "*", 81 | "react-native-device-info": ">=5.2.1", 82 | "tslib": "*" 83 | }, 84 | "peerDependenciesMeta": { 85 | "react-native-device-info": { 86 | "optional": true 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /policheck-exclusions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | COMMON\CONFIG\RUSH 5 | 6 | .GIT 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /rush.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", 3 | "npmVersion": "9.9.3", 4 | "rushVersion": "5.153.1", 5 | "projectFolderMaxDepth": 4, 6 | "projects": [ 7 | { 8 | "packageName": "applicationinsights-js-release-tools", 9 | "projectFolder": "tools/release-tools", 10 | "shouldPublish": false 11 | }, 12 | { 13 | "packageName": "@microsoft/ai-test-framework", 14 | "projectFolder": "common/Tests/Framework", 15 | "shouldPublish": true 16 | }, 17 | { 18 | "packageName": "@microsoft/applicationinsights-rollup-plugin-uglify3-js", 19 | "projectFolder": "tools/rollup-plugin-uglify3-js", 20 | "shouldPublish": true 21 | }, 22 | { 23 | "packageName": "@microsoft/applicationinsights-react-native", 24 | "projectFolder": "applicationinsights-react-native", 25 | "shouldPublish": true 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | # Temporary files created by Metro to check the health of the file watcher 17 | .metro-health-check* 18 | -------------------------------------------------------------------------------- /sample/App.js: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar'; 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | 4 | import { ApplicationInsights } from '@microsoft/applicationinsights-web'; 5 | 6 | // import { ReactNativeManualDevicePlugin } from '@microsoft/applicationinsights-react-native/dist-esm/manualIndex'; // for android 7 | import { ReactNativeManualDevicePlugin } from '@microsoft/applicationinsights-react-native/manual'; // for web 8 | 9 | var RNPlugin = new ReactNativeManualDevicePlugin(); 10 | var appInsights = new ApplicationInsights({ 11 | config: { 12 | disableDeviceCollection: true, 13 | instrumentationKey: '814a172a-92fd-4950-9023-9cf13bb65696', 14 | extensions: [RNPlugin] 15 | } 16 | }); 17 | appInsights.loadAppInsights(); 18 | appInsights.trackPageView(); 19 | appInsights.trackEvent({name: 'some event'}); 20 | console.log("current app", appInsights.context); 21 | export default function App() { 22 | return ( 23 | 24 | Click F12 and see network, there would be track flow there 25 | 26 | 27 | ); 28 | } 29 | 30 | const styles = StyleSheet.create({ 31 | container: { 32 | flex: 1, 33 | backgroundColor: '#fff', 34 | alignItems: 'center', 35 | justifyContent: 'center', 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # expo-manual-demo 2 | This example is built on https://docs.expo.dev/tutorial/create-your-first-app/ 3 | This demo shows how to use ApplicationInsights with ReactNativeManualDevicePlugin. 4 | 5 | # Start 6 | 7 | npm install 8 | 9 | npm run start 10 | 11 | android user press 'a' 12 | web user press 'w' 13 | -------------------------------------------------------------------------------- /sample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "StickerSmash", 4 | "slug": "StickerSmash", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "assetBundlePatterns": [ 15 | "**/*" 16 | ], 17 | "ios": { 18 | "supportsTablet": true 19 | }, 20 | "android": { 21 | "adaptiveIcon": { 22 | "foregroundImage": "./assets/adaptive-icon.png", 23 | "backgroundColor": "#ffffff" 24 | } 25 | }, 26 | "web": { 27 | "favicon": "./assets/favicon.png" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sample/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/applicationinsights-react-native/5ab89069d9c71a5da8fb5eb1d686a52c1a8e588b/sample/assets/adaptive-icon.png -------------------------------------------------------------------------------- /sample/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/applicationinsights-react-native/5ab89069d9c71a5da8fb5eb1d686a52c1a8e588b/sample/assets/favicon.png -------------------------------------------------------------------------------- /sample/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/applicationinsights-react-native/5ab89069d9c71a5da8fb5eb1d686a52c1a8e588b/sample/assets/icon.png -------------------------------------------------------------------------------- /sample/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/applicationinsights-react-native/5ab89069d9c71a5da8fb5eb1d686a52c1a8e588b/sample/assets/splash.png -------------------------------------------------------------------------------- /sample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "applicationinsights-reactnative-sample", 3 | "version": "1.1.1", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web" 10 | }, 11 | "dependencies": { 12 | "@expo/webpack-config": "^18.0.1", 13 | "@microsoft/applicationinsights-react-native": "^4.3.6", 14 | "@microsoft/applicationinsights-web": "^3.3.6", 15 | "expo": "~48.0.18", 16 | "expo-status-bar": "~1.4.4", 17 | "react": "18.2.0", 18 | "react-dom": "18.2.0", 19 | "react-native": "0.71.8", 20 | "react-native-web": "~0.18.10" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.20.0" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /scripts/dtsgen.js: -------------------------------------------------------------------------------- 1 | // 2 | // This script wrap the generated api dts file with a oneDS namespace and copyright notice the version 3 | // 4 | // node ../../scripts\dtsgen.js ./dist-esm/applicationinsights-web.d.ts 'Microsoft.ApplicationInsights' ./ 5 | // 6 | const fs = require("fs"); 7 | const path = require("path"); 8 | 9 | function parseArgs(expectedArgs) { 10 | var passedArgs = process.argv; 11 | var theArgs = { 12 | "$script" : passedArgs[1] 13 | }; 14 | 15 | for (var lp = 0; lp < expectedArgs.length; lp++) { 16 | var argIdx = 2 + lp; 17 | var expArg = expectedArgs[lp]; 18 | var value = expArg.value; 19 | if (passedArgs.length > argIdx) { 20 | value = passedArgs[argIdx]; 21 | if (value && value.length > 2 && ( 22 | (value[0] === "'" && value[value.length - 1] === "'") || 23 | (value[0] === '"' && value[value.length - 1] === '"') 24 | )) { 25 | value = value.substring(1, value.length - 1); 26 | } 27 | } 28 | if (expArg.isSwitch) { 29 | // Convert to boolean 30 | value = !!value; 31 | } 32 | 33 | theArgs[expArg.name] = value; 34 | } 35 | 36 | return theArgs; 37 | } 38 | 39 | var theArgs = parseArgs([ 40 | { name: "skuName", value: null}, // The Sku name to place in the copyright notice 41 | { name: "projectPath", value: "./"}, // The root path for the project 42 | { name: "dtsFile", value: ""}, // [Optional] The generated Dts file (if cannot be derived from the package.json) 43 | { name: "hidePrivate", value: false, isSwitch: true}, // [Optional] Switch to hide private properties and functions 44 | ]); 45 | 46 | if (!theArgs.skuName) { 47 | throw "Missing skuName"; 48 | } 49 | 50 | var projectPath = path.resolve(process.cwd(), theArgs.projectPath) 51 | var packagePath = path.resolve(theArgs.projectPath, "package.json"); 52 | console.log(`Using Package: ${packagePath}, current path cwd ${process.cwd()}`); 53 | 54 | var packageJson = require(packagePath); 55 | if (!packageJson || !packageJson.version) { 56 | throw `Missing package.json or version from [${packagePath}]` 57 | } 58 | 59 | var version = packageJson.version 60 | var author = packageJson.author || ""; 61 | var homepage = packageJson.homepage || ""; 62 | var packageName = packageJson.name 63 | packageName = packageName.replace('@microsoft/', '').replace('/', '_'); 64 | 65 | if (!theArgs.dtsFile) { 66 | theArgs.dtsFile = path.resolve(projectPath, "dist", `${packageName}.d.ts`); 67 | } 68 | 69 | var dtsFileRollup = theArgs.dtsFile.replace(`${packageName}.d.ts`, `${packageName}.rollup.d.ts`); 70 | 71 | var rollupContent = 72 | "/*\n" + 73 | ` * ${theArgs.skuName}, ${version}\n` + 74 | " * Copyright (c) Microsoft and contributors. All rights reserved.\n" + 75 | " *\n" + 76 | ` * ${author}\n` + 77 | ` * ${homepage}\n`; 78 | 79 | var newContent = rollupContent + 80 | " */\n\n" + 81 | "declare namespace ApplicationInsights {"; 82 | 83 | rollupContent += 84 | " *\n" + 85 | " * ---------------------------------------------------------------------------\n" + 86 | " * This is a single combined (rollup) declaration file for the package,\n" + 87 | " * use this version if your build environment doesn't support the using the\n" + 88 | " * individual *.d.ts files or default namespace wrapped version.\n" + 89 | ` * - Namespaced version: ${packageName}.d.ts\n` + 90 | " * ---------------------------------------------------------------------------\n" + 91 | " */\n"; 92 | 93 | console.log(`Transforming: ${theArgs.dtsFile}`); 94 | 95 | fs.readFile(theArgs.dtsFile, (err, data) => { 96 | if (err) { 97 | console.error(err); 98 | throw `Failed to read .d.ts file [${theArgs.dtsFile}]`; 99 | } else { 100 | processFile(data.toString()); 101 | } 102 | }); 103 | 104 | function processFile(dtsContents) { 105 | console.log("File..."); 106 | // console.log(dtsContents); 107 | 108 | // Read the generated dts file and append to the new content 109 | var lastLine = "" 110 | 111 | // Prefix every line with 4 spaces (indenting the lines) 112 | var lines = dtsContents.split("\n"); 113 | console.log(`Lines: ${lines.length}`); 114 | // console.log(dtsContents); 115 | 116 | lines.forEach((line) => { 117 | // Trim whitespace from the end of the string 118 | var rollupLine = line.replace(/(\s+$)/g, ''); 119 | 120 | if (line && line.trim().length > 0) { 121 | // Remove exports and declares 122 | line = line.replace('export declare ', ''); 123 | line = line.replace('declare ', ''); 124 | line = line.replace('export { }', ''); 125 | 126 | // Trim whitespace from the end of the string 127 | line = line.replace(/(\s+$)/g, ''); 128 | 129 | if (theArgs.hidePrivate) { 130 | // Hide private properties and functions 131 | line = line.replace(/(^\s+)private (.*);/, '$1// private $2;'); 132 | rollupLine = rollupLine.replace(/(^\s+)private (.*);/, '$1// private $2;'); 133 | } 134 | 135 | rollupContent += `\n${rollupLine}`; 136 | newContent += `\n ${line}`; 137 | } else if (lastLine) { 138 | // Only add 1 blank line 139 | rollupContent += "\n" 140 | newContent += "\n" 141 | } 142 | 143 | lastLine = line 144 | }); 145 | 146 | // Add final trailing closing bracket for the namespace 147 | newContent += "\n}"; 148 | 149 | fs.writeFile(dtsFileRollup, rollupContent, (err, data) => { 150 | if (err) { 151 | console.error(err); 152 | throw `Failed to write ${dtsFileRollup}`; 153 | } 154 | }); 155 | 156 | fs.writeFile(theArgs.dtsFile, newContent, (err, data) => { 157 | if (err) { 158 | console.error(err); 159 | throw `Failed to write ${theArgs.dtsFile}`; 160 | } 161 | }); 162 | } 163 | -------------------------------------------------------------------------------- /scripts/dtsgen.ps1: -------------------------------------------------------------------------------- 1 | ## 2 | ## This script wrap the generated api dts file with a oneDS namespace and copyright notice the version 3 | ## 4 | ## powershell.exe -ExecutionPolicy Bypass ../../scripts\dtsgen.ps1 ./dist-esm/applicationinsights-web.d.ts ./ 'Microsoft.ApplicationInsights' 5 | ## 6 | param ( 7 | [string] $skuName, # The Sku name to place in the copyright notice 8 | [string] $projectPath = "./", # The root path for the project 9 | [string] $dtsFile = "", # [Optional] The generated Dts file (if cannot be derived from the package.json) 10 | [switch] $hidePrivate # [Optional] Switch to hide private properties and functions 11 | ) 12 | 13 | $packagePath = ("$($projectPath)package.json" | Resolve-Path) 14 | if (!(Test-Path "$packagePath")) { 15 | Write-Warning "Missing package.json file [$packagePath]" 16 | exit 17 | } 18 | 19 | Write-Host "Using Package: $packagePath" 20 | 21 | $packageJson = Get-Content "$packagePath" | Out-String | ConvertFrom-Json 22 | $version = $packageJson.version 23 | $author = $packageJson.author 24 | $homepage = $packageJson.homepage 25 | $packageName = $packageJson.name 26 | $packageName = $packageName -replace '@microsoft/', '' 27 | $packageName = $packageName -replace '/', '_' 28 | 29 | if (!$dtsFile) { 30 | $dtsFile = ("$($projectPath)dist/$packageName.d.ts" | Resolve-Path) 31 | } 32 | 33 | Write-Host "Transforming: $dtsFile" 34 | 35 | if (!$dtsFile -or !(Test-Path $dtsFile -ErrorAction Ignore)) { 36 | Write-Error "Missing .d.ts file [$dtsFile]" 37 | exit 38 | } 39 | 40 | $dtsFileRollup = $dtsFile -replace "$packageName.d.ts", "$packageName.rollup.d.ts" 41 | 42 | $rollupContent = 43 | "/*`n" + 44 | " * $skuName, $version`n" + 45 | " * Copyright (c) Microsoft and contributors. All rights reserved.`n" + 46 | " *`n" + 47 | " * $author`n" + 48 | " * $homepage`n"; 49 | 50 | $newContent = $rollupContent + 51 | " */`n`n" + 52 | "declare namespace ApplicationInsights {"; 53 | 54 | $rollupContent = $rollupContent + 55 | " *`n" + 56 | " * ---------------------------------------------------------------------------`n" + 57 | " * This is a single combined (rollup) declaration file for the package,`n" + 58 | " * use this version if your build environment doesn't support the using the`n" + 59 | " * individual *.d.ts files or default namespace wrapped version.`n" + 60 | " * - Namespaced version: $packageName.d.ts`n" + 61 | " * ---------------------------------------------------------------------------`n" + 62 | " */`n"; 63 | 64 | #Read the generated dts file and append to the new content 65 | $lastLine = "" 66 | # Prefix every line with 4 spaces (indenting the lines) 67 | ForEach ($line in (Get-Content $dtsFile)) { 68 | 69 | # Trim whitespace from the end of the string 70 | $rollupLine = $line -replace '(\s+$)', '' 71 | 72 | if ($line) { 73 | 74 | # Remove exports and declares 75 | $line = $line -replace 'export declare ', '' 76 | $line = $line -replace 'declare ', '' 77 | $line = $line -replace 'export { }', '' 78 | 79 | # Trim whitespace from the end of the string 80 | $line = $line -replace '(\s+$)', '' 81 | 82 | if ($hidePrivate) { 83 | #Hide private properties and functions 84 | $line = $line -replace '(^\s+)private (.*);', '${1}// private ${2};' 85 | $rollupLine = $rollupLine -replace '(^\s+)private (.*);', '${1}// private ${2};' 86 | } 87 | 88 | $rollupContent += "`n$rollupLine"; 89 | $newContent += "`n $line"; 90 | } elseif ($lastLine) { 91 | # Only add 1 blank line 92 | $rollupContent += "`n" 93 | $newContent += "`n" 94 | } 95 | 96 | $lastLine = $line 97 | } 98 | 99 | # Add final trailing closing bracket for the namespace 100 | $newContent += "`n}" 101 | 102 | Set-Content -Path $dtsFileRollup -Encoding Ascii -Value $rollupContent 103 | Set-Content -Path $dtsFile -Encoding Ascii -Value $newContent 104 | -------------------------------------------------------------------------------- /tools/grunt-tasks/chrome/bridge.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-contrib-qunit 3 | * https://gruntjs.com/ 4 | * 5 | * Copyright (c) 2016 "Cowboy" Ben Alman, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | /* global QUnit:true */ 10 | (function (factory) { 11 | if (window.self !== window.top) { 12 | // Ignore iframes. https://github.com/gruntjs/grunt-contrib-qunit/issues/202 13 | return; 14 | } 15 | if (typeof define === 'function' && define.amd) { 16 | require(['qunit'], factory); 17 | } else { 18 | factory(QUnit); 19 | } 20 | }(function(QUnit) { 21 | 'use strict'; 22 | 23 | var lastMessage = performance.now(); 24 | 25 | // Don't re-order tests. 26 | QUnit.config.reorder = false; 27 | 28 | // Send messages to the Node process 29 | function sendMessage() { 30 | self.__grunt_contrib_qunit__.apply(self, [].slice.call(arguments)); 31 | lastMessage = performance.now(); 32 | } 33 | 34 | if (self.__grunt_contrib_qunit_timeout__) { 35 | setTimeout(function checkTimeout() { 36 | if ((performance.now() - lastMessage) > self.__grunt_contrib_qunit_timeout__) { 37 | sendMessage('fail.timeout'); 38 | } else { 39 | // Keep checking 40 | setTimeout(checkTimeout, 1000); 41 | } 42 | }, 1000); 43 | } 44 | 45 | // QUnit reporter events 46 | // https://api.qunitjs.com/callbacks/QUnit.on/ 47 | 48 | QUnit.on('testStart', function(obj) { 49 | sendMessage('qunit.on.testStart', obj); 50 | }); 51 | 52 | QUnit.on('testEnd', function(obj) { 53 | // Re-create object to strip out 'assertions' field 54 | 55 | // expected and actual may contain circular objects, which would fail in puppeteer as it uses JSON.stringify to serialize its messages 56 | // In that case, replace actual and expected 57 | var errors = obj.errors; 58 | if (!canBeJSONStringified(errors)) { 59 | errors = obj.errors.map(function (error) { 60 | return { 61 | passed: error.passed, 62 | message: error.message, 63 | stack: error.stack, 64 | actual: replaceIfCannotBeJSONStringified(error.actual), 65 | expected: replaceIfCannotBeJSONStringified(error.expected) 66 | } 67 | }); 68 | } 69 | 70 | sendMessage('qunit.on.testEnd', { 71 | name: obj.name, 72 | moduleName: obj.moduleName, 73 | fullName: obj.fullName, 74 | status: obj.status, 75 | runtime: obj.runtime, 76 | errors: errors, 77 | }); 78 | }); 79 | 80 | function replaceIfCannotBeJSONStringified(obj) { 81 | return canBeJSONStringified(obj) ? obj : obj.toString(); 82 | } 83 | 84 | function canBeJSONStringified(obj) { 85 | try { 86 | JSON.stringify(obj); 87 | return true; 88 | } catch (e) { 89 | return false; 90 | } 91 | } 92 | 93 | QUnit.on('runEnd', function(obj) { 94 | // Re-create object to strip out large 'tests' field (deprecated). 95 | sendMessage('qunit.on.runEnd', { 96 | testCounts: obj.testCounts, 97 | runtime: obj.runtime, 98 | status: obj.status 99 | }); 100 | }); 101 | 102 | // QUnit plugin callbacks (for back-compat) 103 | // https://api.qunitjs.com/callbacks/ 104 | // 105 | // TODO: Remove the below in a future major version of grunt-contrib-qunit, 106 | // after updating docs for grunt.event.on() and announcing their deprecation, 107 | // to give developers time to migrate any event consumers to their 108 | // newer equivalents. 109 | 110 | QUnit.log(function(obj) { 111 | // What is this I don’t even 112 | if (obj.message === '[object Object], undefined:undefined') { 113 | return; 114 | } 115 | 116 | // Parse some stuff before sending it. 117 | var actual; 118 | var expected; 119 | 120 | if (!obj.result) { 121 | // Dumping large objects can be very slow, and the dump isn't used for 122 | // passing tests, so only dump if the test failed. 123 | actual = QUnit.dump.parse(obj.actual); 124 | expected = QUnit.dump.parse(obj.expected); 125 | } 126 | // Send it. 127 | sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source, obj.todo); 128 | }); 129 | 130 | QUnit.testStart(function(obj) { 131 | sendMessage('qunit.testStart', obj.name); 132 | }); 133 | 134 | QUnit.testDone(function(obj) { 135 | sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total, obj.runtime, obj.skipped, obj.todo); 136 | }); 137 | 138 | QUnit.moduleStart(function(obj) { 139 | sendMessage('qunit.moduleStart', obj.name); 140 | }); 141 | 142 | QUnit.moduleDone(function(obj) { 143 | sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total); 144 | }); 145 | 146 | QUnit.begin(function() { 147 | sendMessage('qunit.begin'); 148 | }); 149 | 150 | QUnit.done(function(obj) { 151 | sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime); 152 | }); 153 | })); 154 | -------------------------------------------------------------------------------- /tools/release-tools/README.md: -------------------------------------------------------------------------------- 1 | # 1DS JavaScript Release Tools 2 | 3 | 1DS JavaScript Release tools. 4 | 5 | This script is used internally to both prepare a release and to automatically generate beta/nightly builds. 6 | 7 | ## setVersion.js 8 | 9 | This script is designed as a helper for setting and updating the version number used for all components, in both the package.json and versions directly embedded in the source / test files. 10 | 11 | When run, it will 12 | - Set the specified version in the version.json (which is used as the default when not specified on the command line) 13 | - Updates the "version" within EVERY package.json for all channels/extensions/shared/skus/snippets/examples 14 | - Updates ALL of the referenced versions for the "@microsoft/1ds-xxx" dependencies/peerDependencies/devDependencies, so that when rush creates references they all reference the local build. 15 | 16 | After running this script and the version number has changed you WILL need to also run the "rush update" ```npm run update``` to ensure that the dependencies and hashes identified in the npm-shrinkwrap.json are updated correctly. 17 | 18 | ### When to use 19 | 20 | There are a couple of usages for this script 21 | - When preparing a new release you should run the script with either an explicit version or specify the switch to automatically increment the version number 22 | - ```npm run setVersion 3.2.0``` Sets the version explicitly as 3.2.0 (for ALL components), only use this if all components are on the same version. 23 | - ```npm run setVersion -- -patch``` Increments version to the next patch version number x.y.[z+1] (eg. ```3.1.2``` => ```3.1.3```) This will increment the patch level based on the components current version and not the root package.json version. 24 | - ```npm run setVersion -- -minor``` Increments the version to the next minor version number x.[y+1].0 (eg. ```3.1.2``` => ```3.2.0```) 25 | - During the build pipeline, this script will be called from with the dev-ops pipeline so that we can create an automated pipeline for generating alpha/beta/dev/nightly/release builds, with or without the current build number. This will be used to generate official "Beta" release generation job. 26 | - Note: At this stage the version number will NOT be checked back into the repo 27 | 28 | ### Example Usages 29 | 30 | Not all combinations are show, you can combine several options. 31 | 32 | General help displayed when the passed arguments appear to be incorrect. 33 | 34 | ``` 35 | setVersion.js [|-patch|-minor|-major] [-dev|-alpha|-beta|-release] [-bld ######] [-test] 36 | -------------------------- 37 | - Identifies the version to set for all packages, must start with x.y.z 38 | -patch - Increment the current version to the next patch number (x.y.z => x.y.[z+1] 39 | -minor - Increment the current version to the next minor number (x.y.z => x.[y+1].0 40 | -major - Increment the current version to the next major number (x.y.z => [x+1].0.0 41 | -dev - Add the 'dev' pre-release to the number (x.y.z => x.y.z-dev) 42 | -alpha - Add the 'alpha' pre-release to the number (x.y.z => x.y.z-alpha) 43 | -beta - Add the 'beta' pre-release to the number (x.y.z => x.y.z-beta) 44 | -release - Remove any existing pre-release tags (x.y.z-prerel => x.y.z) 45 | -bld ###### - Append the provided build number to the version (x.y.z => x.y.z-[prerel].######) [prerel] defaults to dev if not defined 46 | -pre ###### - Set the pre-release to the provided value (x.y.z => x.y.z-[prerel]) 47 | -react - Update only the react packages (Require as the react components need to update after the core because of the different versions of TypeScript being used.) 48 | -test - Scan all of the package.json files and log the changes, but DON'T update the files 49 | ``` 50 | 51 | #### Set the version explicitly 52 | 53 | To set the version to specific build number, just pass as one of the arguments 54 | 55 | ```npm run setVersion 3.2.0``` 56 | 57 | ```npm run setVersion -- 3.2.0``` 58 | 59 | The ```--``` is only when passing switch arguments to the script, so when specifying an explicit version it's optional as npm will pass the argument correctly. 60 | 61 | #### Increase to the next patch level 62 | 63 | ```npm run setVersion -- -patch``` (eg. ```3.1.2``` => ```3.1.3```) 64 | 65 | #### Increase to the next minor release 66 | 67 | ```npm run setVersion -- -minor``` (eg. ```3.1.2``` => ```3.2.0```) 68 | 69 | #### Increase to the next major release 70 | 71 | ```npm run setVersion -- -major``` (eg. ```3.1.2``` => ```4.0.0```) 72 | 73 | #### Dev Pre-release 74 | 75 | Change the current version as a ```dev``` pre-release build 76 | 77 | ```npm run setVersion``` (eg. ```3.1.2``` => ```3.1.2-dev```) 78 | 79 | ```npm run setVersion -- -dev``` (eg. ```3.1.2``` => ```3.1.2-dev```) 80 | 81 | #### Dev Pre-release and next patch level 82 | 83 | ```npm run setVersion -- -patch -dev``` (eg. ```3.1.2``` => ```3.1.3-dev```) 84 | 85 | #### Set the version as a release version 86 | 87 | Running this removes any current pre-release tag. 88 | 89 | ```npm run setVersion -- -release``` (eg. ```3.1.2-dev``` => ```3.1.2```) 90 | 91 | #### Set as a specific pre-release 92 | 93 | ```npm run setVersion -- -pre nightly``` (eg. ```3.1.2``` => ```3.1.2-nightly```) 94 | 95 | #### Add a build number to the release (implied pre-release) 96 | 97 | > Using this switch implies that the resulting version WILL be a pre-release complete with a <pre-release> tag. And when no <pre-release> is specified (dev/alpha/beta/etc) ```dev``` will be assumed and added. 98 | > 99 | > And when also used with the release switch the <pre-release> tag will default to ```rc``` 100 | 101 | Build numbers are added using the "." prefix as based on the [semver](https://semver.org/) specification the build number "+" does not uniquely identify or define a sequence for resolving precedence. 102 | 103 | ```npm run setVersion -- -bld 20210525.1``` (eg. ```3.1.2 => 3.1.2-dev.20210525.1```) 104 | 105 | ```npm run setVersion -- -bld 20210525.1 -dev``` (eg. ```3.1.2 => 3.1.2-dev.20210525.1```) 106 | 107 | ```npm run setVersion -- -bld 20210525.1 -pre nightly``` (eg. ```3.1.2 => 3.1.2-nightly.20210525.1```) 108 | 109 | ```npm run setVersion -- -bld 20210525.1 -release``` (eg. ```3.1.2 => 3.1.2-rc.20210525.1```) 110 | 111 | -------------------------------------------------------------------------------- /tools/release-tools/npm-package.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const child_process = require("child_process"); 3 | 4 | const packageGroupDef = "./tools/release-tools/package_groups.json"; 5 | let packageGroup; 6 | let dropFolder; 7 | let dryRun = ""; 8 | 9 | function showHelp() { 10 | var scriptParts; 11 | var scriptName = process.argv[1]; 12 | if (scriptName.indexOf("\\") !== -1) { 13 | scriptParts = scriptName.split("\\"); 14 | scriptName = scriptParts[scriptParts.length - 1]; 15 | } else if (scriptName.indexOf("/") !== -1) { 16 | scriptParts = scriptName.split("/"); 17 | scriptName = scriptParts[scriptParts.length - 1]; 18 | } 19 | 20 | console.log(""); 21 | console.log(scriptName + " "); 22 | console.log("--------------------------"); 23 | console.log(" - Identifies the group to publish, identifies folders, the group must be defined in package_groups.json"); 24 | console.log(" - Identifies the base folder to drop the packages into, defaults to ./drop/packages/"); 25 | } 26 | 27 | function parseArgs() { 28 | console.log("Parsing args - " + process.argv.join(" ")); 29 | if (process.argv.length < 2) { 30 | console.error("!!! Invalid number of arguments -- " + process.argv.length); 31 | return false; 32 | } 33 | 34 | let idx = 2; 35 | while (idx < process.argv.length) { 36 | let theArg = process.argv[idx]; 37 | if (theArg.startsWith("-")) { 38 | if (theArg === "-test") { 39 | dryRun = "--dry-run"; 40 | } else { 41 | console.error("!!! Unknown switch [" + theArg + "] detected"); 42 | return false; 43 | } 44 | } else if (!packageGroup) { 45 | packageGroup = theArg; 46 | } else if (!dropFolder) { 47 | dropFolder = theArg; 48 | } else { 49 | console.error("!!! Invalid Argument [" + theArg + "] detected"); 50 | return false; 51 | } 52 | 53 | idx++; 54 | } 55 | 56 | // Check for required arguments 57 | if (!packageGroup) { 58 | console.error("!!! Missing package group"); 59 | return false; 60 | } 61 | 62 | return true; 63 | } 64 | 65 | function removeTrailingComma(text) { 66 | return text.replace(/,(\s*[}\],])/g, "$1"); 67 | } 68 | 69 | function removeComments(text) { 70 | return text.replace(/^\s*\/\/\s.*$/gm, ""); 71 | } 72 | 73 | function getPackage(packageJsonFile) { 74 | var packageText = removeTrailingComma(fs.readFileSync(packageJsonFile, "utf-8")); 75 | 76 | return JSON.parse(packageText); 77 | } 78 | 79 | function getNpmPackageName(packageJson) { 80 | let packageName = packageJson.name; 81 | let packageVersion = packageJson.version; 82 | 83 | let theNpmPackageName = packageName + "-" + packageVersion; 84 | 85 | theNpmPackageName = theNpmPackageName.replace("@", "").replace("/", "-"); 86 | 87 | return theNpmPackageName + ".tgz"; 88 | } 89 | 90 | function getGroupProjects() { 91 | if (!fs.existsSync(packageGroupDef)) { 92 | console.error("!!! Unable to locate package group definitions [" + packageGroupDef + "]"); 93 | throw new Error("!!! Unable to locate package group definitions."); 94 | } 95 | 96 | var groupText = removeComments(removeTrailingComma(fs.readFileSync(packageGroupDef, "utf-8"))); 97 | 98 | let groupJson = JSON.parse(groupText); 99 | return groupJson[packageGroup] || []; 100 | } 101 | 102 | function movePackage(npmPackageName, packageName) { 103 | let packageFolder = dropFolder; 104 | if (!packageFolder) { 105 | packageFolder = "./drop/packages"; 106 | packageFolder += "/" + packageGroup; 107 | } 108 | 109 | if (!fs.existsSync(packageFolder)) { 110 | fs.mkdirSync(packageFolder, { recursive: true }); 111 | } 112 | 113 | let packageFile = packageFolder + "/" + packageName; 114 | if (fs.existsSync(packageFile)) { 115 | console.log(` -- Removing existing package ${packageFile}`); 116 | fs.unlinkSync(packageFile); 117 | } 118 | 119 | console.log(` -- Moving ${npmPackageName} to ${packageFile}`); 120 | fs.renameSync(npmPackageName, packageFile); 121 | } 122 | 123 | if (parseArgs()) { 124 | var packages = getGroupProjects(); 125 | 126 | console.log(`Creating [${packageGroup}] packages => ${packages.length}`); 127 | packages.forEach((packageRoot) => { 128 | let packageJsonFile = packageRoot + "/package.json"; 129 | 130 | if (!fs.existsSync(packageJsonFile)) { 131 | console.error("!!! Source package.json doesn't exist [" + packageJsonFile + "]"); 132 | throw new Error("!!! Source package.json doesn't exist [" + packageJsonFile + "]"); 133 | } 134 | 135 | const packageJson = getPackage(packageJsonFile); 136 | 137 | const packageName = getNpmPackageName(packageJson); 138 | console.log("\n\n##################################################################"); 139 | console.log("Packaging - " + packageName); 140 | console.log("##################################################################"); 141 | 142 | let npmPackageName = packageRoot + "/" + packageName; 143 | if (fs.existsSync(npmPackageName)) { 144 | console.log(` -- Removing existing package ${npmPackageName}`); 145 | fs.unlinkSync(npmPackageName); 146 | } 147 | 148 | const cwd = process.cwd(); 149 | process.chdir(packageRoot); 150 | try { 151 | let npmCmd = `npm pack ${dryRun}`; 152 | console.log(`Running: \"${npmCmd}\"`); 153 | child_process.execSync(npmCmd); 154 | } finally { 155 | process.chdir(cwd); 156 | } 157 | 158 | if (!dryRun) { 159 | // Move the package to the package folder 160 | movePackage(npmPackageName, packageName); 161 | } 162 | }); 163 | } else { 164 | showHelp(); 165 | process.exit(1); 166 | } 167 | -------------------------------------------------------------------------------- /tools/release-tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "applicationinsights-js-release-tools", 3 | "version": "3.1.3", 4 | "author": "Microsoft Application Insights Team", 5 | "description": "Microsoft Application Insights React Native release tools", 6 | "homepage": "https://github.com/microsoft/applicationinsights-react-native#readme", 7 | "sideEffects": false, 8 | "scripts": { 9 | "update": "rush update", 10 | "build": "", 11 | "rebuild": "", 12 | "test": "", 13 | "updateVer": "node ./tools/release-tools/updateVersion.js" 14 | }, 15 | "keywords": [ 16 | "1DS", 17 | "Js", 18 | "SDK" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/microsoft/applicationinsights-react-native" 23 | }, 24 | "devDependencies": { 25 | "grunt": "^1.5.3", 26 | "globby": "^11.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tools/release-tools/package_groups.json: -------------------------------------------------------------------------------- 1 | // ------------------------------ 2 | // NPM Publish group definitions 3 | // ------------------------------ 4 | { 5 | // DynamicProto packages 6 | "rn": [ 7 | "./applicationinsights-react-native" 8 | ] 9 | } -------------------------------------------------------------------------------- /tools/release-tools/setAiVersion.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const globby = require("globby"); 3 | 4 | let newAiVer = null; 5 | let testOnly = null; 6 | 7 | const theVersion = require(process.cwd() + "/version.json"); 8 | 9 | function showHelp() { 10 | var scriptParts; 11 | var scriptName = process.argv[1]; 12 | if (scriptName.indexOf("\\") !== -1) { 13 | scriptParts = scriptName.split("\\"); 14 | scriptName = scriptParts[scriptParts.length - 1]; 15 | } else if (scriptName.indexOf("/") !== -1) { 16 | scriptParts = scriptName.split("/"); 17 | scriptName = scriptParts[scriptParts.length - 1]; 18 | } 19 | 20 | console.log(""); 21 | console.log(scriptName + " [ [-test]"); 22 | console.log("--------------------------"); 23 | console.log(" - Identifies the application insights version to set for all packages"); 24 | console.log(" -test - Scan all of the package.json files and log the changes, but DON'T update the files"); 25 | } 26 | 27 | function parseArgs() { 28 | if (process.argv.length < 2) { 29 | console.error("!!! Invalid number of arguments -- " + process.argv.length); 30 | return false; 31 | } 32 | 33 | let idx = 2; 34 | while(idx < process.argv.length) { 35 | let theArg = process.argv[idx]; 36 | if (theArg === "-test") { 37 | testOnly = true; 38 | } else if (!newAiVer) { 39 | newAiVer = theArg; 40 | } else { 41 | console.error("!!! Invalid Argument [" + theArg + "] detected"); 42 | return false; 43 | } 44 | 45 | idx ++; 46 | } 47 | 48 | // If no version, 49 | if (!newAiVer) { 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | 56 | function shouldProcess(name) { 57 | if (name.indexOf("node_modules/") !== -1) { 58 | return false; 59 | } 60 | 61 | if (name.indexOf("common/temp") !== -1) { 62 | return false; 63 | } 64 | 65 | if (name.indexOf("examples/") !== -1) { 66 | return true; 67 | } 68 | 69 | if (name.indexOf("sample/") !== -1) { 70 | return true; 71 | } 72 | 73 | if (name.indexOf("applicationinsights-react-native") !== -1) { 74 | return true; 75 | } 76 | 77 | if (name === "package.json") { 78 | return true; 79 | } 80 | 81 | return false; 82 | } 83 | 84 | function shouldUpdateDependency(name) { 85 | if (name.indexOf("@microsoft/applicationinsights-") === -1) { 86 | return false; 87 | } 88 | 89 | if (name.indexOf("applicationinsights-shims") !== -1) { 90 | return false; 91 | } 92 | 93 | if (name.indexOf("applicationinsights-rollup") !== -1) { 94 | return false; 95 | } 96 | 97 | if (name.indexOf("applicationinsights-react-native") !== -1) { 98 | // Don't update references to this package 99 | return false; 100 | } 101 | 102 | return true; 103 | } 104 | 105 | function updateDependencies(target, newVersion) { 106 | let changed = false; 107 | if (target) { 108 | let isDigit = /^\d/.test(newVersion); 109 | Object.keys(target).forEach((value) => { 110 | if (shouldUpdateDependency(value)) { 111 | let version = target[value]; 112 | if (version.startsWith("^") && isDigit) { 113 | if (version !== "^" + newVersion) { 114 | target[value] = "^" + newVersion; 115 | } 116 | } else if (version.startsWith("~") && isDigit) { 117 | if (version !== "~" + newVersion) { 118 | target[value] = "~" + newVersion; 119 | } 120 | } else if (version !== newVersion) { 121 | target[value] = newVersion; 122 | } 123 | 124 | if (version != target[value]) { 125 | console.log(" Updated: " + value + " \"" + version + "\" => \"" + target[value] + "\""); 126 | changed = true; 127 | } else { 128 | console.log(" Skipped: " + value + " \"" + version + "\""); 129 | } 130 | } 131 | }); 132 | } 133 | 134 | return changed; 135 | } 136 | 137 | const setPackageJsonRelease = () => { 138 | const files = globby.sync(["./**/package.json", "!**/node_modules/**"]); 139 | let changed = false; 140 | files.map(packageFile => { 141 | // Don't update node_modules 142 | if (shouldProcess(packageFile)) { 143 | console.log("Loading - " + packageFile); 144 | 145 | let theFilename = packageFile; 146 | const package = require(process.cwd() + "\\" + theFilename); 147 | console.log(" Name - " + package.name); 148 | 149 | let updated = false; 150 | updated |= updateDependencies(package.dependencies, newAiVer); 151 | updated |= updateDependencies(package.peerDependencies, newAiVer); 152 | updated |= updateDependencies(package.devDependencies, newAiVer); 153 | 154 | if (updated && !testOnly) { 155 | // Rewrite the file 156 | const newContent = JSON.stringify(package, null, 4) + "\n"; 157 | fs.writeFileSync(theFilename, newContent); 158 | changed = true; 159 | } 160 | console.log(" -------------------------------------------------------------------------------------"); 161 | } 162 | }); 163 | 164 | return changed; 165 | }; 166 | 167 | if (parseArgs()) { 168 | if (setPackageJsonRelease()) { 169 | console.log("Version updated, now run 'npm run rupdate'"); 170 | } else { 171 | console.log("Nothing Changed"); 172 | } 173 | } else { 174 | showHelp(); 175 | } 176 | -------------------------------------------------------------------------------- /tools/release-tools/updatemanifest.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | let packageRoot = process.cwd(); 5 | let packageJson = packageRoot + "/package.json"; 6 | 7 | function showHelp() { 8 | var scriptParts; 9 | var scriptName = process.argv[1]; 10 | if (scriptName.indexOf("\\") !== -1) { 11 | scriptParts = scriptName.split("\\"); 12 | scriptName = scriptParts[scriptParts.length - 1]; 13 | } else if (scriptName.indexOf("/") !== -1) { 14 | scriptParts = scriptName.split("/"); 15 | scriptName = scriptParts[scriptParts.length - 1]; 16 | } 17 | 18 | console.log(""); 19 | console.log(scriptName + " [] "); 20 | console.log("--------------------------"); 21 | console.log(" - Identifies the source package.json"); 22 | } 23 | 24 | function parseArgs() { 25 | if (process.argv.length < 1) { 26 | console.error("!!! Invalid number of arguments -- " + process.argv.length); 27 | return false; 28 | } 29 | 30 | console.log("cwd: " + process.cwd()); 31 | 32 | let idx = 2; 33 | while (idx < process.argv.length) { 34 | let theArg = process.argv[idx]; 35 | if (!packageJson) { 36 | packageJson = path.resolve(packageRoot, theArg); 37 | let idx = packageJson.lastIndexOf("/"); 38 | if (idx != -1) { 39 | packageRoot = packageJson.substring(0, idx + 1); 40 | } 41 | 42 | if (!packageRoot) { 43 | console.error("!!! Unable to identify package root folder from [" + packageJson + "]"); 44 | return false; 45 | } 46 | 47 | } else { 48 | console.error("!!! Invalid Argument [" + theArg + "] detected"); 49 | return false; 50 | } 51 | 52 | idx++; 53 | } 54 | 55 | return true; 56 | } 57 | 58 | function updateManifest() { 59 | let manifestFile = packageRoot + "/manifest.json"; 60 | if (!manifestFile || !fs.existsSync(manifestFile)) { 61 | console.error("!!! Manifest file [" + manifestFile + "] does not exist"); 62 | return false; 63 | } 64 | 65 | let thePackage = require(packageJson); 66 | let versionParts = thePackage.version.split("-")[0].split("."); 67 | if (versionParts.length < 3) { 68 | console.error("!!! Unsupported version [" + thePackage.version + "]"); 69 | return false; 70 | } 71 | 72 | let theManifest = require(manifestFile); 73 | theManifest.version = "" + versionParts[0] + "." + versionParts[1] + "." + versionParts[2]; 74 | theManifest.version_name = thePackage.version; 75 | 76 | console.log("Updating manifest file"); 77 | // Rewrite the file 78 | const newContent = JSON.stringify(theManifest, null, 4) + "\n"; 79 | fs.writeFileSync(manifestFile, newContent); 80 | 81 | } 82 | 83 | if (parseArgs()) { 84 | if (!fs.existsSync(packageJson)) { 85 | console.error("!!! Source package.json doesn't exist [" + packageJson + "]"); 86 | return false; 87 | } 88 | 89 | updateManifest(); 90 | } else { 91 | showHelp(); 92 | } 93 | -------------------------------------------------------------------------------- /tools/release-tools/zipbrowser.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const archiver = require("archiver"); 4 | 5 | let packageRoot = process.cwd(); 6 | let packageJson = packageRoot + "/package.json"; 7 | let sourceDir = null; 8 | let destPrefix = null; 9 | let destFolder = null; 10 | 11 | function showHelp() { 12 | var scriptParts; 13 | var scriptName = process.argv[1]; 14 | if (scriptName.indexOf("\\") !== -1) { 15 | scriptParts = scriptName.split("\\"); 16 | scriptName = scriptParts[scriptParts.length - 1]; 17 | } else if (scriptName.indexOf("/") !== -1) { 18 | scriptParts = scriptName.split("/"); 19 | scriptName = scriptParts[scriptParts.length - 1]; 20 | } 21 | 22 | console.log(""); 23 | console.log(scriptName + " [] [] "); 24 | console.log("--------------------------"); 25 | console.log(" - Identifies the destination filename zip prefix"); 26 | console.log(" - Identifies the destination folder for the zip file"); 27 | console.log(" - Identifies the source package.json"); 28 | } 29 | 30 | function parseArgs() { 31 | if (process.argv.length < 2) { 32 | console.error("!!! Invalid number of arguments -- " + process.argv.length); 33 | return false; 34 | } 35 | 36 | console.log("cwd: " + process.cwd()); 37 | 38 | let idx = 2; 39 | while (idx < process.argv.length) { 40 | let theArg = process.argv[idx]; 41 | if (!destPrefix) { 42 | destPrefix = theArg; 43 | } else if (!destFolder) { 44 | destFolder = theArg; 45 | } else if (!packageJson) { 46 | packageJson = path.resolve(packageRoot, theArg); 47 | let idx = packageJson.lastIndexOf("/"); 48 | if (idx != -1) { 49 | packageRoot = packageJson.substring(0, idx + 1); 50 | } 51 | 52 | if (!packageRoot) { 53 | console.error("!!! Unable to identify package root folder from [" + packageJson + "]"); 54 | return false; 55 | } 56 | 57 | } else { 58 | console.error("!!! Invalid Argument [" + theArg + "] detected"); 59 | return false; 60 | } 61 | 62 | idx++; 63 | } 64 | 65 | return true; 66 | } 67 | 68 | function normalizeName(filename) { 69 | const cwd = process.cwd(); 70 | 71 | return filename.replace(cwd, "."); 72 | } 73 | 74 | function packFolder() { 75 | const thePackage = require(packageJson); 76 | const packageVersion = thePackage.version; 77 | if (destFolder && !fs.existsSync(packageRoot + "/" + destFolder)) { 78 | fs.mkdirSync(packageRoot + "/" + destFolder); 79 | } 80 | 81 | const outputName = packageRoot + "/" + (destFolder ? destFolder + "/" : "") + destPrefix + "." + packageVersion + ".zip"; 82 | const stream = fs.createWriteStream(outputName); 83 | stream.on("open", () => console.info(`Creating Zip [${normalizeName(outputName)}] from [${normalizeName(sourceDir)}]`)); 84 | stream.on("close", () => console.info("Complete!", "\n")); 85 | stream.on("error", (err) => { 86 | console.error(`Failed to write to zip file - ${err.message}\n`); 87 | process.exit(2); 88 | }); 89 | 90 | const archive = archiver("zip", { zlib: { level: 9 } }); 91 | archive.directory(sourceDir, false); 92 | archive.on("error", (err) => { 93 | console.error(`Failed to generate zip file - ${err.message}\n`); 94 | process.exit(2); 95 | }); 96 | archive.pipe(stream); 97 | archive.finalize(); 98 | 99 | return true; 100 | } 101 | 102 | if (parseArgs()) { 103 | if (!fs.existsSync(packageJson)) { 104 | console.error("!!! Source package.json doesn't exist [" + packageJson + "]"); 105 | return false; 106 | } 107 | 108 | sourceDir = packageRoot + "/browser"; 109 | if (!sourceDir) { 110 | console.error("!!! Browser path [" + packageJson + "] does not exist -- you need to build first"); 111 | return false; 112 | } 113 | 114 | try { 115 | fs.accessSync(sourceDir); 116 | } catch (e) { 117 | console.error("!!! The source [" + sourceDir + "] does not exist"); 118 | return false; 119 | } 120 | 121 | packFolder(); 122 | } else { 123 | showHelp(); 124 | process.exit(1); 125 | } 126 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-prototype-builtins": "off", 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/dist/esm/rollup-plugin-uglify3-js.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Application Insights JavaScript SDK - Rollup Uglify3 Plugin, 1.0.0 3 | * Copyright (c) Microsoft and contributors. All rights reserved. 4 | */ 5 | import * as UglifyJs from 'uglify-js'; 6 | 7 | function isSourceMapEnabled(options) { 8 | if (options) { 9 | return options.sourceMap !== false && options.sourcemap !== false; 10 | } 11 | return false; 12 | } 13 | function _doMinify(code, filename, options, _chunkOptions) { 14 | var theCode = {}; 15 | theCode[filename] = code; 16 | var assign = Object["assign"]; 17 | var theOptions = assign({}, options); 18 | if (theOptions.hasOwnProperty("sourcemap")) { 19 | delete theOptions.sourcemap; 20 | } 21 | if (isSourceMapEnabled(options)) { 22 | theOptions.sourceMap = { 23 | filename: filename 24 | }; 25 | if (filename) { 26 | theOptions.sourceMap.url = filename + ".map"; 27 | } 28 | } 29 | var result = UglifyJs.minify(theCode, theOptions); 30 | if (result.error) { 31 | throw new Error(JSON.stringify(result.error)); 32 | } 33 | var transform = { 34 | code: result.code 35 | }; 36 | if (isSourceMapEnabled(options) && result.map) { 37 | transform.map = result.map; 38 | } 39 | return transform; 40 | } 41 | function uglify(options) { 42 | if (options === void 0) { options = {}; } 43 | return { 44 | name: "ai-rollup-plugin-uglify3-js", 45 | renderChunk: function (code, chunk, chkOpt) { 46 | return _doMinify(code, chunk.filename, options); 47 | } 48 | }; 49 | } 50 | 51 | export { uglify }; 52 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microsoft/applicationinsights-rollup-plugin-uglify3-js", 3 | "author": "Microsoft Corporation", 4 | "version": "1.0.0", 5 | "description": "Microsoft Application Insights JavaScript SDK - Rollup Plugin for Uglify3 support", 6 | "keywords": [ 7 | "azure", 8 | "cloud", 9 | "microsoft", 10 | "application insights", 11 | "rollup", 12 | "rollup-plugin" 13 | ], 14 | "scripts": { 15 | "clean": "grunt clean", 16 | "build": "npm run build:esm && npm run build:bundle", 17 | "build:esm": "grunt rollupuglify", 18 | "build:bundle": "npx rollup -c", 19 | "rebuild": "npm run build", 20 | "test": "", 21 | "lint": "" 22 | }, 23 | "main": "dist/node/rollup-plugin-uglify3-js.js", 24 | "module": "dist/esm/rollup-plugin-uglify3-js.js", 25 | "license": "MIT", 26 | "sideEffects": false, 27 | "devDependencies": { 28 | "grunt": "^1.5.3", 29 | "grunt-cli": "^1.4.3", 30 | "@nevware21/grunt-ts-plugin": "^0.4.3", 31 | "@nevware21/grunt-eslint-ts": "^0.2.2", 32 | "@rollup/plugin-commonjs": "^18.0.0", 33 | "@rollup/plugin-node-resolve": "^11.2.1", 34 | "@rollup/plugin-replace": "^2.3.3", 35 | "rollup-plugin-minify-es": "^1.1.1", 36 | "rollup": "^2.77.2", 37 | "typescript": "^4.3.4", 38 | "tslib": "^2.0.0" 39 | }, 40 | "peerDependencies": { 41 | "tslib": "*" 42 | }, 43 | "dependencies": { 44 | "uglify-js": "3.16.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from "@rollup/plugin-node-resolve"; 2 | import replace from "@rollup/plugin-replace"; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | 5 | const UglifyJs = require('uglify-js'); 6 | 7 | const version = require("./package.json").version; 8 | const inputName = "./out/src/uglify3-js"; 9 | const outputName = "rollup-plugin-uglify3-js"; 10 | const distPath = "./dist/"; 11 | const banner = [ 12 | "/*!", 13 | ` * Application Insights JavaScript SDK - Rollup Uglify3 Plugin, ${version}`, 14 | " * Copyright (c) Microsoft and contributors. All rights reserved.", 15 | " */" 16 | ].join("\n"); 17 | 18 | const nodeUmdRollupConfigFactory = () => { 19 | const nodeRollupConfig = { 20 | input: `${inputName}.js`, 21 | output: { 22 | file: `${distPath}node/${outputName}.js`, 23 | banner: banner, 24 | format: "umd", 25 | name: "Microsoft.ApplicationInsights-Rollup-Plugin-Uglify", 26 | extend: true, 27 | freeze: false, 28 | sourcemap: false, 29 | externalLiveBindings: false, 30 | globals:[ 'UglifyJs' ] 31 | }, 32 | plugins: [ 33 | replace({ 34 | preventAssignment: true, 35 | delimiters: ["", ""], 36 | values: { 37 | "// Copyright (c) Microsoft Corporation. All rights reserved.": "", 38 | "// Licensed under the MIT License.": "" 39 | } 40 | }), 41 | commonjs({ 42 | include: 'node_modules/**', 43 | transformMixedEsModules: true 44 | }) 45 | ] 46 | }; 47 | 48 | return nodeRollupConfig; 49 | }; 50 | 51 | const moduleRollupConfigFactory = (format) => { 52 | const moduleRollupConfig = { 53 | input: `${inputName}.js`, 54 | output: { 55 | file: `${distPath}${format}/${outputName}.js`, 56 | banner: banner, 57 | format: format, 58 | name: "Microsoft.ApplicationInsights-Rollup-Plugin-Uglify", 59 | extend: true, 60 | freeze: false, 61 | sourcemap: false, 62 | externalLiveBindings: false, 63 | globals:[ 'UglifyJs '] 64 | }, 65 | plugins: [ 66 | replace({ 67 | preventAssignment: true, 68 | delimiters: ["", ""], 69 | values: { 70 | "// Copyright (c) Microsoft Corporation. All rights reserved.": "", 71 | "// Licensed under the MIT License.": "" 72 | } 73 | }), 74 | // nodeResolve({ 75 | // module: true, 76 | // browser: false, 77 | // preferBuiltins: false 78 | // }), 79 | commonjs({ 80 | include: 'node_modules/**', 81 | transformMixedEsModules: true 82 | }) 83 | ] 84 | }; 85 | 86 | return moduleRollupConfig; 87 | }; 88 | 89 | export default [ 90 | nodeUmdRollupConfigFactory(), 91 | moduleRollupConfigFactory('esm'), 92 | ]; 93 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/src/uglify3-js.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | import * as UglifyJs from "uglify-js"; 5 | 6 | function isSourceMapEnabled(options) { 7 | if (options) { 8 | return options.sourceMap !== false && options.sourcemap !== false; 9 | } 10 | 11 | return false; 12 | } 13 | 14 | function _doMinify(code, filename, options, _chunkOptions) { 15 | var theCode = {}; 16 | theCode[filename] = code; 17 | 18 | let assign = Object["assign"]; 19 | let theOptions = assign({}, options); 20 | if (theOptions.hasOwnProperty("sourcemap")) { 21 | delete theOptions.sourcemap; 22 | } 23 | 24 | if (isSourceMapEnabled(options)) { 25 | theOptions.sourceMap = { 26 | filename: filename 27 | }; 28 | 29 | if (filename) { 30 | theOptions.sourceMap.url = filename + ".map"; 31 | } 32 | } 33 | 34 | var result = UglifyJs.minify(theCode, theOptions); 35 | 36 | if (result.error) { 37 | throw new Error(JSON.stringify(result.error)); 38 | } 39 | 40 | var transform:any = { 41 | code: result.code 42 | }; 43 | 44 | if (isSourceMapEnabled(options) && result.map) { 45 | transform.map = result.map; 46 | } 47 | 48 | return transform; 49 | } 50 | 51 | export function uglify(options = {}) { 52 | 53 | return { 54 | name: "ai-rollup-plugin-uglify3-js", 55 | renderChunk(code, chunk, chkOpt) { 56 | return _doMinify(code, chunk.filename, options, chkOpt); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tools/rollup-plugin-uglify3-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "inlineSources": true, 5 | "noImplicitAny": false, 6 | "module": "es6", 7 | "moduleResolution": "node", 8 | "target": "es5", 9 | "forceConsistentCasingInFileNames": true, 10 | "importHelpers": false, 11 | "noEmitHelpers": false, 12 | "alwaysStrict": true, 13 | "declaration": true, 14 | "outDir": "./out", 15 | "rootDir": "tools/rollup-plugin-uglify3-js", 16 | "suppressImplicitAnyIndexErrors": true, 17 | "allowSyntheticDefaultImports": true 18 | }, 19 | "files": [ 20 | ] 21 | } -------------------------------------------------------------------------------- /tools/status-tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "applicationinsights-js-status-tools", 3 | "version": "3.1.3-dev", 4 | "author": "Javascript Telemetry SDKs ", 5 | "description": "1DS Web SDK", 6 | "homepage": "https://github.com/microsoft/ApplicationInsights-JS", 7 | "sideEffects": false, 8 | "scripts": { 9 | "clean": "git clean -xdf", 10 | "update": "rush update", 11 | "build": "", 12 | "rebuild": "", 13 | "test": "", 14 | "issues": "node ./github-status.js" 15 | }, 16 | "keywords": [ 17 | "1DS", 18 | "Js", 19 | "SDK" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/microsoft/ApplicationInsights-JS/tree/main/tools/status-tools" 24 | }, 25 | "devDependencies": { 26 | "grunt": "^1.5.3", 27 | "globby": "^11.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tools/subResourceIntegrity/generateIntegrityFile.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const globby = require("globby"); 3 | const crypto = require("crypto"); 4 | const isVersioned = /^(.*\d)(\..*js)$/; 5 | const extractFilename = /^([^\d]*(\.\d{1,3}\.\d{1,3}\.\d{1,3}))(\..*(js|zip))$/; 6 | 7 | function calculateHash(source, algorithm) { 8 | return crypto.createHash(algorithm).update(source).digest().toString('base64'); 9 | } 10 | 11 | function getFilename(inputFile, packageVersion) { 12 | var filename = inputFile; 13 | var path = ""; 14 | var pos = inputFile.lastIndexOf("/"); 15 | if (pos == -1) { 16 | pos = inputFile.lastIndexOf("\\"); 17 | } 18 | 19 | if (pos != -1) { 20 | path = inputFile.substring(0, pos); 21 | filename = inputFile.substring(pos + 1); 22 | } 23 | 24 | var match = null; 25 | var module = filename; 26 | var matchType = ""; 27 | 28 | var verIdx = filename.indexOf("." + packageVersion); 29 | if (verIdx != -1) { 30 | verIdx += (packageVersion.length + 1); 31 | matchType = "Package version"; 32 | // This was added to specific handle package versions with pre-release and version (eg ai.xxx-nightly.20210802) 33 | module = filename.substring(0, verIdx); 34 | match = [ 35 | inputFile, // Raw original file 36 | path + "/" + module, // IntFile group [1] 37 | packageVersion, // Version group [2] 38 | filename.substring(verIdx + 1) // format group (extension) [5] 39 | ]; 40 | } else { 41 | // General Regex match 42 | matchType = "RegEx"; 43 | var versioned = isVersioned.exec(inputFile); 44 | if (versioned) { 45 | match = extractFilename.exec(inputFile); 46 | } else if (filename.endsWith(".js")) { 47 | matchType = "Extension"; 48 | // Handle files with no version eg. applicationinsights-core-js, etc 49 | var idx = filename.indexOf("."); 50 | if (idx != -1) { 51 | module = filename.substring(0, idx); 52 | match = [ 53 | inputFile, // Raw original file 54 | path + "/" + module, // IntFile group 55 | packageVersion, // Version group 56 | filename.substring(idx + 1) // format group (extension) 57 | ]; 58 | } 59 | } 60 | } 61 | 62 | if (match) { 63 | console.log("Loading - " + inputFile + " (" + matchType + ") => (" + JSON.stringify(match) + ")"); 64 | 65 | var intFile = match[1]; 66 | var version = match[2]; 67 | var format = match[3]; 68 | 69 | if (version) { 70 | if (version.startsWith(".")) { 71 | version = version.substring(1); 72 | } 73 | 74 | if (version == packageVersion) { 75 | 76 | var idx = filename.lastIndexOf("." + version); 77 | if (idx != -1) { 78 | module = filename.substring(0, idx); 79 | } 80 | 81 | if (format.startsWith(".")) { 82 | format = format.substring(1); 83 | } 84 | 85 | var data = { 86 | name: filename, 87 | module: module, 88 | version: version, 89 | format: format, 90 | intFile: intFile + ".integrity.json" 91 | }; 92 | 93 | return data; 94 | } 95 | } 96 | } 97 | 98 | return { 99 | name: filename 100 | }; 101 | } 102 | 103 | function processPath(integrityCache, path, version) { 104 | const files = globby.sync(path); 105 | files.map(inputFile => { 106 | var names = getFilename(inputFile, version); 107 | if (names.intFile) { 108 | var src = fs.readFileSync(inputFile, "utf8"); 109 | 110 | const hash256 = calculateHash(src, 'sha256'); 111 | const hash384 = calculateHash(src, 'sha384'); 112 | const hash512 = calculateHash(src, 'sha512'); 113 | 114 | var integrityJson = integrityCache[names.intFile]; 115 | if (!integrityJson) { 116 | integrityJson = { 117 | name: names.module 118 | }; 119 | 120 | if (names.version) { 121 | integrityJson.version = names.version; 122 | } 123 | 124 | // Cache it 125 | integrityCache[names.intFile] = integrityJson; 126 | } else if (integrityJson.name != names.module) { 127 | throw new Error("Error! - Module name [" + integrityJson.name + "] does not match expected [" + names.module + "]"); 128 | } else if (names.version && integrityJson.version != names.version) { 129 | throw new Error("Error! - Module version [" + integrityJson.version + "] does not match expected [" + names.version + "]"); 130 | } 131 | 132 | var name = "@" + names.format; 133 | var details = integrityJson.ext = integrityJson.ext || {}; 134 | var fileDetails = details[name] = details[name] || {}; 135 | fileDetails.file = names.name; 136 | fileDetails.type = "text/javascript; charset=utf-8"; 137 | fileDetails.integrity = `sha256-${hash256} sha384-${hash384} sha512-${hash512}`; 138 | fileDetails.hashes = { 139 | sha256: hash256, 140 | sha384: hash384, 141 | sha512: hash512 142 | }; 143 | } 144 | }); 145 | } 146 | 147 | (function generateIntegrityFile() { 148 | var integrityCache = {}; 149 | 150 | var package = JSON.parse(fs.readFileSync("./package.json", "utf8")); 151 | processPath(integrityCache, "./browser/**/*.js", package.version); 152 | processPath(integrityCache, "./snippet/**/*.js", package.version); 153 | processPath(integrityCache, "./dist/**/*.zip", package.version); 154 | 155 | Object.keys(integrityCache).forEach((name) => { 156 | console.log("Writing - " + name); 157 | fs.writeFileSync(name, JSON.stringify(integrityCache[name], null, 4)); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "inlineSources": true, 5 | "noImplicitAny": false, 6 | "module": "amd", 7 | "target": "es3", 8 | "alwaysStrict": true, 9 | "declaration": true 10 | }, 11 | "files": [], 12 | "exclude": [ 13 | "node_modules/**", 14 | "**/*.d.ts" 15 | ] 16 | } -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "The release value identifies the base version that will be applied via the tools/release-tools/setVersion.js", 3 | "usage": "When creating a new release you should update this value directly or via the eg. 'npm run setVersion -- 3.2.0' or 'npm run setVersion -- -patch' or 'npm run setVersion -- -minor'", 4 | "release": "3.0.2", 5 | "next": "patch", 6 | "pkgs": { 7 | "@microsoft/applicationinsights-react-native": { 8 | "package": "applicationinsights-react-native/package.json", 9 | "release": "4.3.6" 10 | } 11 | } 12 | } 13 | --------------------------------------------------------------------------------